mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 08:01:16 +00:00
134 lines
2.8 KiB
Go
134 lines
2.8 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/mail"
|
|
"time"
|
|
|
|
"github.com/getsentry/sentry-go"
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/warmbly/warmbly/internal/errx"
|
|
"github.com/warmbly/warmbly/internal/infrastructure/db"
|
|
"github.com/warmbly/warmbly/internal/models"
|
|
"github.com/warmbly/warmbly/internal/pkg/argon2"
|
|
)
|
|
|
|
type AuthRepository interface {
|
|
IsValidCredentials(ctx context.Context, email, password string) (uuid.UUID, *errx.Error)
|
|
ExternalLogin(ctx context.Context, email string) (*models.User, *errx.Error)
|
|
ResetPassword(ctx context.Context, userID uuid.UUID, password string) *errx.Error
|
|
}
|
|
|
|
type authRepository struct {
|
|
DB *db.DB
|
|
}
|
|
|
|
func NewAuthRepostory(db *db.DB) AuthRepository {
|
|
return &authRepository{
|
|
DB: db,
|
|
}
|
|
}
|
|
|
|
func (r *authRepository) IsValidCredentials(ctx context.Context, email, password string) (uuid.UUID, *errx.Error) {
|
|
var id uuid.UUID
|
|
var pw string
|
|
|
|
query := `
|
|
SELECT id, password_hash
|
|
FROM users
|
|
WHERE email = $1
|
|
`
|
|
|
|
params := []any{
|
|
email,
|
|
}
|
|
|
|
err := r.DB.QueryRow(
|
|
ctx,
|
|
query,
|
|
params...,
|
|
).Scan(&id, &pw)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return uuid.Nil, errx.ErrCredentials
|
|
}
|
|
db.CaptureError(err, query, params, "queryrow")
|
|
return uuid.Nil, errx.InternalError()
|
|
}
|
|
|
|
val, err := argon2.Verify(password, pw)
|
|
if err != nil {
|
|
sentry.CaptureException(err)
|
|
return uuid.Nil, errx.InternalError()
|
|
}
|
|
|
|
if !val {
|
|
return uuid.Nil, errx.ErrCredentials
|
|
}
|
|
|
|
return id, nil
|
|
}
|
|
|
|
func (r *authRepository) ExternalLogin(ctx context.Context, email string) (*models.User, *errx.Error) {
|
|
id := uuid.NewString()
|
|
vMail, err := mail.ParseAddress(email)
|
|
if err != nil {
|
|
return nil, errx.ErrEmail
|
|
}
|
|
|
|
firstName := vMail.Name
|
|
lastName := ""
|
|
now := time.Now()
|
|
|
|
query := `
|
|
INSERT INTO users (id, email, password_hash, first_name, last_name, created_at, updated_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $6)
|
|
ON CONFLICT (email) DO UPDATE
|
|
SET updated_at = EXCLUDED.updated_at
|
|
RETURNING id, email, first_name, last_name, created_at, updated_at;
|
|
`
|
|
|
|
var params = []any{
|
|
id,
|
|
email,
|
|
"",
|
|
firstName,
|
|
lastName,
|
|
now,
|
|
}
|
|
|
|
var u models.User
|
|
err = r.DB.QueryRow(
|
|
ctx,
|
|
query,
|
|
params...,
|
|
).Scan(&u.ID, &u.Email, &u.FirstName, &u.LastName, &u.CreatedAt, &u.UpdatedAt)
|
|
if err != nil {
|
|
db.CaptureError(err, query, nil, "queryrow")
|
|
return nil, errx.InternalError()
|
|
}
|
|
|
|
return &u, nil
|
|
}
|
|
|
|
func (r *authRepository) ResetPassword(ctx context.Context, userID uuid.UUID, passwordHash string) *errx.Error {
|
|
query := `
|
|
UPDATE users
|
|
SET password_hash = $1, updated_at = now()
|
|
WHERE id = $2
|
|
`
|
|
params := []any{
|
|
passwordHash,
|
|
userID,
|
|
}
|
|
|
|
if _, err := r.DB.Exec(ctx, query, params...); err != nil {
|
|
db.CaptureError(err, query, params, "exec")
|
|
return errx.InternalError()
|
|
}
|
|
|
|
return nil
|
|
}
|