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

Commit

Permalink
✨ Add groups endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Oct 24, 2020
1 parent f27c6b9 commit 818ad11
Show file tree
Hide file tree
Showing 5 changed files with 307 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { AccessTokensModule } from './modules/access-tokens/access-tokens.module
import { AuthModule } from './modules/auth/auth.module';
import { EmailModule } from './modules/email/email.module';
import { EmailsModule } from './modules/emails/emails.module';
import { GroupsModule } from './modules/groups/groups.module';
import { PrismaModule } from './modules/prisma/prisma.module';
import { SessionsModule } from './modules/sessions/sessions.module';
import { UsersModule } from './modules/user/user.module';
Expand All @@ -29,6 +30,7 @@ import { UsersModule } from './modules/user/user.module';
SessionsModule,
AccessTokensModule,
EmailsModule,
GroupsModule,
],
controllers: [AppController],
providers: [
Expand Down
95 changes: 95 additions & 0 deletions src/modules/groups/groups.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
Put,
Query,
Req,
UseGuards,
} from '@nestjs/common';
import { groups } 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 { UserRequest } from '../auth/auth.interface';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { Scopes } from '../auth/scope.decorator';
import { ScopesGuard } from '../auth/scope.guard';
import { CreateGroupDto, ReplaceGroupDto, UpdateGroupDto } from './groups.dto';
import { GroupsService } from './groups.service';

