The project
JeBalance is a tax fraud reporting platform, built for an N-tier architecture course. Citizens file a report; the tax administration processes it through role-protected endpoints.
Features
- File a report — suspect identity, full address, offence type (tax evasion or income concealment) and the country involved.
- Look up a report — retrieve a report by its identifier.
- Administrative tracking — list of unanswered reports, restricted to accounts holding
the
adminFiscalerole. - Protected persons management — promote an individual to VIP status and back to standard, gated by an administrator token.
Architecture
The application follows a Domain Driven Design architecture on the ABP framework, split across three layers.
Web layer — HttpApi. The entry point for requests, and therefore where authentication is configured. JWT validation is declared here:
context.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.IssuerSigningKey)),
ValidateIssuer = true,
ValidIssuer = jwtSettings.Issuer,
ValidateAudience = true,
ValidAudience = jwtSettings.Audience,
ValidateLifetime = true,
};
});
Application layer — business logic. AppService interfaces, DTOs and models are
declared on the Application Contract side, implementations on the Application side.
A neat ABP trait: inheriting from ApplicationService generates REST controllers
automatically from method names, without writing a single controller.
public class DenonciationAppService : ApplicationService, IDenonciationAppService, ITransientDependency
Protecting an endpoint then comes down to one attribute:
[Authorize(Roles = "adminFiscale")]
Entity ↔ DTO mapping is delegated to AutoMapper, which needs no configuration as long as properties share the same names.
Domain and infrastructure layers. Entities inherit from Entity<Guid>, handing
indexing and unique keys to ABP. The DbContext, repositories and Entity Framework Core
migrations live in the EntityFrameworkCore project:
public interface IEfCoreDenonciationRepository : IRepository<Entities.Denonciation, Guid>
{
Task<Guid> RegisterDenonciationAsync(Entities.Denonciation denonciation);
Task<Entities.Denonciation> GetDenonciationAsync(Guid id);
Task<List<Entities.Denonciation>> ListDenonciationNonTraiteAsync();
}
Inheriting from IRepository<Entity, Guid> provides CRUD operations without rewriting them.
Outcome
All endpoints are functional and tested. Time ran short on the Blazor front end, however: report creation, the administrative response and the VIP status change are driven through the API rather than from the UI.