import { Body, Controller, Delete, Get, Path, Post, Put, Query, Request, Route, Security, Tags, } from "tsoa"; import { addUserGroup, addUserRoles, createGroup, createUser, deleteGroup, deleteUser, editUser, getGroups, getRoles, getUser, getUserGroups, getUserList, removeUserGroup, removeUserRoles, getRoleMappings, getUserCount, enableStatus, } from "../keycloak"; import { AppDataSource } from "../database/data-source"; import { Profile } from "../entities/Profile"; import { ProfileEmployee } from "../entities/ProfileEmployee"; import { IsNull } from "typeorm"; // import * as io from "../lib/websocket"; // import elasticsearch from "../elasticsearch"; // import { StorageFolder } from "../interfaces/storage-fs"; // if (!process.env.MINIO_BUCKET) throw Error("Default MinIO bucket must be specified."); // if (!process.env.ELASTICSEARCH_INDEX) throw Error("Default ElasticSearch index must be specified."); // const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX; function stripLeadingSlash(str: string) { return str.replace(/^\//, ""); } @Route("api/v1/org/keycloak") @Tags("Single-Sign On") @Security("bearerAuth") export class KeycloakController extends Controller { private profileRepo = AppDataSource.getRepository(Profile); private profileEmpRepo = AppDataSource.getRepository(ProfileEmployee); @Get("user/{id}") async getUser(@Path("id") id: string) { const userData = await getUser(id); if (!userData) { throw new Error("User not found"); } const rolesData = await getRoleMappings(id); if (!rolesData) { throw new Error("Role mappings not found"); } const userDataWithRoles = { ...userData, roles: rolesData, }; return userDataWithRoles; } // async getUser(@Path() id: string) { // return await getUser(id); // } @Post("user") @Security("bearerAuth", ["system", "admin"]) async createUser( @Request() request: { user: { sub: string; preferred_username: string } }, @Body() body: { username: string; password: string; firstName?: string; lastName?: string; email?: string; roles?: string[]; profileId?: string; }, ) { const userId = await createUser(body.username, body.password, { firstName: body.firstName, lastName: body.lastName, email: body.email, requiredActions: ["UPDATE_PASSWORD"], }); if (typeof userId !== "string") { // throw new Error("ไม่สามารถติดต่อกับระบบจัดการผู้ใช้งานได้"); throw new Error(userId.errorMessage); } const now = new Date().toISOString(); const folderData: any = { pathname: stripLeadingSlash(`${body.username.trim()}/`), path: "", name: body.username.trim(), hidden: false, permissionGroup: [], permissionUser: [], permissionOther: { create: false, read: false, update: false, delete: false, perm: false, }, favourite: false, color: "default", type: "folder", owner: body.username, ownerId: userId, createdAt: now, createdBy: request.user.preferred_username, createdByUserId: request.user.sub, updatedAt: now, updatedBy: request.user.preferred_username, updatedByUserId: request.user.sub, }; // await elasticsearch.index({ // index: DEFAULT_INDEX!, // document: folderData, // refresh: "wait_for", // }); // io.getInstance()?.emit("FolderCreate", folderData); const _roles = { role: body.roles || [], }; const addRole = await this.addRole(userId, _roles); const profile = await this.profileRepo.findOne({ where: { id: body.profileId, }, }); if (profile) { profile.keycloak = userId; await this.profileRepo.save(profile); } return userId; } @Put("user/{userId}") async editUser( @Path() userId: string, @Body() body: { username?: string; password?: string; firstName?: string; lastName?: string; email?: string; attributes?: object; // roles?: string[]; }, ) { // return await editUser(userId, body); const chkUpdate = await editUser(userId, body); if (typeof chkUpdate !== "boolean") { throw new Error(chkUpdate.errorMessage); } // const _rolesUpdate = { // role: body.roles || [], // }; // const addRole = await this.addRole(userId, _rolesUpdate); return chkUpdate; } @Delete("user/{userId}") async deleteUser(@Path() userId: string) { const result = await deleteUser(userId); if (!result) throw new Error("Failed. Cannot delete userId."); const profile = await this.profileRepo.findOne({ where: { id: userId, }, }); if (profile) { const null_: any = null; profile.keycloak = null_; await this.profileRepo.save(profile); } } // @Security("bearerAuth", ["system", "admin"]) @Get("role") async getRole() { const role = await getRoles(); if (Array.isArray(role)) return role.filter( (a) => !["uma_authorization", "offline_access", "default-roles"].some((b) => a.name.includes(b)), ); throw new Error("Failed. Cannot get role."); } @Post("{userId}/role") async addRole(@Path() userId: string, @Body() body: { role: string[] }) { const list = await getRoles(); if (!Array.isArray(list)) throw new Error("Failed. Cannot get role(s) data from the server."); const result = await addUserRoles( userId, list.filter((v) => body.role.includes(v.id)), ); if (!result) throw new Error("Failed. Cannot set user's role."); } @Delete("{userId}/role/{roleId}") async deleteRole(@Path() userId: string, @Path() roleId: string) { const list = await getRoles(); if (!Array.isArray(list)) throw new Error("Failed. Cannot get role(s) data from the server."); const result = await removeUserRoles( userId, list.filter((v) => roleId === v.id), ); if (!result) throw new Error("Failed. Cannot remove user's role."); } @Get("user") async getUserList(@Query() first = "", @Query() max = "", @Query() search = "") { const total = await getUserCount(first, max, search); const result = await getUserList(first, max, search); if (Array.isArray(result)) { const mappedData = await Promise.all( result.map(async (x) => { const roles = await getRoleMappings(x.id); return { id: x.id, username: x.username, firstname: x.firstName, lastname: x.lastName, email: x.email, roles: roles, enabled: x.enabled, }; }), ); const _mapData = { data: mappedData, total: total, }; return _mapData; } throw new Error("Failed. Cannot get user list."); } @Get("group") async getGroup() { const group = await getGroups(); if (Array.isArray(group)) return group; throw new Error("Failed. Cannot get group."); } @Post("group") async createGroup(@Body() body: { name: string }) { const result = await createGroup(body.name); if (!result) throw new Error("Failed. Cannot create group."); } @Delete("group/{groupId}") async deleteGroup(@Path() groupId: string) { const result = await deleteGroup(groupId); if (!result) throw new Error("Failed. Cannot delete group."); } @Get("user/{userId}/group") async getUserGroup(@Path() userId: string) { const result = await getUserGroups(userId); if (!result) throw new Error("Failed. Cannot list group to user."); return result; } @Post("user/{userId}/group/{groupId}") async addUserGroup(@Path() userId: string, @Path() groupId: string) { const result = await addUserGroup(userId, groupId); if (!result) throw new Error("Failed. Cannot assign group to user."); } @Delete("user/{userId}/group/{groupId}") async removeUserGroup(@Path() userId: string, @Path() groupId: string) { const result = await removeUserGroup(userId, groupId); if (!result) throw new Error("Failed. Cannot remove group to user."); } @Get("user/role/{id}") async getRoleUser(@Path("id") id: string) { const result = await getRoleMappings(id); if (!result) { throw new Error("Role mappings not found"); } return result; } @Put("user/{userId}/enableStatus/{status}") async changeEnableStatus(@Path() userId: string, @Path() status: boolean) { const result = await enableStatus(userId, status); if (!result) throw new Error("Failed. Cannot change enable status."); } }