import { Controller, Get, Path, Request, Route, Security, Tags } from "tsoa"; import { AppDataSource } from "../database/data-source"; import { RequestWithUser } from "../middlewares/user"; import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; import HttpSuccess from "../interfaces/http-success"; import { AuthRole } from "../entities/AuthRole"; import { AuthRoleAttr } from "../entities/AuthRoleAttr"; import { PosMaster } from "../entities/PosMaster"; import { Profile } from "../entities/Profile"; import { AuthSys } from "../entities/AuthSys"; import { promisify } from "util"; import { In } from "typeorm"; import permission from "../interfaces/permission"; import { ProfileEmployee } from "../entities/ProfileEmployee"; import { EmployeePosMaster } from "../entities/EmployeePosMaster"; import { OrgRevision } from "../entities/OrgRevision"; const REDIS_HOST = process.env.REDIS_HOST; const REDIS_PORT = process.env.REDIS_PORT; @Route("api/v1/org/permission") @Tags("Permission") @Security("bearerAuth") export class PermissionController extends Controller { private profileRepo = AppDataSource.getRepository(Profile); private profileEmployeeRepo = AppDataSource.getRepository(ProfileEmployee); private posMasterRepository = AppDataSource.getRepository(PosMaster); private posMasterEmpRepository = AppDataSource.getRepository(EmployeePosMaster); private authRoleRepo = AppDataSource.getRepository(AuthRole); private authRoleAttrRepo = AppDataSource.getRepository(AuthRoleAttr); private authSysRepo = AppDataSource.getRepository(AuthSys); private orgRevisionRepository = AppDataSource.getRepository(OrgRevision); private redis = require("redis"); @Get("") public async getPermission(@Request() request: RequestWithUser) { const redisClient = await this.redis.createClient({ host: REDIS_HOST, port: REDIS_PORT, }); const getAsync = promisify(redisClient.get).bind(redisClient); let profile: any = await this.profileRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { profile = await this.profileEmployeeRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } } let reply = await getAsync("role_" + profile.id); if (reply != null) { reply = JSON.parse(reply); } else { const orgRevision = await this.orgRevisionRepository.findOne({ select: ["id"], where: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true, }, }); let posMaster: any = await this.posMasterRepository.findOne({ select: ["authRoleId"], where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { posMaster = await this.posMasterEmpRepository.findOne({ select: ["authRoleId"], where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์"); } } const getDetail = await this.authRoleRepo.findOne({ select: ["id", "roleName", "roleDescription"], where: { id: posMaster.authRoleId }, }); if (!getDetail) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); } const roleAttrData = await this.authRoleAttrRepo.find({ select: [ "authSysId", "parentNode", "attrOwnership", "attrIsCreate", "attrIsList", "attrIsGet", "attrIsUpdate", "attrIsDelete", "attrPrivilege", ], where: { authRoleId: getDetail.id }, }); reply = { ...getDetail, roles: roleAttrData, }; redisClient.setex("role_" + profile.id, 86400, JSON.stringify(reply)); } return new HttpSuccess(reply); } @Get("menu") public async listAuthSys(@Request() request: RequestWithUser) { const orgRevision = await this.orgRevisionRepository.findOne({ select: ["id"], where: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true, }, }); const redisClient = await this.redis.createClient({ host: REDIS_HOST, port: REDIS_PORT, }); const getAsync = promisify(redisClient.get).bind(redisClient); let profileType = "OFFICER"; let profile: any = await this.profileRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { profileType = "EMPLOYEE"; profile = await this.profileEmployeeRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } } let reply = await getAsync("menu_" + profile.id); if (reply != null) { reply = JSON.parse(reply); } else { let posMaster: any = await this.posMasterRepository.findOne({ select: ["authRoleId"], where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { posMaster = await this.posMasterEmpRepository.findOne({ select: ["authRoleId"], where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์"); } } if (!posMaster.authRoleId) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์"); } const authRole = await this.authRoleRepo.findOne({ select: ["id"], where: { id: posMaster.authRoleId }, }); if (!authRole) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์"); } const roleAttrData = await this.authRoleAttrRepo.find({ select: ["authSysId", "parentNode"], where: { authRoleId: authRole.id, attrIsList: true }, }); const parentNode = roleAttrData.map((x) => x.parentNode); const authSysId = roleAttrData.map((x) => x.authSysId); const sysId = parentNode.concat(authSysId); const getList = await this.authSysRepo.find({ select: ["id", "parentId", "sysName", "sysDescription", "icon", "path", "order"], where: { id: In(sysId), }, order: { order: "ASC" }, }); const getListChild = await this.authSysRepo.find({ select: ["id", "parentId", "sysName", "sysDescription", "icon", "path", "order"], where: { parentId: In(sysId), }, order: { order: "ASC" }, }); reply = await getList .filter((x) => x.parentId == null) .sort((a, b) => a.order - b.order) .map((item) => { return { ...item, children: getList .filter((x) => x.parentId == item.id) .sort((a, b) => a.order - b.order) .map((item2) => { return { ...item2, children: getListChild .filter((x) => x.parentId == item2.id) .sort((a, b) => a.order - b.order), }; }), }; }); redisClient.setex("menu_" + profile.id, 86400, JSON.stringify(reply)); } return new HttpSuccess(reply); } /** * API permission (dotnet api) * @summary permission (dotnet api) * @param {string} action action * @param {string} system authSysId */ @Get("dotnet/{action}/{system}") public async dotnet( @Request() req: RequestWithUser, @Path() action: string, @Path() system: string, ) { if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) { throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง"); } let res = await new permission().Permission(req, system.toLocaleUpperCase(), action); return new HttpSuccess(res); } /** * API permission (dotnet api) * @summary permission (dotnet api) * @param {string} action action * @param {string} system authSysId */ @Get("dotnet-org/{action}/{system}/{profileId}") public async dotnetOrg( @Request() req: RequestWithUser, @Path() action: string, @Path() system: string, ) { if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) { throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง"); } let res = await new permission().PermissionOrg(req, system.toLocaleUpperCase(), action); return new HttpSuccess(res); } /** * API permission (dotnet api) * @summary permission (dotnet api) * @param {string} action action * @param {string} system authSysId * @param {string} profileId profileId */ @Get("dotnet-user/{action}/{system}/{profileId}") public async dotnetUser( @Request() req: RequestWithUser, @Path() action: string, @Path() system: string, @Path() profileId: string, ) { if (!["CREATE", "DELETE", "GET", "LIST", "UPDATE"].includes(action)) { throw new HttpError(HttpStatus.NOT_FOUND, "Action ไม่ถูกต้อง"); } let res = await new permission().PermissionOrgByUser( req, system.toLocaleUpperCase(), action, profileId, ); return new HttpSuccess(res); } @Get("org/{system}/{action}") public async listAuthSysOrg( @Request() request: RequestWithUser, @Path() system: string, @Path() action: string, ) { const redisClient = await this.redis.createClient({ host: REDIS_HOST, port: REDIS_PORT, }); const getAsync = promisify(redisClient.get).bind(redisClient); let profileType = "OFFICER"; let profile: any = await this.profileRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { profileType = "EMPLOYEE"; profile = await this.profileEmployeeRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } } let privilege = await this.Permission(request, system, action); let reply = await getAsync("posMaster_" + profile.id); if (reply != null) { reply = JSON.parse(reply); reply.privilege = privilege; } else { const orgRevision = await this.orgRevisionRepository.findOne({ select: ["id"], where: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true, }, }); if (profileType == "OFFICER") { const posMaster = await this.posMasterRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { reply = { orgRootId: null, orgChild1Id: null, orgChild2Id: null, orgChild3Id: null, orgChild4Id: null, privilege: privilege, }; } else { reply = { orgRootId: posMaster.orgRootId, orgChild1Id: posMaster.orgChild1Id, orgChild2Id: posMaster.orgChild2Id, orgChild3Id: posMaster.orgChild3Id, orgChild4Id: posMaster.orgChild4Id, privilege: privilege, }; } redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply)); } else { const posMaster = await this.posMasterEmpRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { reply = { orgRootId: null, orgChild1Id: null, orgChild2Id: null, orgChild3Id: null, orgChild4Id: null, privilege: privilege, }; } else { reply = { orgRootId: posMaster.orgRootId, orgChild1Id: posMaster.orgChild1Id, orgChild2Id: posMaster.orgChild2Id, orgChild3Id: posMaster.orgChild3Id, orgChild4Id: posMaster.orgChild4Id, privilege: privilege, }; } redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply)); } } return new HttpSuccess(reply); } @Get("user/{system}/{action}/{id}") public async listOrgUser( @Request() request: RequestWithUser, @Path() system: string, @Path() action: string, @Path() id: string, ) { const orgRevision = await this.orgRevisionRepository.findOne({ select: ["id"], where: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true, }, }); const redisClient = await this.redis.createClient({ host: REDIS_HOST, port: REDIS_PORT, }); const getAsync = promisify(redisClient.get).bind(redisClient); let org = this.PermissionOrg(request, system, action); let reply = await getAsync("user_" + id); if (reply != null) { reply = JSON.parse(reply); reply.org = org; } else { let profileType = "OFFICER"; let profile: any = await this.profileRepo.findOne({ select: ["id"], where: { id: id }, }); if (!profile) { profileType = "EMPLOYEE"; profile = await this.profileEmployeeRepo.findOne({ select: ["id"], where: { id: id }, }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } } if (profileType == "OFFICER") { const posMaster = await this.posMasterRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { reply = { orgRootId: null, orgChild1Id: null, orgChild2Id: null, orgChild3Id: null, orgChild4Id: null, org: org, }; } else { reply = { orgRootId: posMaster.orgRootId, orgChild1Id: posMaster.orgChild1Id, orgChild2Id: posMaster.orgChild2Id, orgChild3Id: posMaster.orgChild3Id, orgChild4Id: posMaster.orgChild4Id, org: org, }; } redisClient.setex("user_" + profile.id, 86400, JSON.stringify(reply)); } else { const posMaster = await this.posMasterEmpRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { reply = { orgRootId: null, orgChild1Id: null, orgChild2Id: null, orgChild3Id: null, orgChild4Id: null, org: org, }; } else { reply = { orgRootId: posMaster.orgRootId, orgChild1Id: posMaster.orgChild1Id, orgChild2Id: posMaster.orgChild2Id, orgChild3Id: posMaster.orgChild3Id, orgChild4Id: posMaster.orgChild4Id, org: org, }; } redisClient.setex("user_" + profile.id, 86400, JSON.stringify(reply)); } } return new HttpSuccess(reply); } public async getPermissionFunc(@Request() request: RequestWithUser) { const redisClient = await this.redis.createClient({ host: REDIS_HOST, port: REDIS_PORT, }); const getAsync = promisify(redisClient.get).bind(redisClient); let profile: any = await this.profileRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { profile = await this.profileEmployeeRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } } let reply = await getAsync("role_" + profile.id); if (reply != null) { reply = JSON.parse(reply); } else { const orgRevision = await this.orgRevisionRepository.findOne({ select: ["id"], where: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true, }, }); let posMaster: any = await this.posMasterRepository.findOne({ select: ["authRoleId"], where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { posMaster = await this.posMasterEmpRepository.findOne({ select: ["authRoleId"], where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลสิทธิ์"); } } const getDetail = await this.authRoleRepo.findOne({ select: ["id", "roleName", "roleDescription"], where: { id: posMaster.authRoleId }, }); if (!getDetail) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); } const roleAttrData = await this.authRoleAttrRepo.find({ select: [ "authSysId", "parentNode", "attrOwnership", "attrIsCreate", "attrIsList", "attrIsGet", "attrIsUpdate", "attrIsDelete", "attrPrivilege", ], where: { authRoleId: getDetail.id }, }); reply = { ...getDetail, roles: roleAttrData, }; redisClient.setex("role_" + profile.id, 86400, JSON.stringify(reply)); } return reply; } public async Permission(req: RequestWithUser, system: string, action: string) { // if ( // req.headers.hasOwnProperty("api_key") && // req.headers["api_key"] && // req.headers["api_key"] == process.env.API_KEY // ) { // return null; // } let x: any = await this.getPermissionFunc(req); let permission = false; let role = x.roles.find((x: any) => x.authSysId == system); if (!role) throw "ไม่มีสิทธิ์เข้าระบบ"; if (role.attrOwnership == "OWNER") return "OWNER"; if (action.trim().toLocaleUpperCase() == "CREATE") permission = role.attrIsCreate; if (action.trim().toLocaleUpperCase() == "DELETE") permission = role.attrIsDelete; if (action.trim().toLocaleUpperCase() == "GET") permission = role.attrIsGet; if (action.trim().toLocaleUpperCase() == "LIST") permission = role.attrIsList; if (action.trim().toLocaleUpperCase() == "UPDATE") permission = role.attrIsUpdate; if (permission == false) throw "ไม่มีสิทธิ์ใช้งานระบบนี้"; return role.attrPrivilege; } public async listAuthSysOrgFunc(request: RequestWithUser, system: string, action: string) { const redisClient = await this.redis.createClient({ host: REDIS_HOST, port: REDIS_PORT, }); const getAsync = promisify(redisClient.get).bind(redisClient); let profileType = "OFFICER"; let profile: any = await this.profileRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { profileType = "EMPLOYEE"; profile = await this.profileEmployeeRepo.findOne({ select: ["id"], where: { keycloak: request.user.sub }, }); if (!profile) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); } } let reply = await getAsync("posMaster_" + profile.id); if (reply != null) { reply = JSON.parse(reply); } else { let privilege = await this.Permission(request, system, action); const orgRevision = await this.orgRevisionRepository.findOne({ select: ["id"], where: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true, }, }); if (profileType == "OFFICER") { const posMaster = await this.posMasterRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { reply = { orgRootId: null, orgChild1Id: null, orgChild2Id: null, orgChild3Id: null, orgChild4Id: null, privilege: privilege, }; } else { reply = { orgRootId: posMaster.orgRootId, orgChild1Id: posMaster.orgChild1Id, orgChild2Id: posMaster.orgChild2Id, orgChild3Id: posMaster.orgChild3Id, orgChild4Id: posMaster.orgChild4Id, privilege: privilege, }; } redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply)); } else { const posMaster = await this.posMasterEmpRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { reply = { orgRootId: null, orgChild1Id: null, orgChild2Id: null, orgChild3Id: null, orgChild4Id: null, privilege: privilege, }; } else { reply = { orgRootId: posMaster.orgRootId, orgChild1Id: posMaster.orgChild1Id, orgChild2Id: posMaster.orgChild2Id, orgChild3Id: posMaster.orgChild3Id, orgChild4Id: posMaster.orgChild4Id, privilege: privilege, }; } redisClient.setex("posMaster_" + profile.id, 86400, JSON.stringify(reply)); } } return reply; } public async PermissionOrg(req: RequestWithUser, system: string, action: string) { let x: any = await this.listAuthSysOrgFunc(req, system, action); let privilege = x.privilege; let data: any = { root: [null], child1: [null], child2: [null], child3: [null], child4: [null], }; let node = 4; if (x.orgChild1Id == null) { node = 0; } else if (x.orgChild2Id == null) { node = 1; } else if (x.orgChild3Id == null) { node = 2; } else if (x.orgChild4Id == null) { node = 3; } if (privilege == "ROOT") { data = { root: [x.orgRootId], child1: null, child2: null, child3: null, child4: null, }; } else if (privilege == "CHILD") { data = { root: node >= 0 ? [x.orgRootId] : null, child1: node >= 1 ? [x.orgChild1Id] : null, child2: node >= 2 ? [x.orgChild2Id] : null, child3: node >= 3 ? [x.orgChild3Id] : null, child4: node >= 4 ? [x.orgChild4Id] : null, }; } else if (privilege == "NORMAL") { data = { root: [x.orgRootId], child1: [x.orgChild1Id], child2: [x.orgChild2Id], child3: [x.orgChild3Id], child4: [x.orgChild4Id], }; } else if (privilege == "SPECIFIC") { } else if (privilege == "OWNER") { data = { root: null, child1: null, child2: null, child3: null, child4: null, }; } return data; } @Get("checkOrg/{keycloakId}") public async checkOrg(@Path() keycloakId: string) { const redisClient = await this.redis.createClient({ host: REDIS_HOST, port: REDIS_PORT, }); // const getAsync = promisify(redisClient.get).bind(redisClient); // let profileType = "OFFICER"; let profile: any = await this.profileRepo.findOne({ select: ["id"], where: { keycloak: keycloakId }, }); // if (!profile) { // profileType = "EMPLOYEE"; // profile = await this.profileEmployeeRepo.findOne({ // select: ["id"], // where: { keycloak: keycloakId }, // }); // if (!profile) { // throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูลบุคคลนี้ในระบบ"); // } // } let reply: any; const orgRevision = await this.orgRevisionRepository.findOne({ select: ["id"], where: { orgRevisionIsDraft: false, orgRevisionIsCurrent: true, }, }); // if (profileType == "OFFICER") { const posMaster = await this.posMasterRepository.findOne({ where: { current_holderId: profile.id, orgRevisionId: orgRevision?.id, }, }); if (!posMaster) { reply = { orgRootId: null, orgChild1Id: null, orgChild2Id: null, orgChild3Id: null, orgChild4Id: null, }; } else { reply = { orgRootId: posMaster.orgRootId, orgChild1Id: posMaster.orgChild1Id, orgChild2Id: posMaster.orgChild2Id, orgChild3Id: posMaster.orgChild3Id, orgChild4Id: posMaster.orgChild4Id, }; } redisClient.setex("org_" + profile.id, 86400, JSON.stringify(reply)); //Create Redis // } else { // const posMaster = await this.posMasterEmpRepository.findOne({ // where: { // current_holderId: profile.id, // orgRevisionId: orgRevision?.id, // }, // }); // if (!posMaster) { // reply = { // orgRootId: null, // orgChild1Id: null, // orgChild2Id: null, // orgChild3Id: null, // orgChild4Id: null, // }; // } else { // reply = { // orgRootId: posMaster.orgRootId, // orgChild1Id: posMaster.orgChild1Id, // orgChild2Id: posMaster.orgChild2Id, // orgChild3Id: posMaster.orgChild3Id, // orgChild4Id: posMaster.orgChild4Id, // }; // } // redisClient.setex("org_" + profile.id, 86400, JSON.stringify(reply)); // } return new HttpSuccess(reply); } }