63 lines
1.8 KiB
Go
63 lines
1.8 KiB
Go
package user
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.faercol.me/faercol/polyculeconnect/polyculeconnect/internal/model"
|
|
)
|
|
|
|
type UserDB interface {
|
|
AddUser(ctx context.Context, user *model.User) error
|
|
GetUserBySubject(ctx context.Context, subject string) (*model.User, error)
|
|
}
|
|
|
|
var ErrNotFound = errors.New("not found")
|
|
|
|
const getUserQuery = `
|
|
SELECT id, name, family_name, given_name, nickname, picture, updated_at, email, email_verified
|
|
FROM user
|
|
WHERE id = ?
|
|
`
|
|
const insertUserQuery = `
|
|
INSERT OR REPLACE INTO user (id, name, family_name, given_name, nickname, picture, updated_at, email, email_verified)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
`
|
|
|
|
type sqlUserDB struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
func (db *sqlUserDB) GetUserBySubject(ctx context.Context, subject string) (*model.User, error) {
|
|
row := db.db.QueryRowContext(ctx, getUserQuery, subject)
|
|
var res model.User
|
|
if err := row.Scan(&res.Subject, &res.Name, &res.FamilyName, &res.GivenName, &res.Nickname, &res.Picture, &res.UpdatedAt, &res.Email, &res.EmailVerified); err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return nil, ErrNotFound
|
|
}
|
|
return nil, fmt.Errorf("failed to read result from DB: %w", err)
|
|
}
|
|
return &res, nil
|
|
}
|
|
|
|
func (db *sqlUserDB) AddUser(ctx context.Context, user *model.User) error {
|
|
tx, err := db.db.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to start transaction: %w", err)
|
|
}
|
|
defer func() { _ = tx.Rollback() }()
|
|
|
|
if _, err := tx.ExecContext(ctx, insertUserQuery, user.Subject, user.Name, user.FamilyName, user.GivenName, user.Nickname, user.Picture, user.UpdatedAt, user.Email, user.EmailVerified); 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 New(db *sql.DB) *sqlUserDB {
|
|
return &sqlUserDB{db: db}
|
|
}
|