Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,11 @@ export class UpdateEcosystemInvitationDto {
@IsString({ message: 'ecosystemId should be a string' })
@Transform(({ value }) => value?.trim())
ecosystemId: string;

@ApiProperty({ example: '6e672a9c-64f0-4d98-b312-f578f633810b' })
@IsUUID()
@IsNotEmpty({ message: 'OrgId is required for updating status' })
@IsString({ message: 'OrgId should be a string' })
@Transform(({ value }) => value?.trim())
orgId: string;
}
7 changes: 4 additions & 3 deletions apps/api-gateway/src/ecosystem/ecosystem.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class EcosystemController {
};
return res.status(HttpStatus.CREATED).json(finalResponse);
} catch (error) {
if (error instanceof ConflictException || HttpStatus.CONFLICT === error.status) {
if (error instanceof ConflictException || HttpStatus.CONFLICT === error.statusCode) {
return res.status(HttpStatus.CONFLICT).json({
status: HttpStatus.CONFLICT,
message: error.message
Expand All @@ -116,7 +116,7 @@ export class EcosystemController {
message: ResponseMessages.errorMessages.serverError
};

return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(finalResponse);
return res.status(HttpStatus.OK).json(finalResponse);
}
}

Expand Down Expand Up @@ -147,7 +147,8 @@ export class EcosystemController {
const result = await this.ecosystemService.updateEcosystemInvitationStatus(
status,
reqUser.id,
updateInvitation.ecosystemId
updateInvitation.ecosystemId,
updateInvitation.orgId
);

if (result) {
Expand Down
15 changes: 10 additions & 5 deletions apps/api-gateway/src/ecosystem/ecosystem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,22 @@ export class EcosystemService {
});
}

async updateEcosystemInvitationStatus(status: Invitation, reqUser: string, ecosystemId: string): Promise<boolean> {
async updateEcosystemInvitationStatus(
status: Invitation,
reqUser: string,
ecosystemId: string,
orgId: string
): Promise<boolean> {
return this.natsClient.sendNatsMessage(this.serviceProxy, 'update-ecosystem-invitation-status', {
status,
reqUser,
ecosystemId
ecosystemId,
orgId
});
}

async deleteEcosystemOrgs(ecosystemId: string, userIds: string[]): Promise<{ count: number }> {
return this.natsClient.sendNatsMessage(this.serviceProxy, 'delete-ecosystem-orgs', { userIds, ecosystemId });
async deleteEcosystemOrgs(ecosystemId: string, orgIds: string[]): Promise<{ count: number }> {
return this.natsClient.sendNatsMessage(this.serviceProxy, 'delete-ecosystem-orgs', { orgIds, ecosystemId });
}

async updateEcosystemOrgStatus(
Expand All @@ -87,7 +93,6 @@ export class EcosystemService {
});
}

// eslint-disable-next-line camelcase
async getAllEcosystemOrgsByEcosystemId(
ecosystemId: string,
pageDetail: IPaginationSortingDto
Expand Down
37 changes: 26 additions & 11 deletions apps/ecosystem/repositories/ecosystem.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,13 +350,18 @@ export class EcosystemRepository {
}
}

async getEcosystemInvitationsByEmail(email: string, ecosystemId: string): Promise<ecosystem_invitations> {
async getEcosystemInvitationsByEmail(
email: string,
ecosystemId: string,
invitedOrg: string
): Promise<ecosystem_invitations> {
try {
return this.prisma.ecosystem_invitations.findUnique({
where: {
email_ecosystemId: {
email_ecosystemId_invitedOrg: {
email,
ecosystemId
ecosystemId,
invitedOrg
}
}
});
Expand All @@ -368,20 +373,30 @@ export class EcosystemRepository {

async updateEcosystemInvitationStatusByEmail(
email: string,
orgId: string,
ecosystemId: string,
status: Invitation
): Promise<ecosystem_invitations> {
try {
return this.prisma.ecosystem_invitations.update({
where: {
email_ecosystemId: {
return this.prisma.$transaction(async (tx) => {
const record = await tx.ecosystem_invitations.findFirst({
where: {
email,
ecosystemId
ecosystemId,
invitedOrg: orgId
}
},
data: {
status
});

if (!record) {
throw new Error('Invitation not found for this specific organization');
}

return tx.ecosystem_invitations.update({
where: {
id: record.id
},
data: { status }
});
});
} catch (error) {
this.logger.error(`Error in updateEcosystemInvitationStatusByEmail: ${error.message}`);
Expand Down Expand Up @@ -1336,7 +1351,7 @@ export class EcosystemRepository {
return { totalPages, data };
}

async getEcosystemByRole(userId: string, role: string): Promise<{ ecosystemRole: { name: string } }> {
async getEcosystemByRole(userId: string, role: string): Promise<{ ecosystemRole: { name: string } } | null> {
try {
return this.prisma.ecosystem_orgs.findFirst({
where: {
Expand Down
8 changes: 7 additions & 1 deletion apps/ecosystem/src/ecosystem.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,14 @@ export class EcosystemController {
status: Invitation;
reqUser: string;
ecosystemId: string;
orgId: string;
}): Promise<boolean> {
return this.ecosystemService.updateEcosystemInvitationStatus(payload.status, payload.reqUser, payload.ecosystemId);
return this.ecosystemService.updateEcosystemInvitationStatus(
payload.status,
payload.reqUser,
payload.ecosystemId,
payload.orgId
);
}

/**
Expand Down
24 changes: 20 additions & 4 deletions apps/ecosystem/src/ecosystem.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,12 @@ export class EcosystemService {
}
const organization = await this.organizationRepository.getOrgProfile(orgId);
const user = await this.ecosystemRepository.getUserById(organization.createdBy);
const checkUser = await this.ecosystemRepository.getEcosystemInvitationsByEmail(user.email, ecosystemId);
const checkUser = await this.ecosystemRepository.getEcosystemInvitationsByEmail(user.email, ecosystemId, orgId);

if (checkUser && Invitation.REJECTED === checkUser.status && ecosystemId === checkUser.ecosystemId) {
const reopenedInvitation = await this.ecosystemRepository.updateEcosystemInvitationStatusByEmail(
user.email,
orgId,
ecosystemId,
Invitation.PENDING
);
Expand All @@ -242,13 +243,17 @@ export class EcosystemService {
}
}

if (checkUser?.ecosystemId === ecosystemId && checkUser.status === Invitation.PENDING) {
if (
checkUser?.ecosystemId === ecosystemId &&
checkUser.invitedOrg === orgId &&
checkUser.status === Invitation.PENDING
) {
throw new RpcException({
statusCode: HttpStatus.CONFLICT,
message: `Invitation already exists for org with email ${user.email}`
});
}
await this.ecosystemRepository.createEcosystemInvitation({
const invitation = await this.ecosystemRepository.createEcosystemInvitation({
email: user.email,
invitedUserId: user.id,
userId: reqUser,
Expand All @@ -257,6 +262,11 @@ export class EcosystemService {
ecosystemId,
orgId
});

if (invitation && reqUser === user.id) {
await this.updateEcosystemInvitationStatus(Invitation.ACCEPTED, reqUser, ecosystemId, orgId);
return true;
}
const ecosystem = await this.ecosystemRepository.getEcosystemById(ecosystemId);
const emailData = new EmailDto();
const inviteMemberTemplate = new InviteMemberToEcosystem();
Expand Down Expand Up @@ -311,7 +321,12 @@ export class EcosystemService {
}
}

async updateEcosystemInvitationStatus(status: Invitation, reqUser: string, ecosystemId: string): Promise<boolean> {
async updateEcosystemInvitationStatus(
status: Invitation,
reqUser: string,
ecosystemId: string,
orgId: string
): Promise<boolean> {
try {
const user = await this.ecosystemRepository.getUserById(reqUser);

Expand All @@ -321,6 +336,7 @@ export class EcosystemService {

const result = await this.ecosystemRepository.updateEcosystemInvitationStatusByEmail(
user.email,
orgId,
ecosystemId,
status
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
Warnings:

- A unique constraint covering the columns `[email,ecosystemId,invitedOrg]` on the table `ecosystem_invitations` will be added. If there are existing duplicate values, this will fail.

*/
-- DropIndex
DROP INDEX "ecosystem_invitations_email_ecosystemId_key";

-- CreateIndex
CREATE UNIQUE INDEX "ecosystem_invitations_email_ecosystemId_invitedOrg_key" ON "ecosystem_invitations"("email", "ecosystemId", "invitedOrg");
2 changes: 1 addition & 1 deletion libs/prisma-service/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ model ecosystem_invitations {
organisation organisation? @relation(fields: [invitedOrg], references: [id])
ecosystem ecosystem? @relation(fields: [ecosystemId], references: [id])
user user? @relation(fields: [userId], references: [id])
@@unique([email, ecosystemId])
@@unique([email, ecosystemId, invitedOrg])
}


Expand Down
36 changes: 15 additions & 21 deletions libs/supabase/src/supabase.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,25 @@ import { SupabaseClient, createClient } from '@supabase/supabase-js';

@Injectable({ scope: Scope.REQUEST })
export class SupabaseService {
private readonly logger = new Logger(SupabaseService.name);
private clientInstance: SupabaseClient;
constructor() {}

private readonly logger = new Logger(SupabaseService.name);
private clientInstance: SupabaseClient;
constructor(
) { }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getClient(): SupabaseClient<any, 'public', any> {
this.logger.log('getting supabase client... ');

// eslint-disable-next-line @typescript-eslint/no-explicit-any
getClient(): SupabaseClient<any, "public", any> {
this.logger.log('getting supabase client...');

if (this.clientInstance) {
this.logger.log('client exists - returning for current Scope.REQUEST');
return this.clientInstance;
}
if (this.clientInstance) {
this.logger.log('client exists - returning for current Scope.REQUEST');
return this.clientInstance;
}

this.logger.log('initialising new supabase client for new Scope.REQUEST');
this.logger.log('initialising new supabase client for new Scope.REQUEST');

this.clientInstance = createClient(

process.env.SUPABASE_URL,
process.env.SUPABASE_KEY
);
this.clientInstance = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY);

this.logger.log('auth has been set!');
this.logger.log('auth has been set!');

return this.clientInstance;
}
return this.clientInstance;
}
}