✨ Casbin permission check
This commit is contained in:
parent
0bf265926a
commit
5cef6d72e4
@ -9,6 +9,8 @@ public class Account : BaseModel
|
|||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
[MaxLength(256)] public string Name { get; set; } = string.Empty;
|
[MaxLength(256)] public string Name { get; set; } = string.Empty;
|
||||||
[MaxLength(256)] public string Nick { get; set; } = string.Empty;
|
[MaxLength(256)] public string Nick { get; set; } = string.Empty;
|
||||||
|
[MaxLength(32)] public string Language { get; set; } = string.Empty;
|
||||||
|
public bool IsSuperuser { get; set; } = false;
|
||||||
|
|
||||||
public ICollection<AccountContact> Contacts { get; set; } = new List<AccountContact>();
|
public ICollection<AccountContact> Contacts { get; set; } = new List<AccountContact>();
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ public class AuthController(AppDatabase db, AccountService accounts, AuthService
|
|||||||
{
|
{
|
||||||
[Required] [MaxLength(256)] public string Account { get; set; } = string.Empty;
|
[Required] [MaxLength(256)] public string Account { get; set; } = string.Empty;
|
||||||
[MaxLength(512)] public string? DeviceId { get; set; }
|
[MaxLength(512)] public string? DeviceId { get; set; }
|
||||||
public List<string> Claims { get; set; } = new();
|
|
||||||
public List<string> Audiences { get; set; } = new();
|
public List<string> Audiences { get; set; } = new();
|
||||||
|
public List<string> Scopes { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("challenge")]
|
[HttpPost("challenge")]
|
||||||
@ -34,8 +34,8 @@ public class AuthController(AppDatabase db, AccountService accounts, AuthService
|
|||||||
Account = account,
|
Account = account,
|
||||||
ExpiredAt = Instant.FromDateTimeUtc(DateTime.UtcNow.AddHours(1)),
|
ExpiredAt = Instant.FromDateTimeUtc(DateTime.UtcNow.AddHours(1)),
|
||||||
StepTotal = 1,
|
StepTotal = 1,
|
||||||
Claims = request.Claims,
|
|
||||||
Audiences = request.Audiences,
|
Audiences = request.Audiences,
|
||||||
|
Scopes = request.Scopes,
|
||||||
IpAddress = ipAddress,
|
IpAddress = ipAddress,
|
||||||
UserAgent = userAgent,
|
UserAgent = userAgent,
|
||||||
DeviceId = request.DeviceId,
|
DeviceId = request.DeviceId,
|
||||||
@ -46,6 +46,18 @@ public class AuthController(AppDatabase db, AccountService accounts, AuthService
|
|||||||
return challenge;
|
return challenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("challenge/{id}/factors")]
|
||||||
|
public async Task<ActionResult<List<AccountAuthFactor>>> GetChallengeFactors([FromRoute] Guid id)
|
||||||
|
{
|
||||||
|
var challenge = await db.AuthChallenges
|
||||||
|
.Include(e => e.Account)
|
||||||
|
.Include(e => e.Account.AuthFactors)
|
||||||
|
.Where(e => e.Id == id).FirstOrDefaultAsync();
|
||||||
|
return challenge is null
|
||||||
|
? new NotFoundObjectResult("Auth challenge was not found.")
|
||||||
|
: challenge.Account.AuthFactors.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public class PerformChallengeRequest
|
public class PerformChallengeRequest
|
||||||
{
|
{
|
||||||
[Required] public long FactorId { get; set; }
|
[Required] public long FactorId { get; set; }
|
||||||
@ -59,10 +71,10 @@ public class AuthController(AppDatabase db, AccountService accounts, AuthService
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
var challenge = await db.AuthChallenges.FindAsync(id);
|
var challenge = await db.AuthChallenges.FindAsync(id);
|
||||||
if (challenge is null) return new NotFoundResult();
|
if (challenge is null) return new NotFoundObjectResult("Auth challenge was not found.");
|
||||||
|
|
||||||
var factor = await db.AccountAuthFactors.FindAsync(request.FactorId);
|
var factor = await db.AccountAuthFactors.FindAsync(request.FactorId);
|
||||||
if (factor is null) return new NotFoundResult();
|
if (factor is null) return new NotFoundObjectResult("Auth factor was not found.");
|
||||||
|
|
||||||
if (challenge.StepRemain == 0) return challenge;
|
if (challenge.StepRemain == 0) return challenge;
|
||||||
if (challenge.ExpiredAt.HasValue && challenge.ExpiredAt.Value < Instant.FromDateTimeUtc(DateTime.UtcNow))
|
if (challenge.ExpiredAt.HasValue && challenge.ExpiredAt.Value < Instant.FromDateTimeUtc(DateTime.UtcNow))
|
||||||
@ -84,67 +96,72 @@ public class AuthController(AppDatabase db, AccountService accounts, AuthService
|
|||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
return challenge;
|
return challenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("challenge/{id}/grant")]
|
|
||||||
public async Task<ActionResult<SignedTokenPair>> GrantChallengeToken([FromRoute] Guid id)
|
|
||||||
{
|
|
||||||
var challenge = await db.AuthChallenges
|
|
||||||
.Include(e => e.Account)
|
|
||||||
.Where(e => e.Id == id)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
if (challenge is null) return new NotFoundResult();
|
|
||||||
if (challenge.StepRemain != 0) return new BadRequestResult();
|
|
||||||
|
|
||||||
var session = await db.AuthSessions
|
|
||||||
.Where(e => e.Challenge == challenge)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
if (session is not null) return new BadRequestResult();
|
|
||||||
|
|
||||||
session = new Session
|
|
||||||
{
|
|
||||||
LastGrantedAt = Instant.FromDateTimeUtc(DateTime.UtcNow),
|
|
||||||
ExpiredAt = Instant.FromDateTimeUtc(DateTime.UtcNow.AddDays(30)),
|
|
||||||
Account = challenge.Account,
|
|
||||||
Challenge = challenge,
|
|
||||||
};
|
|
||||||
|
|
||||||
db.AuthSessions.Add(session);
|
|
||||||
await db.SaveChangesAsync();
|
|
||||||
|
|
||||||
return auth.CreateToken(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TokenExchangeRequest
|
public class TokenExchangeRequest
|
||||||
{
|
{
|
||||||
public string GrantType { get; set; } = string.Empty;
|
public string GrantType { get; set; } = string.Empty;
|
||||||
public string RefreshToken { get; set; } = string.Empty;
|
public string? RefreshToken { get; set; }
|
||||||
|
public string? Code { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("token")]
|
[HttpPost("token")]
|
||||||
public async Task<ActionResult<SignedTokenPair>> ExchangeToken([FromBody] TokenExchangeRequest request)
|
public async Task<ActionResult<SignedTokenPair>> ExchangeToken([FromBody] TokenExchangeRequest request)
|
||||||
{
|
{
|
||||||
|
Session? session;
|
||||||
switch (request.GrantType)
|
switch (request.GrantType)
|
||||||
{
|
{
|
||||||
|
case "authorization_code":
|
||||||
|
var code = Guid.TryParse(request.Code, out var codeId) ? codeId : Guid.Empty;
|
||||||
|
if (code == Guid.Empty)
|
||||||
|
return new BadRequestObjectResult("Invalid or missing authorization code.");
|
||||||
|
var challenge = await db.AuthChallenges
|
||||||
|
.Include(e => e.Account)
|
||||||
|
.Where(e => e.Id == code)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (challenge is null)
|
||||||
|
return new NotFoundObjectResult("Authorization code not found or expired.");
|
||||||
|
if (challenge.StepRemain != 0)
|
||||||
|
return new BadRequestObjectResult("Challenge not yet completed.");
|
||||||
|
|
||||||
|
session = await db.AuthSessions
|
||||||
|
.Where(e => e.Challenge == challenge)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
if (session is not null)
|
||||||
|
return new BadRequestObjectResult("Session already exists for this challenge.");
|
||||||
|
|
||||||
|
session = new Session
|
||||||
|
{
|
||||||
|
LastGrantedAt = Instant.FromDateTimeUtc(DateTime.UtcNow),
|
||||||
|
ExpiredAt = Instant.FromDateTimeUtc(DateTime.UtcNow.AddDays(30)),
|
||||||
|
Account = challenge.Account,
|
||||||
|
Challenge = challenge,
|
||||||
|
};
|
||||||
|
|
||||||
|
db.AuthSessions.Add(session);
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
|
return auth.CreateToken(session);
|
||||||
case "refresh_token":
|
case "refresh_token":
|
||||||
var handler = new JwtSecurityTokenHandler();
|
var handler = new JwtSecurityTokenHandler();
|
||||||
var token = handler.ReadJwtToken(request.RefreshToken);
|
var token = handler.ReadJwtToken(request.RefreshToken);
|
||||||
var sessionIdClaim = token.Claims.FirstOrDefault(c => c.Type == "session_id")?.Value;
|
var sessionIdClaim = token.Claims.FirstOrDefault(c => c.Type == "session_id")?.Value;
|
||||||
|
|
||||||
if (!Guid.TryParse(sessionIdClaim, out var sessionId))
|
if (!Guid.TryParse(sessionIdClaim, out var sessionId))
|
||||||
return new UnauthorizedResult();
|
return new UnauthorizedObjectResult("Invalid or missing session_id claim in refresh token.");
|
||||||
|
|
||||||
|
session = await db.AuthSessions.FirstOrDefaultAsync(s => s.Id == sessionId);
|
||||||
|
if (session is null)
|
||||||
|
return new NotFoundObjectResult("Session not found or expired.");
|
||||||
|
|
||||||
var session = await db.AuthSessions.FirstOrDefaultAsync(s => s.Id == sessionId);
|
|
||||||
if (session is null) return new NotFoundResult();
|
|
||||||
|
|
||||||
session.LastGrantedAt = Instant.FromDateTimeUtc(DateTime.UtcNow);
|
session.LastGrantedAt = Instant.FromDateTimeUtc(DateTime.UtcNow);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
return auth.CreateToken(session);
|
return auth.CreateToken(session);
|
||||||
default:
|
default:
|
||||||
return new BadRequestResult();
|
return new BadRequestObjectResult("Unsupported grant type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[HttpGet("test")]
|
[HttpGet("test")]
|
||||||
public async Task<ActionResult> Test()
|
public async Task<ActionResult> Test()
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using Casbin;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
|
||||||
@ -13,8 +15,68 @@ public class SignedTokenPair
|
|||||||
public Instant ExpiredAt { get; set; }
|
public Instant ExpiredAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AuthService(AppDatabase db, IConfiguration config)
|
public class AuthService(AppDatabase db, IConfiguration config, IEnforcer enforcer)
|
||||||
{
|
{
|
||||||
|
public async Task<bool> AssignRoleToUserAsync(string user, string role, string domain = "global")
|
||||||
|
{
|
||||||
|
var added = await enforcer.AddGroupingPolicyAsync(user, role, domain);
|
||||||
|
if (added) await enforcer.SavePolicyAsync();
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> CreateRoleAsync(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> 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)
|
public SignedTokenPair CreateToken(Session session)
|
||||||
{
|
{
|
||||||
var privateKeyPem = File.ReadAllText(config["Jwt:PrivateKeyPath"]!);
|
var privateKeyPem = File.ReadAllText(config["Jwt:PrivateKeyPath"]!);
|
||||||
@ -23,29 +85,29 @@ public class AuthService(AppDatabase db, IConfiguration config)
|
|||||||
var key = new RsaSecurityKey(rsa);
|
var key = new RsaSecurityKey(rsa);
|
||||||
|
|
||||||
var creds = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);
|
var creds = new SigningCredentials(key, SecurityAlgorithms.RsaSha256);
|
||||||
|
var claims = new List<Claim>
|
||||||
|
{
|
||||||
|
new("user_id", session.Account.Id.ToString()),
|
||||||
|
new("session_id", session.Id.ToString())
|
||||||
|
};
|
||||||
|
|
||||||
var accessTokenClaims = new JwtSecurityToken(
|
|
||||||
issuer: "solar-network",
|
|
||||||
audience: string.Join(',', session.Challenge.Audiences),
|
|
||||||
claims: new List<Claim>
|
|
||||||
{
|
|
||||||
new("user_id", session.Account.Id.ToString()),
|
|
||||||
new("session_id", session.Id.ToString())
|
|
||||||
},
|
|
||||||
expires: DateTime.Now.AddMinutes(30),
|
|
||||||
signingCredentials: creds
|
|
||||||
);
|
|
||||||
var refreshTokenClaims = new JwtSecurityToken(
|
var refreshTokenClaims = new JwtSecurityToken(
|
||||||
issuer: "solar-network",
|
issuer: "solar-network",
|
||||||
audience: string.Join(',', session.Challenge.Audiences),
|
audience: string.Join(',', session.Challenge.Audiences),
|
||||||
claims: new List<Claim>
|
claims: claims,
|
||||||
{
|
|
||||||
new("user_id", session.Account.Id.ToString()),
|
|
||||||
new("session_id", session.Id.ToString())
|
|
||||||
},
|
|
||||||
expires: DateTime.Now.AddDays(30),
|
expires: DateTime.Now.AddDays(30),
|
||||||
signingCredentials: creds
|
signingCredentials: creds
|
||||||
);
|
);
|
||||||
|
|
||||||
|
session.Challenge.Scopes.ForEach(c => claims.Add(new Claim("scope", c)));
|
||||||
|
if(session.Account.IsSuperuser) claims.Add(new Claim("is_superuser", "1"));
|
||||||
|
var accessTokenClaims = new JwtSecurityToken(
|
||||||
|
issuer: "solar-network",
|
||||||
|
audience: string.Join(',', session.Challenge.Audiences),
|
||||||
|
claims: claims,
|
||||||
|
expires: DateTime.Now.AddMinutes(30),
|
||||||
|
signingCredentials: creds
|
||||||
|
);
|
||||||
|
|
||||||
var handler = new JwtSecurityTokenHandler();
|
var handler = new JwtSecurityTokenHandler();
|
||||||
var accessToken = handler.WriteToken(accessTokenClaims);
|
var accessToken = handler.WriteToken(accessTokenClaims);
|
||||||
|
34
DysonNetwork.Sphere/Auth/CasbinRequirement.cs
Normal file
34
DysonNetwork.Sphere/Auth/CasbinRequirement.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using Casbin;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Sphere.Auth;
|
||||||
|
|
||||||
|
public class CasbinRequirement(string domain, string obj, string act) : IAuthorizationRequirement
|
||||||
|
{
|
||||||
|
public string Domain { get; } = domain;
|
||||||
|
public string Object { get; } = obj;
|
||||||
|
public string Action { get; } = act;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CasbinAuthorizationHandler(IEnforcer enforcer)
|
||||||
|
: AuthorizationHandler<CasbinRequirement>
|
||||||
|
{
|
||||||
|
protected override async Task HandleRequirementAsync(
|
||||||
|
AuthorizationHandlerContext context,
|
||||||
|
CasbinRequirement requirement)
|
||||||
|
{
|
||||||
|
var userId = context.User.FindFirst("user_id")?.Value;
|
||||||
|
if (userId == null) return;
|
||||||
|
var isSuperuser = context.User.FindFirst("is_superuser")?.Value == "1";
|
||||||
|
if (isSuperuser) userId = "super:" + userId;
|
||||||
|
|
||||||
|
var allowed = await enforcer.EnforceAsync(
|
||||||
|
userId,
|
||||||
|
requirement.Domain,
|
||||||
|
requirement.Object,
|
||||||
|
requirement.Action
|
||||||
|
);
|
||||||
|
|
||||||
|
if (allowed) context.Succeed(requirement);
|
||||||
|
}
|
||||||
|
}
|
@ -22,8 +22,8 @@ public class Challenge : BaseModel
|
|||||||
public int StepRemain { get; set; }
|
public int StepRemain { get; set; }
|
||||||
public int StepTotal { get; set; }
|
public int StepTotal { get; set; }
|
||||||
[Column(TypeName = "jsonb")] public List<long> BlacklistFactors { get; set; } = new();
|
[Column(TypeName = "jsonb")] public List<long> BlacklistFactors { get; set; } = new();
|
||||||
[Column(TypeName = "jsonb")] public List<string> Claims { get; set; } = new();
|
|
||||||
[Column(TypeName = "jsonb")] public List<string> Audiences { get; set; } = new();
|
[Column(TypeName = "jsonb")] public List<string> Audiences { get; set; } = new();
|
||||||
|
[Column(TypeName = "jsonb")] public List<string> Scopes { get; set; } = new();
|
||||||
[MaxLength(128)] public string? IpAddress { get; set; }
|
[MaxLength(128)] public string? IpAddress { get; set; }
|
||||||
[MaxLength(512)] public string? UserAgent { get; set; }
|
[MaxLength(512)] public string? UserAgent { get; set; }
|
||||||
[MaxLength(256)] public string? DeviceId { get; set; }
|
[MaxLength(256)] public string? DeviceId { get; set; }
|
||||||
|
14
DysonNetwork.Sphere/Casbin.conf
Normal file
14
DysonNetwork.Sphere/Casbin.conf
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[request_definition]
|
||||||
|
r = sub, dom, obj, act
|
||||||
|
|
||||||
|
[policy_definition]
|
||||||
|
p = sub, dom, obj, act
|
||||||
|
|
||||||
|
[role_definition]
|
||||||
|
g = _, _, _
|
||||||
|
|
||||||
|
[policy_effect]
|
||||||
|
e = some(where (p.eft == allow))
|
||||||
|
|
||||||
|
[matchers]
|
||||||
|
m = r.sub.StartsWith("super:") || (g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act)
|
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
|
<PackageReference Include="Casbin.NET" Version="2.12.0" />
|
||||||
|
<PackageReference Include="Casbin.NET.Adapter.EFCore" Version="2.5.0" />
|
||||||
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
|
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2" />
|
||||||
|
@ -14,7 +14,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|||||||
namespace DysonNetwork.Sphere.Migrations
|
namespace DysonNetwork.Sphere.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(AppDatabase))]
|
[DbContext(typeof(AppDatabase))]
|
||||||
[Migration("20250409150800_AddAuthSession")]
|
[Migration("20250410150812_AddAuthSession")]
|
||||||
partial class AddAuthSession
|
partial class AddAuthSession
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -177,11 +177,6 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("blacklist_factors");
|
.HasColumnName("blacklist_factors");
|
||||||
|
|
||||||
b.Property<List<string>>("Claims")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasColumnName("claims");
|
|
||||||
|
|
||||||
b.Property<Instant>("CreatedAt")
|
b.Property<Instant>("CreatedAt")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasColumnName("created_at");
|
.HasColumnName("created_at");
|
||||||
@ -209,6 +204,11 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnType("character varying(1024)")
|
.HasColumnType("character varying(1024)")
|
||||||
.HasColumnName("nonce");
|
.HasColumnName("nonce");
|
||||||
|
|
||||||
|
b.Property<List<string>>("Scopes")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("scopes");
|
||||||
|
|
||||||
b.Property<int>("StepRemain")
|
b.Property<int>("StepRemain")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
.HasColumnName("step_remain");
|
.HasColumnName("step_remain");
|
@ -22,8 +22,8 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
step_remain = table.Column<int>(type: "integer", nullable: false),
|
step_remain = table.Column<int>(type: "integer", nullable: false),
|
||||||
step_total = table.Column<int>(type: "integer", nullable: false),
|
step_total = table.Column<int>(type: "integer", nullable: false),
|
||||||
blacklist_factors = table.Column<List<long>>(type: "jsonb", nullable: false),
|
blacklist_factors = table.Column<List<long>>(type: "jsonb", nullable: false),
|
||||||
claims = table.Column<List<string>>(type: "jsonb", nullable: false),
|
|
||||||
audiences = table.Column<List<string>>(type: "jsonb", nullable: false),
|
audiences = table.Column<List<string>>(type: "jsonb", nullable: false),
|
||||||
|
scopes = table.Column<List<string>>(type: "jsonb", nullable: false),
|
||||||
ip_address = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
ip_address = table.Column<string>(type: "character varying(128)", maxLength: 128, nullable: true),
|
||||||
user_agent = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
|
user_agent = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: true),
|
||||||
device_id = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
device_id = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
|
365
DysonNetwork.Sphere/Migrations/20250410161354_AddSuperUser.Designer.cs
generated
Normal file
365
DysonNetwork.Sphere/Migrations/20250410161354_AddSuperUser.Designer.cs
generated
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using DysonNetwork.Sphere;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using NodaTime;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace DysonNetwork.Sphere.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDatabase))]
|
||||||
|
[Migration("20250410161354_AddSuperUser")]
|
||||||
|
partial class AddSuperUser
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.3")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Account.Account", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<Instant>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("created_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("DeletedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("deleted_at");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSuperuser")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_superuser");
|
||||||
|
|
||||||
|
b.Property<string>("Language")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(32)
|
||||||
|
.HasColumnType("character varying(32)")
|
||||||
|
.HasColumnName("language");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("Nick")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)")
|
||||||
|
.HasColumnName("nick");
|
||||||
|
|
||||||
|
b.Property<Instant>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("updated_at");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_accounts");
|
||||||
|
|
||||||
|
b.ToTable("accounts", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Account.AccountAuthFactor", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<long>("AccountId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("account_id");
|
||||||
|
|
||||||
|
b.Property<Instant>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("created_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("DeletedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("deleted_at");
|
||||||
|
|
||||||
|
b.Property<string>("Secret")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("secret");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("type");
|
||||||
|
|
||||||
|
b.Property<Instant>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("updated_at");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_account_auth_factors");
|
||||||
|
|
||||||
|
b.HasIndex("AccountId")
|
||||||
|
.HasDatabaseName("ix_account_auth_factors_account_id");
|
||||||
|
|
||||||
|
b.ToTable("account_auth_factors", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Account.AccountContact", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<long>("AccountId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("account_id");
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(1024)
|
||||||
|
.HasColumnType("character varying(1024)")
|
||||||
|
.HasColumnName("content");
|
||||||
|
|
||||||
|
b.Property<Instant>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("created_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("DeletedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("deleted_at");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("type");
|
||||||
|
|
||||||
|
b.Property<Instant>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("updated_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("VerifiedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("verified_at");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_account_contacts");
|
||||||
|
|
||||||
|
b.HasIndex("AccountId")
|
||||||
|
.HasDatabaseName("ix_account_contacts_account_id");
|
||||||
|
|
||||||
|
b.ToTable("account_contacts", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Auth.Challenge", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
b.Property<long>("AccountId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("account_id");
|
||||||
|
|
||||||
|
b.Property<List<string>>("Audiences")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("audiences");
|
||||||
|
|
||||||
|
b.Property<List<long>>("BlacklistFactors")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("blacklist_factors");
|
||||||
|
|
||||||
|
b.Property<Instant>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("created_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("DeletedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("deleted_at");
|
||||||
|
|
||||||
|
b.Property<string>("DeviceId")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("character varying(256)")
|
||||||
|
.HasColumnName("device_id");
|
||||||
|
|
||||||
|
b.Property<Instant?>("ExpiredAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expired_at");
|
||||||
|
|
||||||
|
b.Property<string>("IpAddress")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("character varying(128)")
|
||||||
|
.HasColumnName("ip_address");
|
||||||
|
|
||||||
|
b.Property<string>("Nonce")
|
||||||
|
.HasMaxLength(1024)
|
||||||
|
.HasColumnType("character varying(1024)")
|
||||||
|
.HasColumnName("nonce");
|
||||||
|
|
||||||
|
b.Property<List<string>>("Scopes")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("scopes");
|
||||||
|
|
||||||
|
b.Property<int>("StepRemain")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("step_remain");
|
||||||
|
|
||||||
|
b.Property<int>("StepTotal")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("step_total");
|
||||||
|
|
||||||
|
b.Property<Instant>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("updated_at");
|
||||||
|
|
||||||
|
b.Property<string>("UserAgent")
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)")
|
||||||
|
.HasColumnName("user_agent");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_auth_challenges");
|
||||||
|
|
||||||
|
b.HasIndex("AccountId")
|
||||||
|
.HasDatabaseName("ix_auth_challenges_account_id");
|
||||||
|
|
||||||
|
b.ToTable("auth_challenges", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Auth.Session", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
b.Property<long>("AccountId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("account_id");
|
||||||
|
|
||||||
|
b.Property<Guid>("ChallengeId")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasColumnName("challenge_id");
|
||||||
|
|
||||||
|
b.Property<Instant>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("created_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("DeletedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("deleted_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("ExpiredAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("expired_at");
|
||||||
|
|
||||||
|
b.Property<Instant?>("LastGrantedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_granted_at");
|
||||||
|
|
||||||
|
b.Property<Instant>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("updated_at");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_auth_sessions");
|
||||||
|
|
||||||
|
b.HasIndex("AccountId")
|
||||||
|
.HasDatabaseName("ix_auth_sessions_account_id");
|
||||||
|
|
||||||
|
b.HasIndex("ChallengeId")
|
||||||
|
.HasDatabaseName("ix_auth_sessions_challenge_id");
|
||||||
|
|
||||||
|
b.ToTable("auth_sessions", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Account.AccountAuthFactor", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
|
||||||
|
.WithMany("AuthFactors")
|
||||||
|
.HasForeignKey("AccountId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_account_auth_factors_accounts_account_id");
|
||||||
|
|
||||||
|
b.Navigation("Account");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Account.AccountContact", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
|
||||||
|
.WithMany("Contacts")
|
||||||
|
.HasForeignKey("AccountId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_account_contacts_accounts_account_id");
|
||||||
|
|
||||||
|
b.Navigation("Account");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Auth.Challenge", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
|
||||||
|
.WithMany("Challenges")
|
||||||
|
.HasForeignKey("AccountId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_auth_challenges_accounts_account_id");
|
||||||
|
|
||||||
|
b.Navigation("Account");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Auth.Session", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("DysonNetwork.Sphere.Account.Account", "Account")
|
||||||
|
.WithMany("Sessions")
|
||||||
|
.HasForeignKey("AccountId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_auth_sessions_accounts_account_id");
|
||||||
|
|
||||||
|
b.HasOne("DysonNetwork.Sphere.Auth.Challenge", "Challenge")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ChallengeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_auth_sessions_auth_challenges_challenge_id");
|
||||||
|
|
||||||
|
b.Navigation("Account");
|
||||||
|
|
||||||
|
b.Navigation("Challenge");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DysonNetwork.Sphere.Account.Account", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("AuthFactors");
|
||||||
|
|
||||||
|
b.Navigation("Challenges");
|
||||||
|
|
||||||
|
b.Navigation("Contacts");
|
||||||
|
|
||||||
|
b.Navigation("Sessions");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace DysonNetwork.Sphere.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddSuperUser : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "is_superuser",
|
||||||
|
table: "accounts",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "language",
|
||||||
|
table: "accounts",
|
||||||
|
type: "character varying(32)",
|
||||||
|
maxLength: 32,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "is_superuser",
|
||||||
|
table: "accounts");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "language",
|
||||||
|
table: "accounts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,16 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasColumnName("deleted_at");
|
.HasColumnName("deleted_at");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSuperuser")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("is_superuser");
|
||||||
|
|
||||||
|
b.Property<string>("Language")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(32)
|
||||||
|
.HasColumnType("character varying(32)")
|
||||||
|
.HasColumnName("language");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
@ -174,11 +184,6 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnType("jsonb")
|
.HasColumnType("jsonb")
|
||||||
.HasColumnName("blacklist_factors");
|
.HasColumnName("blacklist_factors");
|
||||||
|
|
||||||
b.Property<List<string>>("Claims")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasColumnName("claims");
|
|
||||||
|
|
||||||
b.Property<Instant>("CreatedAt")
|
b.Property<Instant>("CreatedAt")
|
||||||
.HasColumnType("timestamp with time zone")
|
.HasColumnType("timestamp with time zone")
|
||||||
.HasColumnName("created_at");
|
.HasColumnName("created_at");
|
||||||
@ -206,6 +211,11 @@ namespace DysonNetwork.Sphere.Migrations
|
|||||||
.HasColumnType("character varying(1024)")
|
.HasColumnType("character varying(1024)")
|
||||||
.HasColumnName("nonce");
|
.HasColumnName("nonce");
|
||||||
|
|
||||||
|
b.Property<List<string>>("Scopes")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("jsonb")
|
||||||
|
.HasColumnName("scopes");
|
||||||
|
|
||||||
b.Property<int>("StepRemain")
|
b.Property<int>("StepRemain")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
.HasColumnName("step_remain");
|
.HasColumnName("step_remain");
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using Casbin;
|
||||||
|
using Casbin.Persist.Adapter.EFCore;
|
||||||
using DysonNetwork.Sphere;
|
using DysonNetwork.Sphere;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Sphere.Account;
|
||||||
using DysonNetwork.Sphere.Auth;
|
using DysonNetwork.Sphere.Auth;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
@ -25,6 +28,23 @@ builder.Services.AddControllers().AddJsonOptions(options =>
|
|||||||
});
|
});
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
|
||||||
|
// Casbin permissions
|
||||||
|
|
||||||
|
var casbinDbContext = new CasbinDbContext<int>(
|
||||||
|
new DbContextOptionsBuilder<CasbinDbContext<int>>()
|
||||||
|
.UseNpgsql(builder.Configuration.GetConnectionString("Guard"))
|
||||||
|
.Options
|
||||||
|
);
|
||||||
|
var casbinEfcore = new EFCoreAdapter<int>(casbinDbContext);
|
||||||
|
casbinDbContext.Database.EnsureCreated();
|
||||||
|
var casbinEncofcer = new Enforcer("Casbin.conf", casbinEfcore);
|
||||||
|
casbinEncofcer.LoadPolicy();
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IEnforcer>(casbinEncofcer);
|
||||||
|
builder.Services.AddSingleton<IAuthorizationHandler, CasbinAuthorizationHandler>();
|
||||||
|
|
||||||
|
// Other pipelines
|
||||||
|
|
||||||
builder.Services.AddAuthorization();
|
builder.Services.AddAuthorization();
|
||||||
builder.Services.AddAuthentication("Bearer").AddJwtBearer(options =>
|
builder.Services.AddAuthentication("Bearer").AddJwtBearer(options =>
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"App": "Host=localhost;Port=5432;Database=dyson_network;Username=postgres;Password=postgres"
|
"App": "Host=localhost;Port=5432;Database=dyson_network;Username=postgres;Password=postgres",
|
||||||
|
"Guard": "Host=localhost;Port=5432;Database=dyson_network_casbin;Username=postgres;Password=postgres"
|
||||||
},
|
},
|
||||||
"Authentication": {
|
"Authentication": {
|
||||||
"Schemes": {
|
"Schemes": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user