diff --git a/src/auth/application/use-cases/sign-up-verify.use-case.ts b/src/auth/application/use-cases/sign-up-verify.use-case.ts index 4de0228..6c950b4 100644 --- a/src/auth/application/use-cases/sign-up-verify.use-case.ts +++ b/src/auth/application/use-cases/sign-up-verify.use-case.ts @@ -11,10 +11,17 @@ import { CACHE_SERVICE } from '@shared/adapters/cache/constants'; import { ICacheService } from '@shared/adapters/cache/ports'; import { SIGNUP_CACHE_KEY } from '@core/auth/infrastructure/constants'; import { SignUpCacheData } from '@core/auth/application/interfaces'; +import { InjectQueue } from '@nestjs/bullmq'; +import { AuthQueues } from '@core/auth/domain/enums'; +import { Queue } from 'bullmq'; +import { CreateUserWorkspaceEvent } from '@core/auth/domain/events/create-user-workspace.event'; +import { AuthUserJobs } from '@core/auth/domain/enums/auth-jobs.enum'; @Injectable() export class SignUpVerifyUseCase { constructor( + @InjectQueue(AuthQueues.AUTH_USER) + private readonly queue: Queue, @Inject(CACHE_SERVICE) private readonly cacheService: ICacheService, @Inject('ISessionRepository') @@ -102,6 +109,9 @@ export class SignUpVerifyUseCase { await this.cacheService.removeOne(SIGNUP_CACHE_KEY(dto.email)); + const event = new CreateUserWorkspaceEvent(user.id, user.firstName); + await this.queue.add(AuthUserJobs.CREATE_WORKSPACE, event); + return { success: true, tokens: { access, refresh }, diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index f66186d..6677e99 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,5 +1,5 @@ import { BullModule } from '@nestjs/bullmq'; -import { Module, forwardRef } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { JwtModule } from '@nestjs/jwt'; import { UserModule } from '@core/user'; @@ -8,12 +8,14 @@ import { AuthFacade } from './application/auth.facade'; import { AuthUseCases } from './application/use-cases'; import { AuthQueues } from './domain/enums'; import { TokenService } from './infrastructure/security'; -import { MailProcessor } from './infrastructure/workers'; +import { MailProcessor, UserProcessor } from './infrastructure/workers'; import { MailAdapter } from '@shared/adapters/mail'; import { STRATEGIES } from './infrastructure/strategies'; import { REPOSITORIES } from './infrastructure/persistence/repositories'; +import { TeamsModule } from '@core/teams'; +import { ProjectsModule } from '@core/projects'; -const WORKERS = [MailProcessor]; +const WORKERS = [MailProcessor, UserProcessor]; @Module({ imports: [ @@ -37,10 +39,10 @@ const WORKERS = [MailProcessor]; }, }), }), - BullModule.registerQueue({ - name: AuthQueues.AUTH_MAIL, - }), + BullModule.registerQueue({ name: AuthQueues.AUTH_MAIL }, { name: AuthQueues.AUTH_USER }), forwardRef(() => UserModule), + TeamsModule, + ProjectsModule, ], controllers: CONTROLLERS, providers: [ diff --git a/src/auth/domain/enums/mail-jobs.enum.ts b/src/auth/domain/enums/auth-jobs.enum.ts similarity index 68% rename from src/auth/domain/enums/mail-jobs.enum.ts rename to src/auth/domain/enums/auth-jobs.enum.ts index e9ff5ab..edfcde8 100644 --- a/src/auth/domain/enums/mail-jobs.enum.ts +++ b/src/auth/domain/enums/auth-jobs.enum.ts @@ -1,5 +1,6 @@ export enum AuthQueues { AUTH_MAIL = 'AUTH_MAIL_QUEUE', + AUTH_USER = 'AUTH_USER_QUEUE', } export enum AuthMailJobs { @@ -7,3 +8,7 @@ export enum AuthMailJobs { SEND_RESET_PASSWORD = 'AUTH_SEND_RESET_PASSWORD', SEND_CHANGE_EMAIL = 'AUTH_SEND_CHANGE_EMAIL', } + +export enum AuthUserJobs { + CREATE_WORKSPACE = 'AUTH_CREATE_WORKSPACE', +} diff --git a/src/auth/domain/enums/index.ts b/src/auth/domain/enums/index.ts index a2f814f..4922399 100644 --- a/src/auth/domain/enums/index.ts +++ b/src/auth/domain/enums/index.ts @@ -1 +1 @@ -export { AuthMailJobs, AuthQueues } from './mail-jobs.enum'; +export { AuthMailJobs, AuthUserJobs, AuthQueues } from './auth-jobs.enum'; diff --git a/src/auth/domain/events/create-user-workspace.event.ts b/src/auth/domain/events/create-user-workspace.event.ts new file mode 100644 index 0000000..cad0e71 --- /dev/null +++ b/src/auth/domain/events/create-user-workspace.event.ts @@ -0,0 +1,6 @@ +export class CreateUserWorkspaceEvent { + constructor( + public userId: string, + public username: string, + ) {} +} diff --git a/src/auth/infrastructure/workers/index.ts b/src/auth/infrastructure/workers/index.ts index d20e25d..03791b1 100644 --- a/src/auth/infrastructure/workers/index.ts +++ b/src/auth/infrastructure/workers/index.ts @@ -1 +1,2 @@ export { MailProcessor } from './mail.processor'; +export { UserProcessor } from './user.processor'; diff --git a/src/auth/infrastructure/workers/user.processor.ts b/src/auth/infrastructure/workers/user.processor.ts new file mode 100644 index 0000000..82200ee --- /dev/null +++ b/src/auth/infrastructure/workers/user.processor.ts @@ -0,0 +1,61 @@ +import { Processor, WorkerHost } from '@nestjs/bullmq'; +import { AuthQueues } from '@core/auth/domain/enums'; +import { Job } from 'bullmq'; +import { CreateTeamUseCase } from '@core/teams/application/use-cases'; +import { CreateProjectUseCase } from '@core/projects/application/use-cases'; +import { AuthUserJobs } from '@core/auth/domain/enums/auth-jobs.enum'; +import { CreateUserWorkspaceEvent } from '@core/auth/domain/events/create-user-workspace.event'; + +@Processor(AuthQueues.AUTH_USER) +export class UserProcessor extends WorkerHost { + constructor( + private readonly createTeamUseCase: CreateTeamUseCase, + private readonly createProjectUseCase: CreateProjectUseCase, + ) { + super(); + } + + async process(job: Job): Promise { + await job.log(`[START] Job ID: ${job.id} | Type: ${job.name}`); + + try { + switch (job.name) { + case AuthUserJobs.CREATE_WORKSPACE: + await this.createWorkspace(job); + break; + + default: + await job.log(`[WRN] No handler for job: ${job.name}`); + await job.updateProgress(100); + } + + await job.log(`[DONE] Job ${job.id} processed`); + } catch (error) { + await job.log(error); + + throw error; + } + } + + private createWorkspace = async (job: Job) => { + const { userId, username } = job.data; + + await job.log(`Start creating a workspace for ${username}`); + await job.updateProgress(20); + + const team = await this.createTeamUseCase.execute(userId, { + name: username, + description: `Personal team for ${username}`, + }); + + await this.createProjectUseCase.execute(userId, team.teamId, { + name: `${username}'s Project`, + description: `Personal project for ${username}`, + key: username.slice(0, 10).toUpperCase(), + visibility: 'private', + }); + + await job.log(`Successfully created a workspace for ${username}`); + await job.updateProgress(100); + }; +} diff --git a/src/projects/projects.module.ts b/src/projects/projects.module.ts index 3689739..3de954e 100644 --- a/src/projects/projects.module.ts +++ b/src/projects/projects.module.ts @@ -2,7 +2,12 @@ import { forwardRef, Module } from '@nestjs/common'; import { ProjectsRepository } from './infrastructure/persistence/repositories'; import { TeamsModule } from '@core/teams'; import { ProjectsController } from './application/controller'; -import { FindProjectQuery, ProjectQueries, ProjectUseCases } from './application/use-cases'; +import { + CreateProjectUseCase, + FindProjectQuery, + ProjectQueries, + ProjectUseCases, +} from './application/use-cases'; import { POLICIES, ProjectAccessPolicy } from './domain/policy'; import { ProjectsFacade } from './application/projects.facade'; @@ -15,6 +20,6 @@ const REPOSITORY = { imports: [forwardRef(() => TeamsModule)], controllers: [ProjectsController], providers: [REPOSITORY, ...POLICIES, ...ProjectUseCases, ...ProjectQueries, ProjectsFacade], - exports: [FindProjectQuery, ProjectAccessPolicy], + exports: [FindProjectQuery, ProjectAccessPolicy, CreateProjectUseCase], }) export class ProjectsModule {} diff --git a/src/teams/application/use-cases/index.ts b/src/teams/application/use-cases/index.ts index 08d0693..e5849ba 100644 --- a/src/teams/application/use-cases/index.ts +++ b/src/teams/application/use-cases/index.ts @@ -58,3 +58,4 @@ export const TeamUseCases = [ ]; export const TEAM_EXTERNAL_QUERIES = [FindTeamQuery, FindTeamMemberQuery]; +export const TEAM_EXTERNAL_COMMANDS = [CreateTeamUseCase]; diff --git a/src/teams/teams.module.ts b/src/teams/teams.module.ts index 922783f..34593b8 100644 --- a/src/teams/teams.module.ts +++ b/src/teams/teams.module.ts @@ -9,7 +9,12 @@ import { BullModule } from '@nestjs/bullmq'; import { TeamsRepository } from './infrastructure/persistence/repositories'; import { TeamQueues } from './domain/enums'; import { TeamsFacade } from './application/team.facade'; -import { TeamQueries, TeamUseCases, TEAM_EXTERNAL_QUERIES } from './application/use-cases'; +import { + TeamQueries, + TeamUseCases, + TEAM_EXTERNAL_QUERIES, + TEAM_EXTERNAL_COMMANDS, +} from './application/use-cases'; import { TeamMemberPolicy } from './domain/policy'; import { MailProcessor } from '@core/teams/infrastructure/workers'; import { LISTENERS } from './infrastructure/listeners'; @@ -37,6 +42,6 @@ const REPOSITORY = { provide: 'ITeamsRepository', useClass: TeamsRepository }; TeamsFacade, MailProcessor, ], - exports: [...TEAM_EXTERNAL_QUERIES], + exports: [...TEAM_EXTERNAL_QUERIES, ...TEAM_EXTERNAL_COMMANDS], }) export class TeamsModule {}