diff --git a/Dockerfile b/Dockerfile index 5158599..63cff85 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,12 @@ COPY Cargo.toml Cargo.lock ./ COPY crates/adapters/auth/Cargo.toml crates/adapters/auth/Cargo.toml COPY crates/adapters/event-payload/Cargo.toml crates/adapters/event-payload/Cargo.toml COPY crates/adapters/event-transport/Cargo.toml crates/adapters/event-transport/Cargo.toml +COPY crates/adapters/exif/Cargo.toml crates/adapters/exif/Cargo.toml COPY crates/adapters/nats/Cargo.toml crates/adapters/nats/Cargo.toml COPY crates/adapters/postgres/Cargo.toml crates/adapters/postgres/Cargo.toml +COPY crates/adapters/sidecar/Cargo.toml crates/adapters/sidecar/Cargo.toml COPY crates/adapters/storage/Cargo.toml crates/adapters/storage/Cargo.toml +COPY crates/adapters/thumbnail/Cargo.toml crates/adapters/thumbnail/Cargo.toml COPY crates/api-types/Cargo.toml crates/api-types/Cargo.toml COPY crates/application/Cargo.toml crates/application/Cargo.toml COPY crates/bootstrap/Cargo.toml crates/bootstrap/Cargo.toml diff --git a/README.md b/README.md index dbf7ddd..d9bb982 100644 --- a/README.md +++ b/README.md @@ -25,21 +25,22 @@ Infrastructure (Axum, Postgres, NATS, S3) | Context | Purpose | |---|---| -| **Identity** | Users, roles, RBAC permissions, groups | +| **Identity** | Users, roles, RBAC permissions, groups, refresh tokens | | **Storage** | Volumes, library paths, ingestion, quotas, BYOS | -| **Catalog** | Assets, metadata layers, stacks, derivatives, duplicates | +| **Catalog** | Assets, metadata layers, stacks, derivatives, duplicates, visibility filtering | | **Organization** | Albums, tags, collections (smart albums) | | **Sharing** | Share scopes, targets, links, invite codes, visibility filters | | **Sidecar** | XMP/JSON export, sync state, conflict resolution | -| **Processing** | Jobs, batches, plugins, pipelines | +| **Processing** | Jobs, batches, plugins, pipelines, directory scanner | ### Project Structure ``` crates/ domain/ pure Rust — entities, value objects, ports, services - common/ errors, events, value objects (SystemId, Checksum, etc.) - identity/ user, role, permission, group + common/ errors, events, value objects (SystemId, Checksum, Email, + Username, MimeType, RelativePath, etc.) + identity/ user, role, permission, group, refresh token storage/ volumes, library paths, ingestion, quotas catalog/ assets, metadata, stacks, derivatives, duplicates organization/ albums, tags, collections @@ -48,41 +49,85 @@ crates/ processing/ jobs, batches, plugins, pipelines application/ CQRS commands + queries with Arc injection - identity/commands/ RegisterUser, LoginUser + identity/commands/ RegisterUser, LoginUser, RefreshToken, Logout identity/queries/ GetProfile storage/commands/ RegisterVolume, RegisterLibraryPath, IngestAsset storage/queries/ CheckQuota - catalog/commands/ RegisterAsset, UpdateMetadata - catalog/queries/ GetTimeline, GetAsset + catalog/commands/ RegisterAsset, UpdateMetadata, CreateStack, DeleteStack, + DeleteAsset, DetectLivePhotos, ResolveDuplicate + catalog/queries/ GetTimeline, GetAsset, GetStack, ReadAssetFile, + ReadDerivative, SearchAssets organization/ CreateAlbum, ManageAlbumEntries, TagAsset, GetAlbum sharing/ ShareResource, GenerateShareLink, RevokeShare, AccessSharedResource sidecar/ ExportSidecar, DetectChanges, Import, ResolveConflict, FullExport/Import - processing/ EnqueueJob, StartJob, CompleteJob, FailJob, ManagePlugin, ConfigurePipeline - testing/ in-memory repo fakes + stub ports + processing/ EnqueueJob, StartJob, CompleteJob, FailJob, ExecutePipeline, + ManagePlugin, ConfigurePipeline, ListJobs, BatchProgress + testing/ in-memory repo fakes + stub ports (in_memory_repo! macro) api-types/ HTTP request/response DTOs with OpenAPI derives - adapters/ postgres, auth (bcrypt, JWT), object storage - presentation/ axum handlers, routes, extractors + adapters/ + auth/ bcrypt password hashing, JWT token issuer (configurable expiry) + postgres/ all repository implementations, event store, migrations + storage/ local filesystem + S3 (feature-gated) + exif/ EXIF metadata extraction + thumbnail/ derivative generation + sidecar/ XMP sidecar reader/writer + event-payload/ domain event serialization + event-transport/ composite publisher (NATS + event store) + nats/ NATS JetStream transport + presentation/ axum handlers, routes, extractors, middleware, parsers bootstrap/ config, DI wiring, entry point - worker/ background job runner + worker/ background job runner (NATS consumer) ``` +### Auth + +- JWT access tokens (1h expiry, configurable) +- Refresh token rotation (30d, SHA-256 hashed, stored in Postgres) +- `POST /auth/login` — returns access + refresh tokens +- `POST /auth/refresh` — rotates refresh token, issues new pair +- `POST /auth/logout` — revokes all refresh tokens for user +- `require_auth` middleware on all protected routes (defense in depth) +- Handlers still use `JwtClaims` extractor for user_id — middleware is the safety net +- Admin-only endpoints gated by role check (processing, storage, sidecar management) + +## Environment Variables + +| Variable | Required | Default | Description | +|---|---|---|---| +| `DATABASE_URL` | yes | — | Postgres connection string | +| `JWT_SECRET` | yes | — | HMAC secret for JWT signing | +| `NATS_URL` | no | `nats://localhost:4222` | NATS server URL | +| `STORAGE_PATH` | no | `./data/media` | Local file storage root | +| `HOST` | no | `0.0.0.0` | Bind address | +| `PORT` | no | `8000` | Bind port | +| `CORS_ALLOWED_ORIGINS` | no | — | Comma-separated origins | +| `RUST_LOG` | no | `info` | Log level filter | + ## Development ```bash # run tests (no DB required) -cargo test -p domain -p application +cargo test --workspace # format + lint cargo fmt --all -cargo clippy -p domain -p application +cargo clippy --workspace ``` -148 tests cover all domain entities, services, and application use cases. +206 tests cover domain entities, services, application use cases, and visibility filtering. -## Status +## Docker -Domain and application layers complete. Next: adapters (Postgres, NATS, filesystem) and presentation layer. +```bash +docker build -t k-photos . +docker run -e DATABASE_URL=... -e JWT_SECRET=... -e NATS_URL=... -p 8000:8000 k-photos +``` + +Worker (background jobs): +```bash +docker run -e DATABASE_URL=... -e NATS_URL=... k-photos ./k_photos-worker +``` ## License