Merge branch 'release/v2.0.0' into 'dev'
Resolve "Prepare release v2.0.0" Closes #23 See merge request leon.hoppe/HopFrame!12
This commit is contained in:
34
.gitlab-ci.yml
Normal file
34
.gitlab-ci.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
image: mcr.microsoft.com/dotnet/sdk:8.0
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- publish
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- echo "Setting up environment"
|
||||||
|
- 'dotnet --version'
|
||||||
|
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- dotnet restore
|
||||||
|
- dotnet build --configuration Release --no-restore
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- "**/bin/Release"
|
||||||
|
|
||||||
|
test:
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- dotnet test --no-restore --verbosity normal
|
||||||
|
|
||||||
|
publish:
|
||||||
|
stage: publish
|
||||||
|
script:
|
||||||
|
- dotnet pack -c Release -o .
|
||||||
|
- for nupkg in *.nupkg; do dotnet nuget push $nupkg -k $NUGET_API_KEY -s https://api.nuget.org/v3/index.json; done
|
||||||
|
only:
|
||||||
|
- main
|
||||||
|
variables:
|
||||||
|
NUGET_API_KEY: $NUGET_API_KEY
|
||||||
12
README.md
12
README.md
@@ -5,21 +5,15 @@ A simple backend management api for ASP.NET Core Web APIs
|
|||||||
- [x] Database management
|
- [x] Database management
|
||||||
- [x] User authentication
|
- [x] User authentication
|
||||||
- [x] Permission management
|
- [x] Permission management
|
||||||
- [x] Frontend dashboards
|
- [x] Generated frontend administration boards
|
||||||
|
|
||||||
## 2.0 Todo list
|
|
||||||
- [x] 1.0 bug fixes
|
|
||||||
- [x] Code cleanup
|
|
||||||
- [x] Relations in database
|
|
||||||
- [x] Generated Admin pages
|
|
||||||
- [x] Pretty Login page for administration
|
|
||||||
- [ ] Clean documentation
|
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
There are two different versions of HopFrame, either the Web API version or the full Blazor web version.
|
There are two different versions of HopFrame, either the Web API version or the full Blazor web version.
|
||||||
|
|
||||||
## Ho to use the Web API version
|
## Ho to use the Web API version
|
||||||
|
|
||||||
|
> **Hint:** For more information about the HopFrame installation and usage go to the [docs](./docs).
|
||||||
|
|
||||||
1. Add the HopFrame.Api library to your project:
|
1. Add the HopFrame.Api library to your project:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
|
|
||||||
<PackageId>HopFrame.Api</PackageId>
|
<PackageId>HopFrame.Api</PackageId>
|
||||||
<Version>1.1.0</Version>
|
<Version>2.0.0</Version>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
|
|||||||
@@ -1,100 +1,4 @@
|
|||||||
# HopFrame API module
|
# HopFrame API module
|
||||||
This module contains some useful endpoints for user login / register management.
|
This module contains some useful endpoints for user login / register management.
|
||||||
|
|
||||||
## Ho to use the Web API version
|
For more information about the HopFrame visit the [docs](https://git.leon-hoppe.de/leon.hoppe/HopFrame).
|
||||||
|
|
||||||
1. Add the HopFrame.Api library to your project:
|
|
||||||
|
|
||||||
```
|
|
||||||
dotnet add package HopFrame.Api
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Create a DbContext that inherits the ``HopDbContext`` and add a data source
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class DatabaseContext : HopDbContextBase {
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
|
|
||||||
base.OnConfiguring(optionsBuilder);
|
|
||||||
|
|
||||||
optionsBuilder.UseSqlite("...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Add the DbContext and HopFrame to your services
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
builder.Services.AddDbContext<DatabaseContext>();
|
|
||||||
builder.Services.AddHopFrame<DatabaseContext>();
|
|
||||||
```
|
|
||||||
|
|
||||||
# Endpoints
|
|
||||||
By default, the module provides a controller for handling authentication based requests by the user.
|
|
||||||
You can explore the contoller by the build in swagger site from ASP .NET.
|
|
||||||
|
|
||||||
## Disable the Endpoints
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
builder.Services.AddDbContext<DatabaseContext>();
|
|
||||||
//builder.Services.AddHopFrame<DatabaseContext>();
|
|
||||||
services.AddHopFrameNoEndpoints<TDbContext>();
|
|
||||||
```
|
|
||||||
|
|
||||||
# Services added in this module
|
|
||||||
You can use these services by specifying them as a dependency. All of them are scoped dependencies.
|
|
||||||
|
|
||||||
## LogicResult
|
|
||||||
Logic result is an extension of the ActionResult for an ApiController. It provides simple Http status results with either a message or data by specifying the generic type.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class LogicResult : ILogicResult {
|
|
||||||
public static LogicResult Ok();
|
|
||||||
|
|
||||||
public static LogicResult BadRequest();
|
|
||||||
|
|
||||||
public static LogicResult BadRequest(string message);
|
|
||||||
|
|
||||||
public static LogicResult Forbidden();
|
|
||||||
|
|
||||||
public static LogicResult Forbidden(string message);
|
|
||||||
|
|
||||||
public static LogicResult NotFound();
|
|
||||||
|
|
||||||
public static LogicResult NotFound(string message);
|
|
||||||
|
|
||||||
public static LogicResult Conflict();
|
|
||||||
|
|
||||||
public static LogicResult Conflict(string message);
|
|
||||||
|
|
||||||
public static LogicResult Forward(LogicResult result);
|
|
||||||
|
|
||||||
public static LogicResult Forward<T>(ILogicResult<T> result);
|
|
||||||
|
|
||||||
public static implicit operator ActionResult(LogicResult v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LogicResult<T> : ILogicResult<T> {
|
|
||||||
public static LogicResult<T> Ok();
|
|
||||||
|
|
||||||
public static LogicResult<T> Ok(T result);
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## IAuthLogic
|
|
||||||
This service handles all logic needed to provide the authentication endpoints by using the LogicResults.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public interface IAuthLogic {
|
|
||||||
Task<LogicResult<SingleValueResult<string>>> Login(UserLogin login);
|
|
||||||
|
|
||||||
Task<LogicResult<SingleValueResult<string>>> Register(UserRegister register);
|
|
||||||
|
|
||||||
Task<LogicResult<SingleValueResult<string>>> Authenticate();
|
|
||||||
|
|
||||||
Task<LogicResult> Logout();
|
|
||||||
|
|
||||||
Task<LogicResult> Delete(UserPasswordValidation validation);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
|
|
||||||
<PackageId>HopFrame.Database</PackageId>
|
<PackageId>HopFrame.Database</PackageId>
|
||||||
<Version>1.1.0</Version>
|
<Version>2.0.0</Version>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
# HopFrame Database module
|
# HopFrame Database module
|
||||||
This module contains all the logic for the database communication
|
This module contains all the logic for the database communication.
|
||||||
|
|
||||||
|
For more information about the HopFrame visit the [docs](https://git.leon-hoppe.de/leon.hoppe/HopFrame).
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<RootNamespace>HopFrame.Security</RootNamespace>
|
<RootNamespace>HopFrame.Security</RootNamespace>
|
||||||
|
|
||||||
<PackageId>HopFrame.Security</PackageId>
|
<PackageId>HopFrame.Security</PackageId>
|
||||||
<Version>1.1.0</Version>
|
<Version>2.0.0</Version>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
|
|||||||
@@ -1,74 +1,4 @@
|
|||||||
# HopFrame Security module
|
# HopFrame Security module
|
||||||
this module contains all handlers for the login and register validation. It also checks the user permissions.
|
this module contains all handlers for the login and register validation. It also checks the user permissions.
|
||||||
|
|
||||||
# Services added in this module
|
For more information about the HopFrame visit the [docs](https://git.leon-hoppe.de/leon.hoppe/HopFrame).
|
||||||
You can use these services by specifying them as a dependency. All of them are scoped dependencies.
|
|
||||||
|
|
||||||
## ITokenContext
|
|
||||||
This service provides the information given by the current request
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public interface ITokenContext {
|
|
||||||
bool IsAuthenticated { get; }
|
|
||||||
|
|
||||||
User User { get; }
|
|
||||||
|
|
||||||
Guid AccessToken { get; }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## IUserService
|
|
||||||
This service simplifies the data access of the user table in the database.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public interface IUserService {
|
|
||||||
Task<IList<User>> GetUsers();
|
|
||||||
|
|
||||||
Task<User> GetUser(Guid userId);
|
|
||||||
|
|
||||||
Task<User> GetUserByEmail(string email);
|
|
||||||
|
|
||||||
Task<User> GetUserByUsername(string username);
|
|
||||||
|
|
||||||
Task<User> AddUser(UserRegister user);
|
|
||||||
|
|
||||||
Task UpdateUser(User user);
|
|
||||||
|
|
||||||
Task DeleteUser(User user);
|
|
||||||
|
|
||||||
Task<bool> CheckUserPassword(User user, string password);
|
|
||||||
|
|
||||||
Task ChangePassword(User user, string password);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## IPermissionService
|
|
||||||
This service handles all permission and group interactions with the data source.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public interface IPermissionService {
|
|
||||||
Task<bool> HasPermission(string permission, Guid user);
|
|
||||||
|
|
||||||
Task<IList<PermissionGroup>> GetPermissionGroups();
|
|
||||||
|
|
||||||
Task<PermissionGroup> GetPermissionGroup(string name);
|
|
||||||
|
|
||||||
Task EditPermissionGroup(PermissionGroup group);
|
|
||||||
|
|
||||||
Task<IList<PermissionGroup>> GetUserPermissionGroups(User user);
|
|
||||||
|
|
||||||
Task RemoveGroupFromUser(User user, PermissionGroup group);
|
|
||||||
|
|
||||||
Task<PermissionGroup> CreatePermissionGroup(string name, bool isDefault = false, string description = null);
|
|
||||||
|
|
||||||
Task DeletePermissionGroup(PermissionGroup group);
|
|
||||||
|
|
||||||
Task<Permission> GetPermission(string name, IPermissionOwner owner);
|
|
||||||
|
|
||||||
Task AddPermission(IPermissionOwner owner, string permission);
|
|
||||||
|
|
||||||
Task RemovePermission(Permission permission);
|
|
||||||
|
|
||||||
Task<string[]> GetFullPermissions(string user);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -78,11 +78,11 @@ public interface IAdminPageGenerator<TModel> {
|
|||||||
IAdminPageGenerator<TModel> DefaultSort<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression, ListSortDirection direction);
|
IAdminPageGenerator<TModel> DefaultSort<TProperty>(Expression<Func<TModel, TProperty>> propertyExpression, ListSortDirection direction);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the repository for the page
|
/// Specifies the repository provider for the page
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TRepository">The specified repository</typeparam>
|
/// <typeparam name="TRepository">The specified provider</typeparam>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
IAdminPageGenerator<TModel> ConfigureRepository<TRepository>() where TRepository : ModelRepository<TModel>;
|
IAdminPageGenerator<TModel> ConfigureProvider<TRepository>() where TRepository : ModelProvider<TModel>;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ internal sealed class AdminPageGenerator<TModel> : IAdminPageGenerator<TModel>,
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAdminPageGenerator<TModel> ConfigureRepository<TRepository>() where TRepository : ModelRepository<TModel> {
|
public IAdminPageGenerator<TModel> ConfigureProvider<TRepository>() where TRepository : ModelProvider<TModel> {
|
||||||
Page.RepositoryProvider = typeof(TRepository);
|
Page.RepositoryProvider = typeof(TRepository);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,20 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
|
|
||||||
|
<PackageId>HopFrame.Web.Admin</PackageId>
|
||||||
|
<Version>2.0.0</Version>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="README.md" Pack="true" PackagePath="\"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace HopFrame.Web.Admin;
|
namespace HopFrame.Web.Admin;
|
||||||
|
|
||||||
public abstract class ModelRepository<TModel> : IModelRepository {
|
public abstract class ModelProvider<TModel> : IModelProvider {
|
||||||
public abstract Task<IEnumerable<TModel>> ReadAll();
|
public abstract Task<IEnumerable<TModel>> ReadAll();
|
||||||
public abstract Task<TModel> Create(TModel model);
|
public abstract Task<TModel> Create(TModel model);
|
||||||
public abstract Task<TModel> Update(TModel model);
|
public abstract Task<TModel> Update(TModel model);
|
||||||
@@ -25,7 +25,7 @@ public abstract class ModelRepository<TModel> : IModelRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IModelRepository {
|
public interface IModelProvider {
|
||||||
Task<IEnumerable<object>> ReadAllO();
|
Task<IEnumerable<object>> ReadAllO();
|
||||||
Task<object> CreateO(object model);
|
Task<object> CreateO(object model);
|
||||||
Task<object> UpdateO(object model);
|
Task<object> UpdateO(object model);
|
||||||
@@ -24,10 +24,12 @@ public class AdminPage {
|
|||||||
public bool ShowDeleteButton { get; set; } = true;
|
public bool ShowDeleteButton { get; set; } = true;
|
||||||
public bool ShowUpdateButton { get; set; } = true;
|
public bool ShowUpdateButton { get; set; } = true;
|
||||||
|
|
||||||
public IModelRepository LoadModelRepository(IServiceProvider provider) {
|
public IModelProvider LoadModelProvider(IServiceProvider provider) {
|
||||||
if (RepositoryProvider is null) return null;
|
if (RepositoryProvider is null) return null;
|
||||||
|
var repoProvider = provider.GetService(RepositoryProvider);
|
||||||
|
if (repoProvider != null) return repoProvider as IModelProvider;
|
||||||
|
|
||||||
var dependencies = AdminContextGenerator.ResolveDependencies(RepositoryProvider, provider);
|
var dependencies = AdminContextGenerator.ResolveDependencies(RepositoryProvider, provider);
|
||||||
return Activator.CreateInstance(RepositoryProvider, dependencies) as IModelRepository;
|
return Activator.CreateInstance(RepositoryProvider, dependencies) as IModelProvider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/HopFrame.Web.Admin/README.md
Normal file
4
src/HopFrame.Web.Admin/README.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# HopFrame admin pages module
|
||||||
|
This module contains all necessary information to create and compile the generated admin pages.
|
||||||
|
|
||||||
|
For more information about the HopFrame visit the [docs](https://git.leon-hoppe.de/leon.hoppe/HopFrame).
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
private Dictionary<AdminPageProperty, FieldIdentifier> _validationIdentifiers;
|
private Dictionary<AdminPageProperty, FieldIdentifier> _validationIdentifiers;
|
||||||
private IDictionary<AdminPageProperty, object> _values;
|
private IDictionary<AdminPageProperty, object> _values;
|
||||||
private Dictionary<AdminPageProperty, object[]> _selectorValues;
|
private Dictionary<AdminPageProperty, object[]> _selectorValues;
|
||||||
private IModelRepository _repository;
|
private IModelProvider _provider;
|
||||||
|
|
||||||
private AdminPage _currentPage;
|
private AdminPage _currentPage;
|
||||||
private object _entry;
|
private object _entry;
|
||||||
@@ -143,7 +143,7 @@
|
|||||||
_currentPage = page;
|
_currentPage = page;
|
||||||
_entry = entryToEdit;
|
_entry = entryToEdit;
|
||||||
_isEdit = entryToEdit is not null;
|
_isEdit = entryToEdit is not null;
|
||||||
_repository = _currentPage.LoadModelRepository(Provider);
|
_provider = _currentPage.LoadModelProvider(Provider);
|
||||||
|
|
||||||
_entry ??= Activator.CreateInstance(_currentPage.ModelType);
|
_entry ??= Activator.CreateInstance(_currentPage.ModelType);
|
||||||
_context = new EditContext(_entry);
|
_context = new EditContext(_entry);
|
||||||
@@ -246,7 +246,7 @@
|
|||||||
foreach (var value in _values) {
|
foreach (var value in _values) {
|
||||||
if (value.Key.Unique) {
|
if (value.Key.Unique) {
|
||||||
if (value.Value == value.Key.GetValue(_entry)) continue;
|
if (value.Value == value.Key.GetValue(_entry)) continue;
|
||||||
var data = _repository!.ReadAllO().GetAwaiter().GetResult();
|
var data = _provider!.ReadAllO().GetAwaiter().GetResult();
|
||||||
foreach (var entry in data) {
|
foreach (var entry in data) {
|
||||||
var other = value.Key.GetValue(entry);
|
var other = value.Key.GetValue(entry);
|
||||||
if (!other.Equals(value.Value)) continue;
|
if (!other.Equals(value.Value)) continue;
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
throw new ArgumentException($"'{property.Name}' cannot be a selector because a admin page for '{type.Name}' does not exist!");
|
throw new ArgumentException($"'{property.Name}' cannot be a selector because a admin page for '{type.Name}' does not exist!");
|
||||||
}
|
}
|
||||||
|
|
||||||
var repo = page.LoadModelRepository(Provider);
|
var repo = page.LoadModelProvider(Provider);
|
||||||
var objects = (await repo!.ReadAllO()).ToArray();
|
var objects = (await repo!.ReadAllO()).ToArray();
|
||||||
_selectorValues[property] = objects;
|
_selectorValues[property] = objects;
|
||||||
|
|
||||||
@@ -346,7 +346,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!_isEdit) {
|
if (!_isEdit) {
|
||||||
await _repository.CreateO(_entry);
|
await _provider.CreateO(_entry);
|
||||||
|
|
||||||
Alerts.FireAsync(new SweetAlertOptions {
|
Alerts.FireAsync(new SweetAlertOptions {
|
||||||
Title = "New entry added!",
|
Title = "New entry added!",
|
||||||
@@ -356,7 +356,7 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await _repository.UpdateO(_entry);
|
await _provider.UpdateO(_entry);
|
||||||
|
|
||||||
Alerts.FireAsync(new SweetAlertOptions {
|
Alerts.FireAsync(new SweetAlertOptions {
|
||||||
Title = "Entry updated!",
|
Title = "Entry updated!",
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using HopFrame.Web.Admin;
|
|||||||
using HopFrame.Web.Admin.Attributes;
|
using HopFrame.Web.Admin.Attributes;
|
||||||
using HopFrame.Web.Admin.Generators;
|
using HopFrame.Web.Admin.Generators;
|
||||||
using HopFrame.Web.Admin.Models;
|
using HopFrame.Web.Admin.Models;
|
||||||
using HopFrame.Web.Repositories;
|
using HopFrame.Web.Provider;
|
||||||
|
|
||||||
namespace HopFrame.Web;
|
namespace HopFrame.Web;
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ internal class HopAdminContext : AdminPagesContext {
|
|||||||
public override void OnModelCreating(IAdminContextGenerator generator) {
|
public override void OnModelCreating(IAdminContextGenerator generator) {
|
||||||
generator.Page<User>()
|
generator.Page<User>()
|
||||||
.Description("On this page you can manage all user accounts.")
|
.Description("On this page you can manage all user accounts.")
|
||||||
.ConfigureRepository<UserProvider>()
|
.ConfigureProvider<UserProvider>()
|
||||||
.ViewPermission(AdminPermissions.ViewUsers)
|
.ViewPermission(AdminPermissions.ViewUsers)
|
||||||
.CreatePermission(AdminPermissions.AddUser)
|
.CreatePermission(AdminPermissions.AddUser)
|
||||||
.UpdatePermission(AdminPermissions.EditUser)
|
.UpdatePermission(AdminPermissions.EditUser)
|
||||||
@@ -63,7 +63,7 @@ internal class HopAdminContext : AdminPagesContext {
|
|||||||
|
|
||||||
generator.Page<PermissionGroup>()
|
generator.Page<PermissionGroup>()
|
||||||
.Description("On this page you can view, create, edit and delete permission groups.")
|
.Description("On this page you can view, create, edit and delete permission groups.")
|
||||||
.ConfigureRepository<GroupProvider>()
|
.ConfigureProvider<GroupProvider>()
|
||||||
.ViewPermission(AdminPermissions.ViewGroups)
|
.ViewPermission(AdminPermissions.ViewGroups)
|
||||||
.CreatePermission(AdminPermissions.AddGroup)
|
.CreatePermission(AdminPermissions.AddGroup)
|
||||||
.UpdatePermission(AdminPermissions.EditGroup)
|
.UpdatePermission(AdminPermissions.EditGroup)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
||||||
|
|
||||||
<PackageId>HopFrame.Web</PackageId>
|
<PackageId>HopFrame.Web</PackageId>
|
||||||
<Version>1.1.0</Version>
|
<Version>2.0.0</Version>
|
||||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
|
|||||||
@@ -113,7 +113,7 @@
|
|||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
|
|
||||||
private AdminPage _pageData;
|
private AdminPage _pageData;
|
||||||
private IModelRepository _modelRepository;
|
private IModelProvider _modelProvider;
|
||||||
private IEnumerable<object> _modelBuffer;
|
private IEnumerable<object> _modelBuffer;
|
||||||
private AdminPageModal _modal;
|
private AdminPageModal _modal;
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
|
|
||||||
if (_pageData.RepositoryProvider is null)
|
if (_pageData.RepositoryProvider is null)
|
||||||
throw new ArgumentException($"AdminPage '{_pageData.Title}' does not specify a model repository!'");
|
throw new ArgumentException($"AdminPage '{_pageData.Title}' does not specify a model repository!'");
|
||||||
_modelRepository = _pageData.LoadModelRepository(Provider);
|
_modelProvider = _pageData.LoadModelProvider(Provider);
|
||||||
|
|
||||||
_hasEditPermission = _pageData.Permissions.Update is null || await Permissions.HasPermission(Auth.User, _pageData.Permissions.Update);
|
_hasEditPermission = _pageData.Permissions.Update is null || await Permissions.HasPermission(Auth.User, _pageData.Permissions.Update);
|
||||||
_hasDeletePermission = _pageData.Permissions.Delete is null || await Permissions.HasPermission(Auth.User, _pageData.Permissions.Delete);
|
_hasDeletePermission = _pageData.Permissions.Delete is null || await Permissions.HasPermission(Auth.User, _pageData.Permissions.Delete);
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task Reload() {
|
private async Task Reload() {
|
||||||
_modelBuffer = await _modelRepository.ReadAllO();
|
_modelBuffer = await _modelProvider.ReadAllO();
|
||||||
_displayedModels = _modelBuffer.ToList();
|
_displayedModels = _modelBuffer.ToList();
|
||||||
|
|
||||||
_currentSortDirection = _pageData.DefaultSortDirection;
|
_currentSortDirection = _pageData.DefaultSortDirection;
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (result.IsConfirmed) {
|
if (result.IsConfirmed) {
|
||||||
await _modelRepository.DeleteO(entry);
|
await _modelProvider.DeleteO(entry);
|
||||||
await Reload();
|
await Reload();
|
||||||
|
|
||||||
await Alerts.FireAsync(new SweetAlertOptions {
|
await Alerts.FireAsync(new SweetAlertOptions {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ using HopFrame.Database.Models;
|
|||||||
using HopFrame.Database.Repositories;
|
using HopFrame.Database.Repositories;
|
||||||
using HopFrame.Web.Admin;
|
using HopFrame.Web.Admin;
|
||||||
|
|
||||||
namespace HopFrame.Web.Repositories;
|
namespace HopFrame.Web.Provider;
|
||||||
|
|
||||||
internal sealed class GroupProvider(IGroupRepository repo) : ModelRepository<PermissionGroup> {
|
internal sealed class GroupProvider(IGroupRepository repo) : ModelProvider<PermissionGroup> {
|
||||||
public override async Task<IEnumerable<PermissionGroup>> ReadAll() {
|
public override async Task<IEnumerable<PermissionGroup>> ReadAll() {
|
||||||
return await repo.GetPermissionGroups();
|
return await repo.GetPermissionGroups();
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,9 @@ using HopFrame.Database.Models;
|
|||||||
using HopFrame.Database.Repositories;
|
using HopFrame.Database.Repositories;
|
||||||
using HopFrame.Web.Admin;
|
using HopFrame.Web.Admin;
|
||||||
|
|
||||||
namespace HopFrame.Web.Repositories;
|
namespace HopFrame.Web.Provider;
|
||||||
|
|
||||||
internal sealed class UserProvider(IUserRepository repo) : ModelRepository<User> {
|
internal sealed class UserProvider(IUserRepository repo) : ModelProvider<User> {
|
||||||
public override async Task<IEnumerable<User>> ReadAll() {
|
public override async Task<IEnumerable<User>> ReadAll() {
|
||||||
return await repo.GetUsers();
|
return await repo.GetUsers();
|
||||||
}
|
}
|
||||||
@@ -1,60 +1,4 @@
|
|||||||
# HopFrame Web module
|
# HopFrame Web module
|
||||||
This module contains useful helpers for Blazor Apps and an Admin Dashboard.
|
This module contains useful helpers for Blazor Apps and an Admin Dashboard.
|
||||||
|
|
||||||
## How to use the Blazor API
|
For more information about the HopFrame visit the [docs](https://git.leon-hoppe.de/leon.hoppe/HopFrame).
|
||||||
|
|
||||||
1. Add the HopFrame.Web library to your project
|
|
||||||
|
|
||||||
```
|
|
||||||
dotnet add package HopFrame.Web
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Create a DbContext that inherits the ``HopDbContext`` and add a data source
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public class DatabaseContext : HopDbContextBase {
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
|
|
||||||
base.OnConfiguring(optionsBuilder);
|
|
||||||
|
|
||||||
optionsBuilder.UseSqlite("...");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Add the DbContext and HopFrame to your services
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
builder.Services.AddDbContext<DatabaseContext>();
|
|
||||||
builder.Services.AddHopFrame<DatabaseContext>();
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Add the authentication middleware to your app
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
app.UseMiddleware<AuthMiddleware>();
|
|
||||||
```
|
|
||||||
|
|
||||||
5. Add the HopFrame pages to your Razor components
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
app.MapRazorComponents<App>()
|
|
||||||
.AddHopFrameAdminPages()
|
|
||||||
.AddInteractiveServerRenderMode();
|
|
||||||
```
|
|
||||||
|
|
||||||
# Services added in this module
|
|
||||||
You can use these services by specifying them as a dependency. All of them are scoped dependencies.
|
|
||||||
|
|
||||||
## IAuthService
|
|
||||||
This service handles all the authentication like login or register. It properly creates all tokens so the user can be identified
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
public interface IAuthService {
|
|
||||||
Task Register(UserRegister register);
|
|
||||||
Task<bool> Login(UserLogin login);
|
|
||||||
Task Logout();
|
|
||||||
|
|
||||||
Task<TokenEntry> RefreshLogin();
|
|
||||||
Task<bool> IsLoggedIn();
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ public class AdminContext : AdminPagesContext {
|
|||||||
.Parser<Employee>((model, e) => model.AddressId = e.EmployeeId);
|
.Parser<Employee>((model, e) => model.AddressId = e.EmployeeId);
|
||||||
|
|
||||||
generator.Page<Employee>()
|
generator.Page<Employee>()
|
||||||
.ConfigureRepository<EmployeeProvider>()
|
.ConfigureProvider<EmployeeProvider>()
|
||||||
.ListingProperty(e => e.Name);
|
.ListingProperty(e => e.Name);
|
||||||
|
|
||||||
generator.Page<Address>()
|
generator.Page<Address>()
|
||||||
.ConfigureRepository<AddressProvider>()
|
.ConfigureProvider<AddressProvider>()
|
||||||
.ListingProperty(a => a.City);
|
.ListingProperty(a => a.City);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ using RestApiTest.Models;
|
|||||||
|
|
||||||
namespace FrontendTest.Providers;
|
namespace FrontendTest.Providers;
|
||||||
|
|
||||||
public class AddressProvider(DatabaseContext context) : ModelRepository<Address> {
|
public class AddressProvider(DatabaseContext context) : ModelProvider<Address> {
|
||||||
|
|
||||||
public override async Task<IEnumerable<Address>> ReadAll() {
|
public override async Task<IEnumerable<Address>> ReadAll() {
|
||||||
return await context.Addresses.ToArrayAsync();
|
return await context.Addresses.ToArrayAsync();
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using RestApiTest.Models;
|
|||||||
|
|
||||||
namespace FrontendTest.Providers;
|
namespace FrontendTest.Providers;
|
||||||
|
|
||||||
public class EmployeeProvider(DatabaseContext context) : ModelRepository<Employee> {
|
public class EmployeeProvider(DatabaseContext context) : ModelProvider<Employee> {
|
||||||
|
|
||||||
public override async Task<IEnumerable<Employee>> ReadAll() {
|
public override async Task<IEnumerable<Employee>> ReadAll() {
|
||||||
return await context.Employees
|
return await context.Employees
|
||||||
|
|||||||
Reference in New Issue
Block a user