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

View File

@@ -196,7 +196,7 @@ export class AccessService extends BaseService<AccessEntity> {
if (ids.length === 0) {
return [];
}
if (!userId) {
if (userId==null) {
return [];
}
return await this.repository.find({

View File

@@ -89,7 +89,7 @@ export class AddonService extends BaseService<AddonEntity> {
if (ids.length === 0) {
return [];
}
if (!userId) {
if (userId==null) {
return [];
}
return await this.repository.find({
@@ -145,7 +145,7 @@ export class AddonService extends BaseService<AddonEntity> {
if (!id) {
throw new ValidateException("id不能为空");
}
if (!userId) {
if (userId==null) {
throw new ValidateException("userId不能为空");
}
await this.repository.update(

View File

@@ -311,6 +311,8 @@ export default {
days: "天",
lastCheckTime: "上次检查时间",
disabled: "禁用启用",
ipAddress: "IP地址",
ipAddressHelper: "填写则固定检查此IP不从DNS获取域名的IP地址",
ipCheck: "开启IP检查",
ipCheckHelper: "开启后会检查IP或源站上的证书有效期",
ipSyncAuto: "自动同步IP",

View File

@@ -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: {
title: t("certd.fields.group"),
type: "dict-select",

View File

@@ -66,6 +66,9 @@ CREATE INDEX "index_domain_project_id" ON "cd_domain" ("project_id");
ALTER TABLE user_settings ADD COLUMN project_id integer;
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");
ALTER TABLE cd_site_info ADD COLUMN ip_address varchar(128);

View File

@@ -46,7 +46,7 @@ export class ConnectController extends BaseController {
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) {
throw new Error("初始化OAuth插件失败");
}
@@ -251,7 +251,7 @@ export class ConnectController extends BaseController {
provider.addonId = conf.addonId;
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();
if (logoutUrl){
provider.logoutUrl = logoutUrl;

View File

@@ -29,7 +29,7 @@ export class OpenCertController extends BaseOpenController {
const openKey: OpenKey = this.ctx.openKey;
const userId = openKey.userId;
if (!userId) {
if (userId==null) {
throw new CodeException(Constants.res.openKeyError);
}
const projectId = openKey.projectId;

View File

@@ -18,7 +18,7 @@ export class CaptchaService {
const settings = await this.sysSettingsService.getPublicSettings();
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",
name: "image"
});

View File

@@ -160,7 +160,7 @@ export class EmailService implements IEmailService {
const emailConf = await this.sysSettingsService.getSetting<SysEmailConf>(SysEmailConf);
const template = emailConf?.templates?.[req.type]
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) {
content = await addon.buildContent({ data: req.data })
}
@@ -168,7 +168,7 @@ export class EmailService implements IEmailService {
if (isPlus() && !content ) {
//看看有没有通用模版
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) {
content = await addon.buildContent({ data: req.data })
}

View File

@@ -109,10 +109,10 @@ export class DomainService extends BaseService<DomainEntity> {
* @param userId
* @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 taskService = this.taskServiceBuilder.create({ userId: userId });
const taskService = this.taskServiceBuilder.create({ userId: userId, projectId: projectId });
const subDomainGetter = await taskService.getSubDomainsGetter();
const domainParser = new DomainParser(subDomainGetter)
@@ -133,6 +133,7 @@ export class DomainService extends BaseService<DomainEntity> {
where: {
domain: In(allDomains),
userId,
projectId,
disabled: false,
}
})
@@ -153,6 +154,7 @@ export class DomainService extends BaseService<DomainEntity> {
where: {
domain: In(allDomains),
userId,
projectId,
status: "valid",
}
})

View File

@@ -72,7 +72,7 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
if (!param.domain) {
throw new ValidateException("域名不能为空");
}
if (!param.userId) {
if (param.userId == null) {
throw new ValidateException("userId不能为空");
}
if (param.domain.startsWith("*.")) {

View File

@@ -71,6 +71,9 @@ export class SiteInfoEntity {
@Column({ name: 'group_id', comment: '分组id' })
groupId: number;
@Column({ name: 'ip_address', comment: 'IP地址', length: 128 })
ipAddress: string;
@Column({ name: 'project_id', comment: '项目id' })
projectId: number;

View File

@@ -40,12 +40,12 @@ export class CertInfoFacade {
}
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(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})
}else{
throw new CodeException({
@@ -103,9 +103,9 @@ export class CertInfoFacade {
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 = []
for (const item of req.domains) {
@@ -133,6 +133,7 @@ export class CertInfoFacade {
return await this.pipelineService.createAutoPipeline({
domains: req.domains,
email,
projectId: req.projectId,
userId: req.userId,
from: "OpenAPI"
})

View File

@@ -32,7 +32,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
}
async getUserDomainCount(userId: number) {
if (!userId) {
if (userId==null) {
throw new Error('userId is required');
}
return await this.repository.sum('domainCount', {
@@ -84,8 +84,8 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
});
}
async getMatchCertList(params: { domains: string[]; userId: number }) {
const { domains, userId } = params;
async getMatchCertList(params: { domains: string[]; userId: number,projectId?:number }) {
const { domains, userId,projectId } = params;
if (!domains) {
throw new CodeException({
...Constants.res.openCertNotFound,
@@ -102,6 +102,7 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
},
where: {
userId,
projectId,
},
order: {
id: 'DESC',

View File

@@ -16,9 +16,10 @@ export class AddonGetterService {
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({
userId
userId,
projectId,
});
const ctx = {
http,
@@ -58,13 +59,13 @@ export class AddonGetterService {
return await newAddon(entity.addonType, entity.type, input, ctx);
}
async getById(id: any, userId: number): Promise<any> {
return await this.getAddonById(id, true, userId);
async getById(id: any, userId: number, projectId?: number): Promise<any> {
return await this.getAddonById(id, true, userId, projectId);
}
async getBlank(addonType:string,subType:string){
return await this.getAddonById(null,false,0,{
async getBlank(addonType:string,subType:string,projectId?: number){
return await this.getAddonById(null,false,0,projectId,{
type: addonType, name:subType
})
}

View File

@@ -3,15 +3,17 @@ import {DomainService} from "../../../cert/service/domain-service.js";
export class DomainVerifierGetter implements IDomainVerifierGetter {
private userId: number;
private projectId: number;
private domainService: DomainService;
constructor(userId: number, domainService: DomainService) {
constructor(userId: number, projectId: number, domainService: DomainService) {
this.userId = userId;
this.projectId = projectId;
this.domainService = domainService;
}
async getVerifiers(domains: string[]): Promise<DomainVerifiers>{
return await this.domainService.getDomainVerifiers(this.userId,domains);
return await this.domainService.getDomainVerifiers(this.userId,this.projectId,domains);
}
}

View File

@@ -4,17 +4,19 @@ import { DomainService } from "../../../cert/service/domain-service.js";
export class SubDomainsGetter implements ISubDomainsGetter {
userId: number;
projectId: number;
subDomainService: SubDomainService;
domainService: DomainService;
constructor(userId: number, subDomainService: SubDomainService, domainService: DomainService) {
constructor(userId: number, projectId: number, subDomainService: SubDomainService, domainService: DomainService) {
this.userId = userId;
this.projectId = projectId;
this.subDomainService = subDomainService;
this.domainService = domainService;
}
async getSubDomains() {
return await this.subDomainService.getListByUserId(this.userId)
return await this.subDomainService.getListByUserId(this.userId, this.projectId)
}
async hasSubDomain(fullDomain: string) {

View File

@@ -48,7 +48,7 @@ export class TaskServiceGetter implements IServiceGetter{
async getSubDomainsGetter(): Promise<SubDomainsGetter> {
const subDomainsService:SubDomainService = await this.appCtx.getAsync("subDomainService")
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> {
@@ -69,7 +69,7 @@ export class TaskServiceGetter implements IServiceGetter{
async getDomainVerifierGetter(): Promise<DomainVerifierGetter> {
const domainService:DomainService = await this.appCtx.getAsync("domainService")
return new DomainVerifierGetter(this.userId, domainService);
return new DomainVerifierGetter(this.userId, this.projectId, domainService);
}
}
@Provide()

View File

@@ -88,7 +88,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
if (!id) {
throw new ValidateException('id不能为空');
}
if (!userId) {
if (userId==null) {
throw new ValidateException('userId不能为空');
}
const res = await this.repository.findOne({
@@ -135,7 +135,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
if (!id) {
throw new ValidateException('id不能为空');
}
if (!userId) {
if (userId==null) {
throw new ValidateException('userId不能为空');
}
await this.repository.update(

View File

@@ -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 randomMin = Math.floor(Math.random() * 60);
@@ -1162,6 +1162,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
bean.type = "cert_auto";
bean.disabled = false
bean.keepHistoryCount = 30
bean.projectId = req.projectId
await this.save(bean)

View File

@@ -22,13 +22,14 @@ export class SubDomainService extends BaseService<SubDomainEntity> {
return this.repository;
}
async getListByUserId(userId:number):Promise<string[]>{
if (!userId) {
async getListByUserId(userId:number, projectId?: number):Promise<string[]>{
if (userId==null) {
return [];
}
const list = await this.find({
where: {
userId,
projectId,
disabled: false,
},
});
@@ -37,17 +38,18 @@ export class SubDomainService extends BaseService<SubDomainEntity> {
}
async add(bean: SubDomainEntity) {
const {domain, userId} = bean;
const {domain, userId, projectId} = bean;
if (!domain) {
throw new Error('域名不能为空');
}
if (!userId) {
if (userId==null) {
throw new Error('用户ID不能为空');
}
const exist = await this.repository.findOne({
where: {
domain,
userId,
projectId,
},
});
if (exist) {