# Data Model This document describes the data model for the dalex-todo-proto application using Mermaid diagrams. ## Entity Relationship Diagram ```mermaid erDiagram USER ||--o{ TODO : owns USER { string id PK "Keycloak User ID" string username "From Keycloak" string email "From Keycloak" } TODO { int id PK "Auto-increment primary key" string userId FK "Reference to User (Keycloak ID)" string title "Todo title (required)" string description "Optional description" datetime createdAt "Creation timestamp" datetime completedAt "Completion timestamp (nullable)" boolean isCompleted "Completion status" } ``` ## Database Schema ```mermaid classDiagram class Todo { +int Id +string UserId +string Title +string Description +DateTime CreatedAt +DateTime CompletedAt +bool IsCompleted +GetAge() TimeSpan +IsOld() bool } class TodoDbContext { +DbSet~Todo~ Todos +OnModelCreating(ModelBuilder) } TodoDbContext --> Todo : manages ``` ## Data Flow Architecture ```mermaid flowchart TB subgraph Client ["Frontend (Vue 3)"] UI[User Interface] KC_CLIENT[Keycloak Client] API_CLIENT[API Client] end subgraph Keycloak ["Keycloak Server"] AUTH[Authentication] TOKEN[JWT Token Service] end subgraph Backend ["ASP.NET Core Backend"] JWT_VALIDATE[JWT Validation] API[REST API Endpoints] BL[Business Logic] end subgraph Database ["SQLite Database"] DB[(Todos Table)] end UI --> KC_CLIENT KC_CLIENT <--> AUTH AUTH --> TOKEN TOKEN --> API_CLIENT API_CLIENT --> JWT_VALIDATE JWT_VALIDATE --> API API --> BL BL <--> DB style Client fill:#e1f5ff style Keycloak fill:#fff4e1 style Backend fill:#e8f5e9 style Database fill:#f3e5f5 ``` ## Todo Entity Details ### Fields | Field | Type | Nullable | Description | |-------|------|----------|-------------| | `Id` | int | No | Primary key, auto-increment | | `UserId` | string | No | Keycloak user identifier (from JWT token) | | `Title` | string | No | Todo title/summary | | `Description` | string | Yes | Optional detailed description | | `CreatedAt` | DateTime | No | UTC timestamp when todo was created | | `CompletedAt` | DateTime | Yes | UTC timestamp when todo was marked complete | | `IsCompleted` | bool | No | Completion status flag | ### Indexes - **Primary Key**: `Id` - **Index**: `UserId` (for efficient user-specific queries) ### Constraints - `UserId` is required (enforced at database and application level) - `Title` is required (enforced at database and application level) - `CreatedAt` is automatically set on creation - `CompletedAt` is set when `IsCompleted` changes to `true` - `CompletedAt` is cleared when `IsCompleted` changes to `false` ## API Data Transfer Objects (DTOs) ```mermaid classDiagram class TodoCreateDto { +string Title +string Description } class TodoUpdateDto { +string Title +string Description +bool? IsCompleted } class Todo { +int Id +string UserId +string Title +string Description +DateTime CreatedAt +DateTime CompletedAt +bool IsCompleted } TodoCreateDto ..> Todo : creates TodoUpdateDto ..> Todo : updates ``` ## Business Rules ### Sorting Logic ```mermaid flowchart TD START[Get Todos for User] SPLIT{Group by Status} INCOMPLETE[Incomplete Todos] COMPLETE[Complete Todos] SORT_INC[Sort by CreatedAt ASC
Oldest first] SORT_COM[Sort by CompletedAt DESC
Newest first] FILTER{Show Older?} HIDE[Hide todos completed
> 1 week ago] SHOW[Show all] COMBINE[Combine Lists] RESULT[Return Sorted List] START --> SPLIT SPLIT --> INCOMPLETE SPLIT --> COMPLETE INCOMPLETE --> SORT_INC COMPLETE --> SORT_COM SORT_INC --> COMBINE SORT_COM --> FILTER FILTER -->|No| HIDE FILTER -->|Yes| SHOW HIDE --> COMBINE SHOW --> COMBINE COMBINE --> RESULT ``` ### User Isolation - Each user can only see their own todos - `UserId` is extracted from JWT token (Keycloak `sub` or `NameIdentifier` claim) - All queries are filtered by `UserId` - No cross-user data access is possible ## Storage ### SQLite Database - **File Location**: `/app/data/todos.db` (in Docker container) - **Persistence**: Docker volume `todolist-proto_backend-data` - **Schema Management**: Entity Framework Core with automatic migration on startup - **Connection String**: `Data Source=/app/data/todos.db` ### Table Structure ```sql CREATE TABLE "Todos" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Todos" PRIMARY KEY AUTOINCREMENT, "UserId" TEXT NOT NULL, "Title" TEXT NOT NULL, "Description" TEXT NULL, "CreatedAt" TEXT NOT NULL, "CompletedAt" TEXT NULL, "IsCompleted" INTEGER NOT NULL ); CREATE INDEX "IX_Todos_UserId" ON "Todos" ("UserId"); ``` ## Security Considerations 1. **Authentication**: All API endpoints require valid JWT token from Keycloak 2. **Authorization**: Users can only access their own todos (enforced by UserId filtering) 3. **Data Validation**: - Title is required - UserId is required - All inputs are validated before database operations 4. **SQL Injection**: Protected by Entity Framework Core parameterized queries 5. **CORS**: Restricted to frontend origin only (`http://localhost:3030`)