Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: delete organization invitations #375

Merged
merged 5 commits into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion apps/api-gateway/src/organization/organization.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CommonService } from '@credebl/common';
import { Controller, Get, Put, Param, UseGuards, UseFilters, Post, Body, Res, HttpStatus, Query, Delete } from '@nestjs/common';
import { OrganizationService } from './organization.service';
import { CreateOrganizationDto } from './dtos/create-organization-dto';
import IResponseType from '@credebl/common/interfaces/response.interface';
import IResponseType, { IResponse } from '@credebl/common/interfaces/response.interface';
import { Response } from 'express';
import { ApiResponseDto } from '../dtos/apiResponse.dto';
import { UnauthorizedErrorDto } from '../dtos/unauthorized-error.dto';
Expand Down Expand Up @@ -372,4 +372,23 @@ export class OrganizationController {
};
return res.status(HttpStatus.ACCEPTED).json(finalResponse);
}

@Delete('/:orgId/invitations/:invitationId')
@ApiOperation({ summary: 'Delete organization invitation', description: 'Delete organization invitation' })
@ApiResponse({ status: HttpStatus.OK, description: 'Success', type: ApiResponseDto })
@ApiBearerAuth()
@Roles(OrgRoles.OWNER, OrgRoles.ADMIN)
@UseGuards(AuthGuard('jwt'), OrgRolesGuard)
async deleteOrganizationInvitation(
@Param('orgId') orgId: string,
@Param('invitationId') invitationId: string,
@Res() res: Response
): Promise<Response> {
await this.organizationService.deleteOrganizationInvitation(orgId, invitationId);
const finalResponse: IResponse = {
statusCode: HttpStatus.OK,
message: ResponseMessages.organisation.success.orgInvitationDeleted
};
return res.status(HttpStatus.OK).json(finalResponse);
}
}
8 changes: 8 additions & 0 deletions apps/api-gateway/src/organization/organization.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,12 @@ export class OrganizationService extends BaseService {

return this.sendNatsMessage(this.serviceProxy, 'delete-organization', payload);
}

async deleteOrganizationInvitation(
orgId: string,
invitationId: string
): Promise<boolean> {
const payload = {orgId, invitationId};
return this.sendNatsMessage(this.serviceProxy, 'delete-organization-invitation', payload);
}
}
19 changes: 19 additions & 0 deletions apps/organization/repositories/organization.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,4 +585,23 @@ export class OrganizationRepository {
}
}


/**
*
* @param id
* @returns Delete Invitation
*/
async deleteOrganizationInvitation(id: string): Promise<org_invitations> {
try {
return await this.prisma.org_invitations.delete({
where: {
id
}
});
} catch (error) {
this.logger.error(`Delete Org Invitation Error: ${JSON.stringify(error)}`);
throw error;
}
}

}
5 changes: 5 additions & 0 deletions apps/organization/src/organization.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,9 @@ export class OrganizationController {
async deleteOrganization(payload: { orgId: string }): Promise<boolean> {
return this.organizationService.deleteOrganization(payload.orgId);
}

@MessagePattern({ cmd: 'delete-organization-invitation' })
async deleteOrganizationInvitation(payload: { orgId: string; invitationId: string; }): Promise<boolean> {
return this.organizationService.deleteOrganizationInvitation(payload.orgId, payload.invitationId);
}
}
31 changes: 29 additions & 2 deletions apps/organization/src/organization.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// eslint-disable-next-line camelcase
import { organisation, user } from '@prisma/client';
import { Injectable, Logger, ConflictException, InternalServerErrorException, HttpException } from '@nestjs/common';
import { Injectable, Logger, ConflictException, InternalServerErrorException, HttpException, BadRequestException, ForbiddenException } from '@nestjs/common';
import { PrismaService } from '@credebl/prisma-service';
import { CommonService } from '@credebl/common';
import { OrganizationRepository } from '../repositories/organization.repository';
Expand Down Expand Up @@ -565,4 +564,32 @@ export class OrganizationService {
throw error;
}
}

async deleteOrganizationInvitation(orgId: string, invitationId: string): Promise<boolean> {
try {
const invitationDetails = await this.organizationRepository.getInvitationById(invitationId);

// Check invitation is present
if (!invitationDetails) {
throw new NotFoundException(ResponseMessages.user.error.invitationNotFound);
}

// Check if delete process initiated by the org who has created invitation
if (orgId !== invitationDetails.orgId) {
throw new ForbiddenException(ResponseMessages.organisation.error.deleteOrgInvitation);
}

// Check if invitation is already accepted/rejected
if (Invitation.PENDING !== invitationDetails.status) {
throw new BadRequestException(ResponseMessages.organisation.error.invitationStatusInvalid);
}

await this.organizationRepository.deleteOrganizationInvitation(invitationId);

return true;
} catch (error) {
this.logger.error(`delete organization invitation: ${JSON.stringify(error)}`);
throw new RpcException(error.response ? error.response : error);
}
}
}
6 changes: 4 additions & 2 deletions libs/common/src/response-messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ export const ResponseMessages = {
getOrgDashboard: 'Organization dashboard details fetched',
getOrganizations: 'Organizations details fetched successfully',
updateUserRoles: 'User roles updated successfully',
delete: 'Organization deleted successfully'
delete: 'Organization deleted successfully',
orgInvitationDeleted: 'Organization invitation deleted successfully'
},
error: {
exists: 'An organization name is already exist',
Expand All @@ -68,10 +69,11 @@ export const ResponseMessages = {
userNotFound: 'User not found for the given organization',
updateUserRoles: 'Unable to update user roles',
deleteOrg: 'Organization not found',
deleteOrgInvitation: 'Organization does not have access to delete this invitation',
notFound: 'Organization agent not found',
invitationStatusInvalid: 'Unable to delete invitation with accepted/rejected status',
orgNotFound: 'Organization not found'
}

},

fido: {
Expand Down