From d4fb9df013801c3caa9799f1ed51ec2cc6944bd5 Mon Sep 17 00:00:00 2001 From: yosaphatprs Date: Mon, 27 Oct 2025 14:29:44 +0700 Subject: [PATCH] feat: add auth guard on obat and tindakan dokter, fix response on get all users and add auth guard on get all users --- .../api/src/modules/auth/auth.controller.ts | 6 ++-- backend/api/src/modules/auth/auth.module.ts | 1 + .../auth/{ => decorator}/roles.decorator.ts | 2 +- .../auth/{ => guard}/auth.guard.spec.ts | 0 .../modules/auth/{ => guard}/auth.guard.ts | 0 .../auth/{ => guard}/roles.guard.spec.ts | 0 .../modules/auth/{ => guard}/roles.guard.ts | 4 +-- .../api/src/modules/obat/obat.controller.ts | 4 ++- .../rekammedis/rekammedis.controller.ts | 3 +- .../modules/rekammedis/rekammedis.module.ts | 2 +- .../tindakandokter.controller.ts | 3 ++ .../tindakandokter/tindakandokter.module.ts | 1 + .../src/modules/user/dto/query-users.dto.ts | 31 +++++++++++++++++++ .../api/src/modules/user/user.controller.ts | 10 +++++- backend/api/src/modules/user/user.service.ts | 16 +++++++--- 15 files changed, 69 insertions(+), 14 deletions(-) rename backend/api/src/modules/auth/{ => decorator}/roles.decorator.ts (78%) rename backend/api/src/modules/auth/{ => guard}/auth.guard.spec.ts (100%) rename backend/api/src/modules/auth/{ => guard}/auth.guard.ts (100%) rename backend/api/src/modules/auth/{ => guard}/roles.guard.spec.ts (100%) rename backend/api/src/modules/auth/{ => guard}/roles.guard.ts (89%) create mode 100644 backend/api/src/modules/user/dto/query-users.dto.ts diff --git a/backend/api/src/modules/auth/auth.controller.ts b/backend/api/src/modules/auth/auth.controller.ts index de591cd..27359c0 100644 --- a/backend/api/src/modules/auth/auth.controller.ts +++ b/backend/api/src/modules/auth/auth.controller.ts @@ -9,9 +9,9 @@ import { import { CreateUserDto, CreateUserDtoResponse } from './dto/create-user.dto'; import { AuthDto, AuthDtoResponse, UserRole } from './dto/auth.dto'; import { AuthService } from './auth.service'; -import { AuthGuard } from './auth.guard'; -import { RolesGuard } from './roles.guard'; -import { Roles } from './roles.decorator'; +import { AuthGuard } from './guard/auth.guard'; +import { RolesGuard } from './guard/roles.guard'; +import { Roles } from './decorator/roles.decorator'; @Controller('/auth') export class AuthController { diff --git a/backend/api/src/modules/auth/auth.module.ts b/backend/api/src/modules/auth/auth.module.ts index a914552..2218439 100644 --- a/backend/api/src/modules/auth/auth.module.ts +++ b/backend/api/src/modules/auth/auth.module.ts @@ -11,6 +11,7 @@ import { JwtModule } from '@nestjs/jwt'; PrismaModule, ConfigModule, JwtModule.registerAsync({ + global: true, imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ diff --git a/backend/api/src/modules/auth/roles.decorator.ts b/backend/api/src/modules/auth/decorator/roles.decorator.ts similarity index 78% rename from backend/api/src/modules/auth/roles.decorator.ts rename to backend/api/src/modules/auth/decorator/roles.decorator.ts index 1a811e2..a848721 100644 --- a/backend/api/src/modules/auth/roles.decorator.ts +++ b/backend/api/src/modules/auth/decorator/roles.decorator.ts @@ -1,5 +1,5 @@ import { SetMetadata } from '@nestjs/common'; -import { UserRole } from './dto/auth.dto'; +import { UserRole } from '../dto/auth.dto'; export const ROLES_KEY = 'roles'; diff --git a/backend/api/src/modules/auth/auth.guard.spec.ts b/backend/api/src/modules/auth/guard/auth.guard.spec.ts similarity index 100% rename from backend/api/src/modules/auth/auth.guard.spec.ts rename to backend/api/src/modules/auth/guard/auth.guard.spec.ts diff --git a/backend/api/src/modules/auth/auth.guard.ts b/backend/api/src/modules/auth/guard/auth.guard.ts similarity index 100% rename from backend/api/src/modules/auth/auth.guard.ts rename to backend/api/src/modules/auth/guard/auth.guard.ts diff --git a/backend/api/src/modules/auth/roles.guard.spec.ts b/backend/api/src/modules/auth/guard/roles.guard.spec.ts similarity index 100% rename from backend/api/src/modules/auth/roles.guard.spec.ts rename to backend/api/src/modules/auth/guard/roles.guard.spec.ts diff --git a/backend/api/src/modules/auth/roles.guard.ts b/backend/api/src/modules/auth/guard/roles.guard.ts similarity index 89% rename from backend/api/src/modules/auth/roles.guard.ts rename to backend/api/src/modules/auth/guard/roles.guard.ts index 7c7c642..12d8e3f 100644 --- a/backend/api/src/modules/auth/roles.guard.ts +++ b/backend/api/src/modules/auth/guard/roles.guard.ts @@ -5,8 +5,8 @@ import { ForbiddenException, } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; -import { ROLES_KEY } from './roles.decorator'; -import { UserRole } from './dto/auth.dto'; +import { ROLES_KEY } from '../decorator/roles.decorator'; +import { UserRole } from '../dto/auth.dto'; @Injectable() export class RolesGuard implements CanActivate { diff --git a/backend/api/src/modules/obat/obat.controller.ts b/backend/api/src/modules/obat/obat.controller.ts index cdc170c..0944710 100644 --- a/backend/api/src/modules/obat/obat.controller.ts +++ b/backend/api/src/modules/obat/obat.controller.ts @@ -1,11 +1,13 @@ -import { Controller, Get, Query } from '@nestjs/common'; +import { Controller, Get, Query, UseGuards } from '@nestjs/common'; import { ObatService } from './obat.service'; +import { AuthGuard } from '../auth/guard/auth.guard'; @Controller('obat') export class ObatController { constructor(private readonly obatService: ObatService) {} @Get('/') + @UseGuards(AuthGuard) async getAllObat( @Query('take') take: number, @Query('skip') skip: number, diff --git a/backend/api/src/modules/rekammedis/rekammedis.controller.ts b/backend/api/src/modules/rekammedis/rekammedis.controller.ts index 523588a..a29b509 100644 --- a/backend/api/src/modules/rekammedis/rekammedis.controller.ts +++ b/backend/api/src/modules/rekammedis/rekammedis.controller.ts @@ -10,7 +10,7 @@ import { } from '@nestjs/common'; import { RekammedisService } from './rekammedis.service'; import { CreateRekamMedisDto } from './dto/create-rekammedis.dto'; -import { AuthGuard } from '../auth/auth.guard'; +import { AuthGuard } from '../auth/guard/auth.guard'; @Controller('/rekammedis') export class RekamMedisController { @@ -40,6 +40,7 @@ export class RekamMedisController { @Post('/') @Header('Content-Type', 'application/json') + @UseGuards(AuthGuard) async createRekamMedis(@Body() dto: CreateRekamMedisDto) { return this.rekammedisService.createRekamMedis(dto); } diff --git a/backend/api/src/modules/rekammedis/rekammedis.module.ts b/backend/api/src/modules/rekammedis/rekammedis.module.ts index 275e78f..fbac3a0 100644 --- a/backend/api/src/modules/rekammedis/rekammedis.module.ts +++ b/backend/api/src/modules/rekammedis/rekammedis.module.ts @@ -5,7 +5,7 @@ import { PrismaModule } from '../prisma/prisma.module'; import { JwtModule } from '@nestjs/jwt'; @Module({ - imports: [PrismaModule, JwtModule], + imports: [PrismaModule], controllers: [RekamMedisController], providers: [RekammedisService], }) diff --git a/backend/api/src/modules/tindakandokter/tindakandokter.controller.ts b/backend/api/src/modules/tindakandokter/tindakandokter.controller.ts index 921efe4..6808ecc 100644 --- a/backend/api/src/modules/tindakandokter/tindakandokter.controller.ts +++ b/backend/api/src/modules/tindakandokter/tindakandokter.controller.ts @@ -5,14 +5,17 @@ import { HttpCode, Param, Query, + UseGuards, } from '@nestjs/common'; import { TindakanDokterService } from './tindakandokter.service'; +import { AuthGuard } from '../auth/guard/auth.guard'; @Controller('/tindakan') export class TindakanDokterController { constructor(private tindakanDokterService: TindakanDokterService) {} @Get('/') + @UseGuards(AuthGuard) async getAllTindakanDokter( @Query('take') take: number, @Query('tindakan') tindakan: string, diff --git a/backend/api/src/modules/tindakandokter/tindakandokter.module.ts b/backend/api/src/modules/tindakandokter/tindakandokter.module.ts index 8dcc68b..b8613c3 100644 --- a/backend/api/src/modules/tindakandokter/tindakandokter.module.ts +++ b/backend/api/src/modules/tindakandokter/tindakandokter.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { TindakanDokterController } from './tindakandokter.controller'; import { TindakanDokterService } from './tindakandokter.service'; import { PrismaModule } from '../prisma/prisma.module'; +import { JwtModule } from '@nestjs/jwt'; @Module({ imports: [PrismaModule], diff --git a/backend/api/src/modules/user/dto/query-users.dto.ts b/backend/api/src/modules/user/dto/query-users.dto.ts new file mode 100644 index 0000000..5bf83a2 --- /dev/null +++ b/backend/api/src/modules/user/dto/query-users.dto.ts @@ -0,0 +1,31 @@ +import { UserRole } from '@api/modules/auth/dto/auth.dto'; +import { Expose, Transform } from 'class-transformer'; +import { IsEnum, IsOptional } from 'class-validator'; + +export class QueryUsersDto { + search?: string; +} + +export class QueryUsersResponseDto { + @Expose() + // @Transform(({ value }) => (value ? parseInt(value) : null)) + id: bigint; + + @Expose() + name: string; + + @Expose() + username: string; + + @Expose() + @IsEnum(UserRole, { message: 'role must be a valid UserRole' }) + role: UserRole; + + @Expose() + @IsOptional() + created_at?: Date; + + @Expose() + @IsOptional() + updated_at?: Date; +} diff --git a/backend/api/src/modules/user/user.controller.ts b/backend/api/src/modules/user/user.controller.ts index 3c6b42e..9e132ec 100644 --- a/backend/api/src/modules/user/user.controller.ts +++ b/backend/api/src/modules/user/user.controller.ts @@ -10,11 +10,17 @@ import { Query, Req, Res, + UseGuards, UseInterceptors, } from '@nestjs/common'; import type { Request, Response } from 'express'; import { UserService } from './user.service'; import { users } from '@dist/generated/prisma'; +import { AuthGuard } from '../auth/guard/auth.guard'; +import { RolesGuard } from '../auth/guard/roles.guard'; +import { Roles } from '../auth/decorator/roles.decorator'; +import { UserRole } from '../auth/dto/auth.dto'; +import { QueryUsersResponseDto } from './dto/query-users.dto'; @Controller('/users') @UseInterceptors(ClassSerializerInterceptor) @@ -28,8 +34,10 @@ export class UserController { @Get('/') @Header('Content-Type', 'application/json') + @UseGuards(AuthGuard, RolesGuard) + @Roles(UserRole.Admin) @HttpCode(200) - getAllUsers(): Promise { + getAllUsers(): Promise { return this.userService.getAllUsers(); } diff --git a/backend/api/src/modules/user/user.service.ts b/backend/api/src/modules/user/user.service.ts index de4040c..3881815 100644 --- a/backend/api/src/modules/user/user.service.ts +++ b/backend/api/src/modules/user/user.service.ts @@ -1,12 +1,20 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; -import { users } from '@dist/generated/prisma'; +import { QueryUsersResponseDto } from './dto/query-users.dto'; +import { UserRole } from '../auth/dto/auth.dto'; @Injectable() export class UserService { constructor(private prisma: PrismaService) {} - - async getAllUsers(): Promise { - return this.prisma.users.findMany(); + async getAllUsers(): Promise { + const users = await this.prisma.users.findMany(); + return users.map((user) => ({ + id: user.id, + name: user.nama_lengkap, + username: user.username, + role: user.role as UserRole, + created_at: user.created_at || undefined, + updated_at: user.updated_at || undefined, + })); } }