From 9ec42fd5d92fe38db4493a60858eed85cdc1d98a Mon Sep 17 00:00:00 2001 From: kittapath Date: Wed, 27 Nov 2024 13:53:49 +0700 Subject: [PATCH] no message --- src/controllers/ApiKeyController.ts | 132 ++++++++++++++++++ src/entities/ApiHistory.ts | 66 +++++++++ src/entities/ApiKey.ts | 37 +++++ src/entities/ApiName.ts | 34 +++++ .../1732684774187-add_table_apikey.ts | 28 ++++ .../1732688036303-update_apikey_add_name.ts | 14 ++ 6 files changed, 311 insertions(+) create mode 100644 src/controllers/ApiKeyController.ts create mode 100644 src/entities/ApiHistory.ts create mode 100644 src/entities/ApiKey.ts create mode 100644 src/entities/ApiName.ts create mode 100644 src/migration/1732684774187-add_table_apikey.ts create mode 100644 src/migration/1732688036303-update_apikey_add_name.ts diff --git a/src/controllers/ApiKeyController.ts b/src/controllers/ApiKeyController.ts new file mode 100644 index 00000000..f84a315e --- /dev/null +++ b/src/controllers/ApiKeyController.ts @@ -0,0 +1,132 @@ +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"; +@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 สร้าง 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); + apiKey.keyApi = require("crypto").randomBytes(64).toString("base64"); + 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(); + } + + /** + * 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, + keyApi: _data.keyApi, + 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({ + order: { createdAt: "DESC" }, + }); + return new HttpSuccess(apiName); + } +} diff --git a/src/entities/ApiHistory.ts b/src/entities/ApiHistory.ts new file mode 100644 index 00000000..94cffcaf --- /dev/null +++ b/src/entities/ApiHistory.ts @@ -0,0 +1,66 @@ +import { Entity, Column, ManyToOne, JoinColumn } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { ApiKey } from "./ApiKey"; + +@Entity("apiHistory") +export class ApiHistory extends EntityBase { + @Column({ + nullable: true, + comment: "header", + length: 255, + default: null, + }) + headerApi: string; + + @Column({ + nullable: true, + comment: "token", + length: 255, + default: null, + }) + tokenApi: string; + + @Column({ + nullable: true, + comment: "request", + length: 255, + default: null, + }) + requestApi: string; + + @Column({ + nullable: true, + comment: "response", + length: 255, + default: null, + }) + responseApi: string; + + @Column({ + nullable: true, + comment: "ip", + length: 255, + default: null, + }) + ipApi: string; + + @Column({ + nullable: true, + comment: "code", + length: 255, + default: null, + }) + codeApi: string; + + @Column({ + nullable: true, + length: 40, + comment: "คีย์นอก(FK)ของตาราง ApiKey", + default: null, + }) + apiKeyId: string; + + @ManyToOne(() => ApiKey, (apiKey) => apiKey.apiHistorys) + @JoinColumn({ name: "apiKeyId" }) + apiKey: ApiKey; +} diff --git a/src/entities/ApiKey.ts b/src/entities/ApiKey.ts new file mode 100644 index 00000000..2d2bfdb8 --- /dev/null +++ b/src/entities/ApiKey.ts @@ -0,0 +1,37 @@ +import { Entity, Column, ManyToMany, OneToMany } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { ApiName } from "./ApiName"; +import { ApiHistory } from "./ApiHistory"; + +@Entity("apiKey") +export class ApiKey extends EntityBase { + @Column({ + nullable: true, + comment: "ชื่อ", + length: 255, + default: null, + }) + name: string; + + @Column({ + nullable: true, + comment: "keyApi", + length: 255, + default: null, + }) + keyApi: string; + + @ManyToMany(() => ApiName, (apiName) => apiName.apiKeys) + apiNames: ApiName[]; + + @OneToMany(() => ApiHistory, (v) => v.apiKey) + apiHistorys: ApiHistory[]; +} + +export class CreateApiKey { + @Column() + name: string; + + @Column() + apiId: string[]; +} diff --git a/src/entities/ApiName.ts b/src/entities/ApiName.ts new file mode 100644 index 00000000..635e2114 --- /dev/null +++ b/src/entities/ApiName.ts @@ -0,0 +1,34 @@ +import { Entity, Column, ManyToMany, JoinTable } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { ApiKey } from "./ApiKey"; + +@Entity("apiName") +export class ApiName extends EntityBase { + @Column({ + nullable: true, + comment: "ชื่อ", + length: 255, + default: null, + }) + name: string; + + @Column({ + nullable: true, + comment: "path", + length: 255, + default: null, + }) + pathApi: string; + + @Column({ + nullable: true, + comment: "method", + length: 255, + default: null, + }) + methodApi: string; + + @ManyToMany(() => ApiKey, (apiKey) => apiKey.apiNames) + @JoinTable() + apiKeys: ApiKey[]; +} diff --git a/src/migration/1732684774187-add_table_apikey.ts b/src/migration/1732684774187-add_table_apikey.ts new file mode 100644 index 00000000..5f1664df --- /dev/null +++ b/src/migration/1732684774187-add_table_apikey.ts @@ -0,0 +1,28 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddTableApikey1732684774187 implements MigrationInterface { + name = 'AddTableApikey1732684774187' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE \`apiName\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`pathApi\` varchar(255) NULL COMMENT 'path', \`methodApi\` varchar(255) NULL COMMENT 'method', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`apiHistory\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`headerApi\` varchar(255) NULL COMMENT 'header', \`tokenApi\` varchar(255) NULL COMMENT 'token', \`requestApi\` varchar(255) NULL COMMENT 'request', \`responseApi\` varchar(255) NULL COMMENT 'response', \`ipApi\` varchar(255) NULL COMMENT 'ip', \`codeApi\` varchar(255) NULL COMMENT 'code', \`apiKeyId\` varchar(40) NULL COMMENT 'คีย์นอก(FK)ของตาราง ApiKey', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`apiKey\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`name\` varchar(255) NULL COMMENT 'ชื่อ', \`keyApi\` varchar(255) NULL COMMENT 'keyApi', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`api_name_api_keys_api_key\` (\`apiNameId\` varchar(36) NOT NULL, \`apiKeyId\` varchar(36) NOT NULL, INDEX \`IDX_c3041f5a935e01f450e82bf0a2\` (\`apiNameId\`), INDEX \`IDX_9c4f2a7257f66993fe200e9e6d\` (\`apiKeyId\`), PRIMARY KEY (\`apiNameId\`, \`apiKeyId\`)) ENGINE=InnoDB`); + await queryRunner.query(`ALTER TABLE \`apiHistory\` ADD CONSTRAINT \`FK_3d48a4b98bc829f401a6e694f1b\` FOREIGN KEY (\`apiKeyId\`) REFERENCES \`apiKey\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`api_name_api_keys_api_key\` ADD CONSTRAINT \`FK_c3041f5a935e01f450e82bf0a23\` FOREIGN KEY (\`apiNameId\`) REFERENCES \`apiName\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`); + await queryRunner.query(`ALTER TABLE \`api_name_api_keys_api_key\` ADD CONSTRAINT \`FK_9c4f2a7257f66993fe200e9e6dc\` FOREIGN KEY (\`apiKeyId\`) REFERENCES \`apiKey\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`api_name_api_keys_api_key\` DROP FOREIGN KEY \`FK_9c4f2a7257f66993fe200e9e6dc\``); + await queryRunner.query(`ALTER TABLE \`api_name_api_keys_api_key\` DROP FOREIGN KEY \`FK_c3041f5a935e01f450e82bf0a23\``); + await queryRunner.query(`ALTER TABLE \`apiHistory\` DROP FOREIGN KEY \`FK_3d48a4b98bc829f401a6e694f1b\``); + await queryRunner.query(`DROP INDEX \`IDX_9c4f2a7257f66993fe200e9e6d\` ON \`api_name_api_keys_api_key\``); + await queryRunner.query(`DROP INDEX \`IDX_c3041f5a935e01f450e82bf0a2\` ON \`api_name_api_keys_api_key\``); + await queryRunner.query(`DROP TABLE \`api_name_api_keys_api_key\``); + await queryRunner.query(`DROP TABLE \`apiKey\``); + await queryRunner.query(`DROP TABLE \`apiHistory\``); + await queryRunner.query(`DROP TABLE \`apiName\``); + } + +} diff --git a/src/migration/1732688036303-update_apikey_add_name.ts b/src/migration/1732688036303-update_apikey_add_name.ts new file mode 100644 index 00000000..1f883cd8 --- /dev/null +++ b/src/migration/1732688036303-update_apikey_add_name.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateApikeyAddName1732688036303 implements MigrationInterface { + name = 'UpdateApikeyAddName1732688036303' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`apiName\` ADD \`name\` varchar(255) NULL COMMENT 'ชื่อ'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`apiName\` DROP COLUMN \`name\``); + } + +}