Feature/distribution #50
@@ -8,6 +8,8 @@ namespace HopFrame.Database;
|
||||
/// </summary>
|
||||
public abstract class HopDbContextBase : DbContext {
|
||||
|
||||
public static IList<Action<HopDbContextBase>> SaveHandlers = new List<Action<HopDbContextBase>>();
|
||||
|
||||
public virtual DbSet<User> Users { get; set; }
|
||||
public virtual DbSet<Permission> Permissions { get; set; }
|
||||
public virtual DbSet<Token> Tokens { get; set; }
|
||||
@@ -36,4 +38,36 @@ public abstract class HopDbContextBase : DbContext {
|
||||
.WithOne(t => t.Token)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
|
||||
private void OnSaving() {
|
||||
var orphanedPermissions = Permissions
|
||||
.Where(p => p.UserId == null && p.GroupName == null && p.TokenId == null)
|
||||
.ToList();
|
||||
|
||||
foreach (var handler in SaveHandlers) {
|
||||
handler.Invoke(this);
|
||||
}
|
||||
|
||||
Permissions.RemoveRange(orphanedPermissions);
|
||||
}
|
||||
|
||||
public override int SaveChanges() {
|
||||
OnSaving();
|
||||
return base.SaveChanges();
|
||||
}
|
||||
|
||||
public override int SaveChanges(bool acceptAllChangesOnSuccess) {
|
||||
OnSaving();
|
||||
return base.SaveChanges(acceptAllChangesOnSuccess);
|
||||
}
|
||||
|
||||
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) {
|
||||
OnSaving();
|
||||
return base.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken()) {
|
||||
OnSaving();
|
||||
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,18 @@ public class Permission {
|
||||
[ForeignKey("UserId"), JsonIgnore]
|
||||
public virtual User User { get; set; }
|
||||
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
[ForeignKey("GroupName"), JsonIgnore]
|
||||
public virtual PermissionGroup Group { get; set; }
|
||||
|
||||
[MaxLength(255)]
|
||||
public string GroupName { get; set; }
|
||||
|
||||
[ForeignKey("TokenId"), JsonIgnore]
|
||||
public virtual Token Token { get; set; }
|
||||
|
||||
public Guid? TokenId { get; set; }
|
||||
}
|
||||
|
||||
public interface IPermissionOwner;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using HopFrame.Database;
|
||||
using HopFrame.Database.Models;
|
||||
using HopFrame.Security.Authentication.OpenID;
|
||||
using HopFrame.Security.Authentication.OpenID.Implementation;
|
||||
using HopFrame.Security.Authentication.OpenID.Options;
|
||||
@@ -17,32 +19,48 @@ public static class HopFrameAuthenticationExtensions {
|
||||
/// <summary>
|
||||
/// Configures the WebApplication to use the authentication and authorization of the HopFrame API
|
||||
/// </summary>
|
||||
/// <param name="service">The service provider to add the services to</param>
|
||||
/// <param name="services">The service provider to add the services to</param>
|
||||
/// <param name="configuration">The configuration used to configure HopFrame authentication</param>
|
||||
/// <param name="config">Configuration for how the HopFrame services get set up</param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddHopFrameAuthentication(this IServiceCollection service, ConfigurationManager configuration, HopFrameConfig config = null) {
|
||||
public static IServiceCollection AddHopFrameAuthentication(this IServiceCollection services, ConfigurationManager configuration, HopFrameConfig config = null) {
|
||||
config ??= new HopFrameConfig();
|
||||
|
||||
service.AddSingleton(config);
|
||||
service.AddScoped(typeof(ICacheProvider), config.CacheProvider);
|
||||
service.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
service.AddScoped<ITokenContext, TokenContextImplementor>();
|
||||
services.AddSingleton(config);
|
||||
services.AddScoped(typeof(ICacheProvider), config.CacheProvider);
|
||||
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
services.AddScoped<ITokenContext, TokenContextImplementor>();
|
||||
|
||||
if (config.CacheProvider == typeof(MemoryCacheProvider))
|
||||
service.AddMemoryCache();
|
||||
services.AddMemoryCache();
|
||||
|
||||
service.AddHttpClient<OpenIdAccessor>();
|
||||
service.AddScoped<IOpenIdAccessor, OpenIdAccessor>();
|
||||
services.AddHttpClient<OpenIdAccessor>();
|
||||
services.AddScoped<IOpenIdAccessor, OpenIdAccessor>();
|
||||
|
||||
service.AddOptionsFromConfiguration<HopFrameAuthenticationOptions>(configuration);
|
||||
service.AddOptionsFromConfiguration<AdminPermissionOptions>(configuration);
|
||||
service.AddOptionsFromConfiguration<OpenIdOptions>(configuration);
|
||||
services.AddOptionsFromConfiguration<HopFrameAuthenticationOptions>(configuration);
|
||||
services.AddOptionsFromConfiguration<AdminPermissionOptions>(configuration);
|
||||
services.AddOptionsFromConfiguration<OpenIdOptions>(configuration);
|
||||
|
||||
service.AddAuthentication(HopFrameAuthentication.SchemeName).AddScheme<AuthenticationSchemeOptions, HopFrameAuthentication>(HopFrameAuthentication.SchemeName, _ => {});
|
||||
service.AddAuthorization();
|
||||
services.AddAuthentication(HopFrameAuthentication.SchemeName).AddScheme<AuthenticationSchemeOptions, HopFrameAuthentication>(HopFrameAuthentication.SchemeName, _ => {});
|
||||
services.AddAuthorization();
|
||||
|
||||
return service;
|
||||
HopDbContextBase.SaveHandlers.Add(context => {
|
||||
var section = configuration.GetSection("HopFrame:Authentication");
|
||||
var accessToken = section?.GetSection("AccessToken")?.Get<HopFrameAuthenticationOptions.TokenTime>()?.ConstructTimeSpan ?? new HopFrameAuthenticationOptions().AccessTokenTime;
|
||||
var refreshToken = section?.GetSection("RefreshToken")?.Get<HopFrameAuthenticationOptions.TokenTime>()?.ConstructTimeSpan ?? new HopFrameAuthenticationOptions().RefreshTokenTime;
|
||||
|
||||
var now = DateTime.Now;
|
||||
var accessTokenExpiry = now - accessToken;
|
||||
var refreshTokenExpiry = now - refreshToken;
|
||||
var invalidTokens = context.Tokens
|
||||
.Where(t =>
|
||||
(t.Type == Token.AccessTokenType && t.CreatedAt < accessTokenExpiry) ||
|
||||
(t.Type == Token.RefreshTokenType && t.CreatedAt < refreshTokenExpiry))
|
||||
.ToList();
|
||||
context.Tokens.RemoveRange(invalidTokens);
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user