feat: Organization services

This commit is contained in:
sauravdhakal12
2026-02-22 15:47:45 +05:45
parent f4c9174752
commit afed1731d2
42 changed files with 862 additions and 17 deletions

View File

@@ -0,0 +1,148 @@
import {
BadRequestException,
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { OrganizationService } from 'src/organization/organization.service';
import { UserService } from 'src/user/user.service';
import { InviteUserToOrganizationRequestDTO } from './dto';
import { PrismaService } from 'src/prisma/prisma.service';
import {
ORGANIZATION_JOIN_REQUEST,
ORGANIZATION_JOIN_REQUEST_TYPE,
} from 'prisma/generated/prisma/enums';
import { AuthorizationService } from 'src/authorization/authorization.service';
import { USER_ORGANIZATION_OPERATIONS } from 'src/authorization/operations';
import { Prisma } from 'prisma/generated/prisma/client';
@Injectable()
export class OrganizationMembershipService {
constructor(
private readonly userService: UserService,
private readonly orgService: OrganizationService,
private readonly prisma: PrismaService,
private readonly authorization: AuthorizationService,
) {}
async inviteUserToOrg(
userId: string,
dto: InviteUserToOrganizationRequestDTO,
) {
const [orgExists, invitedUser] = await Promise.all([
this.orgService.findById(dto.orgId),
this.userService.getById(dto.invitedUserId),
]);
if (!orgExists) throw new NotFoundException('Organization');
if (!invitedUser) throw new NotFoundException('User');
const userAlreadyPart =
await this.prisma.organizationUserJoinTable.findUnique({
where: {
userId_orgId: {
orgId: dto.orgId,
userId,
},
},
});
if (userAlreadyPart)
throw new BadRequestException('User already part of this organization');
const canInviteUser = await this.authorization.canPerformOperation(
userId,
dto.orgId,
USER_ORGANIZATION_OPERATIONS.INVITE_USERS,
);
if (!canInviteUser) throw new ForbiddenException('Insufficient Permission');
try {
const invitation = await this.prisma.organizationJoinRequest.create({
data: {
...dto,
userId: dto.invitedUserId,
requestType: ORGANIZATION_JOIN_REQUEST_TYPE.INVITED,
},
});
return invitation;
} catch (err) {
if (err instanceof Prisma.PrismaClientKnownRequestError) {
if (err.code === 'P2002')
throw new BadRequestException('User invitation already sent.');
}
throw err;
}
}
requestToJoin() {}
// TODO: reject, rejectReason
async acceptInvite(userId: string, orgId: string) {
const orgExists = await this.orgService.findById(orgId);
if (!orgExists) throw new NotFoundException('Organization');
const [userAlreadyPart, isUserInvited] = await Promise.all([
this.prisma.organizationUserJoinTable.findUnique({
where: {
userId_orgId: {
orgId,
userId,
},
},
}),
this.prisma.organizationJoinRequest.findUnique({
where: {
userId_orgId: {
orgId,
userId,
},
status: ORGANIZATION_JOIN_REQUEST.PENDING,
},
}),
]);
if (userAlreadyPart)
throw new BadRequestException('User already part of this organization');
if (!isUserInvited)
throw new BadRequestException(
'User has no invitations from this organization',
);
return await this.prisma.$transaction(async (tx) => {
await tx.organizationJoinRequest.update({
where: {
userId_orgId: {
userId,
orgId,
},
},
data: {
status: ORGANIZATION_JOIN_REQUEST.ACCEPTED,
},
});
return await tx.organizationUserJoinTable.create({
data: {
orgId,
userId,
},
});
});
}
async getUserInvitations(
userId: string,
requestType: ORGANIZATION_JOIN_REQUEST_TYPE,
status: ORGANIZATION_JOIN_REQUEST = ORGANIZATION_JOIN_REQUEST.PENDING,
) {
return await this.prisma.organizationJoinRequest.findMany({
where: {
userId: userId,
status: status,
requestType: requestType,
},
});
}
}