mirror of
https://github.com/hmaxnl/DotBased.git
synced 2025-04-19 20:18:13 +02:00
Compare commits
9 Commits
2b76f79f24
...
419b58a97a
Author | SHA1 | Date | |
---|---|---|---|
|
419b58a97a | ||
|
6c67276dca | ||
|
1f593a364b | ||
|
eef7cfb2b9 | ||
|
65d625a30d | ||
|
2938e1311f | ||
|
0f6b2fec88 | ||
|
5b4509cac3 | ||
|
e914023c5a |
67
DotBased.AspNet.Authority.EFCore/AuthorityContext.cs
Normal file
67
DotBased.AspNet.Authority.EFCore/AuthorityContext.cs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
using DotBased.AspNet.Authority.EFCore.Models;
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore;
|
||||||
|
|
||||||
|
public class AuthorityContext(DbContextOptions<AuthorityContext> options) : DbContext(options)
|
||||||
|
{
|
||||||
|
public DbSet<AuthorityAttribute> Attributes { get; set; }
|
||||||
|
public DbSet<AuthorityGroup> Groups { get; set; }
|
||||||
|
public DbSet<AuthorityRole> Roles { get; set; }
|
||||||
|
public DbSet<AuthorityUser> Users { get; set; }
|
||||||
|
|
||||||
|
public DbSet<RoleGroup> RoleGroup { get; set; }
|
||||||
|
public DbSet<RoleUser> RoleUser { get; set; }
|
||||||
|
public DbSet<UserGroup> UserGroup { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.Entity<AuthorityAttribute>(attributeEntity =>
|
||||||
|
{
|
||||||
|
attributeEntity.ToTable("authority_attributes");
|
||||||
|
attributeEntity.HasKey(a => new { a.BoundId, a.AttributeKey });
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<AuthorityGroup>(groupEntity =>
|
||||||
|
{
|
||||||
|
groupEntity.ToTable("authority_groups");
|
||||||
|
groupEntity.HasKey(x => x.Id);
|
||||||
|
groupEntity.HasMany(g => g.Attributes).WithOne().HasForeignKey(a => a.BoundId).OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<AuthorityRole>(roleEntity =>
|
||||||
|
{
|
||||||
|
roleEntity.ToTable("authority_roles");
|
||||||
|
roleEntity.HasKey(x => x.Id);
|
||||||
|
roleEntity.HasMany(r => r.Attributes).WithOne().HasForeignKey(a => a.BoundId).OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<AuthorityUser>(userEntity =>
|
||||||
|
{
|
||||||
|
userEntity.ToTable("authority_users");
|
||||||
|
userEntity.HasKey(x => x.Id);
|
||||||
|
userEntity.HasMany(u => u.Attributes).WithOne().HasForeignKey(a => a.BoundId).OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<RoleGroup>(rgEntity =>
|
||||||
|
{
|
||||||
|
rgEntity.ToTable("role_group");
|
||||||
|
rgEntity.HasKey(rg => new { rg.RoleId, rg.GroupId });
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<RoleUser>(ruEntity =>
|
||||||
|
{
|
||||||
|
ruEntity.ToTable("role_user");
|
||||||
|
ruEntity.HasKey(ru => new { ru.RoleId, ru.UserId });
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity<UserGroup>(ugEntity =>
|
||||||
|
{
|
||||||
|
ugEntity.ToTable("user_group");
|
||||||
|
ugEntity.HasKey(ug => new { ug.UserId, ug.GroupId });
|
||||||
|
});
|
||||||
|
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DotBased.AspNet.Authority\DotBased.AspNet.Authority.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.12" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.12">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.12" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
19
DotBased.AspNet.Authority.EFCore/Extensions.cs
Normal file
19
DotBased.AspNet.Authority.EFCore/Extensions.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using DotBased.AspNet.Authority.EFCore.Repositories;
|
||||||
|
using DotBased.AspNet.Authority.Repositories;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore;
|
||||||
|
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddAuthorityContext(this IServiceCollection services, Action<DbContextOptionsBuilder> options)
|
||||||
|
{
|
||||||
|
services.AddDbContextFactory<AuthorityContext>(options);
|
||||||
|
services.AddScoped<IAttributeRepository, AttributeRepository>();
|
||||||
|
services.AddScoped<IGroupRepository, GroupRepository>();
|
||||||
|
services.AddScoped<IRoleRepository, RoleRepository>();
|
||||||
|
services.AddScoped<IUserRepository, UserRepository>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
7
DotBased.AspNet.Authority.EFCore/Models/RoleGroup.cs
Normal file
7
DotBased.AspNet.Authority.EFCore/Models/RoleGroup.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore.Models;
|
||||||
|
|
||||||
|
public class RoleGroup
|
||||||
|
{
|
||||||
|
public Guid RoleId { get; set; }
|
||||||
|
public Guid GroupId { get; set; }
|
||||||
|
}
|
7
DotBased.AspNet.Authority.EFCore/Models/RoleUser.cs
Normal file
7
DotBased.AspNet.Authority.EFCore/Models/RoleUser.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore.Models;
|
||||||
|
|
||||||
|
public class RoleUser
|
||||||
|
{
|
||||||
|
public Guid RoleId { get; set; }
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
}
|
7
DotBased.AspNet.Authority.EFCore/Models/UserGroup.cs
Normal file
7
DotBased.AspNet.Authority.EFCore/Models/UserGroup.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore.Models;
|
||||||
|
|
||||||
|
public class UserGroup
|
||||||
|
{
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
public Guid GroupId { get; set; }
|
||||||
|
}
|
23
DotBased.AspNet.Authority.EFCore/README.md
Normal file
23
DotBased.AspNet.Authority.EFCore/README.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# EF Core database
|
||||||
|
|
||||||
|
## Add migration project
|
||||||
|
```csharp
|
||||||
|
options.UseSqlite("Data Source=dev-dotbased.db", c => c.MigrationsAssembly("PROJECT-NAME"));
|
||||||
|
```
|
||||||
|
|
||||||
|
## EF Tool
|
||||||
|
|
||||||
|
Add migration
|
||||||
|
```shell
|
||||||
|
dotnet ef migrations add MIGRATION-NAME --project PROJECT-NAME
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove migrations
|
||||||
|
```shell
|
||||||
|
dotnet ef migrations remove --project PROJECT-NAME
|
||||||
|
```
|
||||||
|
|
||||||
|
Update database
|
||||||
|
```shell
|
||||||
|
dotnet ef database update --project PROJECT-NAME
|
||||||
|
```
|
|
@ -0,0 +1,33 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
using DotBased.AspNet.Authority.Repositories;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore.Repositories;
|
||||||
|
|
||||||
|
public class AttributeRepository : IAttributeRepository
|
||||||
|
{
|
||||||
|
public Task<ListResult<AuthorityAttributeItem>> GetAttributesAsync(int limit = 20, int offset = 0, string search = "",
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityAttribute>> GetAttributeByIdAsync(string id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityAttribute>> CreateAttributeAsync(AuthorityAttribute attribute, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityAttribute>> UpdateAttributeAsync(AuthorityAttribute attribute, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result> DeleteAttributeAsync(AuthorityAttribute attribute, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
using DotBased.AspNet.Authority.Repositories;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore.Repositories;
|
||||||
|
|
||||||
|
public class GroupRepository : IGroupRepository
|
||||||
|
{
|
||||||
|
public Task<ListResult<AuthorityGroupItem>> GetGroupsAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityAttribute>> GetGroupByIdAsync(string id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityAttribute>> CreateGroupAsync(AuthorityGroup group, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityAttribute>> UpdateGroupAsync(AuthorityGroup group, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result> DeleteGroupAsync(AuthorityGroup group, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
using DotBased.AspNet.Authority.Repositories;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore.Repositories;
|
||||||
|
|
||||||
|
public class RoleRepository : IRoleRepository
|
||||||
|
{
|
||||||
|
public Task<ListResult<AuthorityRoleItem>> GetRolesAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityRole>> GetRoleByIdAsync(string id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityRole>> CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result<AuthorityRole>> UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Result> DeleteRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
217
DotBased.AspNet.Authority.EFCore/Repositories/UserRepository.cs
Normal file
217
DotBased.AspNet.Authority.EFCore/Repositories/UserRepository.cs
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
using DotBased.AspNet.Authority.Repositories;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace DotBased.AspNet.Authority.EFCore.Repositories;
|
||||||
|
|
||||||
|
public class UserRepository(IDbContextFactory<AuthorityContext> contextFactory) : IUserRepository
|
||||||
|
{
|
||||||
|
public async Task<ListResult<AuthorityUserItem>> GetAuthorityUsersAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var query = context.Users.AsQueryable();
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
query = query.Where(u =>
|
||||||
|
$"{u.Id} {u.Name} {u.UserName} {u.EmailAddress} {u.PhoneNumber}".Contains(search,
|
||||||
|
StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalCount = query.Count();
|
||||||
|
var selected = query.Skip(offset).Take(limit).Select(u => new AuthorityUserItem()
|
||||||
|
{
|
||||||
|
Id = u.Id,
|
||||||
|
UserName = u.UserName,
|
||||||
|
EmailAddress = u.EmailAddress,
|
||||||
|
PhoneNumber = u.PhoneNumber
|
||||||
|
});
|
||||||
|
return ListResult<AuthorityUserItem>.Ok(selected, totalCount, limit, offset);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return ListResult<AuthorityUserItem>.Failed("Failed to get users.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<AuthorityUser>> GetAuthorityUserByIdAsync(string id, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
if (!Guid.TryParse(id, out var guid))
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("Invalid id!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await context.Users.FirstOrDefaultAsync(u => u.Id == guid, cancellationToken: cancellationToken);
|
||||||
|
return Result<AuthorityUser>.HandleResult(user, "User not found.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("Failed to get user.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<AuthorityUser>> CreateUserAsync(AuthorityUser user, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
if (user.Id == Guid.Empty)
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("Id cannot be empty!");
|
||||||
|
}
|
||||||
|
var entity = context.Users.Add(user);
|
||||||
|
var saveResult = await context.SaveChangesAsync(cancellationToken);
|
||||||
|
return saveResult <= 0 ? Result<AuthorityUser>.Failed("Failed to create user!") : Result<AuthorityUser>.Ok(entity.Entity);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("Failed to create user.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<AuthorityUser>> UpdateUserAsync(AuthorityUser user, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var usr = await context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken: cancellationToken);
|
||||||
|
if (usr == null)
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("User not found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usr.Version != user.Version || usr.SecurityVersion != user.SecurityVersion)
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("Version validation failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var entity = context.Users.Update(user);
|
||||||
|
var saveResult = await context.SaveChangesAsync(cancellationToken);
|
||||||
|
return saveResult <= 0 ? Result<AuthorityUser>.Failed("Failed to save updated user!") : Result<AuthorityUser>.Ok(entity.Entity);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("Failed to update user!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> DeleteUserAsync(AuthorityUser user, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var usr = await context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken: cancellationToken);
|
||||||
|
if (usr == null)
|
||||||
|
{
|
||||||
|
return Result.Failed("User not found!");
|
||||||
|
}
|
||||||
|
context.Users.Remove(usr);
|
||||||
|
var saveResult = await context.SaveChangesAsync(cancellationToken);
|
||||||
|
return saveResult <= 0 ? Result.Failed("Failed to delete user!") : Result.Ok();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result.Failed("Failed to delete user!", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<AuthorityUser>> GetUserByEmailAsync(string email, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var usr = await context.Users.FirstOrDefaultAsync(u => u.EmailAddress == email, cancellationToken: cancellationToken);
|
||||||
|
return Result<AuthorityUser>.HandleResult(usr, "User not found by given email address.");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result<AuthorityUser>.Failed("An error occured while getting the user.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> SetVersionAsync(AuthorityUser user, long version, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var usr = await context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken);
|
||||||
|
if (usr == null)
|
||||||
|
{
|
||||||
|
return Result.Failed("Failed to find user with given id!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usr.Version != user.Version)
|
||||||
|
{
|
||||||
|
return Result.Failed("Stored user version doesn't match current user version!");
|
||||||
|
}
|
||||||
|
|
||||||
|
usr.Version = version;
|
||||||
|
context.Users.Update(usr);
|
||||||
|
var saveResult = await context.SaveChangesAsync(cancellationToken);
|
||||||
|
return saveResult <= 0 ? Result.Failed("Failed to update user!") : Result.Ok();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result.Failed("An error occured while updating the version.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<long>> GetVersionAsync(AuthorityUser user, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var usrVersion = await context.Users.Where(u => u.Id == user.Id).Select(u => u.Version).FirstOrDefaultAsync(cancellationToken);
|
||||||
|
return Result<long>.HandleResult(usrVersion, "Failed to get user version!");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result<long>.Failed("An error occured while getting the user version.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> SetSecurityVersionAsync(AuthorityUser user, long securityVersion, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var usr = await context.Users.FirstOrDefaultAsync(u => u.Id == user.Id, cancellationToken);
|
||||||
|
if (usr == null)
|
||||||
|
{
|
||||||
|
return Result.Failed("Failed to find user with given id!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usr.SecurityVersion != user.SecurityVersion)
|
||||||
|
{
|
||||||
|
return Result.Failed("Stored user version doesn't match current user version!");
|
||||||
|
}
|
||||||
|
|
||||||
|
usr.SecurityVersion = securityVersion;
|
||||||
|
context.Users.Update(usr);
|
||||||
|
var saveResult = await context.SaveChangesAsync(cancellationToken);
|
||||||
|
return saveResult <= 0 ? Result.Failed("Failed to update user!") : Result.Ok();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result.Failed("An error occured while updating the security version.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<long>> GetSecurityVersionAsync(AuthorityUser user, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
var usrVersion = await context.Users.Where(u => u.Id == user.Id).Select(u => u.SecurityVersion).FirstOrDefaultAsync(cancellationToken);
|
||||||
|
return Result<long>.HandleResult(usrVersion, "Failed to get user security version!");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return Result<long>.Failed("An error occured while getting the user security version.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Folder Include="Models\Data\" />
|
||||||
<Folder Include="Models\Security\" />
|
<Folder Include="Models\Security\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -34,13 +34,13 @@ public partial class AuthorityManager
|
||||||
return errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok();
|
return errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ListResult<AuthorityUser>> SearchUsersAsync(string query, int maxResults = 20, int offset = 0, CancellationToken? cancellationToken = null)
|
public async Task<ListResult<AuthorityUserItem>> SearchUsersAsync(string query, int maxResults = 20, int offset = 0, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var searchResult = await UserRepository.GetAuthorityUsersAsync(query, maxResults, offset, cancellationToken);
|
var result = await UserRepository.GetAuthorityUsersAsync(maxResults, offset, query, cancellationToken);
|
||||||
return searchResult.Item1 == null ? ListResult<AuthorityUser>.Failed("No results!") : ListResult<AuthorityUser>.Ok(searchResult.Item1, searchResult.Item2);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AuthorityResult<AuthorityUser>> UpdatePasswordAsync(AuthorityUser user, string password, CancellationToken? cancellationToken = null)
|
public async Task<AuthorityResult<AuthorityUser>> UpdatePasswordAsync(AuthorityUser user, string password, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var passwordValidation = await ValidatePasswordAsync(user, password);
|
var passwordValidation = await ValidatePasswordAsync(user, password);
|
||||||
if (!passwordValidation.Success)
|
if (!passwordValidation.Success)
|
||||||
|
@ -54,10 +54,10 @@ public partial class AuthorityManager
|
||||||
user.SecurityVersion = GenerateVersion();
|
user.SecurityVersion = GenerateVersion();
|
||||||
|
|
||||||
var updateResult = await UserRepository.UpdateUserAsync(user, cancellationToken);
|
var updateResult = await UserRepository.UpdateUserAsync(user, cancellationToken);
|
||||||
return updateResult == null ? AuthorityResult<AuthorityUser>.Error("Failed to save updates!") : AuthorityResult<AuthorityUser>.Ok(updateResult);
|
return AuthorityResult<AuthorityUser>.FromResult(updateResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AuthorityResult<AuthorityUser>> CreateUserAsync(AuthorityUser userModel, string password, CancellationToken? cancellationToken = null)
|
public async Task<AuthorityResult<AuthorityUser>> CreateUserAsync(AuthorityUser userModel, string password, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var userValidation = await ValidateUserAsync(userModel);
|
var userValidation = await ValidateUserAsync(userModel);
|
||||||
var passwordValidation = await ValidatePasswordAsync(userModel, password);
|
var passwordValidation = await ValidatePasswordAsync(userModel, password);
|
||||||
|
@ -75,19 +75,17 @@ public partial class AuthorityManager
|
||||||
userModel.PasswordHash = hashedPassword;
|
userModel.PasswordHash = hashedPassword;
|
||||||
|
|
||||||
var userCreationResult = await UserRepository.CreateUserAsync(userModel, cancellationToken);
|
var userCreationResult = await UserRepository.CreateUserAsync(userModel, cancellationToken);
|
||||||
|
|
||||||
return userCreationResult != null
|
return AuthorityResult<AuthorityUser>.FromResult(userCreationResult);
|
||||||
? AuthorityResult<AuthorityUser>.Ok(userCreationResult)
|
|
||||||
: AuthorityResult<AuthorityUser>.Error("Failed to create user in repository!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Result<AuthorityUser>> UpdateUserAsync(AuthorityUser model, CancellationToken? cancellationToken = null)
|
public async Task<Result<AuthorityUser>> UpdateUserAsync(AuthorityUser model, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var updateResult = await UserRepository.UpdateUserAsync(model, cancellationToken);
|
var updateResult = await UserRepository.UpdateUserAsync(model, cancellationToken);
|
||||||
return updateResult != null ? Result<AuthorityUser>.Ok(updateResult) : Result<AuthorityUser>.Failed("Failed to update user in repository!");
|
return updateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> DeleteUserAsync(AuthorityUser model, CancellationToken? cancellationToken = null)
|
public async Task<Result> DeleteUserAsync(AuthorityUser model, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var deleteResult = await UserRepository.DeleteUserAsync(model, cancellationToken);
|
var deleteResult = await UserRepository.DeleteUserAsync(model, cancellationToken);
|
||||||
return deleteResult;
|
return deleteResult;
|
||||||
|
|
|
@ -1,26 +1,18 @@
|
||||||
namespace DotBased.AspNet.Authority.Models.Authority;
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
public class AuthorityAttribute
|
public class AuthorityAttribute(string attributeKey, Guid bound)
|
||||||
{
|
{
|
||||||
public AuthorityAttribute(string attributeKey, string bound)
|
public AuthorityAttribute() : this(string.Empty, Guid.NewGuid())
|
||||||
{
|
{
|
||||||
AttributeKey = attributeKey;
|
|
||||||
BoundId = bound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthorityAttribute()
|
public Guid BoundId { get; set; } = bound;
|
||||||
{
|
|
||||||
AttributeKey = string.Empty;
|
|
||||||
BoundId = string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string AttributeKey { get; set; } // ClaimType/Authority.attribute.enabled
|
|
||||||
|
|
||||||
public string BoundId { get; set; } // Bound to User, Group, Role id
|
public string AttributeKey { get; set; } = attributeKey;
|
||||||
|
|
||||||
public object? AttributeValue { get; set; }
|
public string AttributeValue { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string? Type { get; set; } // AspNet.Claim.Role/Property/Data.JSON, Data.Raw, Data.Base64 etc.
|
public string? Type { get; set; }
|
||||||
|
|
||||||
public long Version { get; set; }
|
public long Version { get; set; }
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
|
public class AuthorityAttributeItem
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -1,23 +1,18 @@
|
||||||
namespace DotBased.AspNet.Authority.Models.Authority;
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
public class AuthorityGroup
|
public class AuthorityGroup()
|
||||||
{
|
{
|
||||||
public AuthorityGroup(string name) : this()
|
public AuthorityGroup(string name) : this()
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthorityGroup()
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
{
|
|
||||||
Id = Guid.NewGuid();
|
|
||||||
CreatedDate = DateTime.Now;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
public long Version { get; set; }
|
public long Version { get; set; }
|
||||||
|
|
||||||
public DateTime CreatedDate { get; set; }
|
public DateTime CreatedDate { get; set; } = DateTime.Now;
|
||||||
|
public ICollection<AuthorityAttribute> Attributes { get; set; } = [];
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
|
public class AuthorityGroupItem
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
namespace DotBased.AspNet.Authority.Models.Authority;
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
public abstract class AuthorityRole()
|
public class AuthorityRole()
|
||||||
{
|
{
|
||||||
public AuthorityRole(string name) : this()
|
public AuthorityRole(string name) : this()
|
||||||
{
|
{
|
||||||
|
@ -15,5 +15,7 @@ public abstract class AuthorityRole()
|
||||||
|
|
||||||
public DateTime CreatedDate { get; set; } = DateTime.Now;
|
public DateTime CreatedDate { get; set; } = DateTime.Now;
|
||||||
|
|
||||||
|
public IEnumerable<AuthorityAttribute> Attributes { get; set; } = [];
|
||||||
|
|
||||||
public override string ToString() => Name ?? string.Empty;
|
public override string ToString() => Name ?? string.Empty;
|
||||||
}
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
|
public class AuthorityRoleItem
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Text;
|
||||||
using DotBased.AspNet.Authority.Attributes;
|
using DotBased.AspNet.Authority.Attributes;
|
||||||
|
|
||||||
namespace DotBased.AspNet.Authority.Models.Authority;
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
@ -19,7 +20,9 @@ public class AuthorityUser()
|
||||||
|
|
||||||
public DateTime LockedDate { get; set; }
|
public DateTime LockedDate { get; set; }
|
||||||
|
|
||||||
public string? UserName { get; set; }
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
|
||||||
public string? PasswordHash { get; set; }
|
public string? PasswordHash { get; set; }
|
||||||
|
|
||||||
|
@ -41,5 +44,17 @@ public class AuthorityUser()
|
||||||
|
|
||||||
public bool PhoneNumberConfirmed { get; set; }
|
public bool PhoneNumberConfirmed { get; set; }
|
||||||
|
|
||||||
public override string ToString() => UserName ?? EmailAddress ?? string.Empty;
|
public ICollection<AuthorityAttribute> Attributes { get; set; } = [];
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var strBuilder = new StringBuilder();
|
||||||
|
strBuilder.Append(!string.IsNullOrWhiteSpace(Name) ? Name : UserName);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(EmailAddress)) return strBuilder.ToString();
|
||||||
|
|
||||||
|
strBuilder.Append(strBuilder.Length == 0 ? EmailAddress : $" ({EmailAddress})");
|
||||||
|
|
||||||
|
return strBuilder.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
|
public class AuthorityUserItem
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public string? EmailAddress { get; set; } = string.Empty;
|
||||||
|
public string? PhoneNumber { get; set; } = string.Empty;
|
||||||
|
}
|
|
@ -2,20 +2,23 @@ using DotBased.AspNet.Authority.Models.Validation;
|
||||||
|
|
||||||
namespace DotBased.AspNet.Authority.Models;
|
namespace DotBased.AspNet.Authority.Models;
|
||||||
|
|
||||||
public class AuthorityResult<TResultValue>
|
public class AuthorityResult<TResultValue> : Result<TResultValue>
|
||||||
{
|
{
|
||||||
public AuthorityResult(bool success, string errorMessage = "", TResultValue? value = default, ResultFailReason reason = ResultFailReason.None, List<ValidationError>? errors = null)
|
public static AuthorityResult<TResultValue> FromResult(Result<TResultValue> result) => new AuthorityResult<TResultValue>(result);
|
||||||
|
|
||||||
|
public AuthorityResult(Result<TResultValue> result) : base(result)
|
||||||
|
{
|
||||||
|
Reason = ResultFailReason.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorityResult(bool success, string errorMessage = "", TResultValue? value = default, ResultFailReason reason = ResultFailReason.None, List<ValidationError>? errors = null) : base(success, errorMessage, value, null)
|
||||||
{
|
{
|
||||||
Success = success;
|
Success = success;
|
||||||
ErrorMessage = errorMessage;
|
Message = errorMessage;
|
||||||
Value = value;
|
Value = value;
|
||||||
Reason = reason;
|
Reason = reason;
|
||||||
ValidationErrors = errors;
|
ValidationErrors = errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Success { get; }
|
|
||||||
public string ErrorMessage { get; }
|
|
||||||
public TResultValue? Value { get; }
|
|
||||||
public ResultFailReason Reason { get; }
|
public ResultFailReason Reason { get; }
|
||||||
public List<ValidationError>? ValidationErrors { get; }
|
public List<ValidationError>? ValidationErrors { get; }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
namespace DotBased.AspNet.Authority.Repositories;
|
namespace DotBased.AspNet.Authority.Repositories;
|
||||||
|
|
||||||
public interface IAttributeRepository
|
public interface IAttributeRepository
|
||||||
{
|
{
|
||||||
|
public Task<ListResult<AuthorityAttributeItem>> GetAttributesAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityAttribute>> GetAttributeByIdAsync(string id, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityAttribute>> CreateAttributeAsync(AuthorityAttribute attribute, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityAttribute>> UpdateAttributeAsync(AuthorityAttribute attribute, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result> DeleteAttributeAsync(AuthorityAttribute attribute, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
|
@ -1,6 +1,12 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
namespace DotBased.AspNet.Authority.Repositories;
|
namespace DotBased.AspNet.Authority.Repositories;
|
||||||
|
|
||||||
public interface IGroupRepository
|
public interface IGroupRepository
|
||||||
{
|
{
|
||||||
|
public Task<ListResult<AuthorityGroupItem>> GetGroupsAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityAttribute>> GetGroupByIdAsync(string id, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityAttribute>> CreateGroupAsync(AuthorityGroup group, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityAttribute>> UpdateGroupAsync(AuthorityGroup group, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result> DeleteGroupAsync(AuthorityGroup group, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
|
@ -1,6 +1,12 @@
|
||||||
|
using DotBased.AspNet.Authority.Models.Authority;
|
||||||
|
|
||||||
namespace DotBased.AspNet.Authority.Repositories;
|
namespace DotBased.AspNet.Authority.Repositories;
|
||||||
|
|
||||||
public interface IRoleRepository
|
public interface IRoleRepository
|
||||||
{
|
{
|
||||||
|
public Task<ListResult<AuthorityRoleItem>> GetRolesAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityRole>> GetRoleByIdAsync(string id, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityRole>> CreateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result<AuthorityRole>> UpdateRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default);
|
||||||
|
public Task<Result> DeleteRoleAsync(AuthorityRole role, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
|
@ -4,15 +4,14 @@ namespace DotBased.AspNet.Authority.Repositories;
|
||||||
|
|
||||||
public interface IUserRepository
|
public interface IUserRepository
|
||||||
{
|
{
|
||||||
public Task<AuthorityUser?> GetAuthorityUserByIdAsync(string id, CancellationToken? cancellationToken = null);
|
public Task<ListResult<AuthorityUserItem>> GetAuthorityUsersAsync(int limit = 20, int offset = 0, string search = "", CancellationToken cancellationToken = default);
|
||||||
public Task<string> GetAuthorityUserIdAsync(AuthorityUser user, CancellationToken? cancellationToken = null);
|
public Task<Result<AuthorityUser>> GetAuthorityUserByIdAsync(string id, CancellationToken cancellationToken = default);
|
||||||
public Task<Tuple<List<AuthorityUser>?, int>> GetAuthorityUsersAsync(string query, int maxResults = 20, int offset = 0, CancellationToken? cancellationToken = null);
|
public Task<Result<AuthorityUser>> CreateUserAsync(AuthorityUser user, CancellationToken cancellationToken = default);
|
||||||
public Task<AuthorityUser?> GetAuthorityUserByEmailAsync(string email, CancellationToken? cancellationToken = null);
|
public Task<Result<AuthorityUser>> UpdateUserAsync(AuthorityUser user, CancellationToken cancellationToken = default);
|
||||||
public Task SetVersionAsync(AuthorityUser user, long version, CancellationToken? cancellationToken = null);
|
public Task<Result> DeleteUserAsync(AuthorityUser user, CancellationToken cancellationToken = default);
|
||||||
public Task<long> GetVersionAsync(AuthorityUser user, CancellationToken? cancellationToken = null);
|
public Task<Result<AuthorityUser>> GetUserByEmailAsync(string email, CancellationToken cancellationToken = default);
|
||||||
public Task SetSecurityVersionAsync(AuthorityUser user, long version, CancellationToken? cancellationToken = null);
|
public Task<Result> SetVersionAsync(AuthorityUser user, long version, CancellationToken cancellationToken = default);
|
||||||
public Task<long> GetSecurityVersionAsync(AuthorityUser user, CancellationToken? cancellationToken = null);
|
public Task<Result<long>> GetVersionAsync(AuthorityUser user, CancellationToken cancellationToken = default);
|
||||||
public Task<AuthorityUser?> CreateUserAsync(AuthorityUser user, CancellationToken? cancellationToken = null);
|
public Task<Result> SetSecurityVersionAsync(AuthorityUser user, long securityVersion, CancellationToken cancellationToken = default);
|
||||||
public Task<AuthorityUser?> UpdateUserAsync(AuthorityUser user, CancellationToken? cancellationToken = null);
|
public Task<Result<long>> GetSecurityVersionAsync(AuthorityUser user, CancellationToken cancellationToken = default);
|
||||||
public Task<bool> DeleteUserAsync(AuthorityUser user, CancellationToken? cancellationToken = null);
|
|
||||||
}
|
}
|
|
@ -25,7 +25,7 @@ public class UserValidator : IUserValidator
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var userEmailResult = await manager.UserRepository.GetAuthorityUserByEmailAsync(user.EmailAddress);
|
var userEmailResult = await manager.UserRepository.GetUserByEmailAsync(user.EmailAddress);
|
||||||
if (userEmailResult != null)
|
if (userEmailResult != null)
|
||||||
{
|
{
|
||||||
errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.EmailExists",
|
errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.EmailExists",
|
||||||
|
|
|
@ -24,6 +24,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.AspNet.Authority",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.Data", "DotBased.Data\DotBased.Data.csproj", "{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.Data", "DotBased.Data\DotBased.Data.csproj", "{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotBased.AspNet.Authority.EFCore", "DotBased.AspNet.Authority.EFCore\DotBased.AspNet.Authority.EFCore.csproj", "{F1F3F60B-911F-4036-8A2B-CEC18A8F59DD}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -66,6 +68,10 @@ Global
|
||||||
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F1F3F60B-911F-4036-8A2B-CEC18A8F59DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F1F3F60B-911F-4036-8A2B-CEC18A8F59DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F1F3F60B-911F-4036-8A2B-CEC18A8F59DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F1F3F60B-911F-4036-8A2B-CEC18A8F59DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{EBBDAF9A-BFC7-4BDC-8C51-0501B59A1DDC} = {2156FB93-C252-4B33-8A0C-73C82FABB163}
|
{EBBDAF9A-BFC7-4BDC-8C51-0501B59A1DDC} = {2156FB93-C252-4B33-8A0C-73C82FABB163}
|
||||||
|
@ -76,5 +82,6 @@ Global
|
||||||
{624E7B11-8A18-46E5-AB1F-6AF6097F9D4D} = {2156FB93-C252-4B33-8A0C-73C82FABB163}
|
{624E7B11-8A18-46E5-AB1F-6AF6097F9D4D} = {2156FB93-C252-4B33-8A0C-73C82FABB163}
|
||||||
{A3ADC9AF-39B7-4EC4-8022-946118A8C322} = {624E7B11-8A18-46E5-AB1F-6AF6097F9D4D}
|
{A3ADC9AF-39B7-4EC4-8022-946118A8C322} = {624E7B11-8A18-46E5-AB1F-6AF6097F9D4D}
|
||||||
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4} = {2156FB93-C252-4B33-8A0C-73C82FABB163}
|
{2DF9FEEF-5A60-4B41-9B5F-F883DCE33EF4} = {2156FB93-C252-4B33-8A0C-73C82FABB163}
|
||||||
|
{F1F3F60B-911F-4036-8A2B-CEC18A8F59DD} = {624E7B11-8A18-46E5-AB1F-6AF6097F9D4D}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -43,11 +43,16 @@ public class Result<TValue> : Result
|
||||||
|
|
||||||
public new static Result<TValue> Failed(string message, Exception? exception = null) =>
|
public new static Result<TValue> Failed(string message, Exception? exception = null) =>
|
||||||
new(false, message, default, exception);
|
new(false, message, default, exception);
|
||||||
|
|
||||||
|
public new static Result<TValue> HandleResult(TValue? value, string failedMessage, Exception? exception = null)
|
||||||
|
{
|
||||||
|
return value == null ? Failed(failedMessage, exception) : Ok(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ListResult<TItem> : Result
|
public class ListResult<TItem> : Result
|
||||||
{
|
{
|
||||||
public ListResult(bool success, string message, int totalCount, IEnumerable<TItem>? items, Exception? exception) : base(success, message, exception)
|
public ListResult(bool success, string message, int totalCount, IEnumerable<TItem>? items, int limit = -1, int offset = -1, Exception? exception = null) : base(success, message, exception)
|
||||||
{
|
{
|
||||||
Items = items != null ? new List<TItem>(items) : new List<TItem>();
|
Items = items != null ? new List<TItem>(items) : new List<TItem>();
|
||||||
TotalCount = totalCount;
|
TotalCount = totalCount;
|
||||||
|
@ -69,9 +74,19 @@ public class ListResult<TItem> : Result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int TotalCount { get; }
|
public int TotalCount { get; }
|
||||||
|
|
||||||
public static ListResult<TItem> Ok(IEnumerable<TItem> items, int totalCount = -1) =>
|
/// <summary>
|
||||||
new(true, string.Empty, totalCount, items, null);
|
/// The limit this result contains
|
||||||
|
/// </summary>
|
||||||
|
public int Limit { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The offset this result has the items from.
|
||||||
|
/// </summary>
|
||||||
|
public int Offset { get; }
|
||||||
|
|
||||||
|
public static ListResult<TItem> Ok(IEnumerable<TItem> items, int totalCount = -1, int limit = -1, int offset = -1) =>
|
||||||
|
new(true, string.Empty, totalCount, items);
|
||||||
|
|
||||||
public new static ListResult<TItem> Failed(string message, Exception? exception = null) =>
|
public new static ListResult<TItem> Failed(string message, Exception? exception = null) =>
|
||||||
new(false, message, -1, null, exception);
|
new(false, message, -1, null);
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
using DotBased.AspNet.Authority;
|
using DotBased.AspNet.Authority;
|
||||||
|
using DotBased.AspNet.Authority.EFCore;
|
||||||
using DotBased.Logging;
|
using DotBased.Logging;
|
||||||
using DotBased.Logging.MEL;
|
using DotBased.Logging.MEL;
|
||||||
using DotBased.Logging.Serilog;
|
using DotBased.Logging.Serilog;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using TestWebApi;
|
using TestWebApi;
|
||||||
using ILogger = Serilog.ILogger;
|
using ILogger = Serilog.ILogger;
|
||||||
|
@ -19,7 +21,10 @@ LogService.AddLogAdapter(new BasedSerilogAdapter(serilogLogger));
|
||||||
|
|
||||||
builder.Logging.ClearProviders();
|
builder.Logging.ClearProviders();
|
||||||
builder.Logging.AddDotBasedLoggerProvider(LogService.Options);
|
builder.Logging.AddDotBasedLoggerProvider(LogService.Options);
|
||||||
|
builder.Services.AddAuthorityContext(options =>
|
||||||
|
{
|
||||||
|
options.UseSqlite("Data Source=dev-dotbased.db", c => c.MigrationsAssembly("TestWebApi"));
|
||||||
|
});
|
||||||
builder.Services.AddAuthority(options =>
|
builder.Services.AddAuthority(options =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,17 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8"/>
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8"/>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.12">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.12" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\DotBased.AspNet.Authority.EFCore\DotBased.AspNet.Authority.EFCore.csproj" />
|
||||||
<ProjectReference Include="..\DotBased.AspNet.Authority\DotBased.AspNet.Authority.csproj" />
|
<ProjectReference Include="..\DotBased.AspNet.Authority\DotBased.AspNet.Authority.csproj" />
|
||||||
<ProjectReference Include="..\DotBased.Logging.MEL\DotBased.Logging.MEL.csproj" />
|
<ProjectReference Include="..\DotBased.Logging.MEL\DotBased.Logging.MEL.csproj" />
|
||||||
<ProjectReference Include="..\DotBased.Logging.Serilog\DotBased.Logging.Serilog.csproj" />
|
<ProjectReference Include="..\DotBased.Logging.Serilog\DotBased.Logging.Serilog.csproj" />
|
||||||
|
|
18
obs_DotBased/.obsidian/workspace.json
vendored
18
obs_DotBased/.obsidian/workspace.json
vendored
|
@ -4,21 +4,17 @@
|
||||||
"type": "split",
|
"type": "split",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "68f3abbbf106a47b",
|
"id": "89533e49f06550fb",
|
||||||
"type": "tabs",
|
"type": "tabs",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "9629cc68ecd8963f",
|
"id": "65943ca25b411f17",
|
||||||
"type": "leaf",
|
"type": "leaf",
|
||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "empty",
|
||||||
"state": {
|
"state": {},
|
||||||
"file": "Modules/AspNet/DotBased.Authority/Repositories/UserRepository.md",
|
|
||||||
"mode": "source",
|
|
||||||
"source": false
|
|
||||||
},
|
|
||||||
"icon": "lucide-file",
|
"icon": "lucide-file",
|
||||||
"title": "UserRepository"
|
"title": "New tab"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -162,10 +158,10 @@
|
||||||
"command-palette:Open command palette": false
|
"command-palette:Open command palette": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"active": "9629cc68ecd8963f",
|
"active": "65943ca25b411f17",
|
||||||
"lastOpenFiles": [
|
"lastOpenFiles": [
|
||||||
"Modules/AspNet/DotBased.Authority/Repository.md",
|
|
||||||
"Modules/AspNet/DotBased.Authority/Repositories/UserRepository.md",
|
"Modules/AspNet/DotBased.Authority/Repositories/UserRepository.md",
|
||||||
|
"Modules/AspNet/DotBased.Authority/Repository.md",
|
||||||
"Modules/AspNet/DotBased.Authority/Repositories",
|
"Modules/AspNet/DotBased.Authority/Repositories",
|
||||||
"Modules/AspNet/DotBased.Authority/Data diagram.canvas",
|
"Modules/AspNet/DotBased.Authority/Data diagram.canvas",
|
||||||
"Modules/AspNet/DotBased.Authority/Models/AuthorityAttribute.md",
|
"Modules/AspNet/DotBased.Authority/Models/AuthorityAttribute.md",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user