Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
# Glense Environment Variables
# Copy this file to .env and fill in your values
# Usage: source .env before running services, or set in your shell profile
# Copy this file to .env and fill in your values.
# Usage: docker compose --env-file .env up

# ===================
# DonationService
# Shared Secrets
# ===================
# Neon PostgreSQL connection string
DONATION_DB_CONNECTION_STRING="Host=your-neon-host.neon.tech;Database=neondb;Username=your_user;Password=your_password;SslMode=Require"
JWT_SECRET_KEY=YourSuperSecretKeyThatIsAtLeast32CharactersLongForHS256Algorithm
JWT_ISSUER=GlenseAccountService
JWT_AUDIENCE=GlenseApp

# Inter-service API key (used for service-to-service authentication)
INTERNAL_API_KEY=GlenseInternalServiceKey_ChangeMe_AtLeast32Chars!

# ===================
# Database Credentials
# ===================
POSTGRES_USER=glense
POSTGRES_PASSWORD=changeme

# ===================
# AccountService
# RabbitMQ Credentials
# ===================
# PostgreSQL connection string
ACCOUNT_DB_CONNECTION_STRING="Host=postgres_account;Port=5432;Database=glense_account;Username=glense;Password=your_password"
RABBITMQ_USER=guest
RABBITMQ_PASS=guest

# JWT Configuration
JWT_SECRET_KEY="YourSecretKeyThatIsAtLeast32CharactersLong"
JWT_ISSUER="GlenseAccountService"
JWT_AUDIENCE="GlenseApp"
# ===================
# Connection Strings
# ===================
ACCOUNT_DB_CONNECTION_STRING=Host=postgres_account;Port=5432;Database=glense_account;Username=glense;Password=changeme
VIDEO_DB_CONNECTION_STRING=Host=postgres_video;Port=5432;Database=glense_video;Username=glense;Password=changeme
DONATION_DB_CONNECTION_STRING=Host=postgres_donation;Port=5432;Database=glense_donation;Username=glense;Password=changeme
CHAT_DB_CONNECTION_STRING=Host=postgres_chat;Port=5432;Database=glense_chat;Username=glense;Password=changeme
96 changes: 41 additions & 55 deletions DEV_QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,29 @@

## Prerequisites

- .NET 8 SDK
- .NET 8 SDK (for running services outside Docker)
- Node.js v22
- Docker Desktop **or** Podman
- Docker Desktop or Podman

## Start everything

### 1. Start databases + microservices
## Setup

```bash
# Docker Desktop (recommended):
docker compose up --build postgres_account postgres_donation account_service donation_service -d
# 1. Copy environment file
cp .env.example .env

# Or Podman:
podman machine start
# Copy the DOCKER_HOST export line from podman's output, then:
docker compose up --build postgres_account postgres_donation account_service donation_service -d
```
# 2. Start infrastructure + services
docker compose up --build -d

### 2. Start the API Gateway (new terminal)
# 3. Start frontend
cd glense.client && npm install && npm run dev

```bash
cd Glense.Server
dotnet run --urls http://localhost:5050
```

### 3. Start the frontend (new terminal)

```bash
cd glense.client
npm install
npm run dev
```

### 4. Seed test users (new terminal)

```bash
# 4. Seed test data
./scripts/seed.sh
```

Creates 3 users (password for all: `Password123!`):
## Test users

Password for all: `Password123!`

| Username | Email | Type | Wallet |
|----------|-------|------|--------|
Expand All @@ -53,57 +36,60 @@ Creates 3 users (password for all: `Password123!`):

| Service | Port | Notes |
|---------|------|-------|
| Frontend (Vite) | 5173+ | Opens next free port |
| Frontend (Vite) | 5173 | Opens next free port if taken |
| API Gateway | 5050 | All frontend requests go here |
| Account Service | 5001 | Auth, profiles, notifications |
| Account Service | 5001 (REST), 5003 (gRPC) | Auth, profiles, notifications |
| Video Catalogue | 5002 | Upload, comments, playlists |
| Donation Service | 5100 | Wallets, donations |
| Chat Service | 5004 | Rooms, messages, SignalR |
| RabbitMQ Management | 15672 | Default: guest/guest (override in .env) |
| PostgreSQL (Account) | 5432 | |
| PostgreSQL (Video) | 5433 | |
| PostgreSQL (Donation) | 5434 | |
| PostgreSQL (Chat) | 5435 | |

