Add backend foundation and config-driven workbench

This commit is contained in:
2026-04-01 15:01:44 +08:00
parent 88b8f05f03
commit 94a1f0ba78
68 changed files with 10833 additions and 0 deletions

View 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
}