feat: add isPublic field to Query entity and implement QueryPublicGuard for public query access control
This commit is contained in:
@ -19,6 +19,7 @@ import { TLogType } from "../logger/logger.types";
|
||||
import { QueryResponse } from "src/vm/vm.constants";
|
||||
import { Query } from "../entities/query.entity";
|
||||
import { Token } from "src/api/entities/token.entity";
|
||||
import { QueryPublicGuard } from "../guards/query-public";
|
||||
|
||||
@UseGuards(ApiTokenGuard)
|
||||
export abstract class BaseQueryController {
|
||||
@ -36,7 +37,8 @@ export abstract class BaseQueryController {
|
||||
@Post("create")
|
||||
async createQuery(
|
||||
@Req() req: Request & { apiToken: Token },
|
||||
@Body() queryData: { source: string; isTypescript?: number }
|
||||
@Body()
|
||||
queryData: { source: string; isTypescript?: number; isPublic?: number }
|
||||
) {
|
||||
return this.queryHandlerService.createQuery(
|
||||
{
|
||||
@ -50,21 +52,24 @@ export abstract class BaseQueryController {
|
||||
@Post("update/:id")
|
||||
@UseGuards(QueryGuard)
|
||||
async updateQuery(
|
||||
@Body() updateData: Partial<{ source: string; isTypescript?: number }>,
|
||||
@Body()
|
||||
updateData: Partial<{
|
||||
source: string;
|
||||
isTypescript?: number;
|
||||
isPublic?: number;
|
||||
}>,
|
||||
@Param("id") id: string
|
||||
) {
|
||||
return this.queryHandlerService.updateQuery(id, updateData);
|
||||
}
|
||||
|
||||
@Post("/run/:id")
|
||||
@UseGuards(QueryGuard)
|
||||
async runQuery(
|
||||
@Param("id") id: string,
|
||||
@Body() query: Record<string, any>,
|
||||
@Headers() headers: Record<string, any>,
|
||||
@Res() res: Response,
|
||||
@Req() req: Request & { query: Query }
|
||||
) {
|
||||
private async run(
|
||||
id: string,
|
||||
query: Record<string, any>,
|
||||
headers: Record<string, any>,
|
||||
res: Response,
|
||||
req: Request & { query: Query }
|
||||
): Promise<QueryResponse> {
|
||||
let queryResult: QueryResponse;
|
||||
const loggerTraceId =
|
||||
headers["x-trace-id"] || LoggerService.generateTraceId();
|
||||
@ -143,6 +148,30 @@ export abstract class BaseQueryController {
|
||||
res.send(queryResult?.response || null);
|
||||
}
|
||||
|
||||
@Post("/run-public/:id")
|
||||
@UseGuards(QueryPublicGuard)
|
||||
async runPublicQuery(
|
||||
@Param("id") id: string,
|
||||
@Body() query: Record<string, any>,
|
||||
@Headers() headers: Record<string, any>,
|
||||
@Res() res: Response,
|
||||
@Req() req: Request & { query: Query }
|
||||
) {
|
||||
return this.run(id, query, headers, res, req);
|
||||
}
|
||||
|
||||
@Post("/run/:id")
|
||||
@UseGuards(QueryGuard)
|
||||
async runQuery(
|
||||
@Param("id") id: string,
|
||||
@Body() query: Record<string, any>,
|
||||
@Headers() headers: Record<string, any>,
|
||||
@Res() res: Response,
|
||||
@Req() req: Request & { query: Query }
|
||||
) {
|
||||
return this.run(id, query, headers, res, req);
|
||||
}
|
||||
|
||||
@Delete("/delete/:id")
|
||||
@UseGuards(QueryGuard)
|
||||
async deleteQuery(@Param("id") id: string) {
|
||||
|
||||
@ -30,4 +30,7 @@ export class Query {
|
||||
|
||||
@Column({ type: "tinyint", default: 0 })
|
||||
isTypescript: number;
|
||||
|
||||
@Column({ type: "tinyint", default: 0 })
|
||||
isPublic: number;
|
||||
}
|
||||
|
||||
44
src/query/guards/query-public.ts
Normal file
44
src/query/guards/query-public.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
Inject,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { QueryHandlerService } from "src/query/handler/query.handler.service";
|
||||
|
||||
@Injectable()
|
||||
export class QueryPublicGuard implements CanActivate {
|
||||
constructor(
|
||||
@Inject(QueryHandlerService)
|
||||
private readonly queryHandlerService: QueryHandlerService
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
|
||||
const queryId = request.params?.id;
|
||||
|
||||
if (!queryId) {
|
||||
throw new UnauthorizedException("Query ID is required");
|
||||
}
|
||||
|
||||
const query = await this.queryHandlerService.getQueryById(queryId);
|
||||
|
||||
if (!query) {
|
||||
throw new UnauthorizedException("Query not found");
|
||||
}
|
||||
|
||||
if (!query.isActive) {
|
||||
throw new UnauthorizedException("Query is inactive");
|
||||
}
|
||||
|
||||
if (query.isPublic !== 1) {
|
||||
throw new UnauthorizedException("Query is not public");
|
||||
}
|
||||
|
||||
request.query = query;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user