chore: project

This commit is contained in:
xiaojunnuo
2026-02-13 23:51:27 +08:00
parent 83d81b64b3
commit 956d68695c
21 changed files with 75 additions and 38 deletions
@@ -196,7 +196,7 @@ export class AccessService extends BaseService<AccessEntity> {
if (ids.length === 0) { if (ids.length === 0) {
return []; return [];
} }
if (!userId) { if (userId==null) {
return []; return [];
} }
return await this.repository.find({ return await this.repository.find({
@@ -89,7 +89,7 @@ export class AddonService extends BaseService<AddonEntity> {
if (ids.length === 0) { if (ids.length === 0) {
return []; return [];
} }
if (!userId) { if (userId==null) {
return []; return [];
} }
return await this.repository.find({ return await this.repository.find({
@@ -145,7 +145,7 @@ export class AddonService extends BaseService<AddonEntity> {
if (!id) { if (!id) {
throw new ValidateException("id不能为空"); throw new ValidateException("id不能为空");
} }
if (!userId) { if (userId==null) {
throw new ValidateException("userId不能为空"); throw new ValidateException("userId不能为空");
} }
await this.repository.update( await this.repository.update(
@@ -311,6 +311,8 @@ export default {
days: "天", days: "天",
lastCheckTime: "上次检查时间", lastCheckTime: "上次检查时间",
disabled: "禁用启用", disabled: "禁用启用",
ipAddress: "IP地址",
ipAddressHelper: "填写则固定检查此IP,不从DNS获取域名的IP地址",
ipCheck: "开启IP检查", ipCheck: "开启IP检查",
ipCheckHelper: "开启后,会检查IP(或源站)上的证书有效期", ipCheckHelper: "开启后,会检查IP(或源站)上的证书有效期",
ipSyncAuto: "自动同步IP", ipSyncAuto: "自动同步IP",
@@ -556,6 +556,20 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
}, },
}, },
}, },
ipAddress: {
title: t("certd.monitor.ipAddress"),
search: {
show: false,
},
type: "text",
form: {
helper: t("certd.monitor.ipAddressHelper"),
},
column: {
width: 150,
sorter: true,
},
},
groupId: { groupId: {
title: t("certd.fields.group"), title: t("certd.fields.group"),
type: "dict-select", type: "dict-select",
@@ -66,6 +66,9 @@ CREATE INDEX "index_domain_project_id" ON "cd_domain" ("project_id");
ALTER TABLE user_settings ADD COLUMN project_id integer; ALTER TABLE user_settings ADD COLUMN project_id integer;
CREATE INDEX "index_user_settings_project_id" ON "user_settings" ("project_id"); CREATE INDEX "index_user_settings_project_id" ON "user_settings" ("project_id");
ALTER TABLE cd_group ADD COLUMN project_id integer;
CREATE INDEX "index_group_project_id" ON "cd_group" ("project_id");
@@ -104,3 +107,6 @@ CREATE INDEX "index_audit_log_user_id" ON "cd_audit_log" ("user_id");
CREATE INDEX "index_audit_log_project_id" ON "cd_audit_log" ("project_id"); CREATE INDEX "index_audit_log_project_id" ON "cd_audit_log" ("project_id");
ALTER TABLE cd_site_info ADD COLUMN ip_address varchar(128);
@@ -46,7 +46,7 @@ export class ConnectController extends BaseController {
throw new Error(`未配置该OAuth类型:${type}`); throw new Error(`未配置该OAuth类型:${type}`);
} }
const addon = await this.addonGetterService.getAddonById(setting.addonId, true, 0); const addon = await this.addonGetterService.getAddonById(setting.addonId, true, 0,null);
if (!addon) { if (!addon) {
throw new Error("初始化OAuth插件失败"); throw new Error("初始化OAuth插件失败");
} }
@@ -251,7 +251,7 @@ export class ConnectController extends BaseController {
provider.addonId = conf.addonId; provider.addonId = conf.addonId;
provider.addonTitle = addonEntity.name; provider.addonTitle = addonEntity.name;
const addon = await this.addonGetterService.getAddonById(conf.addonId,true,0); const addon = await this.addonGetterService.getAddonById(conf.addonId,true,0,null);
const {logoutUrl} = await addon.buildLogoutUrl(); const {logoutUrl} = await addon.buildLogoutUrl();
if (logoutUrl){ if (logoutUrl){
provider.logoutUrl = logoutUrl; provider.logoutUrl = logoutUrl;
@@ -29,7 +29,7 @@ export class OpenCertController extends BaseOpenController {
const openKey: OpenKey = this.ctx.openKey; const openKey: OpenKey = this.ctx.openKey;
const userId = openKey.userId; const userId = openKey.userId;
if (!userId) { if (userId==null) {
throw new CodeException(Constants.res.openKeyError); throw new CodeException(Constants.res.openKeyError);
} }
const projectId = openKey.projectId; const projectId = openKey.projectId;
@@ -18,7 +18,7 @@ export class CaptchaService {
const settings = await this.sysSettingsService.getPublicSettings(); const settings = await this.sysSettingsService.getPublicSettings();
captchaAddonId = settings.captchaAddonId ?? 0; captchaAddonId = settings.captchaAddonId ?? 0;
} }
const addon: ICaptchaAddon = await this.addonGetterService.getAddonById(captchaAddonId, true, 0, { const addon: ICaptchaAddon = await this.addonGetterService.getAddonById(captchaAddonId, true, 0,null, {
type: "captcha", type: "captcha",
name: "image" name: "image"
}); });
@@ -160,7 +160,7 @@ export class EmailService implements IEmailService {
const emailConf = await this.sysSettingsService.getSetting<SysEmailConf>(SysEmailConf); const emailConf = await this.sysSettingsService.getSetting<SysEmailConf>(SysEmailConf);
const template = emailConf?.templates?.[req.type] const template = emailConf?.templates?.[req.type]
if (isPlus() && template && template.addonId) { if (isPlus() && template && template.addonId) {
const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getAddonById(template.addonId, true, 0) const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getAddonById(template.addonId, true, 0,null)
if (addon) { if (addon) {
content = await addon.buildContent({ data: req.data }) content = await addon.buildContent({ data: req.data })
} }
@@ -168,7 +168,7 @@ export class EmailService implements IEmailService {
if (isPlus() && !content ) { if (isPlus() && !content ) {
//看看有没有通用模版 //看看有没有通用模版
if (emailConf?.templates?.common && emailConf?.templates?.common.addonId) { if (emailConf?.templates?.common && emailConf?.templates?.common.addonId) {
const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getAddonById(emailConf.templates.common.addonId, true, 0) const addon: ITemplateProvider<EmailContent> = await this.addonGetterService.getAddonById(emailConf.templates.common.addonId, true, 0,null)
if (addon) { if (addon) {
content = await addon.buildContent({ data: req.data }) content = await addon.buildContent({ data: req.data })
} }
@@ -109,10 +109,10 @@ export class DomainService extends BaseService<DomainEntity> {
* @param userId * @param userId
* @param domains //去除* 且去重之后的域名列表 * @param domains //去除* 且去重之后的域名列表
*/ */
async getDomainVerifiers(userId: number, domains: string[]): Promise<DomainVerifiers> { async getDomainVerifiers(userId: number, projectId: number, domains: string[]): Promise<DomainVerifiers> {
const mainDomainMap: Record<string, string> = {} const mainDomainMap: Record<string, string> = {}
const taskService = this.taskServiceBuilder.create({ userId: userId }); const taskService = this.taskServiceBuilder.create({ userId: userId, projectId: projectId });
const subDomainGetter = await taskService.getSubDomainsGetter(); const subDomainGetter = await taskService.getSubDomainsGetter();
const domainParser = new DomainParser(subDomainGetter) const domainParser = new DomainParser(subDomainGetter)
@@ -133,6 +133,7 @@ export class DomainService extends BaseService<DomainEntity> {
where: { where: {
domain: In(allDomains), domain: In(allDomains),
userId, userId,
projectId,
disabled: false, disabled: false,
} }
}) })
@@ -153,6 +154,7 @@ export class DomainService extends BaseService<DomainEntity> {
where: { where: {
domain: In(allDomains), domain: In(allDomains),
userId, userId,
projectId,
status: "valid", status: "valid",
} }
}) })
@@ -72,7 +72,7 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
if (!param.domain) { if (!param.domain) {
throw new ValidateException("域名不能为空"); throw new ValidateException("域名不能为空");
} }
if (!param.userId) { if (param.userId == null) {
throw new ValidateException("userId不能为空"); throw new ValidateException("userId不能为空");
} }
if (param.domain.startsWith("*.")) { if (param.domain.startsWith("*.")) {
@@ -71,6 +71,9 @@ export class SiteInfoEntity {
@Column({ name: 'group_id', comment: '分组id' }) @Column({ name: 'group_id', comment: '分组id' })
groupId: number; groupId: number;
@Column({ name: 'ip_address', comment: 'IP地址', length: 128 })
ipAddress: string;
@Column({ name: 'project_id', comment: '项目id' }) @Column({ name: 'project_id', comment: '项目id' })
projectId: number; projectId: number;
@@ -40,12 +40,12 @@ export class CertInfoFacade {
} }
const domainArr = domains.split(','); const domainArr = domains.split(',');
const matchedList = await this.certInfoService.getMatchCertList({domains:domainArr,userId}) const matchedList = await this.certInfoService.getMatchCertList({domains:domainArr,userId,projectId})
if (matchedList.length === 0 ) { if (matchedList.length === 0 ) {
if(req.autoApply === true){ if(req.autoApply === true){
//自动申请,先创建自动申请流水线 //自动申请,先创建自动申请流水线
const pipeline:PipelineEntity = await this.createAutoPipeline({domains:domainArr,userId}) const pipeline:PipelineEntity = await this.createAutoPipeline({domains:domainArr,userId,projectId})
await this.triggerApplyPipeline({pipelineId:pipeline.id}) await this.triggerApplyPipeline({pipelineId:pipeline.id})
}else{ }else{
throw new CodeException({ throw new CodeException({
@@ -103,9 +103,9 @@ export class CertInfoFacade {
return matched; return matched;
} }
async createAutoPipeline(req:{domains:string[],userId:number}){ async createAutoPipeline(req:{domains:string[],userId:number,projectId:number}){
const verifierGetter = new DomainVerifierGetter(req.userId, this.domainService) const verifierGetter = new DomainVerifierGetter(req.userId, req.projectId, this.domainService)
const allDomains = [] const allDomains = []
for (const item of req.domains) { for (const item of req.domains) {
@@ -133,6 +133,7 @@ export class CertInfoFacade {
return await this.pipelineService.createAutoPipeline({ return await this.pipelineService.createAutoPipeline({
domains: req.domains, domains: req.domains,
email, email,
projectId: req.projectId,
userId: req.userId, userId: req.userId,
from: "OpenAPI" from: "OpenAPI"
}) })
@@ -32,7 +32,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
} }
async getUserDomainCount(userId: number) { async getUserDomainCount(userId: number) {
if (!userId) { if (userId==null) {
throw new Error('userId is required'); throw new Error('userId is required');
} }
return await this.repository.sum('domainCount', { return await this.repository.sum('domainCount', {
@@ -84,8 +84,8 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
}); });
} }
async getMatchCertList(params: { domains: string[]; userId: number }) { async getMatchCertList(params: { domains: string[]; userId: number,projectId?:number }) {
const { domains, userId } = params; const { domains, userId,projectId } = params;
if (!domains) { if (!domains) {
throw new CodeException({ throw new CodeException({
...Constants.res.openCertNotFound, ...Constants.res.openCertNotFound,
@@ -102,6 +102,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
}, },
where: { where: {
userId, userId,
projectId,
}, },
order: { order: {
id: 'DESC', id: 'DESC',
@@ -16,9 +16,10 @@ export class AddonGetterService {
addonService: AddonService; addonService: AddonService;
async getAddonById(id: any, checkUserId: boolean, userId?: number, defaultAddon?:{type:string,name:string} ): Promise<any> { async getAddonById(id: any, checkUserId: boolean, userId?: number, projectId?: number, defaultAddon?:{type:string,name:string} ): Promise<any> {
const serviceGetter = this.taskServiceBuilder.create({ const serviceGetter = this.taskServiceBuilder.create({
userId userId,
projectId,
}); });
const ctx = { const ctx = {
http, http,
@@ -58,13 +59,13 @@ export class AddonGetterService {
return await newAddon(entity.addonType, entity.type, input, ctx); return await newAddon(entity.addonType, entity.type, input, ctx);
} }
async getById(id: any, userId: number): Promise<any> { async getById(id: any, userId: number, projectId?: number): Promise<any> {
return await this.getAddonById(id, true, userId); return await this.getAddonById(id, true, userId, projectId);
} }
async getBlank(addonType:string,subType:string){ async getBlank(addonType:string,subType:string,projectId?: number){
return await this.getAddonById(null,false,0,{ return await this.getAddonById(null,false,0,projectId,{
type: addonType, name:subType type: addonType, name:subType
}) })
} }
@@ -3,15 +3,17 @@ import {DomainService} from "../../../cert/service/domain-service.js";
export class DomainVerifierGetter implements IDomainVerifierGetter { export class DomainVerifierGetter implements IDomainVerifierGetter {
private userId: number; private userId: number;
private projectId: number;
private domainService: DomainService; private domainService: DomainService;
constructor(userId: number, domainService: DomainService) { constructor(userId: number, projectId: number, domainService: DomainService) {
this.userId = userId; this.userId = userId;
this.projectId = projectId;
this.domainService = domainService; this.domainService = domainService;
} }
async getVerifiers(domains: string[]): Promise<DomainVerifiers>{ async getVerifiers(domains: string[]): Promise<DomainVerifiers>{
return await this.domainService.getDomainVerifiers(this.userId,domains); return await this.domainService.getDomainVerifiers(this.userId,this.projectId,domains);
} }
} }
@@ -4,17 +4,19 @@ import { DomainService } from "../../../cert/service/domain-service.js";
export class SubDomainsGetter implements ISubDomainsGetter { export class SubDomainsGetter implements ISubDomainsGetter {
userId: number; userId: number;
projectId: number;
subDomainService: SubDomainService; subDomainService: SubDomainService;
domainService: DomainService; domainService: DomainService;
constructor(userId: number, subDomainService: SubDomainService, domainService: DomainService) { constructor(userId: number, projectId: number, subDomainService: SubDomainService, domainService: DomainService) {
this.userId = userId; this.userId = userId;
this.projectId = projectId;
this.subDomainService = subDomainService; this.subDomainService = subDomainService;
this.domainService = domainService; this.domainService = domainService;
} }
async getSubDomains() { async getSubDomains() {
return await this.subDomainService.getListByUserId(this.userId) return await this.subDomainService.getListByUserId(this.userId, this.projectId)
} }
async hasSubDomain(fullDomain: string) { async hasSubDomain(fullDomain: string) {
@@ -48,7 +48,7 @@ export class TaskServiceGetter implements IServiceGetter{
async getSubDomainsGetter(): Promise<SubDomainsGetter> { async getSubDomainsGetter(): Promise<SubDomainsGetter> {
const subDomainsService:SubDomainService = await this.appCtx.getAsync("subDomainService") const subDomainsService:SubDomainService = await this.appCtx.getAsync("subDomainService")
const domainService:DomainService = await this.appCtx.getAsync("domainService") const domainService:DomainService = await this.appCtx.getAsync("domainService")
return new SubDomainsGetter(this.userId, subDomainsService,domainService) return new SubDomainsGetter(this.userId,this.projectId, subDomainsService,domainService)
} }
async getAccessService(): Promise<AccessGetter> { async getAccessService(): Promise<AccessGetter> {
@@ -69,7 +69,7 @@ export class TaskServiceGetter implements IServiceGetter{
async getDomainVerifierGetter(): Promise<DomainVerifierGetter> { async getDomainVerifierGetter(): Promise<DomainVerifierGetter> {
const domainService:DomainService = await this.appCtx.getAsync("domainService") const domainService:DomainService = await this.appCtx.getAsync("domainService")
return new DomainVerifierGetter(this.userId, domainService); return new DomainVerifierGetter(this.userId, this.projectId, domainService);
} }
} }
@Provide() @Provide()
@@ -88,7 +88,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
if (!id) { if (!id) {
throw new ValidateException('id不能为空'); throw new ValidateException('id不能为空');
} }
if (!userId) { if (userId==null) {
throw new ValidateException('userId不能为空'); throw new ValidateException('userId不能为空');
} }
const res = await this.repository.findOne({ const res = await this.repository.findOne({
@@ -135,7 +135,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
if (!id) { if (!id) {
throw new ValidateException('id不能为空'); throw new ValidateException('id不能为空');
} }
if (!userId) { if (userId==null) {
throw new ValidateException('userId不能为空'); throw new ValidateException('userId不能为空');
} }
await this.repository.update( await this.repository.update(
@@ -1082,7 +1082,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
} }
} }
async createAutoPipeline(req: { domains: string[]; email: string; userId: number, from: string }) { async createAutoPipeline(req: { domains: string[]; email: string; userId: number,projectId?:number, from: string }) {
const randomHour = Math.floor(Math.random() * 6); const randomHour = Math.floor(Math.random() * 6);
const randomMin = Math.floor(Math.random() * 60); const randomMin = Math.floor(Math.random() * 60);
@@ -1162,6 +1162,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
bean.type = "cert_auto"; bean.type = "cert_auto";
bean.disabled = false bean.disabled = false
bean.keepHistoryCount = 30 bean.keepHistoryCount = 30
bean.projectId = req.projectId
await this.save(bean) await this.save(bean)
@@ -22,13 +22,14 @@ export class SubDomainService extends BaseService<SubDomainEntity> {
return this.repository; return this.repository;
} }
async getListByUserId(userId:number):Promise<string[]>{ async getListByUserId(userId:number, projectId?: number):Promise<string[]>{
if (!userId) { if (userId==null) {
return []; return [];
} }
const list = await this.find({ const list = await this.find({
where: { where: {
userId, userId,
projectId,
disabled: false, disabled: false,
}, },
}); });
@@ -37,17 +38,18 @@ export class SubDomainService extends BaseService<SubDomainEntity> {
} }
async add(bean: SubDomainEntity) { async add(bean: SubDomainEntity) {
const {domain, userId} = bean; const {domain, userId, projectId} = bean;
if (!domain) { if (!domain) {
throw new Error('域名不能为空'); throw new Error('域名不能为空');
} }
if (!userId) { if (userId==null) {
throw new Error('用户ID不能为空'); throw new Error('用户ID不能为空');
} }
const exist = await this.repository.findOne({ const exist = await this.repository.findOne({
where: { where: {
domain, domain,
userId, userId,
projectId,
}, },
}); });
if (exist) { if (exist) {