The app is created with the aim to solve common problem when travelling in group and that is to calculate the expenses among its members and settle the depths created within the group.
Application consists of 2 independently functional parts: backend build on ASP.NET core and frontend build on Blazor WebAssembly.
There is also Entities project, which groups common data structures across the BE and FE (DTOs).
The backend is build on top of ASP.NET as API controllers. There are 3 contollers / main routes (auth, group, user)
Custom exception middleware is used, which will handle thrown exceptions and is used as flow controll (together with checks) in API routes. Custom HttpStatusException
is used to add error status code in the HTTP request (if exception thrown is not HttpStatusException
, then status code 500 is used instead). PostgreSQL is used as the database provider, however any EF Core supported database can be used after (possibly none/slight) modification.
JWT token authorization is used and authorized routes are stateless, consuming only the data from request (including the token), making the application effectively stateless. Currently, there is just a single user role used, however admin user role is ready for future extension.
Helpers are also used to separate repeating or important code.
Frontend is build as Blazor WebAssembly.
It highly uses component structure, with the aim to minimize code duplication.
Custom auth route handler has been build, which allows pages to be for authorized users only.
This is achieved by using @attribute [Authorize]
. Futher improvement is possible by utilizing user roles on the frontend side, disabling the user to use for example admin .
API services are used, which serve as both data stores and data getters. They also have OnChange event subscriber,
which enables changes subscription. Also provider alternatives are provided, which exposes data as cascading paramether
for seamless data pass with automatic OnChange update.
Needless to say, the frontend works only with this backend.
Firstly, BE needs appsettings.json
file to set variables. This file should be put in the root of WebApplication folder. Expected shape of the file is
{
"ConnectionStrings": {
"PostgreSql": "connection_string_here"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"JWT": {
"Secret": "your_secret_here"
}
}
Then Nuget package restore is needed. Then it can be run/build/published normally as any other ASP.NET application.
By modifying launchSettings.json
you can adjust the port, on which the application is running.
Only requirement for running frontend is doing Nuget package restore. Application can be run, debugged or published. Using dotnet publish --configuration Release
for publishing for public access
is recommended, because of IL trimming, which can reduce the size of the bundle. Content is placed under wwwroot
folder and is suitable for static file hosting with single page
application settings. Please note, that when published, by default the files produced are both compressed and uncompressed, potentionally saving network traffic of clients.
Basic usage of the application can be divided into several parts.
First part consist of basic user managment. User can log in, register and logout. This is done via login/register forms, when the user is not logged in and logout button, when the user is logged in. This can be further improved by adding user account managment, with the possibility of password/username change, etc.
Second part is the managing of user relationship with other users. User can send, reject and accept friend request. This module is prerequisite for the third module. When the user accepts the friend request, they become friends and this friend can be added to user group.
Third part is the user managment. Data are structured in 3 layers. First layer is SinglePurposeUserGroup
. It is a group, which stands for singe event (vacation, ...),
which sets the lifetime boundaries of the group. This group is named, contain the group members and collection of underlying payment structure. Second layer is
UnidirectionalPaymentGroup
, which stands for a single payment reason (payment for the gasoline...). This group is also named, contains the person, who paid the transaction and and the list of
payment targets (SinglePayment
). From this setup, group settlement can be
calculated as the list of transactions, which when executed, people will not owe money to the other group members.