docs: add PlantUML backend architecture diagram
- Introduced a detailed PlantUML diagram illustrating backend modules, services, controllers, and key relationships. - Enhanced documentation with visual representation of system architecture for improved understanding.
This commit is contained in:
756
backend.plantuml
Normal file
756
backend.plantuml
Normal file
@@ -0,0 +1,756 @@
|
||||
@startuml
|
||||
|
||||
!theme plain
|
||||
top to bottom direction
|
||||
skinparam linetype ortho
|
||||
|
||||
class AdminController {
|
||||
constructor(adminService: AdminService):
|
||||
getStats(): Promise<{users: number, contents: numbe…
|
||||
}
|
||||
class AdminModule
|
||||
class AdminService {
|
||||
constructor(usersRepository: UsersRepository, contentsRepository: ContentsRepository, categoriesRepository: CategoriesRepository):
|
||||
getStats(): Promise<{users: number, contents: numbe…
|
||||
}
|
||||
class AllExceptionsFilter {
|
||||
logger: Logger
|
||||
catch(exception: unknown, host: ArgumentsHost): void
|
||||
}
|
||||
class ApiKeysController {
|
||||
constructor(apiKeysService: ApiKeysService):
|
||||
create(req: AuthenticatedRequest, createApiKeyDto: CreateApiKeyDto): Promise<{name: string, key: string, exp…
|
||||
findAll(req: AuthenticatedRequest): Promise<any>
|
||||
revoke(req: AuthenticatedRequest, id: string): Promise<any>
|
||||
}
|
||||
class ApiKeysModule
|
||||
class ApiKeysRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
create(data: {userId: string; name: string; prefix: string; keyHash: string; expiresAt?: Date}): Promise<any>
|
||||
findAll(userId: string): Promise<any>
|
||||
revoke(userId: string, keyId: string): Promise<any>
|
||||
findActiveByKeyHash(keyHash: string): Promise<any>
|
||||
updateLastUsed(id: string): Promise<any>
|
||||
}
|
||||
class ApiKeysService {
|
||||
constructor(apiKeysRepository: ApiKeysRepository, hashingService: HashingService):
|
||||
logger: Logger
|
||||
create(userId: string, name: string, expiresAt?: Date): Promise<{name: string, key: string, exp…
|
||||
findAll(userId: string): Promise<any>
|
||||
revoke(userId: string, keyId: string): Promise<any>
|
||||
validateKey(key: string): Promise<any>
|
||||
}
|
||||
class AppController {
|
||||
constructor(appService: AppService):
|
||||
getHello(): string
|
||||
}
|
||||
class AppModule {
|
||||
configure(consumer: MiddlewareConsumer): void
|
||||
}
|
||||
class AppService {
|
||||
getHello(): string
|
||||
}
|
||||
class AuditLogInDb
|
||||
class AuthController {
|
||||
constructor(authService: AuthService, bootstrapService: BootstrapService, configService: ConfigService):
|
||||
register(registerDto: RegisterDto): Promise<{message: string, userId: any}>
|
||||
login(loginDto: LoginDto, userAgent: string, req: Request, res: Response): Promise<Response<any, Record<string, an…
|
||||
verifyTwoFactor(verify2faDto: Verify2faDto, userAgent: string, req: Request, res: Response): Promise<Response<any, Record<string, an…
|
||||
refresh(req: Request, res: Response): Promise<Response<any, Record<string, an…
|
||||
logout(req: Request, res: Response): Promise<Response<any, Record<string, an…
|
||||
bootstrapAdmin(token: string, username: string): Promise<{message: string}>
|
||||
}
|
||||
class AuthGuard {
|
||||
constructor(jwtService: JwtService, configService: ConfigService):
|
||||
canActivate(context: ExecutionContext): Promise<boolean>
|
||||
}
|
||||
class AuthModule
|
||||
class AuthService {
|
||||
constructor(usersService: UsersService, hashingService: HashingService, jwtService: JwtService, sessionsService: SessionsService, configService: ConfigService):
|
||||
logger: Logger
|
||||
generateTwoFactorSecret(userId: string): Promise<{secret: string, qrCodeDataUrl:…
|
||||
enableTwoFactor(userId: string, token: string): Promise<{message: string}>
|
||||
disableTwoFactor(userId: string, token: string): Promise<{message: string}>
|
||||
register(dto: RegisterDto): Promise<{message: string, userId: any}>
|
||||
login(dto: LoginDto, userAgent?: string, ip?: string): Promise<{message: string, requires2FA: …
|
||||
verifyTwoFactorLogin(userId: string, token: string, userAgent?: string, ip?: string): Promise<{message: string, access_token:…
|
||||
refresh(refreshToken: string): Promise<{access_token: string, refresh_…
|
||||
logout(): Promise<{message: string}>
|
||||
}
|
||||
class AuthenticatedRequest {
|
||||
user: {sub: string, username: string}
|
||||
}
|
||||
class BootstrapService {
|
||||
constructor(rbacService: RbacService, usersService: UsersService, configService: ConfigService):
|
||||
logger: Logger
|
||||
bootstrapToken: string | null
|
||||
onApplicationBootstrap(): Promise<void>
|
||||
generateBootstrapToken(): void
|
||||
consumeToken(token: string, username: string): Promise<{message: string}>
|
||||
}
|
||||
class CategoriesController {
|
||||
constructor(categoriesService: CategoriesService):
|
||||
findAll(): Promise<any>
|
||||
findOne(id: string): Promise<any>
|
||||
create(createCategoryDto: CreateCategoryDto): Promise<any>
|
||||
update(id: string, updateCategoryDto: UpdateCategoryDto): Promise<any>
|
||||
remove(id: string): Promise<any>
|
||||
}
|
||||
class CategoriesModule
|
||||
class CategoriesRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
findAll(): Promise<any>
|
||||
countAll(): Promise<number>
|
||||
findOne(id: string): Promise<any>
|
||||
create(data: CreateCategoryDto & {slug: string}): Promise<any>
|
||||
update(id: string, data: UpdateCategoryDto & {slug?: string; updatedAt: Date}): Promise<any>
|
||||
remove(id: string): Promise<any>
|
||||
}
|
||||
class CategoriesService {
|
||||
constructor(categoriesRepository: CategoriesRepository, cacheManager: Cache):
|
||||
logger: Logger
|
||||
clearCategoriesCache(): Promise<void>
|
||||
findAll(): Promise<any>
|
||||
findOne(id: string): Promise<any>
|
||||
create(data: CreateCategoryDto): Promise<any>
|
||||
update(id: string, data: UpdateCategoryDto): Promise<any>
|
||||
remove(id: string): Promise<any>
|
||||
}
|
||||
class CategoryInDb
|
||||
class ClamScanner {
|
||||
scanStream(stream: Readable): Promise<{isInfected: boolean, viruses: …
|
||||
}
|
||||
class CommonModule
|
||||
class ContentInDb
|
||||
class ContentType {
|
||||
MEME:
|
||||
GIF:
|
||||
}
|
||||
class ContentsController {
|
||||
constructor(contentsService: ContentsService):
|
||||
create(req: AuthenticatedRequest, createContentDto: CreateContentDto): Promise<any>
|
||||
getUploadUrl(req: AuthenticatedRequest, fileName: string): Promise<{url: string, key: string}>
|
||||
upload(req: AuthenticatedRequest, file: Express.Multer.File, uploadContentDto: UploadContentDto): Promise<any>
|
||||
explore(req: AuthenticatedRequest, limit: number, offset: number, sort?: "trend" | "recent", tag?: string, category?: string, author?: string): Promise<{data: any, totalCount: any}>
|
||||
trends(req: AuthenticatedRequest, limit: number, offset: number): Promise<{data: any, totalCount: any}>
|
||||
recent(req: AuthenticatedRequest, limit: number, offset: number): Promise<{data: any, totalCount: any}>
|
||||
findOne(idOrSlug: string, req: AuthenticatedRequest, res: Response): Promise<Response<any, Record<string, an…
|
||||
incrementViews(id: string): Promise<void>
|
||||
incrementUsage(id: string): Promise<void>
|
||||
update(id: string, req: AuthenticatedRequest, updateContentDto: any): Promise<any>
|
||||
remove(id: string, req: AuthenticatedRequest): Promise<any>
|
||||
removeAdmin(id: string): Promise<any>
|
||||
updateAdmin(id: string, updateContentDto: any): Promise<any>
|
||||
}
|
||||
class ContentsModule
|
||||
class ContentsRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
findAll(options: FindAllOptions): Promise<any>
|
||||
create(data: NewContentInDb & {userId: string}, tagNames?: string[]): Promise<any>
|
||||
findOne(idOrSlug: string, userId?: string): Promise<any>
|
||||
count(options: {tag?: string; category?: string; author?: string; query?: string; favoritesOnly?: boolean; userId?: string}): Promise<number>
|
||||
incrementViews(id: string): Promise<void>
|
||||
incrementUsage(id: string): Promise<void>
|
||||
softDelete(id: string, userId: string): Promise<any>
|
||||
softDeleteAdmin(id: string): Promise<any>
|
||||
update(id: string, data: Partial<typeof contents.$inferInsert>): Promise<any>
|
||||
findBySlug(slug: string): Promise<any>
|
||||
purgeSoftDeleted(before: Date): Promise<any>
|
||||
}
|
||||
class ContentsService {
|
||||
constructor(contentsRepository: ContentsRepository, s3Service: IStorageService, mediaService: IMediaService, configService: ConfigService, cacheManager: Cache):
|
||||
logger: Logger
|
||||
clearContentsCache(): Promise<void>
|
||||
getUploadUrl(userId: string, fileName: string): Promise<{url: string, key: string}>
|
||||
uploadAndProcess(userId: string, file: Express.Multer.File, data: UploadContentDto): Promise<any>
|
||||
findAll(options: {limit: number; offset: number; sortBy?: "trend" | "recent"; tag?: string; category?: string; author?: string; query?: string; favoritesOnly?: boolean; userId?: string}): Promise<{data: any, totalCount: any}>
|
||||
create(userId: string, data: CreateContentDto): Promise<any>
|
||||
incrementViews(id: string): Promise<void>
|
||||
incrementUsage(id: string): Promise<void>
|
||||
remove(id: string, userId: string): Promise<any>
|
||||
removeAdmin(id: string): Promise<any>
|
||||
updateAdmin(id: string, data: any): Promise<any>
|
||||
update(id: string, userId: string, data: any): Promise<any>
|
||||
findOne(idOrSlug: string, userId?: string): Promise<any>
|
||||
generateBotHtml(content: {title: string; storageKey: string}): string
|
||||
generateSlug(text: string): string
|
||||
ensureUniqueSlug(title: string): Promise<string>
|
||||
}
|
||||
class CrawlerDetectionMiddleware {
|
||||
logger: Logger
|
||||
SUSPICIOUS_PATTERNS: RegExp[]
|
||||
BOT_USER_AGENTS: RegExp[]
|
||||
use(req: Request, res: Response, next: NextFunction): void
|
||||
}
|
||||
class CreateApiKeyDto {
|
||||
name: string
|
||||
expiresAt: string
|
||||
}
|
||||
class CreateCategoryDto {
|
||||
name: string
|
||||
description: string
|
||||
iconUrl: string
|
||||
}
|
||||
class CreateContentDto {
|
||||
type: "meme" | "gif"
|
||||
title: string
|
||||
storageKey: string
|
||||
mimeType: string
|
||||
fileSize: number
|
||||
categoryId: string
|
||||
tags: string[]
|
||||
}
|
||||
class CreateReportDto {
|
||||
contentId: string
|
||||
tagId: string
|
||||
reason: "inappropriate" | "spam" | "copyright" …
|
||||
description: string
|
||||
}
|
||||
class CryptoModule
|
||||
class CryptoService {
|
||||
constructor(hashingService: HashingService, jwtService: JwtService, encryptionService: EncryptionService, postQuantumService: PostQuantumService):
|
||||
hashEmail(email: string): Promise<string>
|
||||
hashIp(ip: string): Promise<string>
|
||||
getPgpEncryptionKey(): string
|
||||
hashPassword(password: string): Promise<string>
|
||||
verifyPassword(password: string, hash: string): Promise<boolean>
|
||||
generateJwt(payload: jose.JWTPayload, expiresIn?: string): Promise<string>
|
||||
verifyJwt(token: string): Promise<T>
|
||||
encryptContent(content: string): Promise<string>
|
||||
decryptContent(jwe: string): Promise<string>
|
||||
signContent(content: string): Promise<string>
|
||||
verifyContentSignature(jws: string): Promise<string>
|
||||
generatePostQuantumKeyPair(): {publicKey: Uint8Array<ArrayBufferLike>…
|
||||
encapsulate(publicKey: Uint8Array): {cipherText: Uint8Array, sharedSecret: …
|
||||
decapsulate(cipherText: Uint8Array, secretKey: Uint8Array): Uint8Array<ArrayBufferLike>
|
||||
}
|
||||
class DatabaseModule
|
||||
class DatabaseService {
|
||||
constructor(configService: ConfigService):
|
||||
logger: Logger
|
||||
pool: Pool
|
||||
db: ReturnType<typeof drizzle>
|
||||
onModuleInit(): Promise<void>
|
||||
onModuleDestroy(): Promise<void>
|
||||
getDatabaseConnectionString(): string
|
||||
}
|
||||
class EncryptionService {
|
||||
constructor(configService: ConfigService):
|
||||
logger: Logger
|
||||
jwtSecret: Uint8Array
|
||||
encryptionKey: Uint8Array
|
||||
encryptContent(content: string): Promise<string>
|
||||
decryptContent(jwe: string): Promise<string>
|
||||
signContent(content: string): Promise<string>
|
||||
verifyContentSignature(jws: string): Promise<string>
|
||||
getPgpEncryptionKey(): string
|
||||
}
|
||||
class Env
|
||||
class FavoriteInDb
|
||||
class FavoritesController {
|
||||
constructor(favoritesService: FavoritesService):
|
||||
add(req: AuthenticatedRequest, contentId: string): Promise<any>
|
||||
remove(req: AuthenticatedRequest, contentId: string): Promise<any>
|
||||
list(req: AuthenticatedRequest, limit: number, offset: number): Promise<any>
|
||||
}
|
||||
class FavoritesModule
|
||||
class FavoritesRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
findContentById(contentId: string): Promise<any>
|
||||
add(userId: string, contentId: string): Promise<any>
|
||||
remove(userId: string, contentId: string): Promise<any>
|
||||
findByUserId(userId: string, limit: number, offset: number): Promise<any>
|
||||
}
|
||||
class FavoritesService {
|
||||
constructor(favoritesRepository: FavoritesRepository):
|
||||
logger: Logger
|
||||
addFavorite(userId: string, contentId: string): Promise<any>
|
||||
removeFavorite(userId: string, contentId: string): Promise<any>
|
||||
getUserFavorites(userId: string, limit: number, offset: number): Promise<any>
|
||||
}
|
||||
class FindAllOptions {
|
||||
limit: number
|
||||
offset: number
|
||||
sortBy: "trend" | "recent"
|
||||
tag: string
|
||||
category: string
|
||||
author: string
|
||||
query: string
|
||||
favoritesOnly: boolean
|
||||
userId: string
|
||||
}
|
||||
class HTTPLoggerMiddleware {
|
||||
logger: Logger
|
||||
use(request: Request, response: Response, next: NextFunction): void
|
||||
}
|
||||
class HashingService {
|
||||
hashEmail(email: string): Promise<string>
|
||||
hashIp(ip: string): Promise<string>
|
||||
hashSha256(text: string): Promise<string>
|
||||
hashPassword(password: string): Promise<string>
|
||||
verifyPassword(password: string, hash: string): Promise<boolean>
|
||||
}
|
||||
class HealthController {
|
||||
constructor(databaseService: DatabaseService, cacheManager: Cache):
|
||||
check(): Promise<any>
|
||||
}
|
||||
class IMailService {
|
||||
sendEmailValidation(email: string, token: string): Promise<void>
|
||||
sendPasswordReset(email: string, token: string): Promise<void>
|
||||
}
|
||||
class IMediaProcessorStrategy {
|
||||
canHandle(mimeType: string): boolean
|
||||
process(buffer: Buffer, options?: Record<string, unknown>): Promise<MediaProcessingResult>
|
||||
}
|
||||
class IMediaService {
|
||||
scanFile(buffer: Buffer, filename: string): Promise<ScanResult>
|
||||
processImage(buffer: Buffer, format?: "webp" | "avif", resize?: {width?: number; height?: number}): Promise<MediaProcessingResult>
|
||||
processVideo(buffer: Buffer, format?: "webm" | "av1"): Promise<MediaProcessingResult>
|
||||
}
|
||||
class IStorageService {
|
||||
uploadFile(fileName: string, file: Buffer, mimeType: string, metaData?: Record<string, string>, bucketName?: string): Promise<string>
|
||||
getFile(fileName: string, bucketName?: string): Promise<Readable>
|
||||
getFileUrl(fileName: string, expiry?: number, bucketName?: string): Promise<string>
|
||||
getUploadUrl(fileName: string, expiry?: number, bucketName?: string): Promise<string>
|
||||
deleteFile(fileName: string, bucketName?: string): Promise<void>
|
||||
getFileInfo(fileName: string, bucketName?: string): Promise<unknown>
|
||||
moveFile(sourceFileName: string, destinationFileName: string, sourceBucketName?: string, destinationBucketName?: string): Promise<string>
|
||||
getPublicUrl(storageKey: string): string
|
||||
}
|
||||
class ImageProcessorStrategy {
|
||||
logger: Logger
|
||||
canHandle(mimeType: string): boolean
|
||||
process(buffer: Buffer, options?: {format: "webp" | "avif"; resize?: {width?: number; height?: number}}): Promise<MediaProcessingResult>
|
||||
}
|
||||
class JwtService {
|
||||
constructor(configService: ConfigService):
|
||||
logger: Logger
|
||||
jwtSecret: Uint8Array
|
||||
generateJwt(payload: jose.JWTPayload, expiresIn?: string): Promise<string>
|
||||
verifyJwt(token: string): Promise<T>
|
||||
}
|
||||
class LoginDto {
|
||||
email: string
|
||||
password: string
|
||||
}
|
||||
class MailModule
|
||||
class MailService {
|
||||
constructor(mailerService: MailerService, configService: ConfigService):
|
||||
logger: Logger
|
||||
domain: string
|
||||
sendEmailValidation(email: string, token: string): Promise<void>
|
||||
sendPasswordReset(email: string, token: string): Promise<void>
|
||||
}
|
||||
class MediaController {
|
||||
constructor(s3Service: S3Service):
|
||||
logger: Logger
|
||||
getFile(path: string, res: Response): Promise<void>
|
||||
}
|
||||
class MediaModule
|
||||
class MediaProcessingResult {
|
||||
buffer: Buffer
|
||||
mimeType: string
|
||||
extension: string
|
||||
width: number
|
||||
height: number
|
||||
size: number
|
||||
}
|
||||
class MediaProcessingResult {
|
||||
buffer: Buffer
|
||||
mimeType: string
|
||||
extension: string
|
||||
width: number
|
||||
height: number
|
||||
size: number
|
||||
}
|
||||
class MediaService {
|
||||
constructor(configService: ConfigService, imageProcessor: ImageProcessorStrategy, videoProcessor: VideoProcessorStrategy):
|
||||
logger: Logger
|
||||
clamscan: ClamScanner | null
|
||||
isClamAvInitialized: boolean
|
||||
initClamScan(): Promise<void>
|
||||
scanFile(buffer: Buffer, filename: string): Promise<ScanResult>
|
||||
processImage(buffer: Buffer, format?: "webp" | "avif", resize?: {width?: number; height?: number}): Promise<MediaProcessingResult>
|
||||
processVideo(buffer: Buffer, format?: "webm" | "av1"): Promise<MediaProcessingResult>
|
||||
}
|
||||
class NewAuditLogInDb
|
||||
class NewCategoryInDb
|
||||
class NewContentInDb
|
||||
class NewFavoriteInDb
|
||||
class NewReportInDb
|
||||
class NewTagInDb
|
||||
class NewUserInDb
|
||||
class OptionalAuthGuard {
|
||||
constructor(jwtService: JwtService, configService: ConfigService):
|
||||
canActivate(context: ExecutionContext): Promise<boolean>
|
||||
}
|
||||
class PostQuantumService {
|
||||
generatePostQuantumKeyPair(): {publicKey: Uint8Array<ArrayBufferLike>…
|
||||
encapsulate(publicKey: Uint8Array): {cipherText: Uint8Array, sharedSecret: …
|
||||
decapsulate(cipherText: Uint8Array, secretKey: Uint8Array): Uint8Array<ArrayBufferLike>
|
||||
}
|
||||
class PurgeService {
|
||||
constructor(sessionsRepository: SessionsRepository, reportsRepository: ReportsRepository, usersRepository: UsersRepository, contentsRepository: ContentsRepository):
|
||||
logger: Logger
|
||||
purgeExpiredData(): Promise<void>
|
||||
}
|
||||
class RbacRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
findRolesByUserId(userId: string): Promise<any>
|
||||
findPermissionsByUserId(userId: string): Promise<any[]>
|
||||
countRoles(): Promise<number>
|
||||
countAdmins(): Promise<number>
|
||||
createRole(name: string, slug: string, description?: string): Promise<any>
|
||||
assignRole(userId: string, roleSlug: string): Promise<any>
|
||||
}
|
||||
class RbacService {
|
||||
constructor(rbacRepository: RbacRepository):
|
||||
logger: Logger
|
||||
onApplicationBootstrap(): Promise<void>
|
||||
seedRoles(): Promise<void>
|
||||
getUserRoles(userId: string): Promise<any>
|
||||
getUserPermissions(userId: string): Promise<any[]>
|
||||
countAdmins(): Promise<number>
|
||||
assignRoleToUser(userId: string, roleSlug: string): Promise<any>
|
||||
}
|
||||
class RefreshDto {
|
||||
refresh_token: string
|
||||
}
|
||||
class RegisterDto {
|
||||
username: string
|
||||
displayName: string
|
||||
email: string
|
||||
password: string
|
||||
}
|
||||
class ReportInDb
|
||||
class ReportReason {
|
||||
INAPPROPRIATE:
|
||||
SPAM:
|
||||
COPYRIGHT:
|
||||
OTHER:
|
||||
}
|
||||
class ReportStatus {
|
||||
PENDING:
|
||||
REVIEWED:
|
||||
RESOLVED:
|
||||
DISMISSED:
|
||||
}
|
||||
class ReportsController {
|
||||
constructor(reportsService: ReportsService):
|
||||
create(req: AuthenticatedRequest, createReportDto: CreateReportDto): Promise<any>
|
||||
findAll(limit: number, offset: number): Promise<any>
|
||||
updateStatus(id: string, updateReportStatusDto: UpdateReportStatusDto): Promise<any>
|
||||
}
|
||||
class ReportsModule
|
||||
class ReportsRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
create(data: {reporterId: string; contentId?: string; tagId?: string; reason: "inappropriate" | "spam" | "copyright" | "other"; description?: string}): Promise<any>
|
||||
findAll(limit: number, offset: number): Promise<any>
|
||||
updateStatus(id: string, status: "pending" | "reviewed" | "resolved" | "dismissed"): Promise<any>
|
||||
purgeObsolete(now: Date): Promise<any>
|
||||
}
|
||||
class ReportsService {
|
||||
constructor(reportsRepository: ReportsRepository):
|
||||
logger: Logger
|
||||
create(reporterId: string, data: CreateReportDto): Promise<any>
|
||||
findAll(limit: number, offset: number): Promise<any>
|
||||
updateStatus(id: string, status: "pending" | "reviewed" | "resolved" | "dismissed"): Promise<any>
|
||||
}
|
||||
class RequestWithUser {
|
||||
user: {sub?: string, username?: string, id?: …
|
||||
}
|
||||
class RolesGuard {
|
||||
constructor(reflector: Reflector, rbacService: RbacService):
|
||||
canActivate(context: ExecutionContext): Promise<boolean>
|
||||
}
|
||||
class S3Module
|
||||
class S3Service {
|
||||
constructor(configService: ConfigService):
|
||||
logger: Logger
|
||||
minioClient: Minio.Client
|
||||
bucketName: string
|
||||
onModuleInit(): Promise<void>
|
||||
ensureBucketExists(bucketName: string): Promise<void>
|
||||
uploadFile(fileName: string, file: Buffer, mimeType: string, metaData?: Minio.ItemBucketMetadata, bucketName?: string): Promise<string>
|
||||
getFile(fileName: string, bucketName?: string): Promise<stream.Readable>
|
||||
getFileUrl(fileName: string, expiry?: number, bucketName?: string): Promise<string>
|
||||
getUploadUrl(fileName: string, expiry?: number, bucketName?: string): Promise<string>
|
||||
deleteFile(fileName: string, bucketName?: string): Promise<void>
|
||||
getFileInfo(fileName: string, bucketName?: string): Promise<BucketItemStat>
|
||||
moveFile(sourceFileName: string, destinationFileName: string, sourceBucketName?: string, destinationBucketName?: string): Promise<string>
|
||||
getPublicUrl(storageKey: string): string
|
||||
}
|
||||
class ScanResult {
|
||||
isInfected: boolean
|
||||
virusName: string
|
||||
}
|
||||
class ScanResult {
|
||||
isInfected: boolean
|
||||
virusName: string
|
||||
}
|
||||
class SessionData {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
userId: string
|
||||
}
|
||||
class SessionsModule
|
||||
class SessionsRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
create(data: {userId: string; refreshToken: string; userAgent?: string; ipHash?: string | null; expiresAt: Date}): Promise<any>
|
||||
findValidByRefreshToken(refreshToken: string): Promise<any>
|
||||
update(sessionId: string, data: Record<string, unknown>): Promise<any>
|
||||
revoke(sessionId: string): Promise<void>
|
||||
revokeAllByUserId(userId: string): Promise<void>
|
||||
purgeExpired(now: Date): Promise<any>
|
||||
}
|
||||
class SessionsService {
|
||||
constructor(sessionsRepository: SessionsRepository, hashingService: HashingService, jwtService: JwtService):
|
||||
createSession(userId: string, userAgent?: string, ip?: string): Promise<any>
|
||||
refreshSession(oldRefreshToken: string): Promise<any>
|
||||
revokeSession(sessionId: string): Promise<void>
|
||||
revokeAllUserSessions(userId: string): Promise<void>
|
||||
}
|
||||
class TagInDb
|
||||
class TagsController {
|
||||
constructor(tagsService: TagsService):
|
||||
findAll(limit: number, offset: number, query?: string, sort?: "popular" | "recent"): Promise<any>
|
||||
}
|
||||
class TagsModule
|
||||
class TagsRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
findAll(options: {limit: number; offset: number; query?: string; sortBy?: "popular" | "recent"}): Promise<any>
|
||||
}
|
||||
class TagsService {
|
||||
constructor(tagsRepository: TagsRepository):
|
||||
logger: Logger
|
||||
findAll(options: {limit: number; offset: number; query?: string; sortBy?: "popular" | "recent"}): Promise<any>
|
||||
}
|
||||
class UpdateCategoryDto
|
||||
class UpdateConsentDto {
|
||||
termsVersion: string
|
||||
privacyVersion: string
|
||||
}
|
||||
class UpdateReportStatusDto {
|
||||
status: "pending" | "reviewed" | "resolved" | "…
|
||||
}
|
||||
class UpdateUserDto {
|
||||
displayName: string
|
||||
bio: string
|
||||
avatarUrl: string
|
||||
status: "active" | "verification" | "suspended"…
|
||||
role: string
|
||||
}
|
||||
class UploadContentDto {
|
||||
type: "meme" | "gif"
|
||||
title: string
|
||||
categoryId: string
|
||||
tags: string[]
|
||||
}
|
||||
class UserInDb
|
||||
class UsersController {
|
||||
constructor(usersService: UsersService, authService: AuthService):
|
||||
findAll(limit: number, offset: number): Promise<{data: any, totalCount: any}>
|
||||
findPublicProfile(username: string): Promise<any>
|
||||
findMe(req: AuthenticatedRequest): Promise<any>
|
||||
exportMe(req: AuthenticatedRequest): Promise<null | {profile: any, contents:…
|
||||
updateMe(req: AuthenticatedRequest, updateUserDto: UpdateUserDto): Promise<any>
|
||||
updateAvatar(req: AuthenticatedRequest, file: Express.Multer.File): Promise<any>
|
||||
updateConsent(req: AuthenticatedRequest, consentDto: UpdateConsentDto): Promise<any>
|
||||
removeMe(req: AuthenticatedRequest): Promise<any>
|
||||
removeAdmin(uuid: string): Promise<any>
|
||||
updateAdmin(uuid: string, updateUserDto: UpdateUserDto): Promise<any>
|
||||
setup2fa(req: AuthenticatedRequest): Promise<{secret: string, qrCodeDataUrl:…
|
||||
enable2fa(req: AuthenticatedRequest, token: string): Promise<{message: string}>
|
||||
disable2fa(req: AuthenticatedRequest, token: string): Promise<{message: string}>
|
||||
}
|
||||
class UsersModule
|
||||
class UsersRepository {
|
||||
constructor(databaseService: DatabaseService):
|
||||
create(data: {username: string; email: string; passwordHash: string; emailHash: string}): Promise<any>
|
||||
findByEmailHash(emailHash: string): Promise<any>
|
||||
findOneWithPrivateData(uuid: string): Promise<any>
|
||||
countAll(): Promise<number>
|
||||
findAll(limit: number, offset: number): Promise<any>
|
||||
findByUsername(username: string): Promise<any>
|
||||
findOne(uuid: string): Promise<any>
|
||||
update(uuid: string, data: Partial<typeof users.$inferInsert>): Promise<any>
|
||||
getTwoFactorSecret(uuid: string): Promise<any>
|
||||
getUserContents(uuid: string): Promise<any>
|
||||
getUserFavorites(uuid: string): Promise<any>
|
||||
softDeleteUserAndContents(uuid: string): Promise<any>
|
||||
purgeDeleted(before: Date): Promise<any>
|
||||
}
|
||||
class UsersService {
|
||||
constructor(usersRepository: UsersRepository, cacheManager: Cache, rbacService: RbacService, mediaService: IMediaService, s3Service: IStorageService):
|
||||
logger: Logger
|
||||
clearUserCache(username?: string): Promise<void>
|
||||
create(data: {username: string; email: string; passwordHash: string; emailHash: string}): Promise<any>
|
||||
findByEmailHash(emailHash: string): Promise<any>
|
||||
findOneWithPrivateData(uuid: string): Promise<any>
|
||||
findAll(limit: number, offset: number): Promise<{data: any, totalCount: any}>
|
||||
findPublicProfile(username: string): Promise<any>
|
||||
findOne(uuid: string): Promise<any>
|
||||
update(uuid: string, data: UpdateUserDto): Promise<any>
|
||||
updateAvatar(uuid: string, file: Express.Multer.File): Promise<any>
|
||||
updateConsent(uuid: string, termsVersion: string, privacyVersion: string): Promise<any>
|
||||
setTwoFactorSecret(uuid: string, secret: string): Promise<any>
|
||||
toggleTwoFactor(uuid: string, enabled: boolean): Promise<any>
|
||||
getTwoFactorSecret(uuid: string): Promise<string | null>
|
||||
exportUserData(uuid: string): Promise<null | {profile: any, contents:…
|
||||
remove(uuid: string): Promise<any>
|
||||
}
|
||||
class Verify2faDto {
|
||||
userId: string
|
||||
token: string
|
||||
}
|
||||
class VideoProcessorStrategy {
|
||||
logger: Logger
|
||||
canHandle(mimeType: string): boolean
|
||||
process(buffer: Buffer, options?: {format: "webm" | "av1"}): Promise<MediaProcessingResult>
|
||||
}
|
||||
|
||||
AdminController -[#595959,dashed]-> AdminService
|
||||
AdminService -[#595959,dashed]-> CategoriesRepository
|
||||
AdminService -[#595959,dashed]-> ContentsRepository
|
||||
AdminService -[#595959,dashed]-> UsersRepository
|
||||
AllExceptionsFilter -[#595959,dashed]-> RequestWithUser
|
||||
ApiKeysController -[#595959,dashed]-> ApiKeysService
|
||||
ApiKeysController -[#595959,dashed]-> AuthenticatedRequest
|
||||
ApiKeysController -[#595959,dashed]-> CreateApiKeyDto
|
||||
ApiKeysRepository -[#595959,dashed]-> DatabaseService
|
||||
ApiKeysService -[#595959,dashed]-> ApiKeysRepository
|
||||
ApiKeysService -[#595959,dashed]-> ApiKeysService
|
||||
ApiKeysService -[#595959,dashed]-> HashingService
|
||||
AppController -[#595959,dashed]-> AppService
|
||||
AppModule -[#595959,dashed]-> CrawlerDetectionMiddleware
|
||||
AppModule -[#595959,dashed]-> HTTPLoggerMiddleware
|
||||
AuthController -[#595959,dashed]-> AuthService
|
||||
AuthController -[#595959,dashed]-> BootstrapService
|
||||
AuthController -[#595959,dashed]-> LoginDto
|
||||
AuthController -[#595959,dashed]-> RegisterDto
|
||||
AuthController -[#595959,dashed]-> SessionData
|
||||
AuthController -[#595959,dashed]-> Verify2faDto
|
||||
AuthGuard -[#595959,dashed]-> JwtService
|
||||
AuthGuard -[#595959,dashed]-> SessionData
|
||||
AuthService -[#595959,dashed]-> AuthService
|
||||
AuthService -[#595959,dashed]-> HashingService
|
||||
AuthService -[#595959,dashed]-> JwtService
|
||||
AuthService -[#595959,dashed]-> LoginDto
|
||||
AuthService -[#595959,dashed]-> RegisterDto
|
||||
AuthService -[#595959,dashed]-> SessionsService
|
||||
AuthService -[#595959,dashed]-> UsersService
|
||||
BootstrapService -[#595959,dashed]-> BootstrapService
|
||||
BootstrapService -[#595959,dashed]-> RbacService
|
||||
BootstrapService -[#595959,dashed]-> UsersService
|
||||
CategoriesController -[#595959,dashed]-> AuthGuard
|
||||
CategoriesController -[#595959,dashed]-> CategoriesService
|
||||
CategoriesController -[#595959,dashed]-> CreateCategoryDto
|
||||
CategoriesController -[#595959,dashed]-> RolesGuard
|
||||
CategoriesController -[#595959,dashed]-> UpdateCategoryDto
|
||||
CategoriesRepository -[#595959,dashed]-> CreateCategoryDto
|
||||
CategoriesRepository -[#595959,dashed]-> DatabaseService
|
||||
CategoriesRepository -[#595959,dashed]-> UpdateCategoryDto
|
||||
CategoriesService -[#595959,dashed]-> CategoriesRepository
|
||||
CategoriesService -[#595959,dashed]-> CategoriesService
|
||||
CategoriesService -[#595959,dashed]-> CreateCategoryDto
|
||||
CategoriesService -[#595959,dashed]-> UpdateCategoryDto
|
||||
ContentsController -[#595959,dashed]-> AuthGuard
|
||||
ContentsController -[#595959,dashed]-> AuthenticatedRequest
|
||||
ContentsController -[#595959,dashed]-> ContentsService
|
||||
ContentsController -[#595959,dashed]-> CreateContentDto
|
||||
ContentsController -[#595959,dashed]-> OptionalAuthGuard
|
||||
ContentsController -[#595959,dashed]-> RolesGuard
|
||||
ContentsController -[#595959,dashed]-> UploadContentDto
|
||||
ContentsRepository -[#595959,dashed]-> DatabaseService
|
||||
ContentsRepository -[#595959,dashed]-> FindAllOptions
|
||||
ContentsRepository -[#595959,dashed]-> NewContentInDb
|
||||
ContentsService -[#595959,dashed]-> ContentsRepository
|
||||
ContentsService -[#595959,dashed]-> ContentsService
|
||||
ContentsService -[#595959,dashed]-> CreateContentDto
|
||||
ContentsService -[#595959,dashed]-> IMediaService
|
||||
ContentsService -[#595959,dashed]-> IStorageService
|
||||
ContentsService -[#595959,dashed]-> MediaProcessingResult
|
||||
ContentsService -[#595959,dashed]-> MediaService
|
||||
ContentsService -[#595959,dashed]-> S3Service
|
||||
ContentsService -[#595959,dashed]-> UploadContentDto
|
||||
CryptoService -[#595959,dashed]-> EncryptionService
|
||||
CryptoService -[#595959,dashed]-> HashingService
|
||||
CryptoService -[#595959,dashed]-> JwtService
|
||||
CryptoService -[#595959,dashed]-> PostQuantumService
|
||||
DatabaseService -[#595959,dashed]-> DatabaseService
|
||||
EncryptionService -[#595959,dashed]-> EncryptionService
|
||||
FavoritesController -[#595959,dashed]-> AuthenticatedRequest
|
||||
FavoritesController -[#595959,dashed]-> FavoritesService
|
||||
FavoritesRepository -[#595959,dashed]-> DatabaseService
|
||||
FavoritesService -[#595959,dashed]-> FavoritesRepository
|
||||
FavoritesService -[#595959,dashed]-> FavoritesService
|
||||
HealthController -[#595959,dashed]-> DatabaseService
|
||||
IMediaProcessorStrategy -[#595959,dashed]-> MediaProcessingResult
|
||||
IMediaService -[#595959,dashed]-> MediaProcessingResult
|
||||
IMediaService -[#595959,dashed]-> ScanResult
|
||||
ImageProcessorStrategy -[#008200,dashed]-^ IMediaProcessorStrategy
|
||||
ImageProcessorStrategy -[#595959,dashed]-> ImageProcessorStrategy
|
||||
ImageProcessorStrategy -[#595959,dashed]-> MediaProcessingResult
|
||||
JwtService -[#595959,dashed]-> JwtService
|
||||
MailService -[#008200,dashed]-^ IMailService
|
||||
MailService -[#595959,dashed]-> MailService
|
||||
MediaController -[#595959,dashed]-> MediaController
|
||||
MediaController -[#595959,dashed]-> S3Service
|
||||
MediaService -[#595959,dashed]-> ClamScanner
|
||||
MediaService -[#008200,dashed]-^ IMediaService
|
||||
MediaService -[#595959,dashed]-> ImageProcessorStrategy
|
||||
MediaService -[#595959,dashed]-> MediaProcessingResult
|
||||
MediaService -[#595959,dashed]-> MediaService
|
||||
MediaService -[#595959,dashed]-> ScanResult
|
||||
MediaService -[#595959,dashed]-> VideoProcessorStrategy
|
||||
OptionalAuthGuard -[#595959,dashed]-> JwtService
|
||||
OptionalAuthGuard -[#595959,dashed]-> SessionData
|
||||
PurgeService -[#595959,dashed]-> ContentsRepository
|
||||
PurgeService -[#595959,dashed]-> PurgeService
|
||||
PurgeService -[#595959,dashed]-> ReportsRepository
|
||||
PurgeService -[#595959,dashed]-> SessionsRepository
|
||||
PurgeService -[#595959,dashed]-> UsersRepository
|
||||
RbacRepository -[#595959,dashed]-> DatabaseService
|
||||
RbacService -[#595959,dashed]-> RbacRepository
|
||||
RbacService -[#595959,dashed]-> RbacService
|
||||
ReportsController -[#595959,dashed]-> AuthGuard
|
||||
ReportsController -[#595959,dashed]-> AuthenticatedRequest
|
||||
ReportsController -[#595959,dashed]-> CreateReportDto
|
||||
ReportsController -[#595959,dashed]-> ReportsService
|
||||
ReportsController -[#595959,dashed]-> RolesGuard
|
||||
ReportsController -[#595959,dashed]-> UpdateReportStatusDto
|
||||
ReportsRepository -[#595959,dashed]-> DatabaseService
|
||||
ReportsService -[#595959,dashed]-> CreateReportDto
|
||||
ReportsService -[#595959,dashed]-> ReportsRepository
|
||||
ReportsService -[#595959,dashed]-> ReportsService
|
||||
RolesGuard -[#595959,dashed]-> RbacService
|
||||
S3Service -[#008200,dashed]-^ IStorageService
|
||||
S3Service -[#595959,dashed]-> S3Service
|
||||
SessionsRepository -[#595959,dashed]-> DatabaseService
|
||||
SessionsService -[#595959,dashed]-> HashingService
|
||||
SessionsService -[#595959,dashed]-> JwtService
|
||||
SessionsService -[#595959,dashed]-> SessionsRepository
|
||||
TagsController -[#595959,dashed]-> TagsService
|
||||
TagsRepository -[#595959,dashed]-> DatabaseService
|
||||
TagsService -[#595959,dashed]-> TagsRepository
|
||||
TagsService -[#595959,dashed]-> TagsService
|
||||
UsersController -[#595959,dashed]-> AuthGuard
|
||||
UsersController -[#595959,dashed]-> AuthService
|
||||
UsersController -[#595959,dashed]-> AuthenticatedRequest
|
||||
UsersController -[#595959,dashed]-> RolesGuard
|
||||
UsersController -[#595959,dashed]-> UpdateConsentDto
|
||||
UsersController -[#595959,dashed]-> UpdateUserDto
|
||||
UsersController -[#595959,dashed]-> UsersService
|
||||
UsersRepository -[#595959,dashed]-> DatabaseService
|
||||
UsersService -[#595959,dashed]-> IMediaService
|
||||
UsersService -[#595959,dashed]-> IStorageService
|
||||
UsersService -[#595959,dashed]-> MediaService
|
||||
UsersService -[#595959,dashed]-> RbacService
|
||||
UsersService -[#595959,dashed]-> S3Service
|
||||
UsersService -[#595959,dashed]-> UpdateUserDto
|
||||
UsersService -[#595959,dashed]-> UsersRepository
|
||||
UsersService -[#595959,dashed]-> UsersService
|
||||
VideoProcessorStrategy -[#008200,dashed]-^ IMediaProcessorStrategy
|
||||
VideoProcessorStrategy -[#595959,dashed]-> MediaProcessingResult
|
||||
VideoProcessorStrategy -[#595959,dashed]-> VideoProcessorStrategy
|
||||
@enduml
|
||||
Reference in New Issue
Block a user