Files
certd/packages/libs/lib-server/src/user/access/service/access-service.ts
T

278 lines
8.1 KiB
TypeScript
Raw Normal View History

import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
import { InjectEntityModel } from "@midwayjs/typeorm";
2025-07-12 23:00:04 +08:00
import { In, Repository } from "typeorm";
import { AccessGetter, BaseService, PageReq, PermissionException, ValidateException } from "../../../index.js";
import { AccessEntity } from "../entity/access.js";
import { AccessDefine, accessRegistry, newAccess } from "@certd/pipeline";
import { EncryptService } from "./encrypt-service.js";
import { logger, utils } from "@certd/basic";
2023-01-29 13:44:19 +08:00
/**
* 授权
*/
@Provide()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
export class AccessService extends BaseService<AccessEntity> {
2023-01-29 13:44:19 +08:00
@InjectEntityModel(AccessEntity)
repository: Repository<AccessEntity>;
2024-08-27 13:46:19 +08:00
@Inject()
encryptService: EncryptService;
2024-12-22 14:00:46 +08:00
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
2024-10-09 02:34:28 +08:00
//@ts-ignore
2023-01-29 13:44:19 +08:00
getRepository() {
return this.repository;
}
2024-10-14 00:19:55 +08:00
async page(pageReq: PageReq<AccessEntity>) {
const res = await super.page(pageReq);
2024-08-27 13:46:19 +08:00
res.records = res.records.map(item => {
delete item.encryptSetting;
return item;
});
return res;
}
async add(param) {
let oldEntity = null;
if (param._copyFrom) {
oldEntity = await this.info(param._copyFrom);
if (oldEntity == null) {
throw new ValidateException("该授权配置不存在,请确认是否已被删除");
}
if (oldEntity.userId !== param.userId) {
throw new ValidateException("您无权查看该授权配置");
}
}
delete param._copyFrom;
this.encryptSetting(param, oldEntity);
param.keyId = "ac_" + utils.id.simpleNanoId();
2024-08-27 13:46:19 +08:00
return await super.add(param);
}
encryptSetting(param: any, oldSettingEntity?: AccessEntity) {
const accessType = param.type;
const accessDefine: AccessDefine = accessRegistry.getDefine(accessType);
if (!accessDefine) {
throw new ValidateException(`授权类型${accessType}不存在`);
}
const setting = param.setting;
if (!setting) {
return;
}
const json = JSON.parse(setting);
if (accessDefine.subtype) {
param.subtype = json[accessDefine.subtype] || null;
}
2024-08-27 13:46:19 +08:00
let oldSetting = {};
let encryptSetting = {};
const firstEncrypt = !oldSettingEntity || !oldSettingEntity.encryptSetting || oldSettingEntity.encryptSetting === "{}";
2024-08-27 13:46:19 +08:00
if (oldSettingEntity) {
oldSetting = JSON.parse(oldSettingEntity.setting || "{}");
encryptSetting = JSON.parse(oldSettingEntity.encryptSetting || "{}");
2024-08-27 13:46:19 +08:00
}
for (const key in json) {
//加密
2024-10-18 12:06:27 +08:00
let value = json[key];
if (value && typeof value === "string") {
2024-10-18 12:06:27 +08:00
//去除前后空格
value = value.trim();
json[key] = value;
}
2024-08-27 13:46:19 +08:00
const accessInputDefine = accessDefine.input[key];
if (!accessInputDefine) {
2024-09-29 11:50:59 +08:00
continue;
2024-08-27 13:46:19 +08:00
}
if (!accessInputDefine.encrypt || !value || typeof value !== "string") {
2024-08-27 13:46:19 +08:00
//定义无需加密、value为空、不是字符串 这些不需要加密
encryptSetting[key] = {
value: value,
encrypt: false,
};
continue;
}
if (firstEncrypt || oldSetting[key] !== value) {
//星号保护
const length = value.length;
const subIndex = Math.min(2, length);
2024-09-01 04:49:26 +08:00
let starLength = length - subIndex * 2;
starLength = Math.max(2, starLength);
const starString = "*".repeat(starLength);
2024-08-27 13:46:19 +08:00
json[key] = value.substring(0, subIndex) + starString + value.substring(value.length - subIndex);
encryptSetting[key] = {
value: this.encryptService.encrypt(value),
encrypt: true,
};
}
//未改变情况下,不做修改
}
param.encryptSetting = JSON.stringify(encryptSetting);
param.setting = JSON.stringify(json);
}
2025-06-13 12:18:26 +08:00
2024-08-27 13:46:19 +08:00
/**
* 修改
* @param param 数据
*/
async update(param) {
const oldEntity = await this.info(param.id);
if (oldEntity == null) {
throw new ValidateException("该授权配置不存在,请确认是否已被删除");
2024-08-27 13:46:19 +08:00
}
this.encryptSetting(param, oldEntity);
delete param.keyId;
2024-08-27 13:46:19 +08:00
return await super.update(param);
}
async updateAccess(access: any) {
const oldEntity = await this.info(access.id);
if (oldEntity == null) {
throw new ValidateException("该授权配置不存在,请确认是否已被删除");
}
const setting = this.decryptAccessEntity(oldEntity);
for (const key of Object.keys(access)) {
if (key === "id") {
continue;
}
setting[key] = access[key];
}
return await this.update({
id: access.id,
type: oldEntity.type,
setting: JSON.stringify(setting),
});
}
2024-11-20 18:12:10 +08:00
async getSimpleInfo(id: number) {
const entity = await this.info(id);
if (entity == null) {
throw new ValidateException("该授权配置不存在,请确认是否已被删除");
2024-11-20 18:12:10 +08:00
}
return {
id: entity.id,
name: entity.name,
type: entity.type,
subtype: entity.subtype,
2024-11-20 18:12:10 +08:00
userId: entity.userId,
2026-02-13 21:28:17 +08:00
projectId: entity.projectId,
2024-11-20 18:12:10 +08:00
};
}
2026-02-13 21:28:17 +08:00
async getAccessById(id: any, checkUserId: boolean, userId?: number, projectId?: number): Promise<any> {
2023-01-29 13:44:19 +08:00
const entity = await this.info(id);
if (entity == null) {
throw new Error(`该授权配置不存在,请确认是否已被删除:id=${id}`);
}
if (checkUserId) {
if (userId == null) {
throw new ValidateException("userId不能为空");
}
if (userId !== entity.userId) {
throw new PermissionException("您对该Access授权无访问权限");
}
}
2026-02-13 21:28:17 +08:00
if (projectId != null && projectId !== entity.projectId) {
throw new PermissionException("您对该Access授权无访问权限");
2026-02-13 21:28:17 +08:00
}
2023-01-29 13:44:19 +08:00
// const access = accessRegistry.get(entity.type);
2024-09-30 18:00:51 +08:00
const setting = this.decryptAccessEntity(entity);
2024-10-01 23:52:44 +08:00
const input = {
2024-09-30 18:00:51 +08:00
id: entity.id,
...setting,
};
const accessGetter = new AccessGetter(userId, projectId, this.getById.bind(this));
return await newAccess(entity.type, input, accessGetter);
2024-09-30 18:00:51 +08:00
}
2026-02-13 21:28:17 +08:00
async getById(id: any, userId: number, projectId?: number): Promise<any> {
return await this.getAccessById(id, true, userId, projectId);
}
2024-09-30 18:00:51 +08:00
decryptAccessEntity(entity: AccessEntity): any {
2024-08-27 13:46:19 +08:00
let setting = {};
if (entity.encryptSetting && entity.encryptSetting !== "{}") {
2024-08-27 13:46:19 +08:00
setting = JSON.parse(entity.encryptSetting);
for (const key in setting) {
//解密
const encryptValue = setting[key];
let value = encryptValue.value;
if (encryptValue.encrypt) {
value = this.encryptService.decrypt(value);
}
setting[key] = value;
}
} else if (entity.setting) {
setting = JSON.parse(entity.setting);
}
2024-09-30 18:00:51 +08:00
return setting;
2023-01-29 13:44:19 +08:00
}
getDefineList() {
return accessRegistry.getDefineList();
}
2024-03-22 00:50:02 +08:00
getDefineByType(type: string) {
2023-01-29 13:44:19 +08:00
return accessRegistry.getDefine(type);
}
2025-07-12 23:00:04 +08:00
2026-02-13 21:28:17 +08:00
async getSimpleByIds(ids: number[], userId: any, projectId?: number) {
2025-07-12 23:00:04 +08:00
if (ids.length === 0) {
return [];
}
if (userId == null) {
2025-07-12 23:00:04 +08:00
return [];
}
return await this.repository.find({
where: {
id: In(ids),
userId,
2026-02-13 21:28:17 +08:00
projectId,
2025-07-12 23:00:04 +08:00
},
select: {
id: true,
name: true,
type: true,
subtype: true,
userId: true,
projectId: true,
2025-07-12 23:00:04 +08:00
},
});
}
/**
* 复制授权到其他项目
* @param accessId
* @param projectId
*/
async copyTo(accessId: number, projectId?: number) {
const access = await this.info(accessId);
if (access == null) {
throw new Error(`该授权配置不存在,请确认是否已被删除:id=${accessId}`);
}
const keyId = access.keyId;
//检查目标项目里是否已经有相同keyId的配置
const existAccess = await this.repository.findOne({
where: {
keyId,
projectId,
},
});
if (existAccess) {
logger.info(`目标项目已存在相同keyId的授权配置,跳过复制:keyId=${keyId}`);
return existAccess.id;
}
const newAccess = {
...access,
userId: -1,
id: undefined,
projectId,
};
2026-03-17 00:05:53 +08:00
await this.repository.save(newAccess);
return newAccess.id;
}
2023-01-29 13:44:19 +08:00
}