diff --git a/src/api/api.controller.ts b/src/api/api.controller.ts index 4403726..ceb3063 100644 --- a/src/api/api.controller.ts +++ b/src/api/api.controller.ts @@ -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 { AdminGuard } from "./guards/admin.guard"; +import { ApiTokenGuard } from "./guards/api-token.guard"; @Controller("api") +@UseGuards(ApiTokenGuard) +@UseGuards(AdminGuard) export class ApiController { constructor( @Inject(ApiService) diff --git a/src/api/api.module.ts b/src/api/api.module.ts index f0c5a48..610752c 100644 --- a/src/api/api.module.ts +++ b/src/api/api.module.ts @@ -7,7 +7,7 @@ import { ApiController } from "./api.controller"; import { Project } from "../project/entities/project.entity"; import { ApiTokenGuard } from "./guards/api-token.guard"; 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"; @Module({ diff --git a/src/api/entities/token.entity.ts b/src/api/entities/token.entity.ts index 1b1cc87..0a018c4 100644 --- a/src/api/entities/token.entity.ts +++ b/src/api/entities/token.entity.ts @@ -9,6 +9,9 @@ export class Token { @Column({ type: "tinyint", default: 1 }) isActive: boolean; + @Column({ type: "tinyint", default: 0 }) + isAdmin: boolean; + @ManyToOne(() => Project, (project) => project.apiTokens) project: Project; } diff --git a/src/api/guards/admin.guard.ts b/src/api/guards/admin.guard.ts new file mode 100644 index 0000000..6d419f3 --- /dev/null +++ b/src/api/guards/admin.guard.ts @@ -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 { + const request = context.switchToHttp().getRequest(); + const apiToken = request.apiToken; + + if (!apiToken || !apiToken.isAdmin) { + throw new UnauthorizedException("Admin privileges are required"); + } + + return true; + } +} diff --git a/src/query/base/base-query.controller.ts b/src/query/base/base-query.controller.ts index dd42cfd..b9eec0c 100644 --- a/src/query/base/base-query.controller.ts +++ b/src/query/base/base-query.controller.ts @@ -1,5 +1,6 @@ import { Body, + Delete, Headers, Inject, Param, @@ -11,7 +12,7 @@ import { Response } from "express"; import { QueryHandlerService } from "../handler/query.handler.service"; import { ApiTokenGuard } from "src/api/guards/api-token.guard"; 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) export abstract class BaseQueryController { @@ -57,11 +58,12 @@ export abstract class BaseQueryController { res.status(queryResult?.statusCode || 200); if ( - queryResult?.statusCode === 302 && - queryResult?.headers && - queryResult?.headers["Location"] + queryResult?.redirect || + (queryResult?.statusCode === 302 && + queryResult?.headers && + queryResult?.headers["Location"]) ) { - res.redirect(queryResult?.headers["Location"]); + res.redirect(queryResult?.redirect || queryResult?.headers["Location"]); return; } @@ -71,4 +73,10 @@ export abstract class BaseQueryController { res.send(queryResult?.response || null); } + + @Delete("/delete/:id") + @UseGuards(QueryGuard) + async deleteQuery(@Param("id") id: string) { + return this.queryHandlerService.deleteQuery(id); + } } diff --git a/src/api/guards/query.guard.ts b/src/query/guards/query.guard.ts similarity index 100% rename from src/api/guards/query.guard.ts rename to src/query/guards/query.guard.ts diff --git a/src/query/handler/query.handler.service.ts b/src/query/handler/query.handler.service.ts index 86c46a3..5a375ea 100644 --- a/src/query/handler/query.handler.service.ts +++ b/src/query/handler/query.handler.service.ts @@ -68,4 +68,16 @@ export class QueryHandlerService { Object.assign(query, updateData); 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); + } } diff --git a/src/vm/vm.constants.ts b/src/vm/vm.constants.ts index 4413103..028f567 100644 --- a/src/vm/vm.constants.ts +++ b/src/vm/vm.constants.ts @@ -46,7 +46,8 @@ export const registeredModules = { }; export type QueryResponse = { - statusCode: number; + statusCode?: number; response: any; - headers: Record; + headers?: Record; + redirect?: string; };