package authcode import ( "context" "database/sql" "errors" "fmt" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/model" "git.faercol.me/faercol/polyculeconnect/polyculeconnect/logger" ) var ErrNotFound = errors.New("auth code not found") type AuthCodeDB interface { GetAuthCodeByCode(ctx context.Context, code string) (*model.AuthCode, error) CreateAuthCode(ctx context.Context, code model.AuthCode) error } type sqlAuthCodeDB struct { db *sql.DB } func (db *sqlAuthCodeDB) CreateAuthCode(ctx context.Context, code model.AuthCode) error { logger.L.Debugf("Creating auth code for request %s", code.RequestID) tx, err := db.db.BeginTx(ctx, nil) if err != nil { return fmt.Errorf("failed to start transaction: %w", err) } defer func() { _ = tx.Rollback() }() query := `INSERT INTO "auth_code" ("id", "auth_request_id", "code") VALUES ($1, $2, $3)` _, err = tx.ExecContext(ctx, query, code.CodeID, code.RequestID, code.Code) if err != nil { return fmt.Errorf("failed to insert in DB: %w", err) } if err := tx.Commit(); err != nil { return fmt.Errorf("failed to commit transaction: %w", err) } return nil } func (db *sqlAuthCodeDB) GetAuthCodeByCode(ctx context.Context, code string) (*model.AuthCode, error) { logger.L.Debugf("Getting auth code %s from DB", code) query := `SELECT "id", "auth_request_id", "code" FROM "auth_code" WHERE "code" = ?` row := db.db.QueryRowContext(ctx, query, code) var res model.AuthCode if err := row.Scan(&res.CodeID, &res.RequestID, &res.Code); err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, ErrNotFound } return nil, fmt.Errorf("failed to read row from DB: %w", err) } return &res, nil } func New(db *sql.DB) AuthCodeDB { return &sqlAuthCodeDB{db: db} }