hrms-api-org/src/controllers/ApiKeyController.ts
2025-10-25 01:55:54 +07:00

243 lines
7.2 KiB
TypeScript

import {
Controller,
Post,
Delete,
Route,
Security,
Tags,
Body,
Path,
Request,
Response,
Get,
} from "tsoa";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpStatusCode from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import { CreateApiKey, ApiKey } from "../entities/ApiKey";
import { In } from "typeorm";
import { RequestWithUser } from "../middlewares/user";
import { ApiName } from "../entities/ApiName";
import { ApiHistory } from "../entities/ApiHistory";
const jwt = require("jsonwebtoken");
@Route("api/v1/org/apiKey")
@Tags("ApiKey")
@Security("bearerAuth")
@Response(
HttpStatusCode.INTERNAL_SERVER_ERROR,
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
export class ApiKeyController extends Controller {
private apiKeyRepository = AppDataSource.getRepository(ApiKey);
private apiNameRepository = AppDataSource.getRepository(ApiName);
private apiHistoryRepository = AppDataSource.getRepository(ApiHistory);
/**
* API ตรวจสอบและถอดรหัส JWT token
*
* @summary ตรวจสอบ JWT API Key
*/
@Post("verify")
async verifyApiKey(@Body() requestBody: { token: string }) {
try {
const jwtSecret = process.env.JWT_SECRET || "your-default-secret-key";
console.log("JWT_SECRET from env:", process.env.JWT_SECRET ? "exists" : "not found");
console.log("Using secret:", jwtSecret);
const decoded = jwt.verify(requestBody.token, jwtSecret);
return new HttpSuccess({
valid: true,
data: decoded,
});
} catch (error: any) {
console.error("JWT Verification Error:", error.message);
return new HttpSuccess({
valid: false,
error: error.message,
});
}
}
/**
* API สร้าง Api Key
*
* @summary สร้าง Api Key (ADMIN)
*
*/
@Post()
async createApiKey(
@Body()
requestBody: CreateApiKey,
@Request() request: RequestWithUser,
) {
const checkName = await this.apiKeyRepository.findOne({
where: { name: requestBody.name },
});
if (checkName) throw new HttpError(HttpStatusCode.NOT_FOUND, "ชื่อนี้มีอยู่ในระบบแล้ว");
const apiName = await this.apiNameRepository.find({
where: { id: In(requestBody.apiId) },
});
const apiKey = Object.assign(new ApiKey(), requestBody);
// Create JWT token with embedded data
const tokenPayload = {
keyId: apiKey.id || require("crypto").randomUUID(),
name: apiKey.name,
accessType: apiKey.accessType,
dnaRootId: apiKey.dnaRootId,
dnaChild1Id: apiKey.dnaChild1Id,
dnaChild2Id: apiKey.dnaChild2Id,
dnaChild3Id: apiKey.dnaChild3Id,
dnaChild4Id: apiKey.dnaChild4Id,
apiIds: requestBody.apiId,
createdBy: request.user.sub,
createdAt: new Date().toISOString(),
iat: Math.floor(Date.now() / 1000),
};
// Sign JWT with secret (you should use environment variable for the secret)
const jwtSecret = process.env.JWT_SECRET || "your-default-secret-key";
const jwtToken = jwt.sign(tokenPayload, jwtSecret, {
expiresIn: "365d", // 1 year expiration
});
apiKey.keyApi = jwtToken;
apiKey.apiNames = apiName;
apiKey.createdUserId = request.user.sub;
apiKey.createdFullName = request.user.name;
apiKey.lastUpdateUserId = request.user.sub;
apiKey.lastUpdateFullName = request.user.name;
apiKey.createdAt = new Date();
apiKey.lastUpdatedAt = new Date();
await this.apiKeyRepository.save(apiKey);
return new HttpSuccess(apiKey.keyApi);
}
/**
* API ลบ Api Key
*
* @summary ลบ Api Key (ADMIN)
*
* @param {string} id Id Api Key
*/
@Delete("{id}")
async deleteApiKey(@Path() id: string, @Request() req: RequestWithUser) {
const delApiKey = await this.apiKeyRepository.findOne({
where: { id },
relations: ["apiHistorys"],
});
if (!delApiKey) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งนี้");
}
await this.apiHistoryRepository.remove(delApiKey.apiHistorys);
await this.apiKeyRepository.remove(delApiKey);
return new HttpSuccess();
}
/**
* API รายการ Api Key
*
* @summary รายการ Api Key (ADMIN)
*
*/
@Get("list")
async listApiKey() {
const apiKey = await this.apiKeyRepository.find({
relations: ["apiNames", "apiHistorys"],
order: { createdAt: "DESC", apiNames: { createdAt: "DESC" } },
});
const data = apiKey.map((_data) => ({
id: _data.id,
createdAt: _data.createdAt,
createdUserId: _data.createdUserId,
createdFullName: _data.createdFullName,
name: _data.name,
accessType: _data.accessType,
dnaRootId: _data.dnaRootId,
dnaChild1Id: _data.dnaChild1Id,
dnaChild2Id: _data.dnaChild2Id,
dnaChild3Id: _data.dnaChild3Id,
dnaChild4Id: _data.dnaChild4Id,
apiNames: _data.apiNames.map((x) => ({
id: x.id,
name: x.name,
pathApi: x.pathApi,
methodApi: x.methodApi,
})),
amount: _data.apiHistorys.length,
}));
return new HttpSuccess(data);
}
/**
* API รายการ Api Key
*
* @summary รายการ Api Key (ADMIN)
*
*/
@Get("name")
async listApiName() {
const apiName = await this.apiNameRepository.find({
where: { isActive: true },
order: { createdAt: "DESC" },
});
return new HttpSuccess(apiName);
}
/**
* API สร้าง Api Key
*
* @summary สร้าง Api Key (ADMIN)
*
*/
@Post("history")
async getHistory(
@Body()
requestBody: {
startDate: Date;
endDate: Date;
apiNameId: string | null;
},
@Request() request: RequestWithUser,
) {
if (requestBody.apiNameId) {
const apiName = await this.apiNameRepository.findOne({
where: { id: requestBody.apiNameId },
});
if (!apiName)
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบรายการ Web Service นี้ในระบบ");
}
const apiHistory = await AppDataSource.getRepository(ApiHistory)
.createQueryBuilder("apiHistory")
.leftJoinAndSelect("apiHistory.apiKey", "apiKey")
.leftJoinAndSelect("apiHistory.apiName", "apiName")
.andWhere(requestBody.apiNameId ? `apiHistory.apiNameId = :apiNameId` : "1=1", {
apiNameId: requestBody.apiNameId,
})
.andWhere(
`apiHistory.createdAt >= DATE(:startDate) AND apiHistory.createdAt <= DATE(:endDate)`,
{
startDate: new Date(requestBody.startDate),
endDate: new Date(
requestBody.endDate.setDate(new Date(requestBody.endDate).getDate() + 1),
),
},
)
.orderBy("apiHistory.createdAt", "DESC")
.getMany();
const result = apiHistory.map((x) => ({
id: x.id,
apiName: x.apiName.name,
apiKey: x.apiKey.name,
createdAt: x.createdAt,
ipApi: x.ipApi,
}));
return new HttpSuccess(result);
}
}