A RESTful back-end for DigiVault — a digital course marketplace where users can browse, purchase, and review courses, sellers can manage their own catalogue, and administrators can oversee users, orders, and platform operations.
Built with ASP.NET Core 9, following a vertical-slice architecture using the CQRS pattern (MediatR).
Try it live: https://digivaultapi.onrender.com/swagger
The API is hosted on Render's free tier — the first request after a period of inactivity may take up to 50 seconds to respond (cold start). Subsequent requests are fast.
- Features
- Tech Stack
- Project Structure
- API Endpoints
- Getting Started
- Database
- Authentication
- Seeded Data
- User registration and JWT-based authentication
- Course catalogue with search, category filter, price range, and multiple sort options
- Seller panel — create, update, and control visibility of courses
- Shopping cart and wishlist management
- Checkout flow with automatic commission calculation and balance crediting
- Course library (purchased courses)
- Rating and review system tied to course ownership
- Course reporting and notification system
- Admin panel — user management (activate/deactivate), course oversight, order reporting (in progress)
| Technology | Version |
|---|---|
| ASP.NET Core | 9.0 |
| Entity Framework Core | 9.0.1 |
| Npgsql EF Core Provider | 9.0.4 |
| PostgreSQL | 15+ |
| MediatR | 12.4.1 |
| FluentValidation | 11.3.0 |
| Mapster | 7.4.0 |
| BCrypt.Net-Next | 4.0.3 |
| Microsoft.AspNetCore.Authentication.JwtBearer | 9.0.1 |
| Swashbuckle (Swagger) | 7.2.0 |
The project follows a vertical-slice / feature-folder layout where all code related to a domain concept lives together.
DigiVaultAPI/
├── Behaviors/
│ └── ValidationBehavior.cs # MediatR pipeline — runs FluentValidation before handlers
├── Controllers/ # Thin controllers — delegate to MediatR
│ ├── AuthController.cs
│ ├── CoursesController.cs
│ ├── CategoriesController.cs
│ ├── CartController.cs
│ ├── WishlistController.cs
│ ├── OrdersController.cs
│ ├── ProfileController.cs
│ ├── SellerController.cs
│ ├── ReviewsController.cs
│ ├── ReportsController.cs
│ ├── NotificationsController.cs
│ └── AdminController.cs
├── Data/
│ ├── DigiVaultDbContext.cs # EF Core context with fluent configuration
│ └── DigiVaultSeeder.cs # Optional dev seed data
├── Exceptions/ # Domain exceptions (404, 401, 403, 409)
├── Features/ # Vertical slices
│ ├── Admin/
│ ├── Auth/
│ ├── Cart/
│ ├── Categories/
│ ├── Courses/
│ ├── Notifications/
│ ├── Orders/
│ ├── Profile/
│ ├── Reports/
│ ├── Review/
│ └── Wishlist/
│ ├── Handlers/ # MediatR request handlers
│ ├── Messages/ # Request/Response DTOs
│ ├── Providers/ # Read-side (queries)
│ ├── Services/ # Write-side (commands + business rules)
│ ├── Mapping/ # Mapster configuration
│ └── Validators/ # FluentValidation validators
├── Middleware/
│ └── ExceptionHandlerMiddleware.cs
├── Migrations/
├── Models/ # EF Core entities
│ ├── User.cs
│ ├── Course.cs
│ ├── Category.cs
│ ├── Order.cs / OrderItem.cs
│ ├── UserCourse.cs
│ ├── CartItem.cs
│ ├── WishlistItem.cs
│ ├── Review.cs
│ ├── Notification.cs
│ ├── CourseReport.cs
│ └── PlatformSettings.cs
├── appsettings.json
├── appsettings.Development.json.example
├── Dockerfile
└── Program.cs
Endpoints marked with 🔒 require a valid JWT Bearer token. Endpoints marked with 🛡️ additionally require the
Workerrole (admin).
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/auth/login |
— | Authenticate and receive a JWT token |
POST |
/api/auth/register |
— | Create a new user account |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/courses |
— | Paginated course catalogue (search, category, price range, sort) |
GET |
/api/courses/popular |
— | Top courses by sales count |
GET |
/api/courses/newest |
— | Most recently added courses |
GET |
/api/courses/top-rated |
— | Highest-rated courses |
GET |
/api/courses/{id} |
— | Course detail |
GET |
/api/courses/purchased |
🔒 | Courses owned by the authenticated user |
Query parameters for GET /api/courses:
search, categoryId, minPrice, maxPrice, sortBy (popular | newest | top-rated | price-asc | price-desc), page, pageSize
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/categories |
— | List all categories |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/cart |
🔒 | Get current user's cart |
POST |
/api/cart/{idCourse} |
🔒 | Add course to cart |
DELETE |
/api/cart/{idCourse} |
🔒 | Remove course from cart |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/wishlist |
🔒 | Get current user's wishlist |
POST |
/api/wishlist/{idCourse} |
🔒 | Add course to wishlist |
DELETE |
/api/wishlist/{idCourse} |
🔒 | Remove course from wishlist |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/orders |
🔒 | List orders for the authenticated user |
GET |
/api/orders/{idOrder} |
🔒 | Order detail |
POST |
/api/orders |
🔒 | Checkout — creates an order from the cart |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/profile |
🔒 | Get profile data |
PATCH |
/api/profile/name |
🔒 | Update display name |
PATCH |
/api/profile/email |
🔒 | Update email (requires current password) |
PATCH |
/api/profile/password |
🔒 | Change password (requires current password) |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/seller/courses |
🔒 | List courses created by the authenticated seller |
POST |
/api/seller/courses |
🔒 | Create a new course |
PUT |
/api/seller/courses/{id} |
🔒 | Update a course |
PATCH |
/api/seller/courses/{id}/visibility |
🔒 | Toggle course visibility |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/courses/{idCourse}/reviews |
— | List reviews for a course |
POST |
/api/courses/{idCourse}/reviews |
🔒 | Add or update a review (must own the course) |
DELETE |
/api/courses/{idCourse}/reviews |
🔒 | Delete own review |
| Method | Path | Auth | Description |
|---|---|---|---|
POST |
/api/reports |
🔒 | Submit a course report |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/notifications |
🔒 | List notifications for the authenticated user |
PATCH |
/api/notifications/{idNotification} |
🔒 | Mark a notification as read |
| Method | Path | Auth | Description |
|---|---|---|---|
GET |
/api/admin/users |
🛡️ | List all users |
POST |
/api/admin/users/set-as-active |
🛡️ | Activate a user account |
POST |
/api/admin/users/set-as-not-active |
🛡️ | Deactivate a user account |
GET |
/api/admin/courses |
🛡️ | Full course catalogue including hidden courses |
GET |
/api/admin/orders |
🛡️ | Paginated order list with optional filters |
Copy the example configuration file and fill in your values:
cp DigiVaultAPI/appsettings.Development.json.example DigiVaultAPI/appsettings.Development.jsonappsettings.Development.json:
{
"Jwt": {
"Key": "YOUR_SECRET_KEY_MIN_32_CHARACTERS_LONG",
"Issuer": "DigiVaultAPI",
"Audience": "DigiVaultMobile",
"ExpiryMinutes": 60
},
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Port=5432;Database=DigiVaultDb;Username=YOUR_USER;Password=YOUR_PASSWORD"
}
}| Key | Description |
|---|---|
Jwt:Key |
HMAC-SHA256 secret — minimum 32 characters |
Jwt:Issuer |
Token issuer claim |
Jwt:Audience |
Token audience claim |
Jwt:ExpiryMinutes |
Token lifetime in minutes |
ConnectionStrings:DefaultConnection |
PostgreSQL connection string |
# 1. Clone the repository
git clone https://github.com/AIChelminska/DigiVaultAPI.git
cd DigiVaultAPI
# 2. Configure environment (see above)
cp DigiVaultAPI/appsettings.Development.json.example DigiVaultAPI/appsettings.Development.json
# Edit DigiVaultAPI/appsettings.Development.json with your values
# 3. Restore dependencies
dotnet restore
# 4. Run the application
dotnet run --project DigiVaultAPIThe API will be available at:
- HTTP:
http://localhost:5052 - HTTPS:
https://localhost:7084 - Swagger UI:
http://localhost:5052/swagger
The repository ships with a docker-compose.yml that starts both the API and a PostgreSQL database together.
# 1. Create your local env file from the template
cp .env.example .env
# Edit .env — fill in POSTGRES_PASSWORD and JWT_KEY at minimum
# 2. Start both services (API + PostgreSQL)
docker compose up --build
# 3. Stop and remove containers
docker compose downThe API will be available at http://localhost:8080 (configurable via API_HOST_PORT in .env).
The database is exposed on localhost:5433 by default (configurable via POSTGRES_HOST_PORT).
Migrations and seeding run automatically on API startup — no extra steps needed.
The application uses PostgreSQL with Entity Framework Core Code-First migrations.
Migrations run automatically on startup — no manual dotnet ef command is required. On first run the full schema is created from 20260309222115_InitialCreate.
Tables created by the migration:
| Table | Description |
|---|---|
Users |
User accounts with roles, balance, and active flag |
Courses |
Course listings with pricing, rating aggregates, and visibility |
Categories |
Course categories |
Orders / OrderItems |
Purchase records with price and commission snapshots |
UserCourses |
Many-to-many: users ↔ owned courses |
CartItems |
Per-user shopping cart |
WishlistItems |
Per-user wishlist |
Reviews |
Course reviews (one per user per course) |
Notifications |
User notifications |
CourseReports |
User-submitted course reports |
PlatformSettings |
Commission rate and platform balance |
To run migrations manually (if needed):
dotnet ef database update --project DigiVaultAPIThe API uses JWT Bearer tokens.
- Obtain a token via
POST /api/auth/loginorPOST /api/auth/register. - Include the token in the
Authorizationheader of subsequent requests:
Authorization: Bearer <your_token>
Token claims:
| Claim | Value |
|---|---|
IdUser |
User's database ID |
Login |
Username |
ClaimTypes.Role |
User or Worker |
FirstName / LastName |
Display name |
Roles:
| Role | Description |
|---|---|
User |
Standard authenticated user — can buy courses, review, manage cart, etc. |
Worker |
Administrator — has access to all User endpoints plus /api/admin/* |
Swagger UI includes an Authorize button for pasting a Bearer token directly — available both locally and at the live deployment.
On startup the DigiVaultSeeder populates an empty database with sample data so the API is fully explorable via Swagger or any HTTP client without any manual setup.
| Login | Password | Role | Notes |
|---|---|---|---|
test |
test |
User | Has balance, orders, and purchased courses |
test2 |
test |
User | |
test3 |
test |
User | |
test4 |
test |
User | |
test5 |
test |
User | |
admin |
admin |
Worker (Admin) | Full access to /api/admin/* endpoints |
- Platform settings (commission rate)
- Categories and a rich set of courses
- Cart items, wishlist items, orders, order items
- Reviews, notifications, and course reports
This project is open-source and available under the MIT License.