diff --git a/apps/api/src/app/organization/e2e/update-organization.e2e.ts b/apps/api/src/app/organization/e2e/update-organization.e2e.ts new file mode 100644 index 000000000000..0b70814efc70 --- /dev/null +++ b/apps/api/src/app/organization/e2e/update-organization.e2e.ts @@ -0,0 +1,25 @@ +import { OrganizationRepository } from '@novu/dal'; +import { UserSession } from '@novu/testing'; +import { expect } from 'chai'; + +describe('Update Organization - /organizations (PUT)', function () { + let session: UserSession; + const organizationRepository = new OrganizationRepository(); + + beforeEach(async () => { + session = new UserSession(); + await session.initialize(); + }); + + it('should update the organization name', async function () { + const payload = { + name: 'Liberty Powers', + }; + + await session.testAgent.put('/v1/organizations').send(payload); + + const organization = await organizationRepository.findById(session.organization._id); + + expect(organization.name).to.equal(payload.name); + }); +}); diff --git a/apps/api/src/app/organization/organization.controller.ts b/apps/api/src/app/organization/organization.controller.ts index 57ecca86db3e..498988f3bfb0 100644 --- a/apps/api/src/app/organization/organization.controller.ts +++ b/apps/api/src/app/organization/organization.controller.ts @@ -33,6 +33,8 @@ import { IGetOrganizationsDto } from './dtos/get-organizations.dto'; import { GetMyOrganization } from './usecases/get-my-organization/get-my-organization.usecase'; import { GetMyOrganizationCommand } from './usecases/get-my-organization/get-my-organization.command'; import { IGetMyOrganizationDto } from './dtos/get-my-organization.dto'; +import { UpdateOrganizationCommand } from './usecases/update-organization/update-organization-command'; +import { UpdateOrganization } from './usecases/update-organization/update-organization.usecase'; @Controller('/organizations') @UseInterceptors(ClassSerializerInterceptor) @@ -47,7 +49,8 @@ export class OrganizationController { private changeMemberRoleUsecase: ChangeMemberRole, private updateBrandingDetailsUsecase: UpdateBrandingDetails, private getOrganizationsUsecase: GetOrganizations, - private getMyOrganizationUsecase: GetMyOrganization + private getMyOrganizationUsecase: GetMyOrganization, + private updateOrganizationUsecase: UpdateOrganization ) {} @Post('/') @@ -154,4 +157,15 @@ export class OrganizationController { }) ); } + + @Put('/') + async updateOrganization(@UserSession() user: IJwtPayload, @Body() body: { name: string }) { + return await this.updateOrganizationUsecase.execute( + UpdateOrganizationCommand.create({ + name: body.name, + userId: user._id, + id: user.organizationId, + }) + ); + } } diff --git a/apps/api/src/app/organization/usecases/index.ts b/apps/api/src/app/organization/usecases/index.ts index 0aefd178e451..7a1b606ffd02 100644 --- a/apps/api/src/app/organization/usecases/index.ts +++ b/apps/api/src/app/organization/usecases/index.ts @@ -7,6 +7,7 @@ import { ChangeMemberRole } from './membership/change-member-role/change-member- import { UpdateBrandingDetails } from './update-branding-details/update-branding-details.usecase'; import { GetOrganizations } from './get-organizations/get-organizations.usecase'; import { GetMyOrganization } from './get-my-organization/get-my-organization.usecase'; +import { UpdateOrganization } from './update-organization/update-organization.usecase'; export const USE_CASES = [ AddMember, @@ -18,4 +19,5 @@ export const USE_CASES = [ UpdateBrandingDetails, GetOrganizations, GetMyOrganization, + UpdateOrganization, ]; diff --git a/apps/api/src/app/organization/usecases/update-organization/update-organization-command.ts b/apps/api/src/app/organization/usecases/update-organization/update-organization-command.ts new file mode 100644 index 000000000000..cb3f1dfd6f06 --- /dev/null +++ b/apps/api/src/app/organization/usecases/update-organization/update-organization-command.ts @@ -0,0 +1,9 @@ +import { IsDefined } from 'class-validator'; +import { AuthenticatedCommand } from '../../../shared/commands/authenticated.command'; + +export class UpdateOrganizationCommand extends AuthenticatedCommand { + @IsDefined() + public readonly id: string; + + name: string; +} diff --git a/apps/api/src/app/organization/usecases/update-organization/update-organization.usecase.ts b/apps/api/src/app/organization/usecases/update-organization/update-organization.usecase.ts new file mode 100644 index 000000000000..ef4fa32115e9 --- /dev/null +++ b/apps/api/src/app/organization/usecases/update-organization/update-organization.usecase.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@nestjs/common'; +import { OrganizationRepository } from '@novu/dal'; +import { UpdateOrganizationCommand } from './update-organization-command'; + +@Injectable() +export class UpdateOrganization { + constructor(private organizationRepository: OrganizationRepository) {} + + async execute(command: UpdateOrganizationCommand) { + const payload = { + name: command.name, + }; + + await this.organizationRepository.updateOrganization(command.id, payload); + + return payload; + } +} diff --git a/libs/dal/src/repositories/organization/organization.repository.ts b/libs/dal/src/repositories/organization/organization.repository.ts index 205b7e9238b4..32fd6f284e5f 100644 --- a/libs/dal/src/repositories/organization/organization.repository.ts +++ b/libs/dal/src/repositories/organization/organization.repository.ts @@ -35,6 +35,19 @@ export class OrganizationRepository extends BaseRepository< ); } + async updateOrganization(organizationId: string, payload: { name: string }) { + return this.update( + { + _id: organizationId, + }, + { + $set: { + name: payload.name, + }, + } + ); + } + async findPartnerConfigurationDetails(organizationId: string, userId: string, configurationId: string) { const members = await this.memberRepository.findUserActiveMembers(userId);