Skip to content

Commit 7e1df4c

Browse files
committed
Add SuperAdmin authorization policy and JWT claims
1 parent e4ce23f commit 7e1df4c

5 files changed

Lines changed: 48 additions & 2 deletions

File tree

cloud/src/LrmCloud.Api/Helpers/JwtTokenGenerator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ public static (string Token, DateTime ExpiresAt) GenerateToken(
2525
new(ClaimTypes.Name, user.Username ?? user.Email!),
2626
new("auth_type", user.AuthType),
2727
new("plan", user.Plan),
28-
new("email_verified", user.EmailVerified.ToString())
28+
new("email_verified", user.EmailVerified.ToString()),
29+
new("is_superadmin", user.IsSuperAdmin.ToString().ToLowerInvariant())
2930
};
3031

3132
var tokenDescriptor = new SecurityTokenDescriptor

cloud/src/LrmCloud.Api/Program.cs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ public static int Main(string[] args)
174174
// Authorization Service
175175
builder.Services.AddScoped<ILrmAuthorizationService, LrmAuthorizationService>();
176176

177+
// Admin Service
178+
builder.Services.AddScoped<IAdminService, AdminService>();
179+
177180
// Background Jobs
178181
builder.Services.AddHostedService<UsageResetService>();
179182

@@ -270,7 +273,11 @@ public static int Main(string[] args)
270273
};
271274
});
272275

273-
builder.Services.AddAuthorization();
276+
builder.Services.AddAuthorization(options =>
277+
{
278+
options.AddPolicy("SuperAdmin", policy =>
279+
policy.RequireClaim("is_superadmin", "true"));
280+
});
274281

275282
builder.Services.AddControllers()
276283
.AddJsonOptions(options =>
@@ -408,6 +415,36 @@ await context.HttpContext.Response.WriteAsJsonAsync(new
408415
Log.Error(ex, "Database migration failed");
409416
throw;
410417
}
418+
419+
// Seed superadmins from configuration
420+
var superAdminEmails = config.SuperAdmin?.Emails ?? new List<string>();
421+
if (superAdminEmails.Count > 0)
422+
{
423+
Log.Information("Checking superadmin configuration for {Count} email(s)", superAdminEmails.Count);
424+
foreach (var email in superAdminEmails)
425+
{
426+
var normalizedEmail = email.ToLowerInvariant().Trim();
427+
var user = db.Users.FirstOrDefault(u => u.Email == normalizedEmail);
428+
if (user != null)
429+
{
430+
if (!user.IsSuperAdmin)
431+
{
432+
user.IsSuperAdmin = true;
433+
user.UpdatedAt = DateTime.UtcNow;
434+
db.SaveChanges();
435+
Log.Information("User {Email} set as superadmin", normalizedEmail);
436+
}
437+
else
438+
{
439+
Log.Debug("User {Email} is already a superadmin", normalizedEmail);
440+
}
441+
}
442+
else
443+
{
444+
Log.Warning("Superadmin user {Email} not found in database (will be set when user registers)", normalizedEmail);
445+
}
446+
}
447+
}
411448
}
412449

413450
// =============================================================================

cloud/src/LrmCloud.Api/Services/AuthService.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ await _mailService.TrySendEmailAsync(_logger,
418418
AvatarUrl = user.AvatarUrl,
419419
EmailVerified = user.EmailVerified,
420420
Plan = user.Plan,
421+
IsSuperAdmin = user.IsSuperAdmin,
421422
CreatedAt = user.CreatedAt
422423
},
423424
Token = token,
@@ -543,6 +544,7 @@ await _mailService.TrySendEmailAsync(_logger,
543544
AvatarUrl = user.AvatarUrl,
544545
EmailVerified = user.EmailVerified,
545546
Plan = user.Plan,
547+
IsSuperAdmin = user.IsSuperAdmin,
546548
CreatedAt = user.CreatedAt
547549
},
548550
Token = token,
@@ -608,6 +610,7 @@ public async Task<bool> RevokeRefreshTokenAsync(string refreshToken, string? ipA
608610
Plan = user.Plan,
609611
PaymentCustomerId = user.PaymentCustomerId,
610612
PaymentProvider = user.PaymentProvider,
613+
IsSuperAdmin = user.IsSuperAdmin,
611614
TranslationCharsUsed = user.TranslationCharsUsed,
612615
TranslationCharsLimit = user.TranslationCharsLimit,
613616
TranslationCharsResetAt = user.TranslationCharsResetAt,
@@ -669,6 +672,7 @@ public async Task<bool> RevokeRefreshTokenAsync(string refreshToken, string? ipA
669672
Plan = user.Plan,
670673
PaymentCustomerId = user.PaymentCustomerId,
671674
PaymentProvider = user.PaymentProvider,
675+
IsSuperAdmin = user.IsSuperAdmin,
672676
TranslationCharsUsed = user.TranslationCharsUsed,
673677
TranslationCharsLimit = user.TranslationCharsLimit,
674678
TranslationCharsResetAt = user.TranslationCharsResetAt,

cloud/src/LrmCloud.Shared/DTOs/Auth/UserDto.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ public class UserDto
99
public string? AvatarUrl { get; set; }
1010
public bool EmailVerified { get; set; }
1111
public string Plan { get; set; } = "free";
12+
public bool IsSuperAdmin { get; set; }
1213
public DateTime CreatedAt { get; set; }
1314
}

cloud/src/LrmCloud.Shared/DTOs/Auth/UserProfileDto.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ public class UserProfileDto
2222
public string? PaymentCustomerId { get; set; }
2323
public string? PaymentProvider { get; set; }
2424

25+
// Admin
26+
public bool IsSuperAdmin { get; set; }
27+
2528
// LRM Translation Usage & Limits (counts against plan)
2629
public int TranslationCharsUsed { get; set; }
2730
public int TranslationCharsLimit { get; set; }

0 commit comments

Comments
 (0)