Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export type I18nTranslations = {
"userNotExists": string;
"passwordOrEmailError": string;
};
"preview": {
"reject-this-request": string;
};
};
"validation": {
"NOT_EMPTY": string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
I18nModule,
} from 'nestjs-i18n';
import { MockModule } from './mock/mock.module';
import { RejectRequestGuard } from './public/reject.guard';

@Module({
imports: [
Expand Down Expand Up @@ -62,6 +63,10 @@ import { MockModule } from './mock/mock.module';
provide: APP_GUARD,
useClass: AuthGuard,
},
{
provide: APP_GUARD,
useClass: RejectRequestGuard,
},
{
provide: APP_GUARD,
useClass: PermissionGuard,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ import { CreateI18Dto } from './dto/create-i18.dto';
import { UpdateI18Dto } from './dto/update-i18.dto';
import { I18LangService } from './lang.service';
import { Permission } from '../public/permission.decorator';
import { Reject } from '../public/reject.decorator';

@Controller('i18')
export class I18Controller {
constructor(private readonly i18Service: I18Service) {}

@Reject()
@Permission('i18n::add')
@Post()
create(@Body() createI18Dto: CreateI18Dto) {
Expand Down Expand Up @@ -58,6 +60,7 @@ export class I18Controller {
return this.i18Service.findOne(id);
}

@Reject()
@Permission('i18n::update')
@Patch(':id')
update(
Expand All @@ -67,6 +70,7 @@ export class I18Controller {
return this.i18Service.update(id, updateI18Dto);
}

@Reject()
@Permission('i18n::remove')
@Delete(':id')
remove(@Param('id', ParseIntPipe) id: number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import {
import { I18LangService } from './lang.service';
import { CreateLang } from './dto/create-lang.dto';
import { Permission } from '../public/permission.decorator';
import { Reject } from '../public/reject.decorator';

@Controller('/lang')
export class I18nLangController {
constructor(private readonly langService: I18LangService) {}

@Reject()
@Permission('lang::add')
@Post('')
createLang(@Body() data: CreateLang) {
Expand All @@ -28,6 +30,7 @@ export class I18nLangController {
return this.langService.findAll();
}

@Reject()
@Permission('lang::update')
@Patch(':id')
updateLang(
Expand All @@ -37,6 +40,7 @@ export class I18nLangController {
return this.langService.update(id, data);
}

@Reject()
@Permission('lang::remove')
@Delete(':id')
removeLang(@Param('id', ParseIntPipe) id: number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@
"auth":{
"userNotExists": "User not found",
"passwordOrEmailError": "Password or email invalid"
},
"preview": {
"reject-this-request": "The server rejected this request, and modification, addition, or deletion of data is not allowed in demonstration mode"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@
"auth":{
"userNotExists": "用户不存在",
"passwordOrEmailError": "密码或邮箱错误"
},
"preview": {
"reject-this-request": "服务器拒绝了本次请求, 因为演示模式下不允许增加, 删除, 修改数据"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import {
Body,
Patch,
Query,
Delete, Param,
Delete,
Param,
} from '@nestjs/common';
import { MenuService } from './menu.service';
import { CreateMenuDto } from './dto/create-menu.dto';
import { Permission } from '../public/permission.decorator';
import { UpdateMenuDto } from './dto/update-menu.dto';
import { Reject } from '../public/reject.decorator';

@Controller('menu')
export class MenuController {
Expand All @@ -27,21 +29,27 @@ export class MenuController {
return this.menuService.findAllMenu();
}

@Reject()
@Post()
@Permission('menu::add')
async createMenu(@Body() dto: CreateMenuDto) {
return this.menuService.createMenu(dto, false);
}

@Reject()
@Patch()
@Permission('menu::update')
async updateMenu(@Body() dto: UpdateMenuDto) {
return this.menuService.updateMenu(dto);
}

@Reject()
@Delete()
@Permission('menu::remove')
async deleteMenu(@Query('id') id: number, @Query('parentId') parentId: number) {
async deleteMenu(
@Query('id') id: number,
@Query('parentId') parentId: number
) {
return this.menuService.deleteMenu(id, parentId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,20 @@ import { PermissionService } from './permission.service';
import { CreatePermissionDto } from './dto/create-permission.dto';
import { Permission } from '../public/permission.decorator';
import { UpdatePermissionDto } from './dto/update-permission.dto';
import { Reject } from '../public/reject.decorator';

@Controller('permission')
export class PermissionController {
constructor(private readonly permissionService: PermissionService) {}

@Reject()
@Permission('permission::add')
@Post()
create(@Body() dto: CreatePermissionDto) {
return this.permissionService.create(dto, false);
}

@Reject()
@Patch()
@Permission('permission::update')
update(@Body() dto: UpdatePermissionDto) {
Expand All @@ -41,6 +44,7 @@ export class PermissionController {
return this.permissionService.findPermission(page, limit, name);
}

@Reject()
@Delete('/:id')
@Permission('permission::remove')
del(@Param('id') id: number) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { SetMetadata } from '@nestjs/common';

export const Reject = () => SetMetadata('reject', true);
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {
CanActivate,
ExecutionContext,
HttpException,
HttpStatus,
Injectable,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { I18nTranslations } from '../.generate/i18n.generated';
import { I18nContext } from 'nestjs-i18n';

@Injectable()
export class RejectRequestGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
async canActivate(ctx: ExecutionContext): Promise<boolean> {
const i18n = I18nContext.current<I18nTranslations>();
const rejectRequest = this.reflector.getAllAndOverride('reject', [
ctx.getHandler(),
ctx.getClass(),
]);
Comment on lines +17 to +20
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Use constant for metadata key

The 'reject' string should be imported from the decorator file to maintain consistency and avoid duplication.

+import { REJECT_KEY } from './reject.decorator';

-    const rejectRequest = this.reflector.getAllAndOverride('reject', [
+    const rejectRequest = this.reflector.getAllAndOverride(REJECT_KEY, [

Committable suggestion skipped: line range outside the PR's diff.

if (!rejectRequest) {
return true;
}
Comment on lines +15 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add request context validation and logging

The guard should validate the request context and log rejected requests for monitoring purposes.

 async canActivate(ctx: ExecutionContext): Promise<boolean> {
+    const request = ctx.switchToHttp().getRequest();
+    if (!request) {
+      throw new Error('Invalid execution context');
+    }
     const i18n = I18nContext.current<I18nTranslations>();
+    if (!i18n) {
+      throw new Error('I18n context not available');
+    }
     const rejectRequest = this.reflector.getAllAndOverride('reject', [
       ctx.getHandler(),
       ctx.getClass(),
     ]);
     if (!rejectRequest) {
       return true;
     }
+    // Log rejected requests
+    console.log(`Request rejected: ${request.method} ${request.url}`);
     throw new HttpException(
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async canActivate(ctx: ExecutionContext): Promise<boolean> {
const i18n = I18nContext.current<I18nTranslations>();
const rejectRequest = this.reflector.getAllAndOverride('reject', [
ctx.getHandler(),
ctx.getClass(),
]);
if (!rejectRequest) {
return true;
}
async canActivate(ctx: ExecutionContext): Promise<boolean> {
const request = ctx.switchToHttp().getRequest();
if (!request) {
throw new Error('Invalid execution context');
}
const i18n = I18nContext.current<I18nTranslations>();
if (!i18n) {
throw new Error('I18n context not available');
}
const rejectRequest = this.reflector.getAllAndOverride('reject', [
ctx.getHandler(),
ctx.getClass(),
]);
if (!rejectRequest) {
return true;
}
// Log rejected requests
console.log(`Request rejected: ${request.method} ${request.url}`);

throw new HttpException(
i18n.t('exception.preview.reject-this-request', {
lang: I18nContext.current().lang,
}),
HttpStatus.BAD_REQUEST
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import { RoleService } from './role.service';
import { CreateRoleDto } from './dto/create-role.dto';
import { UpdateRoleDto } from './dto/update-role.dto';
import { Permission } from '../public/permission.decorator';
import { Reject } from '../public/reject.decorator';

@Controller('role')
export class RoleController {
constructor(private readonly roleService: RoleService) {}

@Reject()
@Permission('role::add')
@Post()
create(@Body() createRoleDto: CreateRoleDto) {
Expand Down Expand Up @@ -46,12 +48,14 @@ export class RoleController {
return this.roleService.findAllDetail(page, limit, name);
}

@Reject()
@Patch()
@Permission('role::update')
updateRole(@Body() dto: UpdateRoleDto) {
return this.roleService.update(dto);
}

@Reject()
@Delete('/:id')
@Permission('role::remove')
deleteRole(@Param('id') id: number) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import { UpdatePwdAdminDto } from './dto/update-pwd-admin.dto';
import { UpdatePwdUserDto } from './dto/update-pwd-user.dto';
import { I18n, I18nContext } from 'nestjs-i18n';
import { I18nTranslations } from '../.generate/i18n.generated';
import { Reject } from '../public/reject.decorator';

@Controller('user')
export class UserController {
constructor(private readonly userService: UserService) {}
@Reject()
@Post('reg')
@Permission('user::add')
async register(@Body() body: CreateUserDto) {
Expand All @@ -49,11 +51,15 @@ export class UserController {
}
return this.userService.getUserInfo(_email, ['role', 'role.permission']);
}

@Reject()
@Delete('/:email')
@Permission('user::remove')
async delUser(@Param('email') email: string) {
return this.userService.deleteUser(email);
}

@Reject()
@Patch('/update')
@Permission('user::update')
async UpdateUser(@Body() body: UpdateUserDto) {
Expand All @@ -70,12 +76,14 @@ export class UserController {
return this.userService.getAllUser(paginationQuery, name, role, email);
}

@Reject()
@Patch('/admin/updatePwd')
@Permission('user::password::force-update')
async updatePwdAdmin(@Body() body: UpdatePwdAdminDto) {
return this.userService.updatePwdAdmin(body);
}

@Reject()
@Patch('/updatePwd')
@Permission('user::update')
async updatePwdUser(@Body() body: UpdatePwdUserDto) {
Expand Down