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

Commit

Permalink
✨ Add emails module
Browse files Browse the repository at this point in the history
  • Loading branch information
AnandChowdhary committed Oct 23, 2020
1 parent 276c95a commit f7082e0
Show file tree
Hide file tree
Showing 5 changed files with 190 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 @@ -8,6 +8,7 @@ import configuration from './config/configuration';
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 { PrismaModule } from './modules/prisma/prisma.module';
import { SessionsModule } from './modules/sessions/sessions.module';
import { UsersModule } from './modules/user/user.module';
Expand All @@ -27,6 +28,7 @@ import { UsersModule } from './modules/user/user.module';
EmailModule,
SessionsModule,
AccessTokensModule,
EmailsModule,
],
controllers: [AppController],
providers: [
Expand Down
78 changes: 78 additions & 0 deletions src/modules/emails/emails.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Query,
UseGuards,
} from '@nestjs/common';
import { emails } 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 { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { Scopes } from '../auth/scope.decorator';
import { ScopesGuard } from '../auth/scope.guard';
import { CreateEmailDto } from './emails.dto';
import { EmailsService } from './emails.service';

@Controller('users/:userId/emails')
@UseGuards(JwtAuthGuard)
export class EmailController {
constructor(private emailsService: EmailsService) {}

@Post()
@UseGuards(ScopesGuard)
@Scopes('user{userId}:write', 'email:write')
async create(
@Param('userId', ParseIntPipe) userId: number,
@Body() data: CreateEmailDto,
): Promise<Expose<emails>> {
return this.emailsService.createEmail(userId, data);
}

@Get()
@UseGuards(ScopesGuard)
@Scopes('user{userId}:read', 'email:read')
async getAll(
@Param('userId', ParseIntPipe) userId: 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<emails>[]> {
return this.emailsService.getEmails(userId, {
skip,
take,
orderBy,
cursor,
where,
});
}

@Get(':id')
@UseGuards(ScopesGuard)
@Scopes('user{userId}:read', 'email{id}:read')
async get(
@Param('userId', ParseIntPipe) userId: number,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<emails>> {
return this.emailsService.getEmail(userId, Number(id));
}

@Delete(':id')
@UseGuards(ScopesGuard)
@Scopes('user{userId}:delete', 'email{id}:delete')
async remove(
@Param('userId', ParseIntPipe) userId: number,
@Param('id', ParseIntPipe) id: number,
): Promise<Expose<emails>> {
return this.emailsService.deleteEmail(userId, Number(id));
}
}
7 changes: 7 additions & 0 deletions src/modules/emails/emails.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { IsNotEmpty, IsString } from 'class-validator';

export class CreateEmailDto {
@IsString()
@IsNotEmpty()
email: string;
}
23 changes: 23 additions & 0 deletions src/modules/emails/emails.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { AuthService } from '../auth/auth.service';
import { EmailModule } from '../email/email.module';
import { PrismaModule } from '../prisma/prisma.module';
import { UsersService } from '../user/user.service';
import { EmailController } from './emails.controller';
import { EmailsService } from './emails.service';

@Module({
imports: [
PrismaModule,
EmailModule,
ConfigModule,
JwtModule.register({
secret: process.env.JWT_SECRET ?? 'staart',
}),
],
controllers: [EmailController],
providers: [EmailsService, UsersService, AuthService],
})
export class EmailsModule {}
80 changes: 80 additions & 0 deletions src/modules/emails/emails.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import {
HttpException,
HttpStatus,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import {
emails,
emailsCreateInput,
emailsOrderByInput,
emailsWhereInput,
emailsWhereUniqueInput,
} from '@prisma/client';
import { Expose } from 'src/modules/prisma/prisma.interface';
import { AuthService } from '../auth/auth.service';
import { PrismaService } from '../prisma/prisma.service';
import { UsersService } from '../user/user.service';

@Injectable()
export class EmailsService {
constructor(
private prisma: PrismaService,
private users: UsersService,
private auth: AuthService,
) {}

async createEmail(
userId: number,
data: Omit<Omit<emailsCreateInput, 'emailSafe'>, 'user'>,
): Promise<emails> {
const emailSafe = this.users.getSafeEmail(data.email);
const result = await this.prisma.emails.create({
data: { ...data, emailSafe, user: { connect: { id: userId } } },
});
await this.auth.sendEmailVerification(data.email);
return result;
}

async getEmails(
userId: number,
params: {
skip?: number;
take?: number;
cursor?: emailsWhereUniqueInput;
where?: emailsWhereInput;
orderBy?: emailsOrderByInput;
},
): Promise<Expose<emails>[]> {
const { skip, take, cursor, where, orderBy } = params;
const emails = await this.prisma.emails.findMany({
skip,
take,
cursor,
where: { ...where, user: { id: userId } },
orderBy,
});
return emails.map(user => this.prisma.expose<emails>(user));
}

async getEmail(userId: number, id: number): Promise<Expose<emails> | null> {
const email = await this.prisma.emails.findOne({
where: { id },
});
if (email.userId !== userId) throw new UnauthorizedException();
if (!email)
throw new HttpException('Email not found', HttpStatus.NOT_FOUND);
return this.prisma.expose<emails>(email);
}

async deleteEmail(userId: number, id: number): Promise<Expose<emails>> {
const testEmail = await this.prisma.emails.findOne({
where: { id },
});
if (testEmail.userId !== userId) throw new UnauthorizedException();
const email = await this.prisma.emails.delete({
where: { id },
});
return this.prisma.expose<emails>(email);
}
}

0 comments on commit f7082e0

Please sign in to comment.