refactor(nestjs): hook up auth endpoints

This commit is contained in:
Ahmed Bouhuolia
2025-05-08 18:10:02 +02:00
parent 401b3dc111
commit f78d6efe27
26 changed files with 304 additions and 111 deletions

View File

@@ -8,6 +8,7 @@ import {
Req,
Res,
Next,
HttpCode,
} from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { BuildOrganizationService } from './commands/BuildOrganization.service';
@@ -32,60 +33,52 @@ export class OrganizationController {
) {}
@Post('build')
@HttpCode(200)
@ApiOperation({ summary: 'Build organization database' })
@ApiBody({ type: BuildOrganizationDto })
@ApiResponse({
status: 200,
description: 'The organization database has been initialized',
})
async build(
@Body() buildDTO: BuildOrganizationDto,
@Req() req: Request,
@Res() res: Response,
) {
async build(@Body() buildDTO: BuildOrganizationDto) {
const result = await this.buildOrganizationService.buildRunJob(buildDTO);
return res.status(200).send({
return {
type: 'success',
code: 'ORGANIZATION.DATABASE.INITIALIZED',
message: 'The organization database has been initialized.',
data: result,
});
};
}
@Get('current')
@HttpCode(200)
@ApiOperation({ summary: 'Get current organization' })
@ApiResponse({
status: 200,
description: 'Returns the current organization',
})
async currentOrganization(
@Req() req: Request,
@Res() res: Response,
@Next() next: NextFunction,
) {
async currentOrganization() {
const organization =
await this.getCurrentOrgService.getCurrentOrganization();
return res.status(200).send({ organization });
return { organization };
}
@Put()
@HttpCode(200)
@ApiOperation({ summary: 'Update organization information' })
@ApiBody({ type: UpdateOrganizationDto })
@ApiResponse({
status: 200,
description: 'Organization information has been updated successfully',
})
async updateOrganization(
@Body() updateDTO: UpdateOrganizationDto,
@Res() res: Response,
) {
async updateOrganization(@Body() updateDTO: UpdateOrganizationDto) {
await this.updateOrganizationService.execute(updateDTO);
return res.status(200).send({
return {
code: 200,
message: 'Organization information has been updated successfully.',
});
};
}
}

View File

@@ -10,6 +10,8 @@ import { CommandOrganizationValidators } from './commands/CommandOrganizationVal
import { TenancyContext } from '../Tenancy/TenancyContext.service';
import { TenantDBManagerModule } from '../TenantDBManager/TenantDBManager.module';
import { OrganizationBaseCurrencyLocking } from './Organization/OrganizationBaseCurrencyLocking.service';
import { SyncSystemUserToTenantService } from './commands/SyncSystemUserToTenant.service';
import { SyncSystemUserToTenantSubscriber } from './subscribers/SyncSystemUserToTenant.subscriber';
@Module({
providers: [
@@ -20,6 +22,8 @@ import { OrganizationBaseCurrencyLocking } from './Organization/OrganizationBase
OrganizationBuildProcessor,
CommandOrganizationValidators,
OrganizationBaseCurrencyLocking,
SyncSystemUserToTenantService,
SyncSystemUserToTenantSubscriber
],
imports: [
BullModule.registerQueue({ name: OrganizationBuildQueue }),

View File

@@ -0,0 +1,46 @@
import { Inject, Injectable } from '@nestjs/common';
import { pick } from 'lodash';
import { Role } from '@/modules/Roles/models/Role.model';
import { SystemUser } from '@/modules/System/models/SystemUser';
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
import { TenantUser } from '@/modules/Tenancy/TenancyModels/models/TenantUser.model';
@Injectable()
export class SyncSystemUserToTenantService {
constructor(
@Inject(TenantUser.name)
private readonly tenantUserModel: TenantModelProxy<typeof TenantUser>,
@Inject(Role.name)
private readonly roleModel: TenantModelProxy<typeof Role>,
@Inject(SystemUser.name)
private readonly systemUserModel: typeof SystemUser,
) {}
/**
* Syncs system user to tenant user.
* @param {number} systemUserId - System user id.
*/
public async syncSystemUserToTenant(systemUserId: number) {
const adminRole = await this.roleModel().query().findOne('slug', 'admin');
const systemUser = await this.systemUserModel
.query()
.findById(systemUserId);
await this.tenantUserModel()
.query()
.insert({
...pick(systemUser, [
'firstName',
'lastName',
'phoneNumber',
'email',
'active',
'inviteAcceptedAt',
]),
systemUserId: systemUser.id,
roleId: adminRole.id,
});
}
}

View File

@@ -2,6 +2,7 @@ import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
import { throwIfTenantNotExists } from '../Organization/_utils';
import { TenantModel } from '@/modules/System/models/TenantModel';
import { Injectable } from '@nestjs/common';
import { ModelObject } from 'objection';
@Injectable()
export class GetCurrentOrganizationService {
@@ -12,7 +13,7 @@ export class GetCurrentOrganizationService {
* @param {number} tenantId
* @returns {Promise<ITenant[]>}
*/
async getCurrentOrganization(): Promise<TenantModel> {
async getCurrentOrganization(): Promise<ModelObject<TenantModel>> {
const tenant = await this.tenancyContext
.getTenant()
.withGraphFetched('subscriptions')

View File

@@ -0,0 +1,19 @@
import { OnEvent } from '@nestjs/event-emitter';
import { SyncSystemUserToTenantService } from '../commands/SyncSystemUserToTenant.service';
import { events } from '@/common/events/events';
import { IOrganizationBuildEventPayload } from '../Organization.types';
import { Injectable } from '@nestjs/common';
@Injectable()
export class SyncSystemUserToTenantSubscriber {
constructor(
private readonly syncSystemUserToTenantService: SyncSystemUserToTenantService,
) {}
@OnEvent(events.organization.build)
async onOrgBuildSyncSystemUser({ systemUser }: IOrganizationBuildEventPayload) {
await this.syncSystemUserToTenantService.syncSystemUserToTenant(
systemUser.id,
);
}
}