Skip to content
This repository has been archived by the owner on Apr 19, 2023. It is now read-only.

Commit

Permalink
✨ Add group membership controller
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Oct 24, 2020
1 parent 9a16df6 commit 26c0c0e
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 18 deletions.
75 changes: 75 additions & 0 deletions src/modules/memberships/memberships-group.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Query,
} from '@nestjs/common';
import { memberships } from '@prisma/client';
import { Expose } from 'src/modules/prisma/prisma.interface';
import { CursorPipe } from 'src/pipes/cursor.pipe';
import { OptionalIntPipe } from 'src/pipes/optional-int.pipe';
import { OrderByPipe } from 'src/pipes/order-by.pipe';
import { WherePipe } from 'src/pipes/where.pipe';
import { Scopes } from '../auth/scope.decorator';
import { UpdateMembershipDto } from './memberships.dto';
import { MembershipsService } from './memberships.service';

@Controller('groups/:groupId/memberships')
export class GroupMembershipController {
constructor(private membershipsService: MembershipsService) {}

@Get()
@Scopes('group-{groupId}:read-membership')
async getAll(
@Param('groupId', ParseIntPipe) groupId: number,
@Query('skip', OptionalIntPipe) skip?: number,
@Query('take', OptionalIntPipe) take?: number,
@Query('cursor', CursorPipe) cursor?: Record<string, number | string>,
@Query('where', WherePipe) where?: Record<string, number | string>,
@Query('orderBy', OrderByPipe) orderBy?: Record<string, 'asc' | 'desc'>,
): Promise<Expose<memberships>[]> {
return this.membershipsService.getMemberships({
skip,
take,
orderBy,
cursor,
where: { ...where, group: { id: groupId } },
});
}

@Get(':id')
@Scopes('group-{groupId}:read-membership-{id}')
async get(
@Param('groupId', ParseIntPipe) groupId: number,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<memberships>> {
return this.membershipsService.getGroupMembership(groupId, Number(id));
}

@Patch(':id')
@Scopes('group-{groupId}:read-membership-{id}')
async update(
@Body() data: UpdateMembershipDto,
@Param('groupId', ParseIntPipe) groupId: number,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<memberships>> {
return this.membershipsService.updateGroupMembership(
groupId,
Number(id),
data,
);
}

@Delete(':id')
@Scopes('group-{groupId}:delete-membership-{id}')
async remove(
@Param('groupId', ParseIntPipe) groupId: number,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<memberships>> {
return this.membershipsService.deleteGroupMembership(groupId, Number(id));
}
}
8 changes: 4 additions & 4 deletions src/modules/memberships/memberships-user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ export class UserMembershipController {
@Query('where', WherePipe) where?: Record<string, number | string>,
@Query('orderBy', OrderByPipe) orderBy?: Record<string, 'asc' | 'desc'>,
): Promise<Expose<memberships>[]> {
return this.membershipsService.getMemberships(userId, {
return this.membershipsService.getMemberships({
skip,
take,
orderBy,
cursor,
where,
where: { ...where, user: { id: userId } },
});
}

Expand All @@ -44,7 +44,7 @@ export class UserMembershipController {
@Param('userId', ParseIntPipe) userId: number,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<memberships>> {
return this.membershipsService.getMembership(userId, Number(id));
return this.membershipsService.getUserMembership(userId, Number(id));
}

@Delete(':id')
Expand All @@ -53,6 +53,6 @@ export class UserMembershipController {
@Param('userId', ParseIntPipe) userId: number,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<memberships>> {
return this.membershipsService.deleteMembership(userId, Number(id));
return this.membershipsService.deleteUserMembership(userId, Number(id));
}
}
8 changes: 8 additions & 0 deletions src/modules/memberships/memberships.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { IsIn, IsOptional, IsString } from 'class-validator';

export class UpdateMembershipDto {
@IsString()
@IsIn(['OWNER', 'ADMIN', 'MEMBER'])
@IsOptional()
role?: 'OWNER' | 'ADMIN' | 'MEMBER';
}
3 changes: 2 additions & 1 deletion src/modules/memberships/memberships.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Module } from '@nestjs/common';
import { PrismaModule } from '../prisma/prisma.module';
import { GroupMembershipController } from './memberships-group.controller';
import { UserMembershipController } from './memberships-user.controller';
import { MembershipsService } from './memberships.service';

@Module({
imports: [PrismaModule],
controllers: [UserMembershipController],
controllers: [UserMembershipController, GroupMembershipController],
providers: [MembershipsService],
})
export class MembershipsModule {}
73 changes: 60 additions & 13 deletions src/modules/memberships/memberships.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import {
memberships,
membershipsOrderByInput,
membershipsUpdateInput,
membershipsWhereInput,
membershipsWhereUniqueInput,
} from '@prisma/client';
Expand All @@ -16,29 +17,26 @@ import { PrismaService } from '../prisma/prisma.service';
@Injectable()
export class MembershipsService {
constructor(private prisma: PrismaService) {}
async getMemberships(
userId: number,
params: {
skip?: number;
take?: number;
cursor?: membershipsWhereUniqueInput;
where?: membershipsWhereInput;
orderBy?: membershipsOrderByInput;
},
): Promise<Expose<memberships>[]> {
async getMemberships(params: {
skip?: number;
take?: number;
cursor?: membershipsWhereUniqueInput;
where?: membershipsWhereInput;
orderBy?: membershipsOrderByInput;
}): Promise<Expose<memberships>[]> {
const { skip, take, cursor, where, orderBy } = params;
const memberships = await this.prisma.memberships.findMany({
skip,
take,
cursor,
where: { ...where, user: { id: userId } },
where,
orderBy,
include: { group: true },
});
return memberships.map(user => this.prisma.expose<memberships>(user));
}

async getMembership(
async getUserMembership(
userId: number,
id: number,
): Promise<Expose<memberships> | null> {
Expand All @@ -52,7 +50,21 @@ export class MembershipsService {
return this.prisma.expose<memberships>(membership);
}

async deleteMembership(
async getGroupMembership(
groupId: number,
id: number,
): Promise<Expose<memberships> | null> {
const membership = await this.prisma.memberships.findOne({
where: { id },
include: { group: true },
});
if (!membership)
throw new HttpException('Membership not found', HttpStatus.NOT_FOUND);
if (membership.groupId !== groupId) throw new UnauthorizedException();
return this.prisma.expose<memberships>(membership);
}

async deleteUserMembership(
userId: number,
id: number,
): Promise<Expose<memberships>> {
Expand All @@ -69,6 +81,41 @@ export class MembershipsService {
return this.prisma.expose<memberships>(membership);
}

async updateGroupMembership(
groupId: number,
id: number,
data: membershipsUpdateInput,
): Promise<Expose<memberships>> {
const testMembership = await this.prisma.memberships.findOne({
where: { id },
});
if (!testMembership)
throw new HttpException('Membership not found', HttpStatus.NOT_FOUND);
if (testMembership.groupId !== groupId) throw new UnauthorizedException();
const membership = await this.prisma.memberships.update({
where: { id },
data,
});
return this.prisma.expose<memberships>(membership);
}

async deleteGroupMembership(
groupId: number,
id: number,
): Promise<Expose<memberships>> {
const testMembership = await this.prisma.memberships.findOne({
where: { id },
});
if (!testMembership)
throw new HttpException('Membership not found', HttpStatus.NOT_FOUND);
if (testMembership.groupId !== groupId) throw new UnauthorizedException();
await this.verifyDeleteMembership(testMembership.groupId, id);
const membership = await this.prisma.memberships.delete({
where: { id },
});
return this.prisma.expose<memberships>(membership);
}

/** Verify whether a group membership can be deleted */
async verifyDeleteMembership(
groupId: number,
Expand Down

0 comments on commit 26c0c0e

Please sign in to comment.