@Controller('groups')
@UseGuards(JwtAuthGuard)
export class GroupController {
constructor(private groupsService: GroupsService) {}

@Post()
@UseGuards(ScopesGuard)
@Scopes('user:write', 'group:write')
async create(
@Req() req: UserRequest,
@Body() data: CreateGroupDto,
): Promise<Expose<groups>> {
return this.groupsService.createGroup(req.user.id, data);
}

@Get()
@UseGuards(ScopesGuard)
@Scopes('group:read')
async getAll(
@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<groups>[]> {
return this.groupsService.getGroups({
skip,
take,
orderBy,
cursor,
where,
});
}

@Get(':id')
@UseGuards(ScopesGuard)
@Scopes('group{id}:read')
async get(@Param('id', ParseIntPipe) id: number): Promise<Expose<groups>> {
return this.groupsService.getGroup(Number(id));
}

@Patch(':id')
@UseGuards(ScopesGuard)
@Scopes('group{id}:write')
async update(
@Body() data: UpdateGroupDto,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<groups>> {
return this.groupsService.updateGroup(Number(id), data);
}

@Put(':id')
@UseGuards(ScopesGuard)
@Scopes('group{id}:write')
async replace(
@Body() data: ReplaceGroupDto,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<groups>> {
return this.groupsService.updateGroup(Number(id), data);
}

@Delete(':id')
@UseGuards(ScopesGuard)
@Scopes('group{id}:delete')
async remove(@Param('id', ParseIntPipe) id: number): Promise<Expose<groups>> {
return this.groupsService.deleteGroup(Number(id));
}
}
98 changes: 98 additions & 0 deletions src/modules/groups/groups.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {
IsArray,
IsBoolean,
IsNotEmpty,
IsObject,
IsOptional,
IsString,
} from 'class-validator';

export class CreateGroupDto {
@IsBoolean()
@IsOptional()
autoJoinDomain?: boolean;

@IsBoolean()
@IsOptional()
forceTwoFactor?: boolean;

@IsArray()
@IsOptional()
ipRestrictions?: string;

@IsString()
@IsNotEmpty()
name: string;

@IsBoolean()
@IsOptional()
onlyAllowDomain?: boolean;

@IsString()
@IsOptional()
profilePictureUrl?: string;

@IsObject()
@IsOptional()
attributes: Record<string, any>;
}

export class UpdateGroupDto {
@IsBoolean()
@IsOptional()
autoJoinDomain?: boolean;

@IsBoolean()
@IsOptional()
forceTwoFactor?: boolean;

@IsArray()
@IsOptional()
ipRestrictions?: string;

@IsString()
@IsOptional()
name?: string;

@IsBoolean()
@IsOptional()
onlyAllowDomain?: boolean;

@IsString()
@IsOptional()
profilePictureUrl?: string;

@IsObject()
@IsOptional()
attributes: Record<string, any>;
}

export class ReplaceGroupDto {
@IsBoolean()
@IsNotEmpty()
autoJoinDomain: boolean;

@IsBoolean()
@IsNotEmpty()
forceTwoFactor: boolean;

@IsArray()
@IsNotEmpty()
ipRestrictions: string;

@IsString()
@IsNotEmpty()
name: string;

@IsBoolean()
@IsNotEmpty()
onlyAllowDomain: boolean;

@IsString()
@IsNotEmpty()
profilePictureUrl: string;

@IsObject()
@IsNotEmpty()
attributes: Record<string, any>;
}
11 changes: 11 additions & 0 deletions src/modules/groups/groups.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { PrismaModule } from '../prisma/prisma.module';
import { GroupController } from './groups.controller';
import { GroupsService } from './groups.service';

@Module({
imports: [PrismaModule],
controllers: [GroupController],
providers: [GroupsService],
})
export class GroupsModule {}
101 changes: 101 additions & 0 deletions src/modules/groups/groups.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import {
groups,
groupsCreateInput,
groupsOrderByInput,
groupsUpdateInput,
groupsWhereInput,
groupsWhereUniqueInput,
} from '@prisma/client';
import { Expose } from 'src/modules/prisma/prisma.interface';
import { PrismaService } from '../prisma/prisma.service';

@Injectable()
export class GroupsService {
constructor(private prisma: PrismaService) {}

async createGroup(
userId: number,
data: Omit<Omit<groupsCreateInput, 'group'>, 'user'>,
): Promise<groups> {
return this.prisma.groups.create({
data: {
...data,
memberships: {
create: { role: 'OWNER', user: { connect: { id: userId } } },
},
},
});
}

async getGroups(params: {
skip?: number;
take?: number;
cursor?: groupsWhereUniqueInput;
where?: groupsWhereInput;
orderBy?: groupsOrderByInput;
}): Promise<Expose<groups>[]> {
const { skip, take, cursor, where, orderBy } = params;
const groups = await this.prisma.groups.findMany({
skip,
take,
cursor,
where,
orderBy,
});
return groups.map(user => this.prisma.expose<groups>(user));
}

async getGroup(id: number): Promise<Expose<groups> | null> {
const group = await this.prisma.groups.findOne({
where: { id },
});
if (!group)
throw new HttpException('Group not found', HttpStatus.NOT_FOUND);
return this.prisma.expose<groups>(group);
}

async updateGroup(
id: number,
data: groupsUpdateInput,
): Promise<Expose<groups>> {
const testGroup = await this.prisma.groups.findOne({
where: { id },
});
if (!testGroup)
throw new HttpException('Group not found', HttpStatus.NOT_FOUND);
const group = await this.prisma.groups.update({
where: { id },
data,
});
return this.prisma.expose<groups>(group);
}

async replaceGroup(
id: number,
data: groupsCreateInput,
): Promise<Expose<groups>> {
const testGroup = await this.prisma.groups.findOne({
where: { id },
});
if (!testGroup)
throw new HttpException('Group not found', HttpStatus.NOT_FOUND);
const group = await this.prisma.groups.update({
where: { id },
data,
});
return this.prisma.expose<groups>(group);
}

async deleteGroup(id: number): Promise<Expose<groups>> {
const testGroup = await this.prisma.groups.findOne({
where: { id },
});
if (!testGroup)
throw new HttpException('Group not found', HttpStatus.NOT_FOUND);
const group = await this.prisma.groups.delete({
where: { id },
});
return this.prisma.expose<groups>(group);
}
}

0 comments on commit 818ad11

Please sign in to comment.