Merge branch 'feature/documentation' into 'dev'
Resolve "Documentation" Closes #18 See merge request leon.hoppe/HopFrame!10
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
@startuml ApiModels
|
||||
|
||||
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
|
||||
@@ -1,37 +0,0 @@
|
||||
@startuml BaseModels
|
||||
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
|
||||
@@ -1,38 +0,0 @@
|
||||
@startuml DatabaseModels
|
||||
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
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 12 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 13 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,13 +0,0 @@
|
||||
# HopFrame documentation
|
||||
These sides contain all documentation available for the HopFrame modules
|
||||
|
||||
## Content
|
||||
| Topic | Description | Document |
|
||||
|----------|------------------------------------------------|-----------------------|
|
||||
| Models | All models used by the HopFrame | [link](./models.md) |
|
||||
| Services | All services provided by the HopFrame | [link](./services.md) |
|
||||
| Usage | How to properly implement the HopFrame modules | [link](./usage.md) |
|
||||
|
||||
## Dependencies
|
||||
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.
|
||||
30
docs/api/authorization.md
Normal file
30
docs/api/authorization.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# HopFrame Authentication
|
||||
|
||||
With the provided HopFrame services, you can secure your endpoints so that only logged-in users or users with the right permissions can access the endpoint.
|
||||
|
||||
## Usage
|
||||
You can secure your endpoints by adding the `Authorized` attribute.
|
||||
|
||||
```csharp
|
||||
// Everyone can access this endpoint
|
||||
[HttpGet("hello")]
|
||||
public ActionResult<string> HelloWorld() {
|
||||
return "Hello, World!";
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Only logged-in users can access this endpoint
|
||||
[HttpGet("hello"), Authorized]
|
||||
public ActionResult<string> HelloWorld() {
|
||||
return "Hello, World!";
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Only logged-in users with the specified permissions can access this endpoint
|
||||
[HttpGet("hello"), Authorized("test.permission", "test.permission.another")]
|
||||
public ActionResult<string> HelloWorld() {
|
||||
return "Hello, World!";
|
||||
}
|
||||
```
|
||||
21
docs/api/endpoints.md
Normal file
21
docs/api/endpoints.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# HopFrame Endpoints
|
||||
HopFrame currently only supports endpoints for authentication out of the box.
|
||||
|
||||
> **Hint:** with the help of the [repositories](../repositories.md) you can very easily create missing endpoints for HopFrame components yourself.
|
||||
|
||||
## All currently supported endpoints
|
||||
|
||||
> **Hint:** you can use the build-in [swagger](https://swagger.io/) ui to explore and test all endpoints of your application __including__ HopFrame endpoints.
|
||||
|
||||
### SecurityController
|
||||
Base endpoint: `/api/v1/authentication`\
|
||||
**Important:** All primitive data types (including `string`) are return as a [`SingleValueResult`](./models.md#SingleValueResult)
|
||||
|
||||
|
||||
| Method | Endpoint | Payload | Returns |
|
||||
|--------|---------------|--------------------------------------------------------------|-----------------------|
|
||||
| PUT | /login | [UserLogin](../models.md#UserLogin) | access token (string) |
|
||||
| POST | /register | [UserRegister](../models.md#UserRegister) | access token (string) |
|
||||
| GET | /authenticate | | access token (string) |
|
||||
| DELETE | /logout | | |
|
||||
| DELETE | /delete | [UserPasswordValidation](./models.md#UserPasswordValidation) | |
|
||||
16
docs/api/installation.md
Normal file
16
docs/api/installation.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Ho to use the Web API version
|
||||
This Installation adds all HopFrame [endpoints](./endpoints.md) and [repositories](../repositories.md) to the application.
|
||||
|
||||
1. Add the HopFrame.Api library to your project:
|
||||
|
||||
```
|
||||
dotnet add package HopFrame.Api
|
||||
```
|
||||
|
||||
2. Create a [DbContext](../database.md) that inherits the ``HopDbContext`` and add a data source
|
||||
|
||||
3. Add the HopFrame services to your application, provide the previously created `DatabaseContext` that inherits from `HopDbContextBase`
|
||||
|
||||
```csharp
|
||||
builder.Services.AddHopFrame<DatabaseContext>();
|
||||
```
|
||||
33
docs/api/logicresults.md
Normal file
33
docs/api/logicresults.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# LogicResults
|
||||
LogicResults provide another layer of abstraction above the ActionResults.
|
||||
They help you sending the right `HttpStatusCode` with the right data.
|
||||
|
||||
## Usage
|
||||
1. Create an endpoint that returns an `ActionResult`:
|
||||
|
||||
```csharp
|
||||
[HttpGet("hello")]
|
||||
public ActionResult<string> Hello() {
|
||||
return new ActionResult<string>("Hello, World!");
|
||||
}
|
||||
```
|
||||
2. Now instead of directly returning the `ActionResult`, return a `LogicResult`
|
||||
|
||||
```csharp
|
||||
[HttpGet("hello")]
|
||||
public ActionResult<string> Hello() {
|
||||
return LogicResult<string>.Ok("Hello, World!");
|
||||
}
|
||||
```
|
||||
3. This allows you to very easily change the return type by simply calling the right function
|
||||
|
||||
```csharp
|
||||
[HttpGet("hello")]
|
||||
public ActionResult<string> Hello() {
|
||||
if (!Auth.IsLoggedIn)
|
||||
return LogicResult<string>.Forbidden();
|
||||
|
||||
return LogicResult<string>.Ok("Hello, World!");
|
||||
}
|
||||
```
|
||||
> **Hint:** You can also provide an error message for status codes that are not in the 200 range.
|
||||
16
docs/api/models.md
Normal file
16
docs/api/models.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# HopFrame Models
|
||||
All models used by the RestAPI are listed below
|
||||
|
||||
## SingleValueResult
|
||||
```csharp
|
||||
public struct SingleValueResult<TValue>(TValue value) {
|
||||
public TValue Value { get; set; } = value;
|
||||
}
|
||||
```
|
||||
|
||||
## UserPasswordValidation
|
||||
```csharp
|
||||
public sealed class UserPasswordValidation {
|
||||
public string Password { get; set; }
|
||||
}
|
||||
```
|
||||
133
docs/blazor/admin.md
Normal file
133
docs/blazor/admin.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# HopFrame Admin Pages
|
||||
Admin pages can be defined through a `AdminContext` similar to how a `DbContext` is defined. They generate administration pages like [`/administration/users`](./pages.md)
|
||||
simply by reading the structure of the provided model and optionally some additional configuration.
|
||||
|
||||
> **Fun fact:** The already existing pages `/administration/users` and `/administration/groups` are also generated using an internal `AdminContext`.
|
||||
|
||||
## Usage
|
||||
1. Create a class that inherits the `AdminPagesContext` base class
|
||||
|
||||
```csharp
|
||||
public class AdminContext : AdminPagesContext {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
2. Add your admin pages as properties to the class
|
||||
|
||||
```csharp
|
||||
public class AdminContext : AdminPagesContext {
|
||||
|
||||
public AdminPage<Address> Addresses { get; set; }
|
||||
|
||||
public AdminPage<Employee> Employees { get; set; }
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
3. **Optionally** you can further configure your pages in the `OnModelCreating` method
|
||||
|
||||
```csharp
|
||||
public class AdminContext : AdminPagesContext {
|
||||
|
||||
public AdminPage<Address> Addresses { get; set; }
|
||||
public AdminPage<Employee> Employees { get; set; }
|
||||
|
||||
public override void OnModelCreating(IAdminContextGenerator generator) {
|
||||
base.OnModelCreating(generator);
|
||||
|
||||
generator.Page<Employee>()
|
||||
.Property(e => e.Address)
|
||||
.IsSelector();
|
||||
|
||||
generator.Page<Address>()
|
||||
.Property(a => a.Employee)
|
||||
.Ignore();
|
||||
|
||||
generator.Page<Address>()
|
||||
.Property(a => a.AddressId)
|
||||
.IsSelector<Employee>()
|
||||
.Parser<Employee>((model, e) => model.AddressId = e.EmployeeId);
|
||||
|
||||
generator.Page<Employee>()
|
||||
.ConfigureRepository<EmployeeProvider>()
|
||||
.ListingProperty(e => e.Name);
|
||||
|
||||
generator.Page<Address>()
|
||||
.ConfigureRepository<AddressProvider>()
|
||||
.ListingProperty(a => a.City);
|
||||
}
|
||||
}
|
||||
```
|
||||
4. **Optionally** you can also add some of the following attributes to your classes / properties to further configure the admin pages:\
|
||||
\
|
||||
Attributes for classes:
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class AdminButtonConfigAttribute(bool showCreateButton = true, bool showDeleteButton = true, bool showUpdateButton = true) : Attribute {
|
||||
public bool ShowCreateButton { get; set; } = showCreateButton;
|
||||
public bool ShowDeleteButton { get; set; } = showDeleteButton;
|
||||
public bool ShowUpdateButton { get; set; } = showUpdateButton;
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class AdminPermissionsAttribute(string view = null, string create = null, string update = null, string delete = null) : Attribute {
|
||||
public AdminPagePermissions Permissions { get; set; } = new() {
|
||||
Create = create,
|
||||
Update = update,
|
||||
Delete = delete,
|
||||
View = view
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class AdminUrlAttribute(string url) : Attribute {
|
||||
public string Url { get; set; } = url;
|
||||
}
|
||||
```
|
||||
|
||||
Attributes for properties:
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class AdminHideValueAttribute : Attribute;
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class AdminIgnoreAttribute(bool onlyForListing = false) : Attribute {
|
||||
public bool OnlyForListing { get; set; } = onlyForListing;
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class AdminPrefixAttribute(string prefix) : Attribute {
|
||||
public string Prefix { get; set; } = prefix;
|
||||
}
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class AdminUneditableAttribute : Attribute;
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class AdminUniqueAttribute : Attribute;
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class AdminUnsortableAttribute : Attribute;
|
||||
```
|
||||
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class ListingPropertyAttribute : Attribute;
|
||||
```
|
||||
20
docs/blazor/auth.md
Normal file
20
docs/blazor/auth.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Auth Service
|
||||
The `IAuthService` provides some useful methods to handle user authentication (login/register).
|
||||
|
||||
## Usage
|
||||
Simply define the `IAuthService` as a dependency
|
||||
|
||||
```csharp
|
||||
public interface IAuthService {
|
||||
Task Register(UserRegister register);
|
||||
Task<bool> Login(UserLogin login);
|
||||
Task Logout();
|
||||
|
||||
Task<Token> RefreshLogin();
|
||||
Task<bool> IsLoggedIn();
|
||||
}
|
||||
```
|
||||
## Automatically refresh user sessions
|
||||
1. Make sure you have implemented the `AuthMiddleware` how it's described in step 5 of the [installation](./installation.md).
|
||||
|
||||
2. After that, the access token of the user gets automatically refreshed as long as the refresh token is valid.
|
||||
20
docs/blazor/authorization.md
Normal file
20
docs/blazor/authorization.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# HopFrame Authentication
|
||||
|
||||
With the provided HopFrame services, you can secure your blazor pages so that only logged-in users or users with the right permissions can access the page.
|
||||
|
||||
## Usage
|
||||
You can secure your Blazor pages by using the `AuthorizedView` component.
|
||||
Everything placed inside this component will only be displayed if the authorization was successful.
|
||||
You can also redirect the user if the authorization fails by specifying a `RedirectIfUnauthorized` url.
|
||||
|
||||
```html
|
||||
<!-- You can either specify one 'Permission', multiple 'Permissions' or none if the user only needs to be logged-in -->
|
||||
<AuthorizedView Permission="test.permission">
|
||||
<p>This paragraph is only visible if the user is logged-in and has the required permission</p>
|
||||
</AuthorizedView>
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- This component will redirect the user to the login page if the user is unauthorized -->
|
||||
<AuthorizedView RedirectIfUnauthorized="/login" />
|
||||
```
|
||||
36
docs/blazor/installation.md
Normal file
36
docs/blazor/installation.md
Normal file
@@ -0,0 +1,36 @@
|
||||
## How to use the Blazor API
|
||||
This Installation adds all HopFrame [pages](./pages.md) and [repositories](../repositories.md) to the application.
|
||||
|
||||
1. Add the HopFrame.Web library to your project
|
||||
|
||||
```
|
||||
dotnet add package HopFrame.Web
|
||||
```
|
||||
|
||||
2. Create a [DbContext](../database.md) that inherits the ``HopDbContext`` and add a data source
|
||||
|
||||
3. Add the HopFrame services to your application, provide the previously created `DatabaseContext` that inherits from `HopDbContextBase`
|
||||
|
||||
```csharp
|
||||
builder.Services.AddHopFrame<DatabaseContext>();
|
||||
```
|
||||
|
||||
4. **Optional:** You can also add your [AdminContext](./admin.md)
|
||||
|
||||
```csharp
|
||||
builder.Services.AddAdminContext<AdminContext>();
|
||||
```
|
||||
|
||||
5. Add the authentication middleware to your app
|
||||
|
||||
```csharp
|
||||
app.UseMiddleware<AuthMiddleware>();
|
||||
```
|
||||
|
||||
6. Add the HopFrame pages to your Razor components
|
||||
|
||||
```csharp
|
||||
app.MapRazorComponents<App>()
|
||||
.AddHopFrameAdminPages()
|
||||
.AddInteractiveServerRenderMode();
|
||||
```
|
||||
14
docs/blazor/pages.md
Normal file
14
docs/blazor/pages.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# HopFrame Pages
|
||||
By default, the HopFrame provides some blazor pages for managing user accounts and permissions
|
||||
|
||||
## All currently supported blazor pages
|
||||
|
||||
| Page | Endpoint | Permission | Usage |
|
||||
|-----------------|------------------------|----------------------------|--------------------------------------------------------------------------------------------------------|
|
||||
| Admin Dashboard | /administration | hopframe.admin | This page provides an overview to all admin pages built-in and created by [AdminContexts](./admin.md). |
|
||||
| Admin Login | /administration/login | | This page is a simple login screen so no login screen needs to be created to access the admin pages. |
|
||||
| User Dashboard | /administration/users | hopframe.admin.users.view | This page serves as a management site for all users and their permissions. |
|
||||
| Group Dashboard | /administration/groups | hopframe.admin.groups.view | This page serves as a management site for all groups and their permissions. |
|
||||
|
||||
> **Hint:** All pages created by [AdminContexts](./admin.md) are also under the `/administration/` location. This can unfortunately __not__ be changed at the moment.
|
||||
|
||||
35
docs/database.md
Normal file
35
docs/database.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Database initialization
|
||||
You also need to initialize the data source with the tables from HopFrame.
|
||||
|
||||
## Create a DbContext
|
||||
|
||||
1. Create a c# class that inherits from the `HopDbContextBase` and add a data source (In the example Sqlite is used)\
|
||||
**IMPORTANT:** You need to leave the `base.OnConfiguring(optionsBuilder)` in place so the HopFrame model relations are set correctly.
|
||||
|
||||
```csharp
|
||||
public class DatabaseContext : HopDbContextBase {
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
|
||||
optionsBuilder.UseSqlite("...");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Register the `DatabaseContext` as a service
|
||||
|
||||
```csharp
|
||||
builder.Services.AddDbContext<DatabaseContext>();
|
||||
```
|
||||
|
||||
3. Create a database migration
|
||||
|
||||
```bash
|
||||
dotnet ef migrations add Initial
|
||||
```
|
||||
|
||||
4. Apply the migration to the data source
|
||||
|
||||
```bash
|
||||
dotnet ef database update
|
||||
```
|
||||
@@ -1,21 +1,71 @@
|
||||
# Models for HopFrame
|
||||
# HopFrame base models
|
||||
All models listed below are part of the core HopFrame components and accessible in all installation variations
|
||||
|
||||
This page shows all models that HopFrame uses.
|
||||
> **Note:** All properties of the models that are `virtual` are relational properties and don't directly correspond to columns in the database.
|
||||
|
||||
## User
|
||||
```csharp
|
||||
public class User : IPermissionOwner {
|
||||
public Guid Id { get; init; }
|
||||
public string Username { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public virtual List<Permission> Permissions { get; set; }
|
||||
public virtual List<Token> Tokens { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
## Base Models
|
||||
These are the models used by the various database services.
|
||||
## PermissionGroup
|
||||
```csharp
|
||||
public class PermissionGroup : IPermissionOwner {
|
||||
public string Name { get; init; }
|
||||
public bool IsDefaultGroup { get; set; }
|
||||
public string Description { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public virtual List<Permission> Permissions { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
## Permission
|
||||
```csharp
|
||||
public class Permission {
|
||||
public long Id { get; init; }
|
||||
public string PermissionName { get; set; }
|
||||
public DateTime GrantedAt { get; set; }
|
||||
public virtual User User { get; set; }
|
||||
public virtual PermissionGroup Group { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
## Token
|
||||
```csharp
|
||||
public class Token {
|
||||
public int Type { get; set; }
|
||||
public Guid Content { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public virtual User Owner { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
## API Models
|
||||
These are the models used by the REST API and the Blazor API.
|
||||
## UserLogin
|
||||
```csharp
|
||||
public class UserLogin {
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
## UserRegister
|
||||
```csharp
|
||||
public class UserRegister {
|
||||
public string Username { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Database Models
|
||||
These are the models that correspond to the scheme in the Database
|
||||
|
||||

|
||||
## IPermissionOwner
|
||||
```csharp
|
||||
public interface IPermissionOwner;
|
||||
```
|
||||
|
||||
25
docs/readme.md
Normal file
25
docs/readme.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# HopFrame Documentation
|
||||
|
||||
The HopFrame comes in two variations, you can eiter only use the backend with some basic endpoints or with fully fledged blazor pages for managing HopFrame components.
|
||||
|
||||
## Shared HopFrame Modules
|
||||
|
||||
- [Database](./database.md)
|
||||
- [Repositories](./repositories.md)
|
||||
- [Base Models](./models.md)
|
||||
|
||||
## HopFrame Web API
|
||||
|
||||
- [Installation](./api/installation.md)
|
||||
- [Endpoints](./api/endpoints.md)
|
||||
- [Authorization](./api/authorization.md)
|
||||
- [Models](./api/models.md)
|
||||
- [LogicResults](./api/logicresults.md)
|
||||
|
||||
## HopFrame Blazor library
|
||||
|
||||
- [Installation](./blazor/installation.md)
|
||||
- [Pages](./blazor/pages.md)
|
||||
- [Authorization](./blazor/authorization.md)
|
||||
- [Auth Service](./blazor/auth.md)
|
||||
- [Admin Context](./blazor/admin.md)
|
||||
75
docs/repositories.md
Normal file
75
docs/repositories.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# HopFrame Repositories
|
||||
The HopFrame provies repositories for the various build in database models as an abstraction around the `HopDbContext` to ensure, that the data is proccessed and saved correctly.
|
||||
|
||||
## Overview
|
||||
The repositories can also be used by simply defining them as a dependency in your service / controller.
|
||||
|
||||
### User Repository
|
||||
|
||||
```csharp
|
||||
public interface IUserRepository {
|
||||
Task<IList<User>> GetUsers();
|
||||
|
||||
Task<User> GetUser(Guid userId);
|
||||
|
||||
Task<User> GetUserByEmail(string email);
|
||||
|
||||
Task<User> GetUserByUsername(string username);
|
||||
|
||||
Task<User> AddUser(User user);
|
||||
|
||||
Task UpdateUser(User user);
|
||||
|
||||
Task DeleteUser(User user);
|
||||
|
||||
Task<bool> CheckUserPassword(User user, string password);
|
||||
|
||||
Task ChangePassword(User user, string password);
|
||||
}
|
||||
```
|
||||
|
||||
### Group Repository
|
||||
|
||||
```csharp
|
||||
public interface IGroupRepository {
|
||||
Task<IList<PermissionGroup>> GetPermissionGroups();
|
||||
|
||||
Task<IList<PermissionGroup>> GetDefaultGroups();
|
||||
|
||||
Task<IList<PermissionGroup>> GetUserGroups(User user);
|
||||
|
||||
Task<PermissionGroup> GetPermissionGroup(string name);
|
||||
|
||||
Task EditPermissionGroup(PermissionGroup group);
|
||||
|
||||
Task<PermissionGroup> CreatePermissionGroup(PermissionGroup group);
|
||||
|
||||
Task DeletePermissionGroup(PermissionGroup group);
|
||||
}
|
||||
```
|
||||
|
||||
### Permission Repository
|
||||
|
||||
```csharp
|
||||
public interface IPermissionRepository {
|
||||
Task<bool> HasPermission(IPermissionOwner owner, params string[] permissions);
|
||||
|
||||
Task<Permission> AddPermission(IPermissionOwner owner, string permission);
|
||||
|
||||
Task RemovePermission(IPermissionOwner owner, string permission);
|
||||
|
||||
Task<IList<string>> GetFullPermissions(IPermissionOwner owner);
|
||||
}
|
||||
```
|
||||
|
||||
### Token Repository
|
||||
|
||||
```csharp
|
||||
public interface ITokenRepository {
|
||||
Task<Token> GetToken(string content);
|
||||
|
||||
Task<Token> CreateToken(int type, User owner);
|
||||
|
||||
Task DeleteUserTokens(User owner);
|
||||
}
|
||||
```
|
||||
145
docs/services.md
145
docs/services.md
@@ -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();
|
||||
}
|
||||
```
|
||||
@@ -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();
|
||||
```
|
||||
@@ -8,9 +8,18 @@ public interface IAuthLogic {
|
||||
|
||||
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> 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);
|
||||
}
|
||||
@@ -1,5 +1,10 @@
|
||||
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 TValue Value { get; set; } = value;
|
||||
|
||||
|
||||
@@ -19,5 +19,5 @@ public interface IPermissionRepository {
|
||||
|
||||
Task RemovePermission(IPermissionOwner owner, string permission);
|
||||
|
||||
public Task<IList<string>> GetFullPermissions(IPermissionOwner owner);
|
||||
Task<IList<string>> GetFullPermissions(IPermissionOwner owner);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using HopFrame.Database.Models;
|
||||
namespace HopFrame.Database.Repositories;
|
||||
|
||||
public interface ITokenRepository {
|
||||
public Task<Token> GetToken(string content);
|
||||
public Task<Token> CreateToken(int type, User owner);
|
||||
public Task DeleteUserTokens(User owner);
|
||||
Task<Token> GetToken(string content);
|
||||
Task<Token> CreateToken(int type, User owner);
|
||||
Task DeleteUserTokens(User owner);
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace HopFrame.Web.Admin.Models;
|
||||
|
||||
public sealed class AdminPageProperty {
|
||||
|
||||
@@ -7,6 +7,9 @@ using Microsoft.AspNetCore.Http;
|
||||
|
||||
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 async Task InvokeAsync(HttpContext context, RequestDelegate next) {
|
||||
var loggedIn = await auth.IsLoggedIn();
|
||||
@@ -14,7 +17,7 @@ public sealed class AuthMiddleware(IAuthService auth, IPermissionRepository perm
|
||||
if (!loggedIn) {
|
||||
var token = await auth.RefreshLogin();
|
||||
if (token is null) {
|
||||
await next.Invoke(context);
|
||||
next?.Invoke(context);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ using HopFrame.Web.Repositories;
|
||||
|
||||
namespace HopFrame.Web;
|
||||
|
||||
public class HopAdminContext : AdminPagesContext {
|
||||
internal class HopAdminContext : AdminPagesContext {
|
||||
|
||||
public AdminPage<User> Users { get; set; }
|
||||
public AdminPage<PermissionGroup> Groups { get; set; }
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
@using BlazorStrap
|
||||
@using HopFrame.Web.Pages.Administration.Layout
|
||||
@using BlazorStrap.V5
|
||||
@using HopFrame.Security
|
||||
@using HopFrame.Web.Admin.Providers
|
||||
@using HopFrame.Web.Components
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@layout AdminLayout
|
||||
|
||||
<AuthorizedView Permission="@AdminPermissions.IsAdmin" RedirectIfUnauthorized="/administration/login" />
|
||||
|
||||
<PageTitle>Admin Dashboard</PageTitle>
|
||||
|
||||
<BSContainer>
|
||||
|
||||
@@ -30,13 +30,12 @@
|
||||
}
|
||||
</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
|
||||
</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"/>
|
||||
</BSButton>
|
||||
<BSTooltip Placement="Placement.Bottom" Target="logout" ContentAlwaysRendered="false">logout</BSTooltip>
|
||||
</Content>
|
||||
</BSCollapse>
|
||||
</BSContainer>
|
||||
|
||||
Reference in New Issue
Block a user