709 lines
17 KiB
Org Mode
Executable File
709 lines
17 KiB
Org Mode
Executable File
:PROPERTIES:
|
|
:ID: 4a8edaed-9ebd-402b-9c5f-7a0cb4399102
|
|
:END:
|
|
#+title: uml_fyp
|
|
#+filetags: :uni:
|
|
|
|
|
|
* Class diagram
|
|
** class 2:
|
|
@startuml
|
|
skinparam classAttributeIconSize 0
|
|
skinparam packageStyle rectangle
|
|
skinparam linetype ortho
|
|
left to right direction
|
|
|
|
' Entity Layer
|
|
rectangle "Entity Layer" as EntityLayer #E3F2FD {
|
|
class User {
|
|
+id: Long
|
|
+roles: Set<String>
|
|
+firstName: String
|
|
+lastName: String
|
|
+username: String
|
|
+password: String
|
|
+confirmPassword: String
|
|
+email: String
|
|
+phoneNumber: String
|
|
+picture: byte[]
|
|
}
|
|
|
|
class Workspace {
|
|
+id: Long
|
|
+name: String
|
|
+description: String
|
|
+fileCount: int
|
|
+noteCount: int
|
|
+lastAccessed: LocalDateTime
|
|
+dateCreated: LocalDateTime
|
|
}
|
|
|
|
class Library {
|
|
+id: Long
|
|
+name: String
|
|
+description: String
|
|
+dateCreated: LocalDateTime
|
|
+lastAccessed: LocalDateTime
|
|
}
|
|
|
|
class Page {
|
|
+id: Long
|
|
+name: String
|
|
+workspaceId: Long
|
|
+content: Text
|
|
+height: int
|
|
+width: int
|
|
}
|
|
|
|
class FileMetadata {
|
|
+id: Long
|
|
+fileUrl: String
|
|
+userId: String
|
|
+description: String
|
|
+fileData: byte[]
|
|
+fileName: String
|
|
+fileType: String
|
|
}
|
|
|
|
class AiChat {
|
|
+id: Long
|
|
+name: String
|
|
+workspaceId: Long
|
|
+createdAt: LocalDateTime
|
|
+messages: List<AIChatMessage>
|
|
}
|
|
}
|
|
|
|
' Repository Layer
|
|
rectangle "Repository Layer" as RepositoryLayer #E8F5E9 {
|
|
class AiChatRepository
|
|
class FileMetadataRepository
|
|
class LibraryRepository
|
|
class PageRepository
|
|
class UserRepository
|
|
class WorkspaceRepository
|
|
class RegisterRepository
|
|
class AuthRepository
|
|
}
|
|
|
|
' Service Layer
|
|
rectangle "Service Layer" as ServiceLayer #FFF3E0 {
|
|
class AiChatService
|
|
class AuthService
|
|
class FileMetadataService
|
|
class LibraryService
|
|
class PageService
|
|
class RegisterService
|
|
class UserService
|
|
class WorkspaceService
|
|
}
|
|
|
|
' Controller Layer
|
|
rectangle "Controller Layer" as ControllerLayer #F3E5F5 {
|
|
class AiChatController
|
|
class AiChatWebSocketController
|
|
class AuthController
|
|
class FileMetadataController
|
|
class LibraryController
|
|
class PageController
|
|
class RegisterController
|
|
class UserController
|
|
class WorkspaceController
|
|
}
|
|
|
|
' External Python Microservice
|
|
rectangle "External NLP Module (Python FastAPI)" as ExternalNLP #FCE4EC {
|
|
class FastAPINLPServer {
|
|
+/extract_text
|
|
+/keywords
|
|
+/tfidf_keywords
|
|
+/summarize
|
|
+/ner
|
|
}
|
|
}
|
|
|
|
|
|
|
|
rectangle "Frontend Core" as FrontendCore {
|
|
class AboutComponent
|
|
class AccessibilityComponent
|
|
class ContactComponent
|
|
class ForgotPasswordComponent
|
|
class LoginComponent
|
|
class LoginService
|
|
class PrivacyComponent
|
|
class RegisterComponent
|
|
class RegisterService
|
|
class SecurityComponent
|
|
class TermsComponent
|
|
|
|
LoginComponent --> LoginService
|
|
RegisterComponent --> RegisterService
|
|
|
|
LoginService ..> AuthController : REST
|
|
RegisterService ..> RegisterController : REST
|
|
}
|
|
|
|
rectangle "Frontend Entities" as FrontendEntities {
|
|
class AiChatComponent
|
|
class DashboardComponent
|
|
class DefaultLayoutComponent
|
|
class HomeComponent
|
|
class LibraryComponent
|
|
class ProfileComponent
|
|
class WorkspacePageComponent
|
|
class WorkspacesComponent
|
|
|
|
class AiChatServiceFE
|
|
class DashboardServiceFE
|
|
class LayoutServiceFE
|
|
class HomeServiceFE
|
|
class LibraryServiceFE
|
|
class ProfileServiceFE
|
|
class WorkspacePageServiceFE
|
|
class WorkspacesServiceFE
|
|
|
|
AiChatComponent --> AiChatServiceFE
|
|
DashboardComponent --> DashboardServiceFE
|
|
DefaultLayoutComponent --> LayoutServiceFE
|
|
DefaultLayoutComponent --> LoginComponent
|
|
DefaultLayoutComponent --> RegisterComponent
|
|
HomeComponent --> HomeServiceFE
|
|
LibraryComponent --> LibraryServiceFE
|
|
ProfileComponent --> ProfileServiceFE
|
|
WorkspacePageComponent --> WorkspacePageServiceFE
|
|
WorkspacesComponent --> WorkspacesServiceFE
|
|
|
|
ForgotPasswordComponent ..> UserController : REST
|
|
AiChatServiceFE ..> AiChatController : REST
|
|
AiChatServiceFE ..> AiChatWebSocketController : WebSocket
|
|
|
|
DashboardServiceFE ..> WorkspaceController : REST
|
|
DashboardServiceFE ..> PageController : REST
|
|
DashboardServiceFE ..> AiChatController : REST
|
|
|
|
LayoutServiceFE ..> UserController : REST
|
|
|
|
HomeServiceFE ..> AuthController : REST
|
|
|
|
LibraryServiceFE ..> LibraryController : REST
|
|
LibraryServiceFE ..> FileMetadataController : REST
|
|
|
|
ProfileServiceFE ..> UserController : REST
|
|
|
|
WorkspacePageServiceFE ..> PageController : REST
|
|
WorkspacePageServiceFE ..> FileMetadataController : REST
|
|
WorkspacePageServiceFE ..> AiChatController : REST
|
|
|
|
WorkspacesServiceFE ..> WorkspaceController : REST
|
|
AboutComponent --> ContactComponent
|
|
AboutComponent --> TermsComponent
|
|
AboutComponent --> PrivacyComponent
|
|
}
|
|
|
|
class AngularClient
|
|
AngularClient --> FrontendCore
|
|
AngularClient --> FrontendEntities
|
|
AngularClient ..> FastAPINLPServer : REST
|
|
|
|
|
|
' Entity Relationships
|
|
User "1" --> "many" Library
|
|
User "1" --> "many" Workspace
|
|
Library "1" --> "many" Workspace
|
|
Library "1" --> "many" FileMetadata
|
|
Workspace "1" --> "many" Page
|
|
Workspace "1" --> "many" FileMetadata
|
|
Workspace "1" --> "many" AiChat
|
|
|
|
' Controller → Service
|
|
AiChatController --> AiChatService
|
|
AiChatWebSocketController --> AiChatService
|
|
AuthController --> AuthService
|
|
FileMetadataController --> FileMetadataService
|
|
LibraryController --> LibraryService
|
|
PageController --> PageService
|
|
RegisterController --> RegisterService
|
|
UserController --> UserService
|
|
WorkspaceController --> WorkspaceService
|
|
|
|
' Service → Repository
|
|
AiChatService --> AiChatRepository
|
|
AuthService --> AuthRepository
|
|
FileMetadataService --> FileMetadataRepository
|
|
LibraryService --> LibraryRepository
|
|
PageService --> PageRepository
|
|
RegisterService --> RegisterRepository
|
|
UserService --> UserRepository
|
|
WorkspaceService --> WorkspaceRepository
|
|
|
|
' Repository → Entity
|
|
AiChatRepository --> AiChat
|
|
FileMetadataRepository --> FileMetadata
|
|
LibraryRepository --> Library
|
|
PageRepository --> Page
|
|
UserRepository --> User
|
|
WorkspaceRepository --> Workspace
|
|
RegisterRepository --> User
|
|
AuthRepository --> User
|
|
|
|
@enduml
|
|
|
|
** authentication sequence diagram:
|
|
@startuml
|
|
title Full Authentication Flow - Registration to Secured Access
|
|
|
|
skinparam shadowing true
|
|
skinparam packageStyle rectangle
|
|
skinparam handwritten false
|
|
skinparam linetype polyline
|
|
skinparam ParticipantPadding 20
|
|
skinparam maxMessageSize 150
|
|
|
|
actor User
|
|
|
|
== Registration Process ==
|
|
|
|
box "Client" #E3F2FD
|
|
participant UserClient as "User"
|
|
end box
|
|
|
|
box "Backend - Registration" #E8F5E9
|
|
participant RegisterController
|
|
participant UserService
|
|
end box
|
|
|
|
UserClient -> RegisterController : POST /register\n(username, password, confirmPassword)
|
|
RegisterController -> RegisterController : Check if passwords match
|
|
alt Passwords do not match
|
|
RegisterController --> UserClient : 400 Bad Request (Passwords mismatch)
|
|
return
|
|
end
|
|
RegisterController -> RegisterController : Hash password (BCrypt)
|
|
RegisterController -> RegisterController : Load default profile image
|
|
RegisterController -> UserService : createUser(user)
|
|
RegisterController --> UserClient : 200 OK (User Created)
|
|
|
|
== Authentication Process ==
|
|
|
|
box "Backend - Authentication" #FFF3E0
|
|
participant AuthController
|
|
participant AuthenticationManager
|
|
participant JwtUtil
|
|
end box
|
|
|
|
UserClient -> AuthController : POST /auth/login\n(username, password)
|
|
AuthController -> AuthenticationManager : Authenticate credentials
|
|
alt Valid credentials
|
|
AuthController -> JwtUtil : generateToken(userDetails, userId)
|
|
AuthController --> UserClient : 200 OK + JWT
|
|
else Invalid credentials
|
|
AuthController --> UserClient : 401 Unauthorized
|
|
return
|
|
end
|
|
|
|
== Accessing a Protected API ==
|
|
|
|
box "Security Filter Chain" #F3E5F5
|
|
participant JwtRequestFilter
|
|
participant UserDetailsService
|
|
participant JwtUtilFilter as "JwtUtil"
|
|
end box
|
|
|
|
UserClient -> JwtRequestFilter : Request with Authorization header
|
|
JwtRequestFilter -> JwtUtilFilter : extractUsername(jwt)
|
|
JwtRequestFilter -> UserDetailsService : loadUserByUsername
|
|
JwtRequestFilter -> JwtUtilFilter : validateToken(jwt, userDetails)
|
|
alt Valid token
|
|
JwtRequestFilter -> SecurityContext : Set authentication
|
|
else Invalid token
|
|
JwtRequestFilter -> JwtRequestFilter : Log and skip authentication
|
|
end
|
|
JwtRequestFilter --> UserClient : Continue filter chain
|
|
|
|
== @JwtRequired Secured Method Access ==
|
|
|
|
box "AOP - Method Security" #E1F5FE
|
|
participant JwtAspect
|
|
participant JwtUtilAspect as "JwtUtil"
|
|
end box
|
|
|
|
UserClient -> JwtAspect : Call method annotated with @JwtRequired
|
|
JwtAspect -> JwtAspect : Extract JWT from header
|
|
JwtAspect -> JwtUtilAspect : extractUsername(jwt)
|
|
JwtAspect -> SecurityContext : Get UserDetails
|
|
JwtAspect -> JwtUtilAspect : validateToken(jwt, userDetails)
|
|
alt Token valid and user matches
|
|
JwtAspect --> UserClient : Proceed to method execution
|
|
else Invalid/mismatched token
|
|
JwtAspect --> UserClient : Unauthorized exception
|
|
return
|
|
end
|
|
|
|
@enduml
|
|
|
|
** class
|
|
@startuml
|
|
skinparam classAttributeIconSize 0
|
|
skinparam packageStyle rectangle
|
|
|
|
package "High-Level Overview" {
|
|
|
|
' Controller Layer
|
|
package "Controller Layer" {
|
|
class AiChatController
|
|
class AiChatWebSocketController
|
|
class AuthController
|
|
class FileMetadataController
|
|
class LibraryController
|
|
class PageController
|
|
class RegisterController
|
|
class UserController
|
|
class WorkspaceController
|
|
}
|
|
|
|
' Service Layer
|
|
package "Service Layer" {
|
|
class AiChatService
|
|
class AuthService
|
|
class FileMetadataService
|
|
class LibraryService
|
|
class PageService
|
|
class RegisterService
|
|
class UserService
|
|
class WorkspaceService
|
|
}
|
|
|
|
' Repository Layer
|
|
package "Repository Layer" {
|
|
class AiChatRepository
|
|
class FileMetadataRepository
|
|
class LibraryRepository
|
|
class PageRepository
|
|
class UserRepository
|
|
class WorkspaceRepository
|
|
class RegisterRepository
|
|
class AuthRepository
|
|
}
|
|
|
|
' Entity Layer
|
|
package "Entity Layer" {
|
|
|
|
class User {
|
|
+id: Long
|
|
+roles: Set<String>
|
|
+firstName: String
|
|
+lastName: String
|
|
+username: String
|
|
+password: String
|
|
+confirmPassword: String
|
|
+email: String
|
|
+phoneNumber: String
|
|
+picture: byte[]
|
|
}
|
|
|
|
class Workspace {
|
|
+id: Long
|
|
+name: String
|
|
+description: String
|
|
+fileCount: int
|
|
+noteCount: int
|
|
+lastAccessed: LocalDateTime
|
|
+dateCreated: LocalDateTime
|
|
}
|
|
|
|
class Library {
|
|
+id: Long
|
|
+name: String
|
|
+description: String
|
|
+dateCreated: LocalDateTime
|
|
+lastAccessed: LocalDateTime
|
|
}
|
|
|
|
class Page {
|
|
+id: Long
|
|
+name: String
|
|
+workspaceId: Long
|
|
+content: Text
|
|
+height: int
|
|
+width: int
|
|
}
|
|
|
|
class FileMetadata {
|
|
+id: Long
|
|
+fileUrl: String
|
|
+userId: String
|
|
+description: String
|
|
+fileData: byte[]
|
|
+fileName: String
|
|
+fileType: String
|
|
}
|
|
|
|
class AiChat {
|
|
+id: Long
|
|
+name: String
|
|
+workspaceId: Long
|
|
+createdAt: LocalDateTime
|
|
+messages: List<AIChatMessage>
|
|
}
|
|
}
|
|
|
|
' Python NLP Microservice
|
|
package "External NLP Module (Python FastAPI)" {
|
|
class FastAPINLPServer {
|
|
+/extract_text
|
|
+/keywords
|
|
+/tfidf_keywords
|
|
+/summarize
|
|
+/ner
|
|
}
|
|
}
|
|
|
|
' Entity Relationships
|
|
User "1" --> "many" Library
|
|
User "1" --> "many" Workspace
|
|
Library "1" --> "many" Workspace
|
|
Library "1" --> "many" FileMetadata
|
|
Workspace "1" --> "many" Page
|
|
Workspace "1" --> "many" FileMetadata
|
|
Workspace "1" --> "many" AiChat
|
|
|
|
' Controller → Service
|
|
AiChatController --> AiChatService
|
|
AiChatWebSocketController --> AiChatService
|
|
AuthController --> AuthService
|
|
FileMetadataController --> FileMetadataService
|
|
LibraryController --> LibraryService
|
|
PageController --> PageService
|
|
RegisterController --> RegisterService
|
|
UserController --> UserService
|
|
WorkspaceController --> WorkspaceService
|
|
|
|
' Service → Repository
|
|
AiChatService --> AiChatRepository
|
|
AuthService --> AuthRepository
|
|
FileMetadataService --> FileMetadataRepository
|
|
LibraryService --> LibraryRepository
|
|
PageService --> PageRepository
|
|
RegisterService --> RegisterRepository
|
|
UserService --> UserRepository
|
|
WorkspaceService --> WorkspaceRepository
|
|
|
|
' Repository → Entity
|
|
AiChatRepository --> AiChat
|
|
FileMetadataRepository --> FileMetadata
|
|
LibraryRepository --> Library
|
|
PageRepository --> Page
|
|
UserRepository --> User
|
|
WorkspaceRepository --> Workspace
|
|
RegisterRepository --> User
|
|
AuthRepository --> User
|
|
|
|
' Frontend → NLP Server
|
|
|
|
}
|
|
|
|
' Frontend Component
|
|
package "Frontend" {
|
|
class AngularClient
|
|
}
|
|
|
|
' Angular communicates with both backends
|
|
AngularClient ..> AiChatController : REST
|
|
AngularClient ..> AiChatWebSocketController : WebSocket
|
|
AngularClient ..> AuthController : REST
|
|
AngularClient ..> PageController : REST
|
|
AngularClient ..> FileMetadataController : REST
|
|
AngularClient ..> WorkspaceController : REST
|
|
AngularClient ..> LibraryController : REST
|
|
AngularClient ..> RegisterController : REST
|
|
AngularClient ..> UserController : REST
|
|
AngularClient ..> FastAPINLPServer : REST
|
|
|
|
@enduml
|
|
** client-server
|
|
@startuml
|
|
!pragma layout smetana
|
|
|
|
actor User
|
|
|
|
package "Client Side (Angular)" {
|
|
[Angular App] as Frontend
|
|
}
|
|
|
|
package "Spring Boot Backend" {
|
|
[Auth Controller]
|
|
[Note Controller]
|
|
[NLP Proxy Service]
|
|
[Spring Boot App] as Backend
|
|
}
|
|
|
|
package "Database Layer" {
|
|
database "PostgreSQL Database" as DB
|
|
}
|
|
|
|
package "FastAPI NLP Server (Port 9010)" {
|
|
[FastAPI NLP Service] as NLP
|
|
[Summarisation Endpoint] as SumEndpoint
|
|
[Keyword Extraction] as KeywordEndpoint
|
|
[NER Endpoint] as NEREndpoint
|
|
}
|
|
|
|
package "External API" {
|
|
[OpenAI API]
|
|
}
|
|
|
|
' Interactions
|
|
User --> Frontend : Uses Web Interface
|
|
Frontend --> Backend : REST API Calls
|
|
Backend --> [Auth Controller] : Handles Auth
|
|
Backend --> [Note Controller] : Handles Notes
|
|
Backend --> [NLP Proxy Service] : Handles NLP Requests
|
|
[Auth Controller] --> DB : Access users table
|
|
[Note Controller] --> DB : Access notes table
|
|
[NLP Proxy Service] --> NLP : HTTP (port 9010)
|
|
NLP --> SumEndpoint : /summarise
|
|
NLP --> KeywordEndpoint : /keywords
|
|
NLP --> NEREndpoint : /ner
|
|
SumEndpoint --> [OpenAI API] : API call for contextual help
|
|
|
|
note right of Frontend
|
|
Angular app includes:
|
|
- Note Editor
|
|
- Summary View
|
|
- Keyword Panel
|
|
end note
|
|
|
|
note right of Backend
|
|
Spring Boot includes:
|
|
- Auth Controller
|
|
- Note Controller
|
|
- NLP Proxy Service (calls FastAPI)
|
|
end note
|
|
|
|
note right of NLP
|
|
FastAPI exposes endpoints for:
|
|
- Summarisation (Pegasus)
|
|
- Keyword Extraction (TF-IDF, YAKE)
|
|
- NER (spaCy)
|
|
end note
|
|
@enduml
|
|
** high level:
|
|
@startuml
|
|
skinparam componentStyle uml2
|
|
skinparam packageStyle rectangle
|
|
|
|
package "Client (Frontend)" {
|
|
[Angular UI]
|
|
}
|
|
|
|
package "Java Backend (Spring Boot)" {
|
|
[REST API Controller Layer]
|
|
[WebSocket Controller]
|
|
[Service Layer]
|
|
[Repository Layer]
|
|
[JPA Entities]
|
|
}
|
|
|
|
package "Python NLP Service" {
|
|
[FastAPI Server]
|
|
[Summarizer (Pegasus)]
|
|
[Keyword Extractor (YAKE / TF-IDF)]
|
|
[NER (spaCy)]
|
|
[Extract Text (Canvas Object)]
|
|
}
|
|
|
|
package "External Services" {
|
|
[OpenAI API]
|
|
[PostgreSQL DB]
|
|
}
|
|
|
|
' Communication Arrows
|
|
[Angular UI] --> [REST API Controller Layer] : REST API (JSON)
|
|
[Angular UI] --> [WebSocket Controller] : WebSocket
|
|
|
|
[REST API Controller Layer] --> [Service Layer]
|
|
[WebSocket Controller] --> [Service Layer]
|
|
[Service Layer] --> [Repository Layer]
|
|
[Repository Layer] ..> [JPA Entities] : uses
|
|
[Service Layer] --> [OpenAI API] : API calls
|
|
|
|
[Service Layer] --> [FastAPI Server] : REST (NLP Requests)
|
|
[FastAPI Server] --> [Summarizer (Pegasus)]
|
|
[FastAPI Server] --> [Keyword Extractor (YAKE / TF-IDF)]
|
|
[FastAPI Server] --> [NER (spaCy)]
|
|
[FastAPI Server] --> [Extract Text (Canvas Object)]
|
|
|
|
[Repository Layer] --> [PostgreSQL DB] : Hibernate ORM
|
|
@enduml
|
|
|
|
** title AI Chat + Workspace Workflow
|
|
@startuml
|
|
title AI Chat + Workspace Workflow
|
|
|
|
skinparam shadowing true
|
|
skinparam packageStyle rectangle
|
|
skinparam handwritten false
|
|
skinparam linetype polyline
|
|
skinparam ParticipantPadding 20
|
|
skinparam maxMessageSize 150
|
|
|
|
actor User
|
|
|
|
== AI Chat Session Creation ==
|
|
|
|
box "Client" #E3F2FD
|
|
participant AngularClient as "User"
|
|
end box
|
|
|
|
box "Backend - AI Chat" #E8F5E9
|
|
participant AiChatController
|
|
participant AiChatService
|
|
participant AiChatRepository
|
|
end box
|
|
|
|
box "External NLP Service" #FCE4EC
|
|
participant FastAPINLPServer as "FastAPI NLP"
|
|
end box
|
|
|
|
User -> AngularClient : Open AI Chat page
|
|
AngularClient -> AiChatController : POST /ai-chat\n(chat metadata)
|
|
AiChatController -> AiChatService : createChat(chatDto)
|
|
AiChatService -> AiChatRepository : save(chat)
|
|
AiChatService --> AiChatController : chatId
|
|
AiChatController --> AngularClient : 200 OK + chatId
|
|
|
|
User -> AngularClient : Send message via WebSocket
|
|
AngularClient -> AiChatWebSocketController : message
|
|
AiChatWebSocketController -> AiChatService : handleMessage()
|
|
|
|
alt Message requires NLP
|
|
AiChatService -> FastAPINLPServer : POST /summarize or /ner
|
|
FastAPINLPServer --> AiChatService : NLP result
|
|
end
|
|
|
|
AiChatService -> AiChatRepository : update(chat with message)
|
|
AiChatWebSocketController --> AngularClient : Message response
|
|
|
|
== Workspace Creation ==
|
|
|
|
box "Backend - Workspace" #FFF3E0
|
|
participant WorkspaceController
|
|
participant WorkspaceService
|
|
participant WorkspaceRepository
|
|
end box
|
|
|
|
User -> AngularClient : Create Workspace
|
|
AngularClient -> WorkspaceController : POST /workspace\n(name, description)
|
|
WorkspaceController -> WorkspaceService : createWorkspace(dto)
|
|
WorkspaceService -> WorkspaceRepository : save(workspace)
|
|
WorkspaceService --> WorkspaceController : workspaceId
|
|
WorkspaceController --> AngularClient : 200 OK + workspaceId
|
|
|
|
@enduml
|
|
|
|
* Screenshots:
|
|
** Draft 1:
|
|
[[file:~/master-folder/FYP/uml/draft1.png]]
|
|
|