refactor(store): single account name on users; rename profile/laps tables
users.display_name becomes users.name and is now the only human-facing name -- profiles.name is dropped (it duplicated the account name; the Profile page's Name field now edits users.name through PUT /api/profile, which carries Name alongside the profiles columns). The profile table becomes profiles and laps becomes activity_laps, homogeneous with activity_samples. Onboarding pre-fills the display name from the OIDC claim's name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,18 +11,18 @@ import (
|
||||
// state) is scoped to exactly one User -- see
|
||||
// docs/superpowers/specs/2026-07-25-per-user-profile-design.md.
|
||||
type User struct {
|
||||
ID int64
|
||||
OIDCSub string
|
||||
DisplayName string
|
||||
CreatedAt string
|
||||
ID int64
|
||||
OIDCSub string
|
||||
Name string
|
||||
CreatedAt string
|
||||
}
|
||||
|
||||
// GetUserBySub looks up a user by their OIDC subject -- the only lookup key
|
||||
// the session-resolution middleware ever uses.
|
||||
func (db *DB) GetUserBySub(ctx context.Context, oidcSub string) (User, bool, error) {
|
||||
var u User
|
||||
err := db.QueryRowContext(ctx, `SELECT id, oidc_sub, display_name, created_at FROM users WHERE oidc_sub = ?`, oidcSub).
|
||||
Scan(&u.ID, &u.OIDCSub, &u.DisplayName, &u.CreatedAt)
|
||||
err := db.QueryRowContext(ctx, `SELECT id, oidc_sub, name, created_at FROM users WHERE oidc_sub = ?`, oidcSub).
|
||||
Scan(&u.ID, &u.OIDCSub, &u.Name, &u.CreatedAt)
|
||||
if err == sql.ErrNoRows {
|
||||
return User{}, false, nil
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (db *DB) ProvisionUser(ctx context.Context, oidcSub, displayName string) (i
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
res, err := tx.ExecContext(ctx, `INSERT INTO users (oidc_sub, display_name) VALUES (?, ?)`, oidcSub, displayName)
|
||||
res, err := tx.ExecContext(ctx, `INSERT INTO users (oidc_sub, name) VALUES (?, ?)`, oidcSub, displayName)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("create user %q: %w", oidcSub, err)
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func (db *DB) ProvisionUser(ctx context.Context, oidcSub, displayName string) (i
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if _, err := tx.ExecContext(ctx, `INSERT INTO profile (user_id, name) VALUES (?, ?)`, userID, displayName); err != nil {
|
||||
if _, err := tx.ExecContext(ctx, `INSERT INTO profiles (user_id) VALUES (?)`, userID); err != nil {
|
||||
return 0, fmt.Errorf("create profile for user %d: %w", userID, err)
|
||||
}
|
||||
|
||||
@@ -113,3 +113,12 @@ func (db *DB) DeleteUser(ctx context.Context, userID int64) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateUserName renames userID's account -- the single human-facing name
|
||||
// (shown in the header and session info), editable from the Profile page.
|
||||
func (db *DB) UpdateUserName(ctx context.Context, userID int64, name string) error {
|
||||
if _, err := db.ExecContext(ctx, `UPDATE users SET name = ? WHERE id = ?`, name, userID); err != nil {
|
||||
return fmt.Errorf("update name for user %d: %w", userID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user