feat: implement AdminGuard and QueryGuard for enhanced access control; refactor API and query handling; add deleteQuery method in QueryHandlerService; update QueryResponse type for improved response handling
This commit is contained in:
@ -1,7 +1,18 @@
|
|||||||
import { Body, Controller, Delete, Inject, Post } from "@nestjs/common";
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Delete,
|
||||||
|
Inject,
|
||||||
|
Post,
|
||||||
|
UseGuards,
|
||||||
|
} from "@nestjs/common";
|
||||||
import { ApiService } from "./api.service";
|
import { ApiService } from "./api.service";
|
||||||
|
import { AdminGuard } from "./guards/admin.guard";
|
||||||
|
import { ApiTokenGuard } from "./guards/api-token.guard";
|
||||||
|
|
||||||
@Controller("api")
|
@Controller("api")
|
||||||
|
@UseGuards(ApiTokenGuard)
|
||||||
|
@UseGuards(AdminGuard)
|
||||||
export class ApiController {
|
export class ApiController {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(ApiService)
|
@Inject(ApiService)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { ApiController } from "./api.controller";
|
|||||||
import { Project } from "../project/entities/project.entity";
|
import { Project } from "../project/entities/project.entity";
|
||||||
import { ApiTokenGuard } from "./guards/api-token.guard";
|
import { ApiTokenGuard } from "./guards/api-token.guard";
|
||||||
import { RedisModule } from "src/redis/redis.module";
|
import { RedisModule } from "src/redis/redis.module";
|
||||||
import { QueryGuard } from "./guards/query.guard";
|
import { QueryGuard } from "../query/guards/query.guard";
|
||||||
import { QueryModule } from "src/query/query.module";
|
import { QueryModule } from "src/query/query.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
|||||||
@ -9,6 +9,9 @@ export class Token {
|
|||||||
@Column({ type: "tinyint", default: 1 })
|
@Column({ type: "tinyint", default: 1 })
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
|
|
||||||
|
@Column({ type: "tinyint", default: 0 })
|
||||||
|
isAdmin: boolean;
|
||||||
|
|
||||||
@ManyToOne(() => Project, (project) => project.apiTokens)
|
@ManyToOne(() => Project, (project) => project.apiTokens)
|
||||||
project: Project;
|
project: Project;
|
||||||
}
|
}
|
||||||
|
|||||||
27
src/api/guards/admin.guard.ts
Normal file
27
src/api/guards/admin.guard.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import {
|
||||||
|
CanActivate,
|
||||||
|
ExecutionContext,
|
||||||
|
Inject,
|
||||||
|
Injectable,
|
||||||
|
UnauthorizedException,
|
||||||
|
} from "@nestjs/common";
|
||||||
|
import { ApiService } from "../api.service";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AdminGuard implements CanActivate {
|
||||||
|
constructor(
|
||||||
|
@Inject(ApiService)
|
||||||
|
private readonly apiService: ApiService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||||
|
const request = context.switchToHttp().getRequest();
|
||||||
|
const apiToken = request.apiToken;
|
||||||
|
|
||||||
|
if (!apiToken || !apiToken.isAdmin) {
|
||||||
|
throw new UnauthorizedException("Admin privileges are required");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
Body,
|
Body,
|
||||||
|
Delete,
|
||||||
Headers,
|
Headers,
|
||||||
Inject,
|
Inject,
|
||||||
Param,
|
Param,
|
||||||
@ -11,7 +12,7 @@ import { Response } from "express";
|
|||||||
import { QueryHandlerService } from "../handler/query.handler.service";
|
import { QueryHandlerService } from "../handler/query.handler.service";
|
||||||
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
|
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
|
||||||
import { QueryExecuterService } from "../executer/query.executer.service";
|
import { QueryExecuterService } from "../executer/query.executer.service";
|
||||||
import { QueryGuard } from "src/api/guards/query.guard";
|
import { QueryGuard } from "src/query/guards/query.guard";
|
||||||
|
|
||||||
@UseGuards(ApiTokenGuard)
|
@UseGuards(ApiTokenGuard)
|
||||||
export abstract class BaseQueryController {
|
export abstract class BaseQueryController {
|
||||||
@ -57,11 +58,12 @@ export abstract class BaseQueryController {
|
|||||||
res.status(queryResult?.statusCode || 200);
|
res.status(queryResult?.statusCode || 200);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
queryResult?.statusCode === 302 &&
|
queryResult?.redirect ||
|
||||||
queryResult?.headers &&
|
(queryResult?.statusCode === 302 &&
|
||||||
queryResult?.headers["Location"]
|
queryResult?.headers &&
|
||||||
|
queryResult?.headers["Location"])
|
||||||
) {
|
) {
|
||||||
res.redirect(queryResult?.headers["Location"]);
|
res.redirect(queryResult?.redirect || queryResult?.headers["Location"]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,4 +73,10 @@ export abstract class BaseQueryController {
|
|||||||
|
|
||||||
res.send(queryResult?.response || null);
|
res.send(queryResult?.response || null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Delete("/delete/:id")
|
||||||
|
@UseGuards(QueryGuard)
|
||||||
|
async deleteQuery(@Param("id") id: string) {
|
||||||
|
return this.queryHandlerService.deleteQuery(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,4 +68,16 @@ export class QueryHandlerService {
|
|||||||
Object.assign(query, updateData);
|
Object.assign(query, updateData);
|
||||||
return this.queryRepository.save(query);
|
return this.queryRepository.save(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteQuery(id: string) {
|
||||||
|
const query = await this.queryRepository.findOne({ where: { id } });
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
throw new Error("Query not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.redisClient.del(`query_${id}`);
|
||||||
|
|
||||||
|
return this.queryRepository.remove(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,8 @@ export const registeredModules = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type QueryResponse = {
|
export type QueryResponse = {
|
||||||
statusCode: number;
|
statusCode?: number;
|
||||||
response: any;
|
response: any;
|
||||||
headers: Record<string, string>;
|
headers?: Record<string, string>;
|
||||||
|
redirect?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user