Skip to content

Commit

Permalink
feat: added author service (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
nathan2slime committed Jul 14, 2024
1 parent 184fdf6 commit dae0c4d
Show file tree
Hide file tree
Showing 17 changed files with 385 additions and 58 deletions.
17 changes: 8 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,19 @@
"test:e2e": "NODE_ENV=test jest --config ./tests/jest-e2e.json"
},
"dependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mongoose": "^10.0.10",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/terminus": "^10.2.3",
"@typescript-eslint/eslint-plugin": "^7.16.0",
"@typescript-eslint/parser": "^7.16.0",
"bcrypt": "^5.1.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"commitizen": "^4.3.0",
"cookie-parser": "^1.4.6",
"dotenv": "^16.4.5",
"husky": "^9.0.11",
"lint-staged": "^15.2.7",
"mongoose": "^8.5.0",
"mongoose-paginate": "^5.0.3",
"passport-jwt": "^4.0.1",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
Expand All @@ -51,9 +43,16 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@automock/jest": "^2.1.0",
"@typescript-eslint/eslint-plugin": "^7.16.0",
"@typescript-eslint/parser": "^7.16.0",
"commitizen": "^4.3.0",
"@nestjs/cli": "^10.0.0",
"lint-staged": "^15.2.7",
"@nestjs/schematics": "^10.0.0",
"husky": "^9.0.11",
"@nestjs/swagger": "^7.4.0",
"@nestjs/testing": "^10.0.0",
"@types/bcrypt": "^5.0.2",
Expand Down Expand Up @@ -105,5 +104,5 @@
"coverageDirectory": "../coverage",
"testEnvironment": "node"
},
"packageManager": "pnpm@9.2.0"
"packageManager": "pnpm@9.5.0"
}
58 changes: 21 additions & 37 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 3 additions & 7 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@ import { MongooseModule } from '@nestjs/mongoose';

import { AuthModule } from '~/app/auth/auth.module';
import { UserModule } from '~/app/user/user.module';
import { AuthorModule } from '~/app/author/author.module';

import { env } from '~/env';

@Module({
imports: [
MongooseModule.forRoot(env.DATABASE_URL, {
connectionFactory: connection => {
connection.plugin(require('mongoose-paginate'));

return connection;
},
}),
MongooseModule.forRoot(env.DATABASE_URL),
AuthModule,
AuthorModule,
UserModule,
],
controllers: [],
Expand Down
23 changes: 23 additions & 0 deletions src/app/auth/role.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

import { Roles } from '~/app/auth/auth.decorator';
import { Session } from '~/schemas/session.schema';

@Injectable()
export class RoleGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}

canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get(Roles, context.getHandler());

if (roles) {
const req = context.switchToHttp().getRequest();
const session = req.user as Session;

return roles.includes(session.user.role);
}

return true;
}
}
2 changes: 1 addition & 1 deletion src/app/auth/tests/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as bcrypt from 'bcrypt';

import { Test, TestingModule } from '@nestjs/testing';
import { AuthService } from '~/app/auth/auth.service';
import { Model } from 'mongoose';
import { JwtService } from '@nestjs/jwt';
import { getModelToken } from '@nestjs/mongoose';
Expand All @@ -18,6 +17,7 @@ import {
USER_NOT_FOUND,
} from '~/errors';
import { UserService } from '~/app/user/user.service';
import { AuthService } from '~/app/auth/auth.service';

describe('AuthService', () => {
let authService: AuthService;
Expand Down
96 changes: 96 additions & 0 deletions src/app/author/author.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import {
Body,
Controller,
Delete,
Get,
HttpStatus,
Param,
Post,
Put,
Query,
Res,
UseGuards,
} from '@nestjs/common';
import { ApiResponse, ApiTags } from '@nestjs/swagger';
import { Response } from 'express';

import {
CreateAuthorDto,
SearchAuthorDto,
UpdateAuthorDto,
} from '~/app/author/author.dto';
import { AuthorService } from '~/app/author/author.service';
import { JwtAuthGuard } from '~/app/auth/auth.guard';
import { RoleGuard } from '~/app/auth/role.guard';
import { Roles } from '~/app/auth/auth.decorator';
import { Role } from '~/types/role.enum';

@ApiTags('Author')
@Controller('author')
export class AuthorController {
constructor(private readonly authorService: AuthorService) {}

@Post('create')
@ApiResponse({
status: 201,
description: 'Create new author',
})
@UseGuards(JwtAuthGuard, RoleGuard)
@Roles([Role.ADMIN])
async create(@Body() body: CreateAuthorDto, @Res() res: Response) {
const data = await this.authorService.create(body);

return res.status(HttpStatus.CREATED).json(data);
}

@Get(':id')
@ApiResponse({
status: 200,
description: 'Get a author',
})
async getById(@Param('id') id: string, @Res() res: Response) {
const data = await this.authorService.getById(id);

return res.status(HttpStatus.CREATED).json(data);
}

@Delete('delete/:id')
@ApiResponse({
status: 201,
description: 'Delete a author',
})
@UseGuards(JwtAuthGuard, RoleGuard)
@Roles([Role.ADMIN])
async delete(@Param('id') id: string, @Res() res: Response) {
await this.authorService.delete(id);

return res.status(HttpStatus.OK).send();
}

@Put('update/:id')
@ApiResponse({
status: 201,
description: 'Update a author',
})
@UseGuards(JwtAuthGuard, RoleGuard)
@Roles([Role.ADMIN])
async update(
@Body() body: UpdateAuthorDto,
@Param('id') id: string,
@Res() res: Response,
) {
const data = await this.authorService.update(id, body);

return res.status(HttpStatus.OK).json(data);
}

@Get('search')
@ApiResponse({
status: 200,
description: 'Author search',
})
async search(@Query() query: SearchAuthorDto, @Res() res: Response) {
const data = await this.authorService.search(query);
return res.status(HttpStatus.OK).json(data);
}
}
Loading

0 comments on commit dae0c4d

Please sign in to comment.