8b86bd573e
Task 7 – AuthController (POST /api/auth/login|refresh|logout)
- Refresh token in HttpOnly; Secure; SameSite=Strict cookie (rolac_rt)
- Cookie Path scoped to /api/auth; cleared on logout/invalid refresh
Task 8 – appsettings.json (non-secret JWT values + CORS origins)
- appsettings.Development.json carries connection string + JWT secret
(file is gitignored)
Task 9 – Program.cs wiring
- EF Core + Npgsql, ASP.NET Core Identity, JWT Bearer auth
- RoleClaimType=role matches the short JWT claim name written by TokenService
- CORS: AllowCredentials for Angular app
- Swagger UI with Bearer security definition
- Startup: MigrateAsync + DbSeeder.SeedAsync (roles + dev admin)
- DbSeeder: added SeedAsync(IServiceProvider) entry point
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
84 lines
3.3 KiB
C#
84 lines
3.3 KiB
C#
using Microsoft.AspNetCore.Identity;
|
|
using ROLAC.API.Entities;
|
|
|
|
namespace ROLAC.API.Data;
|
|
|
|
public static class DbSeeder
|
|
{
|
|
private static readonly (string Name, string Description)[] Roles =
|
|
[
|
|
("super_admin", "System administrator — full access"),
|
|
("pastor", "Pastor — full member and financial overview"),
|
|
("board_member", "Board member — church governance"),
|
|
("coworker_chair", "Coworker chair — coordinates ministry leaders"),
|
|
("ministry_leader", "Ministry leader — scoped to own ministry"),
|
|
("district_leader", "District leader — manages multiple cell groups"),
|
|
("cell_leader", "Cell leader — scoped to own cell group"),
|
|
("coworker", "Coworker — general worker in assigned ministry"),
|
|
("finance", "Finance — manages giving and expense reports"),
|
|
("secretary", "Secretary — manages member data and scheduling"),
|
|
("worship_leader", "Worship leader — manages song library and setlists (Phase deferred)"),
|
|
("member", "Member — views own profile and service roster"),
|
|
("visitor", "Visitor — public pages only"),
|
|
];
|
|
|
|
public static async Task SeedRolesAsync(RoleManager<AppRole> roleManager)
|
|
{
|
|
foreach (var (name, description) in Roles)
|
|
{
|
|
if (!await roleManager.RoleExistsAsync(name))
|
|
{
|
|
await roleManager.CreateAsync(new AppRole
|
|
{
|
|
Name = name,
|
|
Description = description,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Seeds roles and (in Development) the default admin account.
|
|
/// Called once on application startup after migrations have been applied.
|
|
/// </summary>
|
|
public static async Task SeedAsync(IServiceProvider services)
|
|
{
|
|
var roleManager = services.GetRequiredService<RoleManager<AppRole>>();
|
|
var userManager = services.GetRequiredService<UserManager<AppUser>>();
|
|
var env = services.GetRequiredService<IWebHostEnvironment>();
|
|
|
|
await SeedRolesAsync(roleManager);
|
|
|
|
if (env.IsDevelopment())
|
|
await SeedAdminUserAsync(userManager);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a super_admin test account for local development.
|
|
/// DO NOT call this in production — remove or guard with IsDevelopment().
|
|
/// Credentials: admin@rolac.org / Admin1234!
|
|
/// </summary>
|
|
public static async Task SeedAdminUserAsync(UserManager<AppUser> userManager)
|
|
{
|
|
const string adminEmail = "admin@rolac.org";
|
|
const string adminPassword = "Admin1234!";
|
|
|
|
if (await userManager.FindByEmailAsync(adminEmail) is null)
|
|
{
|
|
var admin = new AppUser
|
|
{
|
|
UserName = adminEmail,
|
|
Email = adminEmail,
|
|
EmailConfirmed = true,
|
|
IsActive = true,
|
|
LanguagePreference = "en",
|
|
CreatedAt = DateTime.UtcNow,
|
|
};
|
|
|
|
var result = await userManager.CreateAsync(admin, adminPassword);
|
|
if (result.Succeeded)
|
|
await userManager.AddToRoleAsync(admin, "super_admin");
|
|
}
|
|
}
|
|
}
|