feat: fb and google oauth
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/prabhupadasays/spsays-bff/internal/model"
|
||||
)
|
||||
|
||||
// ErrOAuthAccountNotFound mirrors the other repo sentinels.
|
||||
var ErrOAuthAccountNotFound = errors.New("oauth account not found")
|
||||
|
||||
// OAuthAccountRepo manages provider linkage rows.
|
||||
type OAuthAccountRepo struct {
|
||||
pg *Postgres
|
||||
}
|
||||
|
||||
func NewOAuthAccountRepo(pg *Postgres) *OAuthAccountRepo {
|
||||
return &OAuthAccountRepo{pg: pg}
|
||||
}
|
||||
|
||||
// FindByProvider returns the linkage row for the given (provider, provider_user_id),
|
||||
// or ErrOAuthAccountNotFound. Use this first on every callback — a hit means
|
||||
// this provider identity has been seen before and we just log the user in.
|
||||
func (r *OAuthAccountRepo) FindByProvider(ctx context.Context, provider, providerUserID string) (*model.OAuthAccount, error) {
|
||||
const q = `
|
||||
SELECT id, user_id, provider, provider_user_id, email, name, avatar_url, created_at, updated_at
|
||||
FROM oauth_accounts
|
||||
WHERE provider = $1 AND provider_user_id = $2
|
||||
LIMIT 1`
|
||||
a := &model.OAuthAccount{}
|
||||
err := r.pg.Pool.QueryRow(ctx, q, provider, providerUserID).Scan(
|
||||
&a.ID, &a.UserID, &a.Provider, &a.ProviderUserID,
|
||||
&a.Email, &a.Name, &a.AvatarURL, &a.CreatedAt, &a.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, ErrOAuthAccountNotFound
|
||||
}
|
||||
return nil, fmt.Errorf("find oauth account: %w", err)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Link inserts a new oauth_accounts row tying a provider identity to an
|
||||
// existing user. Idempotent: a second call for the same (provider, sub)
|
||||
// returns the existing row instead of erroring on the unique constraint.
|
||||
func (r *OAuthAccountRepo) Link(ctx context.Context, userID, provider, providerUserID string, email, name, avatarURL *string) (*model.OAuthAccount, error) {
|
||||
const q = `
|
||||
INSERT INTO oauth_accounts (user_id, provider, provider_user_id, email, name, avatar_url)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
ON CONFLICT (provider, provider_user_id) DO UPDATE
|
||||
SET email = EXCLUDED.email,
|
||||
name = EXCLUDED.name,
|
||||
avatar_url = EXCLUDED.avatar_url,
|
||||
updated_at = now()
|
||||
RETURNING id, user_id, provider, provider_user_id, email, name, avatar_url, created_at, updated_at`
|
||||
a := &model.OAuthAccount{}
|
||||
err := r.pg.Pool.QueryRow(ctx, q, userID, provider, providerUserID, email, name, avatarURL).Scan(
|
||||
&a.ID, &a.UserID, &a.Provider, &a.ProviderUserID,
|
||||
&a.Email, &a.Name, &a.AvatarURL, &a.CreatedAt, &a.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("link oauth account: %w", err)
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
Reference in New Issue
Block a user