Add backend foundation and config-driven workbench
This commit is contained in:
94
backend/internal/store/postgres/user_store.go
Normal file
94
backend/internal/store/postgres/user_store.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID string
|
||||
PublicID string
|
||||
Status string
|
||||
Nickname *string
|
||||
AvatarURL *string
|
||||
}
|
||||
|
||||
type CreateUserParams struct {
|
||||
PublicID string
|
||||
Status string
|
||||
}
|
||||
|
||||
type queryRower interface {
|
||||
QueryRow(context.Context, string, ...any) pgx.Row
|
||||
}
|
||||
|
||||
func (s *Store) FindUserByMobile(ctx context.Context, tx Tx, countryCode, mobile string) (*User, error) {
|
||||
row := tx.QueryRow(ctx, `
|
||||
SELECT u.id, u.user_public_id, u.status, u.nickname, u.avatar_url
|
||||
FROM users u
|
||||
JOIN login_identities li ON li.user_id = u.id
|
||||
WHERE li.provider = 'mobile'
|
||||
AND li.country_code = $1
|
||||
AND li.mobile = $2
|
||||
AND li.status = 'active'
|
||||
LIMIT 1
|
||||
`, countryCode, mobile)
|
||||
return scanUser(row)
|
||||
}
|
||||
|
||||
func (s *Store) CreateUser(ctx context.Context, tx Tx, params CreateUserParams) (*User, error) {
|
||||
row := tx.QueryRow(ctx, `
|
||||
INSERT INTO users (user_public_id, status)
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, user_public_id, status, nickname, avatar_url
|
||||
`, params.PublicID, params.Status)
|
||||
return scanUser(row)
|
||||
}
|
||||
|
||||
func (s *Store) TouchUserLogin(ctx context.Context, tx Tx, userID string) error {
|
||||
_, err := tx.Exec(ctx, `
|
||||
UPDATE users
|
||||
SET last_login_at = NOW()
|
||||
WHERE id = $1
|
||||
`, userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("touch user last login: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeactivateUser(ctx context.Context, tx Tx, userID string) error {
|
||||
_, err := tx.Exec(ctx, `
|
||||
UPDATE users
|
||||
SET status = 'deleted', updated_at = NOW()
|
||||
WHERE id = $1
|
||||
`, userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("deactivate user: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) GetUserByID(ctx context.Context, db queryRower, userID string) (*User, error) {
|
||||
row := db.QueryRow(ctx, `
|
||||
SELECT id, user_public_id, status, nickname, avatar_url
|
||||
FROM users
|
||||
WHERE id = $1
|
||||
`, userID)
|
||||
return scanUser(row)
|
||||
}
|
||||
|
||||
func scanUser(row pgx.Row) (*User, error) {
|
||||
var user User
|
||||
err := row.Scan(&user.ID, &user.PublicID, &user.Status, &user.Nickname, &user.AvatarURL)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("scan user: %w", err)
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
Reference in New Issue
Block a user