store: scope GetProfile/UpdateProfile to a user_id

Part of per-user profile isolation: profile rows are no longer a global
singleton, so every read/write requires the caller's userID. This also
requires scoping ListActivities, ListWorkoutKinds, UpsertActivity,
CreateWorkoutKind, GetSyncState, UpdateSyncState, and ResetAllSyncedData
to userID, plus updating all related tests in the store package.
This commit is contained in:
2026-07-25 13:17:17 +02:00
parent b0a7462ebe
commit ef410863c6
10 changed files with 104 additions and 67 deletions

View File

@@ -29,13 +29,13 @@ func scanWorkoutKind(row interface{ Scan(...any) error }) (WorkoutKind, error) {
const workoutKindColumns = `id, name, description, color, rule_json, priority, is_active, created_at, updated_at`
// CreateWorkoutKind inserts a new workout kind and returns its id.
func (db *DB) CreateWorkoutKind(ctx context.Context, k WorkoutKind) (int64, error) {
func (db *DB) CreateWorkoutKind(ctx context.Context, userID int64, k WorkoutKind) (int64, error) {
res, err := db.ExecContext(ctx, `
INSERT INTO workout_kinds (name, description, color, rule_json, priority, is_active)
VALUES (?,?,?,?,?,?)`,
k.Name, k.Description, k.Color, k.RuleJSON, k.Priority, k.IsActive)
INSERT INTO workout_kinds (user_id, name, description, color, rule_json, priority, is_active)
VALUES (?,?,?,?,?,?,?)`,
userID, k.Name, k.Description, k.Color, k.RuleJSON, k.Priority, k.IsActive)
if err != nil {
return 0, fmt.Errorf("create workout kind %q: %w", k.Name, err)
return 0, fmt.Errorf("create workout kind %q for user %d: %w", k.Name, userID, err)
}
return res.LastInsertId()
}
@@ -78,18 +78,18 @@ func (db *DB) GetWorkoutKindByName(ctx context.Context, name string) (WorkoutKin
return k, true, nil
}
// ListWorkoutKinds returns workout kinds. If activeOnly, soft-deleted
// ListWorkoutKinds returns workout kinds for userID. If activeOnly, soft-deleted
// (is_active=0) kinds are excluded.
func (db *DB) ListWorkoutKinds(ctx context.Context, activeOnly bool) ([]WorkoutKind, error) {
query := `SELECT ` + workoutKindColumns + ` FROM workout_kinds`
func (db *DB) ListWorkoutKinds(ctx context.Context, userID int64, activeOnly bool) ([]WorkoutKind, error) {
query := `SELECT ` + workoutKindColumns + ` FROM workout_kinds WHERE user_id = ?`
if activeOnly {
query += ` WHERE is_active = 1`
query += ` AND is_active = 1`
}
query += ` ORDER BY priority DESC, name`
rows, err := db.QueryContext(ctx, query)
rows, err := db.QueryContext(ctx, query, userID)
if err != nil {
return nil, fmt.Errorf("list workout kinds: %w", err)
return nil, fmt.Errorf("list workout kinds for user %d: %w", userID, err)
}
defer rows.Close()