Added inline documentation + fixed small bugs

This commit is contained in:
2024-11-21 16:15:18 +01:00
parent 6d2f7051ee
commit 986c5cebde
13 changed files with 37 additions and 359 deletions

View File

@@ -1,13 +1,10 @@
# HopFrame documentation # HopFrame Documentation
These sides contain all documentation available for the HopFrame modules
## Content - [x] In code documentation
| Topic | Description | Document | - [ ] Installation
|----------|------------------------------------------------|-----------------------| - [ ] Database usage
| Models | All models used by the HopFrame | [link](./models.md) | - [ ] Authentication usage
| Services | All services provided by the HopFrame | [link](./services.md) | - [ ] LogicResult usage
| Usage | How to properly implement the HopFrame modules | [link](./usage.md) | - [ ] Repositories usage
- [ ] AuthService usage
## Dependencies - [ ] AdminPages usage
Both the HopFrame.Api and HopFrame.Web modules are dependent on the HopFrame.Database and HopFrame.Security modules.
So all models and services provided by these modules are available in the other modules as well.

View File

@@ -1,121 +0,0 @@
# Models for HopFrame
This page shows all models that HopFrame uses.
## Base Models
These are the models used by the various database services.
```plantuml
@startuml
set namespaceSeparator none
namespace HopFrame.Database {
class User {
+Id: Guid
+Username: string
+Email: string
+CreatedAt: DateTime
+Permissions: IList<Permission>
}
class Permission {
+Id: long
+PermissionName: string
+Owner: Guid
+GrantedAt: DateTime
}
class PermissionGroup {
+Name: string
+IsDefaultGroup: bool
+Description: string
+CreatedAt: DateTime
+Permissions: IList<Permission>
}
interface IPermissionOwner {}
}
IPermissionOwner <|-- User
IPermissionOwner <|-- PermissionGroup
User .. Permission
PermissionGroup .. Permission
@enduml
```
## API Models
These are the models used by the REST API and the Blazor API.
```plantuml
@startuml
namespace HopFrame.Security {
class UserLogin {
+Email: string
+Password: string
}
class UserRegister {
+Username: string
+Email: string
+Password: string
}
}
namespace HopFrame.Api {
class SingleValueResult<TValue> {
+Value: TValue
}
class UserPasswordValidation {
+Password: string
}
}
@enduml
```
## Database Models
These are the models that correspond to the scheme in the Database
```plantuml
@startuml
set namespaceSeparator none
namespace HopFrame.Database {
class UserEntry {
+Id: string
+Username: string
+Email: string
+Password: string
+CreatedAt: DateTime
}
class TokenEntry {
+Type: int
+Token: string
+UserId: string
+CreatedAt: DateTime
}
class PermissionEntry {
+RecordId: long
+PermissionText: string
+UserId: string
+GrantedAt: DateTime
}
class GroupEntry {
+Name: string
+Default: bool
+Description: string
+CreatedAt: DateTime
}
}
UserEntry *-- TokenEntry
UserEntry *-- PermissionEntry
@enduml
```

View File

