✨ Magic spell for one time code
🗑️ Drop the usage of casbin ♻️ Refactor the permission service ♻️ Refactor the flow of creating an account 🧱 Email infra structure
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| using System.IdentityModel.Tokens.Jwt; | ||||
| using System.Security.Claims; | ||||
| using System.Security.Cryptography; | ||||
| using System.Text.Json; | ||||
| using Casbin; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| @@ -15,68 +16,43 @@ public class SignedTokenPair | ||||
|     public Instant ExpiredAt { get; set; } | ||||
| } | ||||
|  | ||||
| public class AuthService(AppDatabase db, IConfiguration config, IEnforcer enforcer) | ||||
| public class AuthService(IConfiguration config, IHttpClientFactory httpClientFactory) | ||||
| { | ||||
|     public async Task<bool> AssignRoleToUserAsync(string user, string role, string domain = "global") | ||||
|     public async Task<bool> ValidateCaptcha(string token) | ||||
|     { | ||||
|         var added = await enforcer.AddGroupingPolicyAsync(user, role, domain); | ||||
|         if (added) await enforcer.SavePolicyAsync(); | ||||
|         return added; | ||||
|     } | ||||
|         var provider = config.GetSection("Captcha")["Provider"]?.ToLower(); | ||||
|         var apiSecret = config.GetSection("Captcha")["ApiSecret"]; | ||||
|  | ||||
|     public async Task<bool> AddPermissionToUserAsync(string user, string domain, string obj, string act) | ||||
|     { | ||||
|         var added = await enforcer.AddPolicyAsync(user, domain, obj, act); | ||||
|         if (added) await enforcer.SavePolicyAsync(); | ||||
|         return added; | ||||
|     } | ||||
|      | ||||
|     public async Task<bool> RemovePermissionFromUserAsync(string user, string domain, string obj, string act) | ||||
|     { | ||||
|         var removed = await enforcer.RemovePolicyAsync(user, domain, obj, act); | ||||
|         if (removed) await enforcer.SavePolicyAsync(); | ||||
|         return removed; | ||||
|     } | ||||
|         var client = httpClientFactory.CreateClient(); | ||||
|  | ||||
|     public async Task<bool> CreateRoleAsync(string role, string domain, IEnumerable<(string obj, string act)> permissions) | ||||
|     { | ||||
|         bool anyAdded = false; | ||||
|         foreach (var (obj, act) in permissions) | ||||
|         switch (provider) | ||||
|         { | ||||
|             var added = await enforcer.AddPolicyAsync(role, domain, obj, act); | ||||
|             if (added) anyAdded = true; | ||||
|         } | ||||
|             case "cloudflare": | ||||
|                 var content = new StringContent($"secret={apiSecret}&response={token}", System.Text.Encoding.UTF8, | ||||
|                     "application/x-www-form-urlencoded"); | ||||
|                 var response = await client.PostAsync("https://challenges.cloudflare.com/turnstile/v0/siteverify", | ||||
|                     content); | ||||
|                 response.EnsureSuccessStatusCode(); | ||||
|  | ||||
|         if (anyAdded) await enforcer.SavePolicyAsync(); | ||||
|         return anyAdded; | ||||
|                 var json = await response.Content.ReadAsStringAsync(); | ||||
|                 var cfResult = JsonSerializer.Deserialize<CloudflareVerificationResponse>(json); | ||||
|  | ||||
|                 return cfResult?.Success == true; | ||||
|             case "google": | ||||
|                 content = new StringContent($"secret={apiSecret}&response={token}", System.Text.Encoding.UTF8, | ||||
|                     "application/x-www-form-urlencoded"); | ||||
|                 response = await client.PostAsync("https://www.google.com/recaptcha/api/siteverify", content); | ||||
|                 response.EnsureSuccessStatusCode(); | ||||
|  | ||||
|                 json = await response.Content.ReadAsStringAsync(); | ||||
|                 var capResult = JsonSerializer.Deserialize<GoogleVerificationResponse>(json); | ||||
|  | ||||
|                 return capResult?.Success == true; | ||||
|             default: | ||||
|                 throw new ArgumentException("The server misconfigured for the captcha."); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public async Task<bool> AddPermissionsToRoleAsync(string role, string domain, IEnumerable<(string obj, string act)> permissions) | ||||
|     { | ||||
|         bool anyAdded = false; | ||||
|         foreach (var (obj, act) in permissions) | ||||
|         { | ||||
|             var added = await enforcer.AddPolicyAsync(role, domain, obj, act); | ||||
|             if (added) anyAdded = true; | ||||
|         } | ||||
|  | ||||
|         if (anyAdded) await enforcer.SavePolicyAsync(); | ||||
|         return anyAdded; | ||||
|     } | ||||
|  | ||||
|     public async Task<bool> RemovePermissionsFromRoleAsync(string role, string domain, IEnumerable<(string obj, string act)> permissions) | ||||
|     { | ||||
|         bool anyRemoved = false; | ||||
|         foreach (var (obj, act) in permissions) | ||||
|         { | ||||
|             var removed = await enforcer.RemovePolicyAsync(role, domain, obj, act); | ||||
|             if (removed) anyRemoved = true; | ||||
|         } | ||||
|  | ||||
|         if (anyRemoved) await enforcer.SavePolicyAsync(); | ||||
|         return anyRemoved; | ||||
|     } | ||||
|      | ||||
|     public SignedTokenPair CreateToken(Session session) | ||||
|     { | ||||
|         var privateKeyPem = File.ReadAllText(config["Jwt:PrivateKeyPath"]!); | ||||
| @@ -98,9 +74,9 @@ public class AuthService(AppDatabase db, IConfiguration config, IEnforcer enforc | ||||
|             expires: DateTime.Now.AddDays(30), | ||||
|             signingCredentials: creds | ||||
|         ); | ||||
|          | ||||
|  | ||||
|         session.Challenge.Scopes.ForEach(c => claims.Add(new Claim("scope", c))); | ||||
|         if(session.Account.IsSuperuser) claims.Add(new Claim("is_superuser", "1")); | ||||
|         if (session.Account.IsSuperuser) claims.Add(new Claim("is_superuser", "1")); | ||||
|         var accessTokenClaims = new JwtSecurityToken( | ||||
|             issuer: "solar-network", | ||||
|             audience: string.Join(',', session.Challenge.Audiences), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user