feat: implement ApiTokenGuard for authentication and apply it to relevant controllers

This commit is contained in:
Boris D
2025-10-06 11:06:02 +03:00
parent 1e84297e84
commit 39c40013b2
10 changed files with 85 additions and 39 deletions

View File

@ -5,10 +5,12 @@ import { ProjectModule } from "../project/project.module";
import { ApiService } from "./api.service";
import { ApiController } from "./api.controller";
import { Project } from "../project/entities/project.entity";
import { ApiTokenGuard } from "./guards/api-token.guard";
@Module({
imports: [ProjectModule, TypeOrmModule.forFeature([Token, Project])],
controllers: [ApiController],
providers: [ApiService],
providers: [ApiService, ApiTokenGuard],
exports: [ApiTokenGuard, TypeOrmModule],
})
export class ApiModule {}

View File

@ -0,0 +1,41 @@
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { Token } from "../entities/token.entity";
@Injectable()
export class ApiTokenGuard implements CanActivate {
constructor(
@InjectRepository(Token)
private readonly tokenRepository: Repository<Token>
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = request.params?.token || request.headers?.["x-api-token"];
if (!token) {
throw new UnauthorizedException("API token is required");
}
const tokenEntity = await this.tokenRepository.findOne({
where: { token },
relations: ["project"],
});
if (!tokenEntity) {
throw new UnauthorizedException("Invalid API token");
}
if (!tokenEntity.isActive) {
throw new UnauthorizedException("API token is inactive");
}
return true;
}
}

View File

@ -8,11 +8,13 @@ import { Project } from "src/project/entities/project.entity";
import { DatabaseManagerController } from "./database/database.manager.controller";
import { DatabaseManagerService } from "./database/database.manager.service";
import { DatabaseNodeService } from "./databaseNode/database.node.service";
import { ApiModule } from "src/api/api.module";
@Module({
imports: [
forwardRef(() => ProjectModule),
forwardRef(() => MigrationModule),
forwardRef(() => ApiModule),
TypeOrmModule.forFeature([Database, DatabaseNode, Project]),
],
controllers: [DatabaseManagerController],

View File

@ -1,9 +1,11 @@
import { Controller, Get, Post, Body, Param } from "@nestjs/common";
import { Controller, Get, Post, Body, Param, UseGuards } from "@nestjs/common";
import { DatabaseManagerService } from "./database.manager.service";
import { DatabaseNodeService } from "../databaseNode/database.node.service";
import { MigrationService } from "../migration/migration.service";
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
@Controller("database")
@UseGuards(ApiTokenGuard)
export class DatabaseManagerController {
constructor(
private readonly databaseManagerService: DatabaseManagerService,

View File

@ -1,7 +1,9 @@
import { Body, Controller, Inject, Put } from "@nestjs/common";
import { Body, Controller, Inject, Put, UseGuards } from "@nestjs/common";
import { ProjectService } from "./project.service";
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
@Controller("project")
@UseGuards(ApiTokenGuard)
export class ProjectController {
constructor(
@Inject(ProjectService)

View File

@ -1,11 +1,12 @@
import { Module } from "@nestjs/common";
import { forwardRef, Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { Project } from "./entities/project.entity";
import { ProjectService } from "./project.service";
import { ProjectController } from "./project.controller";
import { ApiModule } from "src/api/api.module";
@Module({
imports: [TypeOrmModule.forFeature([Project])],
imports: [forwardRef(() => ApiModule), TypeOrmModule.forFeature([Project])],
controllers: [ProjectController],
providers: [ProjectService],
exports: [ProjectService],

View File

@ -6,12 +6,15 @@ import {
Param,
Post,
Res,
UseGuards,
} from "@nestjs/common";
import { QueryHandlerService } from "../handler/query.handler.service";
import { QueryExecuterService } from "../executer/query.executer.service";
import { Response } from "express";
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
@Controller("command")
@UseGuards(ApiTokenGuard)
export class CommandController {
constructor(
@Inject(QueryHandlerService)

View File

@ -6,17 +6,38 @@ import {
Param,
Post,
Res,
UseGuards,
} from "@nestjs/common";
import { Response } from "express";
import { QueryExecuterService } from "./query.executer.service";
import { QueryHandlerService } from "./query.handler.service";
import { ApiTokenGuard } from "src/api/guards/api-token.guard";
import { QueryExecuterService } from "../executer/query.executer.service";
@Controller("query")
export class QueryExecuterController {
@UseGuards(ApiTokenGuard)
export class QueryController {
constructor(
@Inject(QueryHandlerService)
private readonly queryHandlerService: QueryHandlerService,
@Inject(QueryExecuterService)
private readonly queryExecuterService: QueryExecuterService
) {}
@Post("create")
async createQuery(
@Body() queryData: { projectToken: string; source: string }
) {
return this.queryHandlerService.createQuery(queryData);
}
@Post("update/:id")
async updateQuery(
@Body() updateData: Partial<{ source: string }>,
@Inject("id") id: string
) {
return this.queryHandlerService.updateQuery(id, updateData);
}
@Post("/run/:token")
async runQuery(
@Param("token") token: string,

View File

@ -1,25 +0,0 @@
import { Body, Controller, Inject, Post } from "@nestjs/common";
import { QueryHandlerService } from "./query.handler.service";
@Controller("query")
export class QueryHandlerController {
constructor(
@Inject(QueryHandlerService)
private readonly queryHandlerService: QueryHandlerService
) {}
@Post("create")
async createQuery(
@Body() queryData: { projectToken: string; source: string }
) {
return this.queryHandlerService.createQuery(queryData);
}
@Post("update/:id")
async updateQuery(
@Body() updateData: Partial<{ source: string }>,
@Inject("id") id: string
) {
return this.queryHandlerService.updateQuery(id, updateData);
}
}

View File

@ -1,25 +1,22 @@
import { forwardRef, Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { Query } from "./entities/query.entity";
import { QueryExecuterController } from "./executer/query.executer.controller";
import { QueryHandlerController } from "./handler/query.handler.controller";
import { QueryController } from "./handler/query.controller";
import { QueryExecuterService } from "./executer/query.executer.service";
import { QueryHandlerService } from "./handler/query.handler.service";
import { ProjectModule } from "src/project/project.module";
import { DatabaseManagerModule } from "src/databaseManager/database.manager.module";
import { CommandController } from "./command/command.controller";
import { ApiModule } from "src/api/api.module";
@Module({
imports: [
forwardRef(() => ProjectModule),
forwardRef(() => DatabaseManagerModule),
forwardRef(() => ApiModule),
TypeOrmModule.forFeature([Query]),
],
controllers: [
QueryExecuterController,
QueryHandlerController,
CommandController,
],
controllers: [QueryController, CommandController],
providers: [QueryExecuterService, QueryHandlerService],
})
export class QueryModule {}