52 lines
1.3 KiB
Plaintext
52 lines
1.3 KiB
Plaintext
@startuml
|
|
title Polling Architecture with Security
|
|
|
|
!define SECURITY_COLOR #FFE6E6
|
|
!define APP_COLOR #E6F3FF
|
|
!define DATA_COLOR #E6FFE6
|
|
|
|
rectangle "Event Happens" as Event APP_COLOR
|
|
rectangle "Sanitize & Rate Check" as Sanitize SECURITY_COLOR
|
|
database "notifications table" as DB DATA_COLOR
|
|
rectangle "REST API\n(session auth + rate limit)" as API SECURITY_COLOR
|
|
rectangle "Frontend Poller\n(30s interval)" as Frontend APP_COLOR
|
|
rectangle "Browser Notification\n(text-only)" as Browser SECURITY_COLOR
|
|
|
|
Event --> Sanitize : bleach.clean()
|
|
Sanitize --> DB : INSERT if under 100/min
|
|
Frontend --> API : GET /api/notifications/unread
|
|
API --> DB : SELECT WHERE user_id = ?
|
|
DB --> API : JSON array
|
|
API --> Frontend : sanitized text
|
|
Frontend --> Browser : plain text display
|
|
|
|
note right of Sanitize
|
|
Security Layer 1:
|
|
- Strip all HTML/JS
|
|
- Check user preferences
|
|
- Rate limit: 100/user/min
|
|
end note
|
|
|
|
note right of API
|
|
Security Layer 2:
|
|
- Session authentication
|
|
- Flask-Limiter: 120/min
|
|
- user_id filter in SQL
|
|
end note
|
|
|
|
note right of Browser
|
|
Security Layer 3:
|
|
- No HTML rendering
|
|
- User permission required
|
|
- Text-only display
|
|
end note
|
|
|
|
note bottom of DB
|
|
Simple Schema:
|
|
- id, user_id, event_type
|
|
- message_text (sanitized)
|
|
- created_at, read_at
|
|
- Auto-delete after 30 days
|
|
end note
|
|
|
|
@enduml |