From 56aacb01347dbd5011245eb12ee99e2085e868e7 Mon Sep 17 00:00:00 2001 From: troogs Date: Sun, 1 Feb 2026 10:29:00 +0100 Subject: [PATCH] Add sample data toggle to user provisioning --- .../Endpoints/ExerciseEndpoints.cs | 21 +++++++++------ src/ASTRAIN.Api/Endpoints/RoutineEndpoints.cs | 26 ++++++++++++------- .../Endpoints/RoutineRunEndpoints.cs | 11 +++++--- src/ASTRAIN.Api/Endpoints/UserEndpoints.cs | 11 +++++--- src/ASTRAIN.Api/Services/UserProvisioning.cs | 13 +++++++--- src/ASTRAIN.Api/appsettings.Development.json | 3 +++ src/ASTRAIN.Api/appsettings.json | 3 +++ 7 files changed, 59 insertions(+), 29 deletions(-) diff --git a/src/ASTRAIN.Api/Endpoints/ExerciseEndpoints.cs b/src/ASTRAIN.Api/Endpoints/ExerciseEndpoints.cs index d11f39d..5206a60 100644 --- a/src/ASTRAIN.Api/Endpoints/ExerciseEndpoints.cs +++ b/src/ASTRAIN.Api/Endpoints/ExerciseEndpoints.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; namespace ASTRAIN.Api.Endpoints; @@ -22,9 +23,10 @@ internal static class ExerciseEndpoints /// The same route group for chaining. public static RouteGroupBuilder MapExerciseEndpoints(this RouteGroupBuilder group) { - group.MapGet("/users/{userId}/exercises", async (string userId, AppDbContext db) => + group.MapGet("/users/{userId}/exercises", async (string userId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var items = await db.Exercises .Where(e => e.UserId == user.Id) .OrderBy(e => e.Name) @@ -35,9 +37,10 @@ internal static class ExerciseEndpoints .WithSummary("List exercises") .WithDescription("Returns the exercises for the specified user."); - group.MapPost("/users/{userId}/exercises", async (string userId, ExerciseUpsertRequest request, AppDbContext db) => + group.MapPost("/users/{userId}/exercises", async (string userId, ExerciseUpsertRequest request, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); if (string.IsNullOrWhiteSpace(request.Name)) { return Results.BadRequest("Name is required."); @@ -57,9 +60,10 @@ internal static class ExerciseEndpoints .WithSummary("Create exercise") .WithDescription("Creates a new exercise for the specified user."); - group.MapPut("/users/{userId}/exercises/{exerciseId:int}", async (string userId, int exerciseId, ExerciseUpsertRequest request, AppDbContext db) => + group.MapPut("/users/{userId}/exercises/{exerciseId:int}", async (string userId, int exerciseId, ExerciseUpsertRequest request, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var exercise = await db.Exercises.FirstOrDefaultAsync(e => e.Id == exerciseId && e.UserId == user.Id); if (exercise is null) { @@ -79,9 +83,10 @@ internal static class ExerciseEndpoints .WithSummary("Update exercise") .WithDescription("Updates the name of an exercise for the specified user."); - group.MapDelete("/users/{userId}/exercises/{exerciseId:int}", async (string userId, int exerciseId, AppDbContext db) => + group.MapDelete("/users/{userId}/exercises/{exerciseId:int}", async (string userId, int exerciseId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var exercise = await db.Exercises.FirstOrDefaultAsync(e => e.Id == exerciseId && e.UserId == user.Id); if (exercise is null) { diff --git a/src/ASTRAIN.Api/Endpoints/RoutineEndpoints.cs b/src/ASTRAIN.Api/Endpoints/RoutineEndpoints.cs index d2b525b..00a1de8 100644 --- a/src/ASTRAIN.Api/Endpoints/RoutineEndpoints.cs +++ b/src/ASTRAIN.Api/Endpoints/RoutineEndpoints.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; namespace ASTRAIN.Api.Endpoints; @@ -22,9 +23,10 @@ internal static class RoutineEndpoints /// The same route group for chaining. public static RouteGroupBuilder MapRoutineEndpoints(this RouteGroupBuilder group) { - group.MapGet("/users/{userId}/routines", async (string userId, AppDbContext db) => + group.MapGet("/users/{userId}/routines", async (string userId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var routines = await db.Routines .Include(r => r.Exercises) .ThenInclude(re => re.Exercise) @@ -46,9 +48,10 @@ internal static class RoutineEndpoints .WithSummary("List routines") .WithDescription("Returns all routines for the specified user."); - group.MapGet("/users/{userId}/routines/{routineId:int}", async (string userId, int routineId, AppDbContext db) => + group.MapGet("/users/{userId}/routines/{routineId:int}", async (string userId, int routineId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var routine = await db.Routines .Include(r => r.Exercises) .ThenInclude(re => re.Exercise) @@ -72,9 +75,10 @@ internal static class RoutineEndpoints .WithSummary("Get routine") .WithDescription("Returns a specific routine and its exercises."); - group.MapPost("/users/{userId}/routines", async (string userId, RoutineUpsertRequest request, AppDbContext db) => + group.MapPost("/users/{userId}/routines", async (string userId, RoutineUpsertRequest request, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); if (string.IsNullOrWhiteSpace(request.Name)) { return Results.BadRequest("Name is required."); @@ -113,9 +117,10 @@ internal static class RoutineEndpoints .WithSummary("Create routine") .WithDescription("Creates a routine and associates exercises with it."); - group.MapPut("/users/{userId}/routines/{routineId:int}", async (string userId, int routineId, RoutineUpsertRequest request, AppDbContext db) => + group.MapPut("/users/{userId}/routines/{routineId:int}", async (string userId, int routineId, RoutineUpsertRequest request, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var routine = await db.Routines .Include(r => r.Exercises) .FirstOrDefaultAsync(r => r.Id == routineId && r.UserId == user.Id); @@ -160,9 +165,10 @@ internal static class RoutineEndpoints .WithSummary("Update routine") .WithDescription("Updates routine metadata and exercise ordering."); - group.MapDelete("/users/{userId}/routines/{routineId:int}", async (string userId, int routineId, AppDbContext db) => + group.MapDelete("/users/{userId}/routines/{routineId:int}", async (string userId, int routineId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var routine = await db.Routines.FirstOrDefaultAsync(r => r.Id == routineId && r.UserId == user.Id); if (routine is null) { diff --git a/src/ASTRAIN.Api/Endpoints/RoutineRunEndpoints.cs b/src/ASTRAIN.Api/Endpoints/RoutineRunEndpoints.cs index e53e54e..5916921 100644 --- a/src/ASTRAIN.Api/Endpoints/RoutineRunEndpoints.cs +++ b/src/ASTRAIN.Api/Endpoints/RoutineRunEndpoints.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; namespace ASTRAIN.Api.Endpoints; @@ -22,9 +23,10 @@ internal static class RoutineRunEndpoints /// The same route group for chaining. public static RouteGroupBuilder MapRoutineRunEndpoints(this RouteGroupBuilder group) { - group.MapGet("/users/{userId}/routines/{routineId:int}/last-run", async (string userId, int routineId, AppDbContext db) => + group.MapGet("/users/{userId}/routines/{routineId:int}/last-run", async (string userId, int routineId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var lastRun = await db.RoutineRuns .Include(rr => rr.Entries) .Where(rr => rr.UserId == user.Id && rr.RoutineId == routineId) @@ -47,9 +49,10 @@ internal static class RoutineRunEndpoints .WithSummary("Get last routine run") .WithDescription("Returns the most recent run summary for a routine."); - group.MapPost("/users/{userId}/routines/{routineId:int}/runs", async (string userId, int routineId, RoutineRunRequest request, AppDbContext db) => + group.MapPost("/users/{userId}/routines/{routineId:int}/runs", async (string userId, int routineId, RoutineRunRequest request, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); var routine = await db.Routines.FirstOrDefaultAsync(r => r.Id == routineId && r.UserId == user.Id); if (routine is null) { diff --git a/src/ASTRAIN.Api/Endpoints/UserEndpoints.cs b/src/ASTRAIN.Api/Endpoints/UserEndpoints.cs index c2e3d61..364be3f 100644 --- a/src/ASTRAIN.Api/Endpoints/UserEndpoints.cs +++ b/src/ASTRAIN.Api/Endpoints/UserEndpoints.cs @@ -4,6 +4,7 @@ using ASTRAIN.Shared.Responses; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Configuration; namespace ASTRAIN.Api.Endpoints; @@ -19,17 +20,19 @@ internal static class UserEndpoints /// The same route group for chaining. public static RouteGroupBuilder MapUserEndpoints(this RouteGroupBuilder group) { - group.MapGet("/users/ensure", async (string? userId, AppDbContext db) => + group.MapGet("/users/ensure", async (string? userId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); return Results.Ok(new EnsureUserResponse(user.Id)); }) .WithSummary("Ensure user") .WithDescription("Ensures a user exists and returns the user id."); - group.MapGet("/users/{userId}", async (string userId, AppDbContext db) => + group.MapGet("/users/{userId}", async (string userId, AppDbContext db, IConfiguration config) => { - var user = await UserProvisioning.EnsureUserAsync(db, userId); + var populateSampleData = config.GetValue("SampleData:Enabled", false); + var user = await UserProvisioning.EnsureUserAsync(db, userId, populateSampleData); return Results.Ok(new EnsureUserResponse(user.Id)); }) .WithSummary("Get user") diff --git a/src/ASTRAIN.Api/Services/UserProvisioning.cs b/src/ASTRAIN.Api/Services/UserProvisioning.cs index 228ab8a..1293954 100644 --- a/src/ASTRAIN.Api/Services/UserProvisioning.cs +++ b/src/ASTRAIN.Api/Services/UserProvisioning.cs @@ -15,8 +15,9 @@ internal static class UserProvisioning /// /// The application database context. /// Optional user id to validate or create. + /// Whether to populate sample data for new users. /// The existing or newly created user. - public static async Task EnsureUserAsync(AppDbContext db, string? userId) + public static async Task EnsureUserAsync(AppDbContext db, string? userId, bool populateSampleData) { if (!string.IsNullOrWhiteSpace(userId) && IsValidUserId(userId)) { @@ -29,7 +30,10 @@ internal static class UserProvisioning var created = new User { Id = userId }; db.Users.Add(created); await db.SaveChangesAsync(); - await PopulateSampleDataAsync(db, created); + if (populateSampleData) + { + await PopulateSampleDataAsync(db, created); + } return created; } @@ -45,7 +49,10 @@ internal static class UserProvisioning var user = new User { Id = newId }; db.Users.Add(user); await db.SaveChangesAsync(); - await PopulateSampleDataAsync(db, user); + if (populateSampleData) + { + await PopulateSampleDataAsync(db, user); + } return user; } } diff --git a/src/ASTRAIN.Api/appsettings.Development.json b/src/ASTRAIN.Api/appsettings.Development.json index 0c208ae..fc9443c 100644 --- a/src/ASTRAIN.Api/appsettings.Development.json +++ b/src/ASTRAIN.Api/appsettings.Development.json @@ -4,5 +4,8 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } + }, + "SampleData": { + "Enabled": false } } diff --git a/src/ASTRAIN.Api/appsettings.json b/src/ASTRAIN.Api/appsettings.json index 07729c7..44ff5b0 100644 --- a/src/ASTRAIN.Api/appsettings.json +++ b/src/ASTRAIN.Api/appsettings.json @@ -8,5 +8,8 @@ "ConnectionStrings": { "Default": "Data Source=Data/astrain.db" }, + "SampleData": { + "Enabled": false + }, "AllowedHosts": "*" }