5.6 KiB
5.6 KiB
Data Model
This document describes the data model for the dalex-todo-proto application using Mermaid diagrams.
Entity Relationship Diagram
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
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
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
UserIdis required (enforced at database and application level)Titleis required (enforced at database and application level)CreatedAtis automatically set on creationCompletedAtis set whenIsCompletedchanges totrueCompletedAtis cleared whenIsCompletedchanges tofalse
API Data Transfer Objects (DTOs)
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
flowchart TD
START[Get Todos for User]
SPLIT{Group by Status}
INCOMPLETE[Incomplete Todos]
COMPLETE[Complete Todos]
SORT_INC[Sort by CreatedAt ASC<br/>Oldest first]
SORT_COM[Sort by CompletedAt DESC<br/>Newest first]
FILTER{Show Older?}
HIDE[Hide todos completed<br/>> 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
UserIdis extracted from JWT token (KeycloaksuborNameIdentifierclaim)- 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
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
- Authentication: All API endpoints require valid JWT token from Keycloak
- Authorization: Users can only access their own todos (enforced by UserId filtering)
- Data Validation:
- Title is required
- UserId is required
- All inputs are validated before database operations
- SQL Injection: Protected by Entity Framework Core parameterized queries
- CORS: Restricted to frontend origin only (
http://localhost:3030)