A cloud-based file storage system built with .NET 9 and a microservices architecture. Users can upload, manage, and share files with fine-grained access control. The system is composed of three independent services orchestrated through an API Gateway.
Client
│
▼
┌─────────────────────┐
│ Ocelot API │ (Port 5000)
│ Gateway │ Routes all incoming requests
└──────┬──────┬───────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌────────────────┐ ┌──────────────┐
│ Auth │ │ FileMetadata │ │ FileStorage │
│ Service │ │ Service │ │ Service │
│ :5001 │ │ :5002 │ │ :5003 │
└──────────┘ └────────────────┘ └──────────────┘
SQLite PostgreSQL Local Disk
Each service is independently structured following Clean Architecture principles:
ServiceName/
├── ServiceName.API/ # HTTP endpoints, middleware
├── ServiceName.Application/ # Business logic, DTOs, interfaces
├── ServiceName.Core/ # Domain models, repository interfaces
└── ServiceName.Infrastructure/ # EF Core, database, migrations
Handles user registration, login, and JWT token validation.
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/register |
Register a new user | No |
| POST | /api/auth/login |
Login and receive a JWT token | No |
| POST | /api/auth/validate |
Validate a JWT token | No |
Features:
- Passwords are hashed with BCrypt
- Tokens are signed with HMAC-SHA256
- JWT tokens expire after 30 minutes
- Role-based claims (
User/Admin) embedded in token - Admin user is seeded automatically on startup via
DbSeeder - Uses SQLite as the database
Manages file metadata (name, description, owner, sharing rules) stored in PostgreSQL.
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/filemetadata/public |
List all public files | No |
| GET | /api/filemetadata/myfiles |
List authenticated user's own files | Yes |
| GET | /api/filemetadata/sharedwithme |
List files shared with the user | Yes |
| GET | /api/filemetadata/admin |
List all files (admin only) | Admin only |
| POST | /api/filemetadata |
Create new file metadata record | Yes |
| PUT | /api/filemetadata/{id} |
Update file metadata | Yes (owner/admin) |
| DELETE | /api/filemetadata/{id} |
Delete file metadata | Yes (owner/admin) |
Sharing Rules:
| Rule | Description |
|---|---|
Public |
Accessible by anyone, no authentication needed |
Private |
Visible only to the owner |
SharedWith |
Accessible by a specific list of user IDs |
Features:
- Uses AutoMapper to map between domain models and DTOs
- Custom JwtValidationMiddleware communicates with the Auth Service to validate every request
- Repository pattern with Entity Framework Core
- Permission checks ensure only owners or admins can modify/delete
Handles the physical storage of file binaries on the local disk.
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/filestorage/{id} |
Upload a file | Yes |
| GET | /api/filestorage/{id} |
Download a file | No |
| DELETE | /api/filestorage/{id} |
Delete a file | Yes |
Features:
- Files are stored locally in the
UploadedFiles/directory - File is saved using the metadata ID as the filename (extension preserved)
- Supports any file type (
application/octet-stream) - Same JWT middleware as FileMetadata for authentication
All client requests go through the Ocelot gateway, which routes them to the appropriate downstream service.
| Upstream (Client) | Downstream (Service) | Port |
|---|---|---|
/api/auth/{everything} |
/auth/{everything} |
5001 |
/api/filemetadata/{everything} |
/filemetadata/{everything} |
5002 |
/api/filestorage/{everything} |
/filestorage/{everything} |
5003 |
| Technology | Usage |
|---|---|
| .NET 9 | Core framework |
| ASP.NET Core Minimal APIs | HTTP endpoint definitions |
| Ocelot | API Gateway and request routing |
| Entity Framework Core 9 | ORM for database access |
| SQLite | Auth service database |
| PostgreSQL | FileMetadata service database |
| BCrypt.Net | Password hashing |
| JWT (System.IdentityModel.Tokens.Jwt) | Authentication tokens |
| AutoMapper | DTO ↔ Domain model mapping |
| Clean Architecture | Project structure pattern |
- .NET 9 SDK
- PostgreSQL (for FileMetadata service)
Authentication Service — src/Services/Authentication/Authentication.API/appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=app.db"
},
"Jwt": {
"Key": "your-secret-key-here",
"Issuer": "CloudFileStorage",
"Audience": "CloudFileStorageUsers"
}
}FileMetadata Service — src/Services/FileMetadata/FileMetadata.API/appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Host=localhost;Database=filemetadata_db;Username=postgres;Password=yourpassword"
}
}Start each service in a separate terminal:
# 1. Authentication Service (port 5001)
cd src/Services/Authentication/Authentication.API
dotnet run
# 2. FileMetadata Service (port 5002)
cd src/Services/FileMetadata/FileMetadata.API
dotnet run
# 3. FileStorage Service (port 5003)
cd src/Services/FileStorage/FileStorage.API
dotnet run
# 4. API Gateway (port 5000)
cd src/ApiGateways/Ocelot.ApiGateway
dotnet runApply database migrations for the FileMetadata service:
cd src/Services/FileMetadata/FileMetadata.Infrastructure
dotnet ef database update- Register —
POST /api/auth/registerwith{ username, email, password } - Login —
POST /api/auth/loginwith{ email, password }→ receive JWT token - Use Token — Include
Authorization: Bearer <token>header in all protected requests - Token Validation — FileMetadata and FileStorage services call the Auth Service internally to validate each token before processing requests
CloudFileStorage/
├── src/
│ ├── ApiGateways/
│ │ └── Ocelot.ApiGateway/ # Ocelot routing configuration
│ ├── Infrastructure/
│ │ └── EventBus.Messages/ # Shared message contracts
│ └── Services/
│ ├── Authentication/ # Auth microservice (4 layers)
│ ├── FileMetadata/ # File metadata microservice (4 layers)
│ └── FileStorage/ # File binary storage microservice (4 layers)
└── CloudFileStorage.sln
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.