## Quick test with curl
## Quick test

```bash
# Health checks
curl http://localhost:5050/health
curl http://localhost:5001/health
curl http://localhost:5002/health
curl http://localhost:5100/health
curl http://localhost:5004/health

# Register a user
# Register
curl -X POST http://localhost:5050/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"test","email":"test@test.com","password":"Password123!","confirmPassword":"Password123!","accountType":"user"}'
-d '{"username":"test","email":"test@test.com","password":"Password123!"}'

# Login
curl -X POST http://localhost:5050/api/auth/login \
-H "Content-Type: application/json" \
-d '{"usernameOrEmail":"test","password":"Password123!"}'

# Search users
curl "http://localhost:5050/api/profile/search?q=keki"

# Check wallet (replace with real user ID from register/login response)
curl http://localhost:5050/api/wallet/user/USER_ID

# Send donation (replace IDs)
curl -X POST http://localhost:5050/api/donation \
-H "Content-Type: application/json" \
-d '{"donorUserId":"DONOR_ID","recipientUserId":"RECIPIENT_ID","amount":10,"message":"Nice!"}'
```
# Use the token from login response:
TOKEN="<paste token here>"

## Stop everything
# Profile
curl http://localhost:5050/api/profile/me -H "Authorization: Bearer $TOKEN"

```bash
docker compose down # stop containers
# Ctrl+C on gateway and frontend terminals
podman machine stop # if using podman
# Search users
curl "http://localhost:5050/api/profile/search?q=keki"
```

## Swagger docs

| Service | URL |
|---------|-----|
| Gateway | http://localhost:5050/swagger |
| Account Service | http://localhost:5001/swagger |
| Donation Service | http://localhost:5100 |
| Account | http://localhost:5001/swagger |
| Video Catalogue | http://localhost:5002/swagger |
| Chat Service | http://localhost:5004/swagger |
| Donation | http://localhost:5100 |
| Chat | http://localhost:5004/swagger |

## Stop

```bash
docker compose down # stop containers
docker compose down -v # stop + wipe database volumes
```
14 changes: 8 additions & 6 deletions Glense.Server/DonationService/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,15 @@
// Health check endpoint for container orchestration
builder.Services.AddHealthChecks();

// CORS policy - Allow frontend origins (both HTTP and HTTPS)
// Configure CORS — restrict to known frontend origins
var allowedOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>()
?? ["http://localhost:5173", "http://localhost:50653", "http://localhost:50654", "http://localhost:3000"];

builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
options.AddPolicy("AllowFrontend", policy =>
{
policy.SetIsOriginAllowed(_ => true) // Allow any origin in development
policy.WithOrigins(allowedOrigins)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
Expand All @@ -112,7 +115,7 @@
var app = builder.Build();

// CORS must be first middleware after exception handling
app.UseCors();
app.UseCors("AllowFrontend");

// Swagger UI available at root path for easy API exploration
if (app.Environment.IsDevelopment())
Expand All @@ -130,8 +133,7 @@
app.MapControllers();
app.MapHealthChecks("/health");

// Auto-create database schema in development
// In production, use proper migrations
// Auto-create database schema on startup
if (app.Environment.IsDevelopment())
{
using var scope = app.Services.CreateScope();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public AccountServiceClient(IHttpClientFactory httpClientFactory, ILogger<Accoun
{
_httpClient = httpClientFactory.CreateClient("AccountService");
_logger = logger;

var apiKey = Environment.GetEnvironmentVariable("INTERNAL_API_KEY");
if (!string.IsNullOrEmpty(apiKey))
{
_httpClient.DefaultRequestHeaders.Add("X-Internal-Api-Key", apiKey);
}
}

public async Task<string?> GetUsernameAsync(Guid userId)
Expand Down
Loading
Loading