@@ -1,145 +0,0 @@
# HopFrame Services
This page describes all services provided by the HopFrame.
You can use these services by specifying them as a dependency. All of them are scoped dependencies.
## HopFrame.Security
### 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);
}
```
## HopFrame.Api
### 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);
}
```
## HopFrame.Web
### 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();
}
```

View File

@@ -1,70 +0,0 @@
# HopFrame Usage
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
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>();
```
## How to use the Blazor API
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();
```

View File

@@ -8,9 +8,18 @@ public interface IAuthLogic {
Task<LogicResult<SingleValueResult<string>>> Register(UserRegister register); Task<LogicResult<SingleValueResult<string>>> Register(UserRegister register);
/// <summary>
/// Reassures that the user has a valid refresh token and generates a new access token
/// </summary>
/// <returns>The newly generated access token</returns>
Task<LogicResult<SingleValueResult<string>>> Authenticate(); Task<LogicResult<SingleValueResult<string>>> Authenticate();
Task<LogicResult> Logout(); Task<LogicResult> Logout();
/// <summary>
/// Deletes the user account that called the endpoint if the provided password is correct
/// </summary>
/// <param name="validation">The password od the user</param>
/// <returns></returns>
Task<LogicResult> Delete(UserPasswordValidation validation); Task<LogicResult> Delete(UserPasswordValidation validation);
} }

View File

@@ -1,5 +1,10 @@
namespace HopFrame.Api.Models; namespace HopFrame.Api.Models;
/// <summary>
/// Useful for endpoints that only return a single int or string
/// </summary>
/// <param name="value">The value of the result</param>
/// <typeparam name="TValue">The type of the result</typeparam>
public struct SingleValueResult<TValue>(TValue value) { public struct SingleValueResult<TValue>(TValue value) {
public TValue Value { get; set; } = value; public TValue Value { get; set; } = value;

View File

@@ -19,5 +19,5 @@ public interface IPermissionRepository {
Task RemovePermission(IPermissionOwner owner, string permission); Task RemovePermission(IPermissionOwner owner, string permission);
public Task<IList<string>> GetFullPermissions(IPermissionOwner owner); Task<IList<string>> GetFullPermissions(IPermissionOwner owner);
} }

View File

@@ -3,7 +3,7 @@ using HopFrame.Database.Models;
namespace HopFrame.Database.Repositories; namespace HopFrame.Database.Repositories;
public interface ITokenRepository { public interface ITokenRepository {
public Task<Token> GetToken(string content); Task<Token> GetToken(string content);
public Task<Token> CreateToken(int type, User owner); Task<Token> CreateToken(int type, User owner);
public Task DeleteUserTokens(User owner); Task DeleteUserTokens(User owner);
} }

View File

@@ -1,5 +1,3 @@
using System.Text.Json.Serialization;
namespace HopFrame.Web.Admin.Models; namespace HopFrame.Web.Admin.Models;
public sealed class AdminPageProperty { public sealed class AdminPageProperty {

View File

@@ -7,6 +7,9 @@ using Microsoft.AspNetCore.Http;
namespace HopFrame.Web; namespace HopFrame.Web;
/// <summary>
/// Assures that the user stays logged in even if the access token is expired
/// </summary>
public sealed class AuthMiddleware(IAuthService auth, IPermissionRepository perms) : IMiddleware { public sealed class AuthMiddleware(IAuthService auth, IPermissionRepository perms) : IMiddleware {
public async Task InvokeAsync(HttpContext context, RequestDelegate next) { public async Task InvokeAsync(HttpContext context, RequestDelegate next) {
var loggedIn = await auth.IsLoggedIn(); var loggedIn = await auth.IsLoggedIn();
@@ -14,7 +17,7 @@ public sealed class AuthMiddleware(IAuthService auth, IPermissionRepository perm
if (!loggedIn) { if (!loggedIn) {
var token = await auth.RefreshLogin(); var token = await auth.RefreshLogin();
if (token is null) { if (token is null) {
await next.Invoke(context); next?.Invoke(context);
return; return;
} }

View File

@@ -8,7 +8,7 @@ using HopFrame.Web.Repositories;
namespace HopFrame.Web; namespace HopFrame.Web;
public class HopAdminContext : AdminPagesContext { internal class HopAdminContext : AdminPagesContext {
public AdminPage<User> Users { get; set; } public AdminPage<User> Users { get; set; }
public AdminPage<PermissionGroup> Groups { get; set; } public AdminPage<PermissionGroup> Groups { get; set; }

View File

@@ -5,11 +5,14 @@
@using BlazorStrap @using BlazorStrap
@using HopFrame.Web.Pages.Administration.Layout @using HopFrame.Web.Pages.Administration.Layout
@using BlazorStrap.V5 @using BlazorStrap.V5
@using HopFrame.Security
@using HopFrame.Web.Admin.Providers @using HopFrame.Web.Admin.Providers
@using HopFrame.Web.Components @using HopFrame.Web.Components
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@layout AdminLayout @layout AdminLayout
<AuthorizedView Permission="@AdminPermissions.IsAdmin" RedirectIfUnauthorized="/administration/login" />
<PageTitle>Admin Dashboard</PageTitle> <PageTitle>Admin Dashboard</PageTitle>
<BSContainer> <BSContainer>

View File

@@ -30,13 +30,12 @@
} }
</BSNav> </BSNav>
<span style="margin-left: auto; line-height: 100%; color: white"> <span style="margin-left: auto; line-height: 100%; color: white; margin-right: 10px">
logged in as @Context?.User.Username logged in as @Context?.User.Username
</span> </span>
<BSButton DataId="logout" Size="Size.ExtraSmall" OnClick="Logout" Color="BSColor.Dark"> <BSButton DataId="logout" Size="Size.ExtraSmall" OnClick="Logout" Color="BSColor.Dark" style="display: grid; align-items: center">
<HopIconDisplay Type="HopIconDisplay.HopIcon.Logout"/> <HopIconDisplay Type="HopIconDisplay.HopIcon.Logout"/>
</BSButton> </BSButton>
<BSTooltip Placement="Placement.Bottom" Target="logout" ContentAlwaysRendered="false">logout</BSTooltip>
</Content> </Content>
</BSCollapse> </BSCollapse>
</BSContainer> </BSContainer>