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:
@@ -52,15 +52,15 @@ type Activity struct {
|
||||
// UpsertActivity inserts a new activity or updates the existing row for the
|
||||
// same garmin_activity_id (idempotent, safe to call on every sync pass), and
|
||||
// returns its internal id.
|
||||
func (db *DB) UpsertActivity(ctx context.Context, a Activity) (int64, error) {
|
||||
func (db *DB) UpsertActivity(ctx context.Context, userID int64, a Activity) (int64, error) {
|
||||
_, err := db.ExecContext(ctx, `
|
||||
INSERT INTO activities (
|
||||
garmin_activity_id, event_type_key, workout_id, start_time_utc,
|
||||
user_id, garmin_activity_id, event_type_key, workout_id, start_time_utc,
|
||||
duration_seconds, distance_meters, avg_hr, max_hr,
|
||||
avg_speed_mps, elevation_gain_m,
|
||||
aerobic_training_effect, anaerobic_training_effect, vo2max_value,
|
||||
raw_json, updated_at
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?, datetime('now'))
|
||||
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, datetime('now'))
|
||||
ON CONFLICT(garmin_activity_id) DO UPDATE SET
|
||||
event_type_key=excluded.event_type_key,
|
||||
workout_id=excluded.workout_id,
|
||||
@@ -77,18 +77,18 @@ func (db *DB) UpsertActivity(ctx context.Context, a Activity) (int64, error) {
|
||||
raw_json=excluded.raw_json,
|
||||
updated_at=datetime('now')
|
||||
`,
|
||||
a.GarminActivityID, a.EventTypeKey, a.WorkoutID, a.StartTimeUTC,
|
||||
userID, a.GarminActivityID, a.EventTypeKey, a.WorkoutID, a.StartTimeUTC,
|
||||
a.DurationSeconds, a.DistanceMeters, a.AvgHR, a.MaxHR,
|
||||
a.AvgSpeedMps, a.ElevationGainM,
|
||||
a.AerobicTrainingEffect, a.AnaerobicTrainingEffect, a.VO2MaxValue,
|
||||
a.RawJSON,
|
||||
)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("upsert activity %d: %w", a.GarminActivityID, err)
|
||||
return 0, fmt.Errorf("upsert activity %d for user %d: %w", a.GarminActivityID, userID, err)
|
||||
}
|
||||
|
||||
var id int64
|
||||
if err := db.QueryRowContext(ctx, `SELECT id FROM activities WHERE garmin_activity_id = ?`, a.GarminActivityID).Scan(&id); err != nil {
|
||||
if err := db.QueryRowContext(ctx, `SELECT id FROM activities WHERE garmin_activity_id = ? AND user_id = ?`, a.GarminActivityID, userID).Scan(&id); err != nil {
|
||||
return 0, fmt.Errorf("fetch id for activity %d: %w", a.GarminActivityID, err)
|
||||
}
|
||||
return id, nil
|
||||
@@ -137,10 +137,10 @@ type ActivityFilter struct {
|
||||
Offset int
|
||||
}
|
||||
|
||||
// ListActivities returns activities newest-first, optionally filtered by date range.
|
||||
func (db *DB) ListActivities(ctx context.Context, f ActivityFilter) ([]Activity, error) {
|
||||
query := `SELECT ` + activityColumns + ` FROM activities WHERE 1=1`
|
||||
var args []any
|
||||
// ListActivities returns activities for userID newest-first, optionally filtered by date range.
|
||||
func (db *DB) ListActivities(ctx context.Context, userID int64, f ActivityFilter) ([]Activity, error) {
|
||||
query := `SELECT ` + activityColumns + ` FROM activities WHERE user_id = ?`
|
||||
args := []any{userID}
|
||||
if f.FromDate != "" {
|
||||
query += ` AND start_time_utc >= ?`
|
||||
args = append(args, f.FromDate)
|
||||
@@ -157,7 +157,7 @@ func (db *DB) ListActivities(ctx context.Context, f ActivityFilter) ([]Activity,
|
||||
|
||||
rows, err := db.QueryContext(ctx, query, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list activities: %w", err)
|
||||
return nil, fmt.Errorf("list activities for user %d: %w", userID, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user