Files
2026-06-21 00:05:07 +03:30

123 lines
5.3 KiB
Markdown

# Balinyaar — Server (ASP.NET Core, Clean Architecture)
Backend API for the Balinyaar application. It is an **ASP.NET Core (.NET 10)** solution organized around **Clean Architecture**, with:
- **CQRS** via `martinothamar/Mediator` (source-generated; not MediatR)
- **ASP.NET Core Identity** with **JWE** (signed + encrypted JWT) and **OTP** authentication
- **Dynamic, permission-based authorization**
- **EF Core** persistence (SQL Server) with the Repository + Unit of Work patterns
- A modular **gRPC plugin** mounted via Application Parts
- Observability out of the box: Serilog, OpenTelemetry, Prometheus metrics, health checks
> Looking for an architecture/file map to navigate the code? See [CLAUDE.md](CLAUDE.md) (agent guide)
> and [CONVENTIONS.md](CONVENTIONS.md) (coding rules).
## Requirements
- [.NET 10 SDK](https://dotnet.microsoft.com/)
- SQL Server (local instance, or the containerized one from `docker-compose.yml`)
## Running locally
From the `server/` folder:
```bash
dotnet restore Baya.sln
dotnet build Baya.sln
dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj
```
By default the API listens on **https://localhost:5002** and serves Swagger UI at **/swagger**.
On startup the app **applies EF Core migrations** and **seeds default users** automatically, so a reachable database (see `appsettings.json``ConnectionStrings`) is required.
### Configuration
Settings live in `src/API/Baya.Web.Api/appsettings.json` (+ `appsettings.Development.json`):
- `ConnectionStrings:SqlServer` — main application database
- `ConnectionStrings:logDb` — Serilog SQL sink database
- `IdentitySettings``SecretKey` (signing), `Encryptkey` (AES-128 encryption, exactly 16 chars), `Issuer`, `Audience`, token lifetimes
## Running with Docker
Generate a development HTTPS certificate (used by the container):
```bash
dotnet dev-certs https -ep $env:USERPROFILE/.aspnet/https/baya.pfx -p Strong@Password
dotnet dev-certs https --trust
```
Build and start the API together with SQL Server 2022:
```bash
docker build -t bobby-baya -f Dockerfile .
docker-compose up -d
```
The compose stack exposes the API on `http://localhost:5000` / `https://localhost:5001` and SQL Server on `localhost:1435`.
## Solution layout
```
src/
├── Core/
│ ├── Baya.Domain Entities + domain primitives (the core / "brain")
│ └── Baya.Application CQRS features, contracts (interfaces), MediatR pipeline
├── Infrastructure/
│ ├── Baya.Infrastructure.Persistence EF Core DbContext, configs, repositories, UoW, migrations
│ ├── Baya.Infrastructure.Identity Identity, JWE/JWT, OTP, dynamic permissions
│ ├── Baya.Infrastructure.CrossCutting Cross-cutting concerns (logging)
│ └── Baya.Infrastructure.Monitoring Health checks, OpenTelemetry, Prometheus
├── API/
│ ├── Baya.Web.Api Presentation: REST controllers, Program.cs (startup)
│ ├── Baya.WebFramework Reusable web config: base controller, filters, middleware, Swagger
│ └── Plugins/Baya.Web.Plugins.Grpc Self-contained gRPC plugin
├── Shared/
│ └── Baya.SharedKernel Shared extensions/helpers referenced by every layer
└── Tests/ xUnit test setup + Identity tests
```
## The layers (why they exist)
### Domain
The core of the project. Each entity may carry its own behavior. Entities derive from a common `BaseEntity`, which lets the persistence layer discover models via reflection to register them and drive migrations.
### Application
Routes requests and defines the **contracts** (interfaces) the system depends on, without knowing their implementations. This is where **CQRS** lives: Commands and Queries are kept separate and dispatched to their handlers by **Mediator** (`martinothamar/Mediator`, source-generated). Cross-cutting concerns (validation, metrics) are applied as Mediator pipeline behaviors.
### Infrastructure
Implements the contracts the Application layer declares — the parts needed to run in the real world:
- **Persistence** — the chosen database (SQL Server via EF Core). Repositories give self-describing, persistence-agnostic data access; Unit of Work keeps multi-step writes atomic and consistent.
- **Identity** — registration, authentication and authorization using ASP.NET Core Identity, with JWE tokens, OTP login, and a dynamic access-control system.
- **CrossCutting** — services used across the whole app, such as logging.
- **Monitoring** — health checks, distributed tracing/metrics, and Prometheus.
### WebFramework
Keeps `Program.cs` thin by moving each piece of configuration into its own reusable class (filters, middleware, Swagger, API versioning, the base controller, etc.).
### Web.Api
The presentation layer — an ASP.NET Core Web API exposing versioned REST controllers under `Controllers/V1`.
### Web.Plugins.Grpc
A standalone module that adds gRPC endpoints to the same host via **Application Parts**, giving modularity (the "plugin" middle ground between a monolith and microservices) without a separate deployment. It registers its services and pipeline through extension methods called from `Program.cs`.
## Tests
```bash
dotnet test Baya.sln
```
Each layer is designed to be testable in isolation; `Baya.Tests.Setup` provides the shared test scaffolding.
## License
See [LICENSE.md](LICENSE.md).