Changeset 0.29.0 (#195)
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.gobha.me/xcaliber/chat-switchboard/models"
|
||||
@@ -186,3 +187,110 @@ func scanOneUser(ctx context.Context, query string, args ...interface{}) (*model
|
||||
ScanJSON(sj, &u.Settings)
|
||||
return &u, nil
|
||||
}
|
||||
// ── CS1 additions (v0.29.0) ─────────────────────────────────────────────
|
||||
|
||||
func (s *UserStore) Exists(ctx context.Context, userID string) (bool, error) {
|
||||
var exists bool
|
||||
err := DB.QueryRowContext(ctx,
|
||||
`SELECT EXISTS(SELECT 1 FROM users WHERE id = $1)`, userID).Scan(&exists)
|
||||
return exists, err
|
||||
}
|
||||
|
||||
func (s *UserStore) SearchActive(ctx context.Context, excludeUserID, query string) ([]store.UserSearchResult, error) {
|
||||
q := `
|
||||
SELECT id, username, COALESCE(display_name, '') AS display_name, COALESCE(handle, '') AS handle
|
||||
FROM users
|
||||
WHERE is_active = true AND id != $1`
|
||||
args := []interface{}{excludeUserID}
|
||||
|
||||
if query != "" {
|
||||
q += ` AND (LOWER(username) LIKE $2 OR LOWER(display_name) LIKE $3 OR LOWER(handle) LIKE $4)`
|
||||
pattern := "%" + strings.ToLower(query) + "%"
|
||||
args = append(args, pattern, pattern, pattern)
|
||||
}
|
||||
|
||||
q += ` ORDER BY username LIMIT 20`
|
||||
|
||||
rows, err := DB.QueryContext(ctx, q, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var results []store.UserSearchResult
|
||||
for rows.Next() {
|
||||
var u store.UserSearchResult
|
||||
if err := rows.Scan(&u.ID, &u.Username, &u.DisplayName, &u.Handle); err != nil {
|
||||
continue
|
||||
}
|
||||
results = append(results, u)
|
||||
}
|
||||
if results == nil {
|
||||
results = []store.UserSearchResult{}
|
||||
}
|
||||
return results, rows.Err()
|
||||
}
|
||||
|
||||
// ── CS2 additions (v0.29.0) ─────────────────────────────────────────────
|
||||
|
||||
func (s *UserStore) CountByRole(ctx context.Context, role string) (int, error) {
|
||||
var count int
|
||||
err := DB.QueryRowContext(ctx,
|
||||
`SELECT COUNT(*) FROM users WHERE role = $1`, role).Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (s *UserStore) MergeSettings(ctx context.Context, userID string, patch []byte) error {
|
||||
_, err := DB.ExecContext(ctx, `
|
||||
UPDATE users SET settings = (
|
||||
CASE WHEN settings IS NULL OR settings = 'null'::jsonb OR jsonb_typeof(settings) != 'object'
|
||||
THEN '{}'::jsonb ELSE settings END
|
||||
) || $1::jsonb, updated_at = NOW() WHERE id = $2
|
||||
`, string(patch), userID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *UserStore) GetVaultKeys(ctx context.Context, userID string) (bool, []byte, []byte, []byte, error) {
|
||||
var vaultSet bool
|
||||
var encUEK, salt, nonce []byte
|
||||
err := DB.QueryRowContext(ctx, `
|
||||
SELECT vault_set, encrypted_uek, uek_salt, uek_nonce
|
||||
FROM users WHERE id = $1
|
||||
`, userID).Scan(&vaultSet, &encUEK, &salt, &nonce)
|
||||
return vaultSet, encUEK, salt, nonce, err
|
||||
}
|
||||
|
||||
func (s *UserStore) UpdateVaultKeys(ctx context.Context, userID string, encUEK, salt, nonce []byte) error {
|
||||
_, err := DB.ExecContext(ctx, `
|
||||
UPDATE users
|
||||
SET encrypted_uek = $1, uek_salt = $2, uek_nonce = $3, updated_at = NOW()
|
||||
WHERE id = $4
|
||||
`, encUEK, salt, nonce, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *UserStore) CountAll(ctx context.Context) (int, error) {
|
||||
var count int
|
||||
err := DB.QueryRowContext(ctx, "SELECT COUNT(*) FROM users").Scan(&count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
// ── CS4 additions (v0.29.0) ─────────────────────────────────────────────
|
||||
|
||||
func (s *UserStore) ClearVaultKeys(ctx context.Context, userID string) error {
|
||||
_, err := DB.ExecContext(ctx, `
|
||||
UPDATE users
|
||||
SET encrypted_uek = NULL, uek_salt = NULL, uek_nonce = NULL, vault_set = false
|
||||
WHERE id = $1
|
||||
`, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *UserStore) InitVaultKeys(ctx context.Context, userID string, encUEK, salt, nonce []byte) error {
|
||||
_, err := DB.ExecContext(ctx, `
|
||||
UPDATE users
|
||||
SET encrypted_uek = $1, uek_salt = $2, uek_nonce = $3, vault_set = true
|
||||
WHERE id = $4
|
||||
`, encUEK, salt, nonce, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user