todolist-proto/DATAMODEL.md

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

  • 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)

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
  • 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

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)