docs(diagrams): update architecture diagrams for activation feature
Updated PlantUML diagrams and regenerated SVG/PNG exports: 01-use-cases: Add activation and admin use cases 02-domain-model: Add activation fields to Student entity 03-sequence-enrollment: Include activation check in flow 04-components: Add activation and admin components 05-entity-relationship: Add activation columns to Student table 06-state-enrollment: Add inactive/pending states 07-deployment: Update for current infrastructure 08-c4-context: Add admin actor and activation system All diagrams validated and exported in both SVG and PNG formats.
|
After Width: | Height: | Size: 70 KiB |
|
|
@ -9,43 +9,84 @@ skinparam actorBackgroundColor #007AFF
|
|||
title Sistema de Registro de Estudiantes - Diagrama de Casos de Uso
|
||||
|
||||
actor "Estudiante" as student
|
||||
actor "Administrador" as admin
|
||||
|
||||
rectangle "Sistema de Inscripción" {
|
||||
usecase "Registrarse en el sistema" as UC1
|
||||
usecase "Iniciar sesión" as UC2
|
||||
usecase "Ver materias disponibles" as UC3
|
||||
usecase "Inscribirse en materia" as UC4
|
||||
usecase "Cancelar inscripción" as UC5
|
||||
usecase "Ver mis inscripciones" as UC6
|
||||
usecase "Ver compañeros de clase" as UC7
|
||||
usecase "Actualizar perfil" as UC8
|
||||
rectangle "Sistema de Inscripción Académica" {
|
||||
' Autenticación (ambos actores)
|
||||
usecase "Iniciar sesión" as UC_LOGIN
|
||||
usecase "Recuperar contraseña" as UC_RECOVER
|
||||
|
||||
usecase "Validar límite de créditos\n(máx 9 créditos)" as UC4a
|
||||
usecase "Validar restricción de profesor\n(no repetir profesor)" as UC4b
|
||||
' Solo estudiantes
|
||||
usecase "Registrarse" as UC_REGISTER
|
||||
usecase "Activar cuenta" as UC_ACTIVATE
|
||||
usecase "Ver dashboard personal" as UC_DASHBOARD
|
||||
usecase "Ver materias disponibles" as UC_SUBJECTS
|
||||
usecase "Inscribirse en materia" as UC_ENROLL
|
||||
usecase "Cancelar inscripción" as UC_UNENROLL
|
||||
usecase "Ver mis inscripciones" as UC_MY_ENROLL
|
||||
usecase "Ver compañeros de clase" as UC_CLASSMATES
|
||||
|
||||
' Solo administrador
|
||||
usecase "Gestionar estudiantes\n(CRUD)" as UC_CRUD
|
||||
usecase "Ver todos los estudiantes" as UC_LIST
|
||||
usecase "Crear estudiante" as UC_CREATE
|
||||
usecase "Editar estudiante" as UC_EDIT
|
||||
usecase "Eliminar estudiante" as UC_DELETE
|
||||
|
||||
' Validaciones (includes)
|
||||
usecase "Validar límite de créditos\n(máx 9 créditos)" as UC_VAL_CREDITS
|
||||
usecase "Validar restricción de profesor\n(no repetir profesor)" as UC_VAL_PROF
|
||||
}
|
||||
|
||||
student --> UC1
|
||||
student --> UC2
|
||||
student --> UC3
|
||||
student --> UC4
|
||||
student --> UC5
|
||||
student --> UC6
|
||||
student --> UC7
|
||||
student --> UC8
|
||||
' Relaciones Estudiante
|
||||
student --> UC_REGISTER
|
||||
student --> UC_LOGIN
|
||||
student --> UC_ACTIVATE
|
||||
student --> UC_RECOVER
|
||||
student --> UC_DASHBOARD
|
||||
student --> UC_SUBJECTS
|
||||
student --> UC_ENROLL
|
||||
student --> UC_UNENROLL
|
||||
student --> UC_MY_ENROLL
|
||||
student --> UC_CLASSMATES
|
||||
|
||||
UC4 ..> UC4a : <<include>>
|
||||
UC4 ..> UC4b : <<include>>
|
||||
' Relaciones Admin
|
||||
admin --> UC_LOGIN
|
||||
admin --> UC_RECOVER
|
||||
admin --> UC_CRUD
|
||||
admin --> UC_LIST
|
||||
|
||||
note right of UC4
|
||||
' Extensiones CRUD
|
||||
UC_CRUD ..> UC_CREATE : <<include>>
|
||||
UC_CRUD ..> UC_EDIT : <<include>>
|
||||
UC_CRUD ..> UC_DELETE : <<include>>
|
||||
|
||||
' Validaciones inscripción
|
||||
UC_ENROLL ..> UC_VAL_CREDITS : <<include>>
|
||||
UC_ENROLL ..> UC_VAL_PROF : <<include>>
|
||||
|
||||
note right of UC_ENROLL
|
||||
Reglas de negocio:
|
||||
- Máximo 3 materias (9 créditos)
|
||||
- No puede tener 2 materias
|
||||
del mismo profesor
|
||||
- Requiere cuenta activada
|
||||
end note
|
||||
|
||||
note right of UC7
|
||||
note right of UC_CLASSMATES
|
||||
Solo muestra nombres
|
||||
de compañeros por materia
|
||||
end note
|
||||
|
||||
note right of UC_ACTIVATE
|
||||
El estudiante recibe
|
||||
código de activación
|
||||
al registrarse
|
||||
end note
|
||||
|
||||
note bottom of admin
|
||||
Acceso completo al
|
||||
CRUD de estudiantes
|
||||
end note
|
||||
|
||||
@enduml
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
|
@ -9,16 +9,40 @@ title Sistema de Registro de Estudiantes - Modelo de Dominio
|
|||
|
||||
package "Domain" {
|
||||
|
||||
class User <<Entity>> {
|
||||
- id: int
|
||||
- username: string
|
||||
- passwordHash: string
|
||||
- recoveryCodeHash: string
|
||||
- role: string
|
||||
- studentId: int?
|
||||
- createdAt: DateTime
|
||||
- lastLoginAt: DateTime?
|
||||
--
|
||||
+ {static} Create(username, passwordHash, ...): User
|
||||
+ UpdatePassword(newHash): void
|
||||
+ UpdateLastLogin(): void
|
||||
+ IsAdmin: bool
|
||||
+ IsStudent: bool
|
||||
}
|
||||
|
||||
class Student <<Entity>> {
|
||||
- id: int
|
||||
- name: string
|
||||
- email: Email
|
||||
- activationCodeHash: string?
|
||||
- activationExpiresAt: DateTime?
|
||||
- enrollments: List<Enrollment>
|
||||
--
|
||||
+ getTotalCredits(): int
|
||||
+ canEnrollIn(subject: Subject): bool
|
||||
+ enroll(subject: Subject): Enrollment
|
||||
+ unenroll(enrollmentId: int): void
|
||||
+ canEnroll(): bool
|
||||
+ hasProfessor(professorId): bool
|
||||
+ addEnrollment(enrollment): void
|
||||
+ removeEnrollment(enrollment): void
|
||||
+ setActivationCode(hash, expiresIn): void
|
||||
+ clearActivationCode(): void
|
||||
+ isActivated: bool
|
||||
+ isActivationExpired(): bool
|
||||
}
|
||||
|
||||
class Subject <<Entity>> {
|
||||
|
|
@ -62,7 +86,14 @@ package "Domain" {
|
|||
- checkProfessorConstraint(student: Student, subject: Subject): void
|
||||
}
|
||||
|
||||
enum UserRoles <<Enumeration>> {
|
||||
Admin
|
||||
Student
|
||||
}
|
||||
|
||||
' Relaciones
|
||||
User "0..1" -- "0..1" Student : vinculado a
|
||||
User --> UserRoles : tiene
|
||||
Student "1" *-- "0..3" Enrollment : tiene
|
||||
Subject "1" *-- "0..*" Enrollment : inscripciones
|
||||
Professor "1" *-- "2" Subject : imparte
|
||||
|
|
@ -72,11 +103,19 @@ package "Domain" {
|
|||
EnrollmentDomainService ..> Subject : valida
|
||||
}
|
||||
|
||||
note bottom of User
|
||||
<b>Autenticación:</b>
|
||||
- PBKDF2-SHA256 (100k iter)
|
||||
- JWT para sesiones
|
||||
- Recovery code para reset
|
||||
end note
|
||||
|
||||
note bottom of Student
|
||||
<b>Invariantes:</b>
|
||||
- Máximo 3 inscripciones
|
||||
- Email válido y único
|
||||
- No repetir profesor
|
||||
- Requiere activación
|
||||
end note
|
||||
|
||||
note bottom of Subject
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
|
@ -5,11 +5,12 @@ skinparam responseMessageBelowArrow true
|
|||
skinparam sequenceParticipantBackgroundColor #F8F9FA
|
||||
skinparam sequenceParticipantBorderColor #495057
|
||||
|
||||
title Secuencia: Inscripción de Estudiante en Materia
|
||||
title Secuencia: Inscripción de Estudiante en Materia (con JWT)
|
||||
|
||||
actor "Estudiante" as user
|
||||
participant "Frontend\n(Angular)" as frontend
|
||||
participant "API GraphQL\n(HotChocolate)" as api
|
||||
participant "JWT Middleware" as jwt
|
||||
participant "EnrollStudentHandler" as handler
|
||||
participant "EnrollmentDomainService" as domainService
|
||||
participant "StudentRepository" as studentRepo
|
||||
|
|
@ -17,14 +18,27 @@ participant "SubjectRepository" as subjectRepo
|
|||
participant "EnrollmentRepository" as enrollRepo
|
||||
database "SQL Server" as db
|
||||
|
||||
== Autenticación (previo) ==
|
||||
|
||||
note over user, frontend
|
||||
El estudiante ya inició sesión
|
||||
y tiene un JWT válido almacenado
|
||||
end note
|
||||
|
||||
== Solicitud de Inscripción ==
|
||||
|
||||
user -> frontend : Selecciona materia\ny hace clic en "Inscribir"
|
||||
activate frontend
|
||||
|
||||
frontend -> api : mutation enrollStudent(\n studentId, subjectId)
|
||||
frontend -> api : mutation enrollStudent(\n studentId, subjectId)\n[Authorization: Bearer <JWT>]
|
||||
activate api
|
||||
|
||||
api -> jwt : Validate JWT
|
||||
activate jwt
|
||||
jwt -> jwt : Verify signature\n& expiration
|
||||
jwt --> api : ClaimsPrincipal
|
||||
deactivate jwt
|
||||
|
||||
api -> handler : Handle(EnrollStudentCommand)
|
||||
activate handler
|
||||
|
||||
|
|
@ -37,6 +51,12 @@ db --> studentRepo : Student data
|
|||
studentRepo --> handler : Student
|
||||
deactivate studentRepo
|
||||
|
||||
alt Cuenta no activada
|
||||
handler --> api : Error: "Cuenta no activada"
|
||||
api --> frontend : { errors: [...] }
|
||||
frontend --> user : Muestra mensaje:\n"Activa tu cuenta primero"
|
||||
end
|
||||
|
||||
handler -> subjectRepo : GetByIdAsync(subjectId)
|
||||
activate subjectRepo
|
||||
subjectRepo -> db : SELECT Subject
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
|
@ -11,19 +11,43 @@ title Sistema de Registro de Estudiantes - Arquitectura de Componentes
|
|||
|
||||
package "Frontend (Angular 21)" as frontend {
|
||||
[App Component] as app
|
||||
|
||||
package "Features" {
|
||||
package "Auth" {
|
||||
[Login Page] as loginPage
|
||||
[Register Page] as registerPage
|
||||
[Reset Password] as resetPage
|
||||
[Activate Account] as activatePage
|
||||
}
|
||||
package "Dashboard" {
|
||||
[Student Dashboard] as studentDash
|
||||
[Admin Dashboard] as adminDash
|
||||
}
|
||||
package "Students" {
|
||||
[Student List] as studentList
|
||||
[Student Form] as studentForm
|
||||
}
|
||||
package "Enrollment" {
|
||||
[Enrollment Page] as enrollPage
|
||||
[Classmates Page] as classmates
|
||||
}
|
||||
}
|
||||
|
||||
package "Core" {
|
||||
[Apollo Client] as apollo
|
||||
[Auth Service] as authSvc
|
||||
[Student Service] as studentSvc
|
||||
[Enrollment Service] as enrollSvc
|
||||
[Connectivity Service] as connSvc
|
||||
[Error Handler] as errorHandler
|
||||
}
|
||||
|
||||
package "Guards" {
|
||||
[Auth Guard] as authGuard
|
||||
[Admin Guard] as adminGuard
|
||||
[Guest Guard] as guestGuard
|
||||
}
|
||||
|
||||
package "Shared" {
|
||||
[Connectivity Overlay] as overlay
|
||||
[Loading Spinner] as spinner
|
||||
|
|
@ -43,26 +67,42 @@ package "Backend (.NET 10)" as backend {
|
|||
[GraphQL API\n(HotChocolate)] as graphql
|
||||
[Query] as query
|
||||
[Mutation] as mutation
|
||||
[Types] as types
|
||||
[Auth Types] as authTypes
|
||||
[Student Types] as studentTypes
|
||||
}
|
||||
|
||||
package "Driven (Secondary)" {
|
||||
[Repositories] as repos
|
||||
[DataLoaders] as loaders
|
||||
[DbContext] as dbContext
|
||||
[JWT Service] as jwtSvc
|
||||
[Password Service] as passSvc
|
||||
}
|
||||
}
|
||||
|
||||
package "Application" as application {
|
||||
[Commands] as commands
|
||||
[Queries] as queries
|
||||
[Handlers] as handlers
|
||||
package "Auth" {
|
||||
[Login Command] as loginCmd
|
||||
[Register Command] as registerCmd
|
||||
[Reset Password] as resetCmd
|
||||
}
|
||||
package "Students" {
|
||||
[Student Commands] as studentCmds
|
||||
[Student Queries] as studentQs
|
||||
}
|
||||
package "Enrollments" {
|
||||
[Enroll Commands] as enrollCmds
|
||||
[Classmates Query] as classmatesQ
|
||||
}
|
||||
[Validators] as validators
|
||||
[DTOs] as dtos
|
||||
}
|
||||
|
||||
package "Domain" as domain {
|
||||
[Entities] as entities
|
||||
[User Entity] as userEntity
|
||||
[Student Entity] as studentEntity
|
||||
[Subject Entity] as subjectEntity
|
||||
[Enrollment Entity] as enrollEntity
|
||||
[Value Objects] as valueObjects
|
||||
[Domain Services] as domainSvc
|
||||
[Ports (Interfaces)] as ports
|
||||
|
|
@ -70,46 +110,67 @@ package "Backend (.NET 10)" as backend {
|
|||
}
|
||||
|
||||
database "SQL Server 2022" as sqlserver {
|
||||
[Students]
|
||||
[Subjects]
|
||||
[Professors]
|
||||
[Enrollments]
|
||||
[Users Table] as tblUsers
|
||||
[Students Table] as tblStudents
|
||||
[Subjects Table] as tblSubjects
|
||||
[Professors Table] as tblProf
|
||||
[Enrollments Table] as tblEnroll
|
||||
}
|
||||
|
||||
cloud "Browser" as browser
|
||||
|
||||
' Conexiones Frontend
|
||||
browser --> app
|
||||
app --> loginPage
|
||||
app --> registerPage
|
||||
app --> studentDash
|
||||
app --> adminDash
|
||||
app --> studentList
|
||||
app --> studentForm
|
||||
app --> enrollPage
|
||||
app --> classmates
|
||||
app --> overlay
|
||||
|
||||
loginPage --> authSvc
|
||||
registerPage --> authSvc
|
||||
resetPage --> authSvc
|
||||
activatePage --> authSvc
|
||||
studentDash --> studentSvc
|
||||
adminDash --> studentSvc
|
||||
studentList --> studentSvc
|
||||
studentForm --> studentSvc
|
||||
enrollPage --> enrollSvc
|
||||
classmates --> enrollSvc
|
||||
overlay --> connSvc
|
||||
|
||||
authSvc --> apollo
|
||||
studentSvc --> apollo
|
||||
enrollSvc --> apollo
|
||||
connSvc ..> errorHandler
|
||||
|
||||
' Guards
|
||||
authGuard ..> authSvc
|
||||
adminGuard ..> authSvc
|
||||
guestGuard ..> authSvc
|
||||
|
||||
' Conexiones Backend
|
||||
apollo --> graphql : HTTP/GraphQL
|
||||
apollo --> graphql : HTTP/GraphQL\n+ JWT Header
|
||||
|
||||
graphql --> query
|
||||
graphql --> mutation
|
||||
query --> handlers
|
||||
mutation --> handlers
|
||||
handlers --> validators
|
||||
handlers --> commands
|
||||
handlers --> queries
|
||||
graphql --> authTypes
|
||||
|
||||
commands --> domainSvc
|
||||
queries --> repos
|
||||
domainSvc --> entities
|
||||
mutation --> loginCmd
|
||||
mutation --> registerCmd
|
||||
mutation --> resetCmd
|
||||
mutation --> studentCmds
|
||||
mutation --> enrollCmds
|
||||
query --> studentQs
|
||||
query --> classmatesQ
|
||||
|
||||
loginCmd --> jwtSvc
|
||||
loginCmd --> passSvc
|
||||
registerCmd --> passSvc
|
||||
studentCmds --> domainSvc
|
||||
enrollCmds --> domainSvc
|
||||
|
||||
domainSvc --> studentEntity
|
||||
domainSvc --> valueObjects
|
||||
|
||||
repos --> dbContext
|
||||
|
|
@ -118,6 +179,7 @@ dbContext --> sqlserver
|
|||
|
||||
' Implementación de puertos
|
||||
repos ..|> ports : implements
|
||||
jwtSvc ..|> ports : implements
|
||||
|
||||
note right of domain
|
||||
<b>Regla de Dependencia:</b>
|
||||
|
|
@ -129,6 +191,12 @@ note bottom of graphql
|
|||
Endpoints:
|
||||
- /graphql
|
||||
- /health
|
||||
Auth: JWT Bearer
|
||||
end note
|
||||
|
||||
note right of jwtSvc
|
||||
HMAC-SHA256
|
||||
Configurable expiration
|
||||
end note
|
||||
|
||||
@enduml
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
|
@ -6,11 +6,25 @@ skinparam classBorderColor #495057
|
|||
|
||||
title Sistema de Registro de Estudiantes - Diagrama Entidad-Relación
|
||||
|
||||
entity "Users" as users {
|
||||
* **Id** : int <<PK>>
|
||||
--
|
||||
* Username : nvarchar(50) <<unique>>
|
||||
* PasswordHash : nvarchar(255)
|
||||
* RecoveryCodeHash : nvarchar(255)
|
||||
* Role : nvarchar(20)
|
||||
StudentId : int <<FK, nullable>>
|
||||
* CreatedAt : datetime2
|
||||
LastLoginAt : datetime2
|
||||
}
|
||||
|
||||
entity "Students" as students {
|
||||
* **Id** : int <<PK>>
|
||||
--
|
||||
* Name : nvarchar(100)
|
||||
* Email : nvarchar(255) <<unique>>
|
||||
ActivationCodeHash : nvarchar(255)
|
||||
ActivationExpiresAt : datetime2
|
||||
* CreatedAt : datetime2
|
||||
UpdatedAt : datetime2
|
||||
}
|
||||
|
|
@ -40,14 +54,23 @@ entity "Enrollments" as enrollments {
|
|||
}
|
||||
|
||||
' Relaciones
|
||||
users ||--o| students : "vinculado a"
|
||||
students ||--o{ enrollments : "tiene"
|
||||
subjects ||--o{ enrollments : "inscripciones"
|
||||
professors ||--|| subjects : "imparte 2"
|
||||
|
||||
note right of users
|
||||
<b>Autenticación:</b>
|
||||
- Password: PBKDF2-SHA256
|
||||
- Roles: Admin, Student
|
||||
- Recovery code para reset
|
||||
end note
|
||||
|
||||
note right of students
|
||||
<b>Restricciones:</b>
|
||||
- Email único
|
||||
- Máximo 3 enrollments
|
||||
- Activación requerida
|
||||
end note
|
||||
|
||||
note right of subjects
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
|
@ -3,10 +3,19 @@
|
|||
skinparam stateBackgroundColor #F8F9FA
|
||||
skinparam stateBorderColor #495057
|
||||
|
||||
title Estado de Inscripción del Estudiante
|
||||
title Estados del Estudiante y sus Inscripciones
|
||||
|
||||
[*] --> SinMaterias : Registro inicial
|
||||
[*] --> Registrado : Registro inicial
|
||||
|
||||
state "Cuenta" as cuenta {
|
||||
state "Registrado\n(Pendiente Activación)" as Registrado
|
||||
state "Activo" as Activo
|
||||
|
||||
Registrado --> Activo : activar(código)
|
||||
Registrado --> Registrado : código expirado\n[regenerar código]
|
||||
}
|
||||
|
||||
state "Inscripciones" as inscripciones {
|
||||
state "Sin Materias" as SinMaterias {
|
||||
state "0 créditos" as cred0
|
||||
}
|
||||
|
|
@ -25,6 +34,23 @@ Parcial --> Parcial : inscribir(materia)\n[créditos < 9]
|
|||
Parcial --> Completa : inscribir(materia)\n[créditos = 6]
|
||||
Completa --> Parcial : cancelar(inscripción)
|
||||
Parcial --> SinMaterias : cancelar(inscripción)\n[única materia]
|
||||
}
|
||||
|
||||
Activo --> SinMaterias : cuenta activa
|
||||
|
||||
state validacion <<choice>>
|
||||
|
||||
SinMaterias --> validacion : intenta inscribir
|
||||
Parcial --> validacion : intenta inscribir
|
||||
|
||||
validacion --> Parcial : [válido y cuenta activa]
|
||||
validacion --> [*] : [inválido]\nmuestra error
|
||||
|
||||
note right of Registrado
|
||||
El estudiante recibe
|
||||
código de activación
|
||||
por email (24h validez)
|
||||
end note
|
||||
|
||||
note right of Completa
|
||||
No puede inscribir
|
||||
|
|
@ -33,17 +59,16 @@ end note
|
|||
|
||||
note left of Parcial
|
||||
<b>Validaciones en cada inscripción:</b>
|
||||
- Cuenta activa
|
||||
- Límite de créditos
|
||||
- No repetir profesor
|
||||
- Materia no duplicada
|
||||
end note
|
||||
|
||||
state validacion <<choice>>
|
||||
|
||||
SinMaterias --> validacion : intenta inscribir
|
||||
Parcial --> validacion : intenta inscribir
|
||||
|
||||
validacion --> Parcial : [válido]
|
||||
validacion --> [*] : [inválido]\nmuestra error
|
||||
note bottom of validacion
|
||||
Si la cuenta no está
|
||||
activa, redirige a
|
||||
página de activación
|
||||
end note
|
||||
|
||||
@enduml
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
|
@ -12,35 +12,58 @@ node "Cliente" as client {
|
|||
}
|
||||
}
|
||||
|
||||
node "Docker Host" as docker {
|
||||
node "K3s Cluster (Namespace: academia)" as k3s {
|
||||
|
||||
node "student-frontend" as frontendContainer <<container>> {
|
||||
node "frontend-deployment" as frontendPod <<Pod>> {
|
||||
component "Nginx" as nginx {
|
||||
[Static Files]
|
||||
[Reverse Proxy]
|
||||
}
|
||||
}
|
||||
|
||||
node "student-api" as apiContainer <<container>> {
|
||||
node "api-deployment" as apiPod <<Pod>> {
|
||||
component "ASP.NET Core" as aspnet {
|
||||
[Kestrel Server]
|
||||
[GraphQL Endpoint]
|
||||
[JWT Auth]
|
||||
[Health Check]
|
||||
}
|
||||
}
|
||||
|
||||
node "student-db" as dbContainer <<container>> {
|
||||
node "sqlserver-statefulset" as dbPod <<StatefulSet>> {
|
||||
database "SQL Server 2022" as sqlserver {
|
||||
[StudentEnrollment DB]
|
||||
}
|
||||
}
|
||||
|
||||
node "Traefik Ingress" as ingress <<Ingress>> {
|
||||
[TLS Termination]
|
||||
[Routing Rules]
|
||||
}
|
||||
|
||||
component "NetworkPolicy" as netpol <<Security>> {
|
||||
[default-deny-ingress]
|
||||
[allow-frontend-ingress]
|
||||
[allow-api-ingress]
|
||||
[allow-sqlserver-from-api]
|
||||
}
|
||||
}
|
||||
|
||||
cloud "Internet" as internet
|
||||
|
||||
' Conexiones
|
||||
browser --> nginx : HTTP :80
|
||||
browser --> internet : HTTPS
|
||||
internet --> ingress : HTTPS :443
|
||||
ingress --> nginx : HTTP :80
|
||||
nginx --> aspnet : HTTP :5000\n/graphql
|
||||
aspnet --> sqlserver : TCP :1433
|
||||
|
||||
note right of ingress
|
||||
<b>Dominio:</b>
|
||||
academia.ingeniumcodex.com
|
||||
<b>TLS:</b> Let's Encrypt
|
||||
end note
|
||||
|
||||
note right of nginx
|
||||
<b>Nginx Config:</b>
|
||||
- Gzip/Brotli compression
|
||||
|
|
@ -55,6 +78,7 @@ note right of aspnet
|
|||
- ReadyToRun
|
||||
- Connection pooling
|
||||
- Rate limiting
|
||||
- JWT validation
|
||||
end note
|
||||
|
||||
note right of sqlserver
|
||||
|
|
@ -64,4 +88,16 @@ note right of sqlserver
|
|||
- Persistent volume
|
||||
end note
|
||||
|
||||
note bottom of k3s
|
||||
<b>CI/CD:</b> Gitea Actions
|
||||
<b>Namespace:</b> academia
|
||||
<b>Seguridad:</b> NetworkPolicy
|
||||
end note
|
||||
|
||||
note right of netpol
|
||||
<b>Flujo permitido:</b>
|
||||
Ingress → Frontend → API → SQL
|
||||
(Todo otro tráfico bloqueado)
|
||||
end note
|
||||
|
||||
@enduml
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
|
@ -10,28 +10,44 @@ skinparam rectangle {
|
|||
}
|
||||
|
||||
actor "Estudiante" as student <<Persona>>
|
||||
actor "Administrador" as admin <<Persona>>
|
||||
|
||||
rectangle "Sistema de Registro\nde Estudiantes" as system <<Software System>> #lightblue {
|
||||
rectangle "Sistema de Inscripción\nAcadémica" as system <<Software System>> #lightblue {
|
||||
}
|
||||
|
||||
rectangle "Base de Datos\nSQL Server" as database <<External System>> #lightgray {
|
||||
}
|
||||
|
||||
student --> system : Usa para registrarse\ne inscribirse en materias
|
||||
system --> database : Lee y escribe\ndatos de inscripciones
|
||||
rectangle "Servidor SMTP\n(Email)" as smtp <<External System>> #lightgray {
|
||||
}
|
||||
|
||||
student --> system : Se registra, activa cuenta,\nse inscribe en materias,\nve compañeros de clase
|
||||
admin --> system : Gestiona estudiantes\n(CRUD completo)
|
||||
system --> database : Lee y escribe\ndatos de usuarios,\nestudiantes e inscripciones
|
||||
system --> smtp : Envía códigos\nde activación
|
||||
|
||||
note right of student
|
||||
<b>Estudiante</b>
|
||||
Usuario del sistema que:
|
||||
- Se registra en el sistema
|
||||
- Se registra y activa cuenta
|
||||
- Se inscribe en materias (máx 3)
|
||||
- Ve sus compañeros de clase
|
||||
- Consulta inscripciones
|
||||
- Consulta sus inscripciones
|
||||
- Accede a su dashboard personal
|
||||
end note
|
||||
|
||||
note left of admin
|
||||
<b>Administrador</b>
|
||||
Usuario privilegiado que:
|
||||
- Gestiona todos los estudiantes
|
||||
- Crea, edita, elimina registros
|
||||
- Visualiza todo el sistema
|
||||
end note
|
||||
|
||||
note right of system
|
||||
<b>Sistema de Registro</b>
|
||||
<b>Sistema de Inscripción Académica</b>
|
||||
Aplicación web que permite:
|
||||
- Autenticación (JWT + PBKDF2)
|
||||
- CRUD de estudiantes
|
||||
- Inscripción en materias
|
||||
- Validación de reglas de negocio
|
||||
|
|
@ -40,15 +56,24 @@ note right of system
|
|||
<b>Stack:</b>
|
||||
Frontend: Angular 21
|
||||
Backend: .NET 10 + GraphQL
|
||||
Auth: JWT + Roles (Admin/Student)
|
||||
end note
|
||||
|
||||
note right of database
|
||||
<b>SQL Server 2022</b>
|
||||
Almacena:
|
||||
- Usuarios (auth)
|
||||
- Estudiantes
|
||||
- Profesores
|
||||
- Materias
|
||||
- Inscripciones
|
||||
end note
|
||||
|
||||
note right of smtp
|
||||
<b>Servicio de Email</b>
|
||||
Para:
|
||||
- Códigos de activación
|
||||
- Notificaciones
|
||||
end note
|
||||
|
||||
@enduml
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 17 KiB |