mirror of
https://github.com/certd/certd.git
synced 2026-04-03 14:10:54 +08:00
chore: project userid fixed -1
This commit is contained in:
@@ -83,7 +83,7 @@ export abstract class BaseController {
|
||||
let userId = this.getUserId()
|
||||
const projectId = await this.getProjectId(permission)
|
||||
if(projectId){
|
||||
userId = 0
|
||||
userId = -1 // 企业管理模式下,用户id固定-1
|
||||
}
|
||||
return {
|
||||
projectId,userId
|
||||
|
||||
@@ -258,12 +258,12 @@ export abstract class BaseService<T> {
|
||||
|
||||
export function checkUserProjectParam(userId: number, projectId: number) {
|
||||
if (projectId != null ){
|
||||
if( userId !==0) {
|
||||
if( userId !==-1) {
|
||||
throw new ValidateException('userId projectId 错误');
|
||||
}
|
||||
return true
|
||||
}else{
|
||||
if( userId > 0) {
|
||||
if( userId != null) {
|
||||
return true
|
||||
}
|
||||
throw new ValidateException('userId不能为空');
|
||||
|
||||
@@ -8,7 +8,7 @@ export class AccessEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
@Column({ name: 'user_id', comment: '用户id' })
|
||||
userId: number;
|
||||
userId: number; // 0为系统级别, -1为企业,大于1为用户
|
||||
@Column({ comment: '名称', length: 100 })
|
||||
name: string;
|
||||
|
||||
@@ -24,9 +24,6 @@ export class AccessEntity {
|
||||
@Column({ name: 'project_id', comment: '项目id' })
|
||||
projectId: number;
|
||||
|
||||
@Column({ comment: '权限等级', length: 100 })
|
||||
level: string; // user common system
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -220,6 +220,7 @@ export default {
|
||||
myProjectDetail: "Project Detail",
|
||||
projectJoin: "Join Project",
|
||||
currentProject: "Current Project",
|
||||
projectMemberManager: "Project Member",
|
||||
},
|
||||
certificateRepo: {
|
||||
title: "Certificate Repository",
|
||||
@@ -822,6 +823,9 @@ export default {
|
||||
admin: "Admin",
|
||||
},
|
||||
projectMemberStatus: "Member Status",
|
||||
|
||||
isSystem: "Is System Project",
|
||||
isSystemHelper: "System-level projects allow running admin plugins",
|
||||
},
|
||||
project: {
|
||||
noProjectJoined: "You haven't joined any projects yet",
|
||||
|
||||
@@ -220,12 +220,12 @@ export default {
|
||||
netTest: "网络测试",
|
||||
enterpriseManager: "企业管理设置",
|
||||
projectManager: "项目管理",
|
||||
projectDetail: "项目详情",
|
||||
enterpriseSetting: "企业设置",
|
||||
myProjectManager: "我的项目",
|
||||
myProjectDetail: "项目详情",
|
||||
projectJoin: "加入项目",
|
||||
currentProject: "当前项目",
|
||||
projectMemberManager: "项目成员管理",
|
||||
},
|
||||
certificateRepo: {
|
||||
title: "证书仓库",
|
||||
@@ -838,6 +838,9 @@ export default {
|
||||
admin: "管理员",
|
||||
},
|
||||
projectMemberStatus: "成员状态",
|
||||
|
||||
isSystem: "是否系统项目",
|
||||
isSystemHelper: "系统级项目允许运行管理员插件",
|
||||
},
|
||||
project: {
|
||||
noProjectJoined: "您还没有加入任何项目",
|
||||
|
||||
@@ -29,21 +29,6 @@ export const certdResources = [
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.currentProject",
|
||||
name: "CurrentProject",
|
||||
path: "/certd/project/detail",
|
||||
component: "/certd/project/detail/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const projectStore = useProjectStore();
|
||||
return projectStore.isEnterprise;
|
||||
},
|
||||
isMenu: true,
|
||||
icon: "ion:apps",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.projectJoin",
|
||||
name: "ProjectJoin",
|
||||
@@ -278,6 +263,21 @@ export const certdResources = [
|
||||
isMenu: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "certd.sysResources.projectMemberManager",
|
||||
name: "ProjectMemberManager",
|
||||
path: "/certd/project/detail",
|
||||
component: "/certd/project/detail/index.vue",
|
||||
meta: {
|
||||
show: () => {
|
||||
const projectStore = useProjectStore();
|
||||
return projectStore.isEnterprise;
|
||||
},
|
||||
isMenu: true,
|
||||
icon: "ion:apps",
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -143,7 +143,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
order: 10,
|
||||
},
|
||||
valueBuilder: ({ row, key, value }) => {
|
||||
row[key] = row.userId > 0 ? "user" : "sys";
|
||||
row[key] = row.userId != 0 ? "user" : "sys";
|
||||
},
|
||||
},
|
||||
...commonColumnsDefine,
|
||||
|
||||
@@ -121,7 +121,7 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
order: 10,
|
||||
},
|
||||
valueBuilder: ({ row, key, value }) => {
|
||||
row[key] = row.userId > 0 ? "user" : "sys";
|
||||
row[key] = row.userId != 0 ? "user" : "sys";
|
||||
},
|
||||
},
|
||||
...commonColumnsDefine,
|
||||
|
||||
@@ -90,35 +90,21 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||
},
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
title: t("certd.disabled"),
|
||||
isSystem: {
|
||||
title: t("certd.ent.isSystem"),
|
||||
type: "dict-switch",
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: t("certd.enabled"), value: false, color: "success" },
|
||||
{ label: t("certd.disabledLabel"), value: true, color: "error" },
|
||||
{ label: t("common.yes"), value: true, color: "success" },
|
||||
{ label: t("common.no"), value: false, color: "error" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
value: false,
|
||||
value: true,
|
||||
helper: t("certd.ent.isSystemHelper"),
|
||||
},
|
||||
column: {
|
||||
width: 100,
|
||||
component: {
|
||||
title: t("certd.clickToToggle"),
|
||||
on: {
|
||||
async click({ value, row }) {
|
||||
Modal.confirm({
|
||||
title: t("certd.prompt"),
|
||||
content: t("certd.confirmToggleStatus", { action: !value ? t("certd.disable") : t("certd.enable") }),
|
||||
onOk: async () => {
|
||||
await api.SetDisabled(row.id, !value);
|
||||
await crudExpose.doRefresh();
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
adminId: {
|
||||
|
||||
@@ -6,6 +6,7 @@ CREATE TABLE "cd_project"
|
||||
"name" varchar(512) NOT NULL,
|
||||
"admin_id" integer NOT NULL,
|
||||
"disabled" boolean NOT NULL DEFAULT (false),
|
||||
"is_system" boolean NOT NULL DEFAULT (false),
|
||||
"create_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP),
|
||||
"update_time" datetime NOT NULL DEFAULT (CURRENT_TIMESTAMP)
|
||||
);
|
||||
@@ -13,7 +14,7 @@ CREATE TABLE "cd_project"
|
||||
|
||||
CREATE INDEX "index_project_user_id" ON "cd_project" ("user_id");
|
||||
CREATE INDEX "index_project_admin_id" ON "cd_project" ("admin_id");
|
||||
INSERT INTO cd_project (id, user_id, "admin_id", "name", "disabled") VALUES (1, 0, 1,'default', false);
|
||||
INSERT INTO cd_project (id, user_id, "admin_id", "name", "disabled") VALUES (1, -1, 1,'default', false,false);
|
||||
|
||||
ALTER TABLE cd_cert_info ADD COLUMN project_id integer;
|
||||
CREATE INDEX "index_cert_project_id" ON "cd_cert_info" ("project_id");
|
||||
|
||||
@@ -21,12 +21,18 @@ export class BasicController extends BaseController {
|
||||
@Post('/preBindUser', { summary: 'sys:settings:edit' })
|
||||
public async preBindUser(@Body(ALL) body: PreBindUserReq) {
|
||||
// 设置缓存内容
|
||||
if (body.userId == null || body.userId <= 0) {
|
||||
throw new Error("用户ID不能为空");
|
||||
}
|
||||
await this.plusService.userPreBind(body.userId);
|
||||
return this.ok({});
|
||||
}
|
||||
|
||||
@Post('/bindUser', { summary: 'sys:settings:edit' })
|
||||
public async bindUser(@Body(ALL) body: BindUserReq) {
|
||||
if (body.userId == null || body.userId <= 0) {
|
||||
throw new Error("用户ID不能为空");
|
||||
}
|
||||
const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo);
|
||||
installInfo.bindUserId = body.userId;
|
||||
await this.sysSettingsService.saveSetting(installInfo);
|
||||
|
||||
@@ -14,7 +14,7 @@ export class SysAddonController extends AddonController {
|
||||
|
||||
async getProjectUserId(permission:string){
|
||||
return {
|
||||
projectId:null,userId:0
|
||||
projectId:null,userId:0 //0为系统级别
|
||||
}
|
||||
}
|
||||
getUserId() {
|
||||
|
||||
@@ -40,7 +40,7 @@ export class SysProjectController extends CrudController<ProjectEntity> {
|
||||
bean.userId = this.getUserId();
|
||||
return super.add({
|
||||
...bean,
|
||||
userId:0,
|
||||
userId:-1, //企业用户id固定为-1
|
||||
adminId: bean.userId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export class TwoFactorService {
|
||||
}
|
||||
|
||||
async offAuthenticator(userId:number) {
|
||||
if (!userId) {
|
||||
if (!userId || userId <= 0) {
|
||||
throw new Error("userId is required");
|
||||
}
|
||||
|
||||
|
||||
@@ -358,7 +358,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
async checkList(sites: SiteInfoEntity[],isCommon: boolean) {
|
||||
const cache = {}
|
||||
const getFromCache = async (userId: number,projectId?: number) =>{
|
||||
const key = `${userId}-${projectId??""}`
|
||||
const key = `${userId}_${projectId??""}`
|
||||
if (cache[key]) {
|
||||
return cache[key];
|
||||
}
|
||||
@@ -424,7 +424,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
if (!req.text) {
|
||||
throw new Error("text is required");
|
||||
}
|
||||
if (!req.userId) {
|
||||
if (req.userId == null) {
|
||||
throw new Error("userId is required");
|
||||
}
|
||||
|
||||
@@ -479,7 +479,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
}
|
||||
|
||||
clearSiteMonitorJob(userId: number,projectId?: number) {
|
||||
this.cron.remove(`siteMonitor-${userId}-${projectId||""}`);
|
||||
this.cron.remove(`siteMonitor_${userId}_${projectId||""}`);
|
||||
}
|
||||
|
||||
async registerSiteMonitorJob(userId?: number,projectId?: number) {
|
||||
@@ -502,7 +502,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
}
|
||||
//注册个人的 或项目的
|
||||
this.cron.register({
|
||||
name: `siteMonitor-${userId}-${projectId||""}`,
|
||||
name: `siteMonitor_${userId}_${projectId||""}`,
|
||||
cron: setting.cron,
|
||||
job: () => this.triggerJobOnce(userId,projectId),
|
||||
});
|
||||
@@ -511,9 +511,9 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
}
|
||||
|
||||
async triggerJobOnce(userId?:number,projectId?:number) {
|
||||
logger.info(`站点证书检查开始执行[${userId??'所有用户'}-${projectId??'所有项目'}]`);
|
||||
logger.info(`站点证书检查开始执行[${userId??'所有用户'}_${projectId??'所有项目'}]`);
|
||||
const query:any = { disabled: false };
|
||||
if(userId){
|
||||
if(userId!=null){
|
||||
query.userId = userId;
|
||||
if(projectId){
|
||||
query.projectId = projectId;
|
||||
@@ -541,7 +541,7 @@ export class SiteInfoService extends BaseService<SiteInfoEntity> {
|
||||
await this.checkList(records,isCommon);
|
||||
}
|
||||
|
||||
logger.info(`站点证书检查完成[${userId??'所有用户'}-${projectId??'所有项目'}]`);
|
||||
logger.info(`站点证书检查完成[${userId??'所有用户'}_${projectId??'所有项目'}]`);
|
||||
}
|
||||
|
||||
async batchDelete(ids: number[], userId: number,projectId?:number): Promise<void> {
|
||||
|
||||
@@ -43,7 +43,7 @@ export class SiteIpService extends BaseService<SiteIpEntity> {
|
||||
}
|
||||
|
||||
async add(data: SiteIpEntity) {
|
||||
if (!data.userId) {
|
||||
if (data.userId == null) {
|
||||
throw new Error("userId is required");
|
||||
}
|
||||
data.disabled = false;
|
||||
|
||||
@@ -188,11 +188,11 @@ export class HistoryService extends BaseService<HistoryEntity> {
|
||||
const where: any = {
|
||||
createTime: MoreThan(todayEnd.add(-param.days, 'day').toDate()),
|
||||
};
|
||||
if (param.userId > 0) {
|
||||
where.userId = param.userId;
|
||||
}
|
||||
|
||||
if (param.projectId > 0) {
|
||||
where.projectId = param.projectId;
|
||||
}else if (param.userId > 0) {
|
||||
where.userId = param.userId;
|
||||
}
|
||||
const result = await this.getRepository()
|
||||
.createQueryBuilder('main')
|
||||
|
||||
@@ -50,6 +50,7 @@ import { nanoid } from "nanoid";
|
||||
import { set } from "lodash-es";
|
||||
import { executorQueue } from "@certd/lib-server";
|
||||
import parser from "cron-parser";
|
||||
import { ProjectService } from "../../sys/enterprise/service/project-service.js";
|
||||
const runningTasks: Map<string | number, Executor> = new Map();
|
||||
|
||||
|
||||
@@ -107,6 +108,9 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
@Inject()
|
||||
certInfoService: CertInfoService;
|
||||
|
||||
@Inject()
|
||||
projectService: ProjectService;
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
@@ -252,6 +256,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
//修改
|
||||
old = await this.info(bean.id);
|
||||
bean.order = old.order;
|
||||
bean.userId = old.userId;
|
||||
bean.projectId = old.projectId;
|
||||
}
|
||||
if (!old || !old.webhookKey) {
|
||||
bean.webhookKey = await this.genWebhookKey();
|
||||
@@ -262,6 +268,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
|
||||
const pipeline = JSON.parse(bean.content || "{}");
|
||||
RunnableCollection.initPipelineRunnableType(pipeline);
|
||||
pipeline.userId = bean.userId;
|
||||
pipeline.projectId = bean.projectId;
|
||||
let domains = [];
|
||||
if (pipeline.stages) {
|
||||
RunnableCollection.each(pipeline.stages, (runnable: any) => {
|
||||
@@ -295,8 +303,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
} else if (bean.type === "cert_auto") {
|
||||
fromType = "auto";
|
||||
}
|
||||
const userId = pipeline.userId || bean.userId;
|
||||
const projectId = pipeline.projectId ?? bean.projectId ??null;
|
||||
const userId = bean.userId;
|
||||
const projectId = bean.projectId ??null;
|
||||
await this.certInfoService.updateDomains(pipeline.id, userId, projectId , domains, fromType);
|
||||
return {
|
||||
...bean,
|
||||
@@ -672,9 +680,12 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
};
|
||||
|
||||
const userId = entity.userId;
|
||||
const historyId = await this.historyService.start(entity, triggerType);
|
||||
const projectId = entity.projectId;
|
||||
let userIsAdmin = false
|
||||
if(userId){
|
||||
|
||||
if (projectId && projectId>0) {
|
||||
userIsAdmin = await this.projectService.isAdmin(projectId);
|
||||
}else if(userId>0){
|
||||
userIsAdmin = await this.userService.isAdmin(userId);
|
||||
}
|
||||
const user: UserInfo = {
|
||||
@@ -682,7 +693,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
role: userIsAdmin ? "admin" : "user"
|
||||
};
|
||||
|
||||
|
||||
const historyId = await this.historyService.start(entity, triggerType);
|
||||
const sysInfo: SysInfo = {};
|
||||
if (isComm()) {
|
||||
const siteInfo = await this.sysSettingsService.getSetting<SysSiteInfo>(SysSiteInfo);
|
||||
@@ -690,7 +701,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
}
|
||||
|
||||
const taskServiceGetter = this.taskServiceBuilder.create({
|
||||
userId
|
||||
userId,
|
||||
projectId
|
||||
});
|
||||
const accessGetter = await taskServiceGetter.get<IAccessService>("accessService");
|
||||
const notificationGetter = await taskServiceGetter.get<INotificationService>("notificationService");
|
||||
@@ -920,7 +932,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
throw new NeedVIPException("此功能需要升级专业版");
|
||||
}
|
||||
for (const id of ids) {
|
||||
if (userId) {
|
||||
if (userId && userId > 0) {
|
||||
await this.checkUserId(id, userId);
|
||||
}
|
||||
if(projectId){
|
||||
@@ -1104,6 +1116,10 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
|
||||
|
||||
private async checkUserStatus(userId: number) {
|
||||
if(isEnterprise()){
|
||||
//企业模式不检查用户状态,都允许运行流水线
|
||||
return
|
||||
}
|
||||
const userEntity = await this.userService.info(userId);
|
||||
if (userEntity == null) {
|
||||
throw new Error("用户不存在");
|
||||
|
||||
@@ -19,6 +19,10 @@ export class ProjectEntity {
|
||||
@Column({ name: 'disabled', comment: '禁用' })
|
||||
disabled: boolean;
|
||||
|
||||
@Column({ name: 'is_system', comment: '是否系统项目' })
|
||||
isSystem: boolean; //系统项目内的流水线允许运行管理员级别的插件
|
||||
|
||||
|
||||
@Column({
|
||||
name: 'create_time',
|
||||
comment: '创建时间',
|
||||
|
||||
@@ -23,7 +23,7 @@ export class ProjectMemberService extends BaseService<ProjectMemberEntity> {
|
||||
if (!projectId) {
|
||||
throw new Error('项目ID不能为空');
|
||||
}
|
||||
if (!userId) {
|
||||
if (!userId || userId <= 0) {
|
||||
throw new Error('用户ID不能为空');
|
||||
}
|
||||
const exist = await this.repository.findOne({
|
||||
|
||||
@@ -11,9 +11,12 @@ const projectCache = new LRUCache<string, any>({
|
||||
ttl: 1000 * 60 * 10,
|
||||
});
|
||||
|
||||
const ENTERPRISE_USER_ID = -1 //企业模式下 企业userId 固定为-1
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class ProjectService extends BaseService<ProjectEntity> {
|
||||
|
||||
@InjectEntityModel(ProjectEntity)
|
||||
repository: Repository<ProjectEntity>;
|
||||
|
||||
@@ -36,7 +39,7 @@ export class ProjectService extends BaseService<ProjectEntity> {
|
||||
const exist = await this.repository.findOne({
|
||||
where: {
|
||||
name,
|
||||
userId: 0,
|
||||
userId: ENTERPRISE_USER_ID,
|
||||
},
|
||||
});
|
||||
if (exist) {
|
||||
@@ -57,7 +60,7 @@ export class ProjectService extends BaseService<ProjectEntity> {
|
||||
async setDisabled(id: number, disabled: boolean) {
|
||||
await this.repository.update({
|
||||
id,
|
||||
userId: 0,
|
||||
userId: ENTERPRISE_USER_ID,
|
||||
}, {
|
||||
disabled,
|
||||
});
|
||||
@@ -69,7 +72,7 @@ export class ProjectService extends BaseService<ProjectEntity> {
|
||||
const projectIds = memberList.map(item => item.projectId);
|
||||
const projectList = await this.repository.createQueryBuilder('project')
|
||||
.where(' project.disabled = false')
|
||||
.where(' project.userId = :userId', { userId: 0 })
|
||||
.where(' project.userId = :userId', { userId: ENTERPRISE_USER_ID })
|
||||
.where(' project.id IN (:...projectIds) or project.adminId = :userId', { projectIds, userId })
|
||||
.getMany();
|
||||
|
||||
@@ -93,7 +96,7 @@ export class ProjectService extends BaseService<ProjectEntity> {
|
||||
let projectList: any = await this.find({
|
||||
where: {
|
||||
disabled: false,
|
||||
userId: 0,
|
||||
userId: ENTERPRISE_USER_ID,
|
||||
},
|
||||
})
|
||||
const projectMemberItemList: ProjectMemberItem[] = projectList
|
||||
@@ -269,4 +272,9 @@ export class ProjectService extends BaseService<ProjectEntity> {
|
||||
})
|
||||
}
|
||||
|
||||
async isAdmin(projectId: number): Promise<boolean> {
|
||||
const project = await this.info(projectId);
|
||||
return project?.isSystem ?? false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user