fix: 修复旧流水线保存时清空证书仓库证书内容的bug

This commit is contained in:
xiaojunnuo
2026-08-30 01:52:25 +08:00
parent 9842a24a50
commit f58f2f3cd6
3 changed files with 90 additions and 74 deletions
@@ -73,10 +73,11 @@ export class DomainService extends BaseService<DomainEntity> {
if (!param.domain) {
throw new Error("domain 不能为空");
}
const old = await this.repository.findOne({
const query = this.buildUserProjectQuery(param.userId, param.projectId);
const old = await this.findOne({
where: {
domain: param.domain,
userId: param.userId,
...query
},
});
if (old) {
@@ -96,11 +97,11 @@ export class DomainService extends BaseService<DomainEntity> {
if (!old) {
throw new Error("domain记录不存在");
}
const query = this.buildUserProjectQuery(param.userId, param.projectId);
const same = await this.repository.findOne({
where: {
domain: param.domain,
userId: old.userId,
...query,
id: Not(param.id),
},
});
@@ -222,7 +223,6 @@ export class DomainService extends BaseService<DomainEntity> {
}
domainVerifiers[domain] = null;
}
return domainVerifiers;
}
@@ -243,20 +243,28 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
}
const userProjectQuery = this.buildUserProjectQuery(userId, projectId);
const taskIds = applyTasks.map(task => task.taskId);
const foundHistory = await this.repository.find({
where: {
pipelineId,
status: CertStatus.active,
...userProjectQuery,
},
});
for (const task of applyTasks) {
// 每个申请任务维护一条 active 记录(不重复创建,最新真证书申请成功后旧记录会被标记为 inactive)
const found = await this.repository.findOne({
where: {
pipelineId,
taskId: task.taskId,
status: CertStatus.active,
...userProjectQuery,
},
});
const bean = new CertInfoEntity();
let found = foundHistory.find(item => item.taskId === task.taskId);
if (!found && foundHistory.length == 1 && applyTasks.length == 1){
found = foundHistory[0];
}
if (found) {
//已有 active 记录(空占位或真证书):更新域名信息
bean.id = found.id;
if (!found.taskId) {
bean.taskId = task.taskId;
}
} else {
//创建空证书记录
bean.pipelineId = pipelineId;
@@ -281,7 +289,6 @@ export class CertInfoService extends BaseService<CertInfoEntity> {
taskId: Or(IsNull(), Not(In(taskIds))),
});
}
/**
* 根据流水线类型推导证书来源(与流水线保存逻辑保持一致)
*/
@@ -2,7 +2,7 @@ import { Inject, Provide, Scope, ScopeEnum } from "@midwayjs/core";
import { addonRegistry, BaseService, PageReq, PlusService, SysInstallInfo, SysPluginSetting, SysSettingsService } from "@certd/lib-server";
import { PluginEntity } from "../entity/plugin.js";
import { InjectEntityModel } from "@midwayjs/typeorm";
import { Brackets, Equal, IsNull, Like, Not, Or, Repository } from "typeorm";
import { Brackets, Equal, In, IsNull, Like, Not, Or, Repository } from "typeorm";
import { isComm } from "@certd/plus-core";
import { BuiltInPluginService } from "../../pipeline/service/builtin-plugin-service.js";
import { merge } from "lodash-es";
@@ -711,6 +711,7 @@ export class PluginService extends BaseService<PluginEntity> {
if (param.type === "builtIn") {
return await super.add({
disabled: false,
...param,
});
}
@@ -732,6 +733,7 @@ export class PluginService extends BaseService<PluginEntity> {
}
const res = await super.add({
disabled: false,
...param,
...plugin,
});
@@ -762,19 +764,10 @@ export class PluginService extends BaseService<PluginEntity> {
return "";
}
private normalizeOnlinePluginRecord(item: OnlinePluginBean, syncTime: number, old?: PluginEntity) {
private normalizeOnlinePluginRecord(item: OnlinePluginBean, syncTime: number) {
const fullName = this.getOnlinePluginFullName(item);
let extra: Record<string, any> = {};
if (old?.extra) {
try {
extra = (yaml.load(old.extra) as Record<string, any>) || {};
} catch (e) {
extra = {};
}
}
delete extra.dependPlugins;
return this.repository.create({
id: old?.id,
return {
appId: item.appId,
developerId: item.developerId,
fullName,
@@ -794,9 +787,9 @@ export class PluginService extends BaseService<PluginEntity> {
dependPlugins: toDependPluginsYaml(item.dependPlugins),
extra: Object.keys(extra).length > 0 ? yaml.dump(extra) : null,
syncTime,
type: old?.type || "store",
type: "store",
updateTime: new Date(),
});
};
}
private toOnlinePluginBean(item: PluginEntity): OnlinePluginBean {
@@ -964,19 +957,6 @@ export class PluginService extends BaseService<PluginEntity> {
await this.plusService.register();
// 只同步市场列表元数据,插件 YAML 内容仍然在安装时按版本下载。
const createdAtLt = Date.now();
const existingList = await this.find({
where: {
type: "store",
},
});
const existingMap = new Map<string, PluginEntity>();
for (const item of existingList) {
const fullName = item.fullName || this.getOnlinePluginFullName(item as any);
if (fullName) {
existingMap.set(fullName, item);
}
}
const syncTime = new Date().getTime();
let pageStart = 0;
while (true) {
@@ -984,7 +964,6 @@ export class PluginService extends BaseService<PluginEntity> {
url: "/activation/plugin/page",
method: "post",
data: {
createdAtLt,
page: {
start: pageStart,
limit: ONLINE_PLUGIN_SYNC_PAGE_SIZE,
@@ -998,23 +977,44 @@ export class PluginService extends BaseService<PluginEntity> {
},
});
const list = res?.list || [];
const pluginMap = new Map<string, OnlinePluginBean>();
for (const item of list) {
const record = { ...item };
const fullName = this.getOnlinePluginFullName(record);
if (!fullName) {
continue;
}
record.fullName = fullName;
pluginMap.set(fullName, record);
}
const records = Array.from(pluginMap.values()).map(item => {
return this.normalizeOnlinePluginRecord(item, syncTime, existingMap.get(item.fullName));
const fullNames = list.map(item => this.getOnlinePluginFullName(item));
const existingRecords = await this.repository.find({
where: {
type: "store",
fullName: In(fullNames),
},
});
if (records.length > 0) {
await this.addOrUpdate(records);
for (const record of records) {
existingMap.set(record.fullName, record);
const existingMap = new Map(existingRecords.map(item => [item.fullName, item]));
for (const item of list) {
const itemFromStore:any = this.normalizeOnlinePluginRecord(item, syncTime);
const fullName = itemFromStore.fullName;
const existingRecord = existingMap.get(fullName);
if (existingRecord) {
//本地已存在,只更新市场相关字段
if (existingRecord.installed){
//如果本地已经安装的,则只同步版本 分数 下载量
const updateBean: Record<string, any> = {
id: existingRecord.id,
score: itemFromStore.score,
downloadCount: itemFromStore.downloadCount,
latestVersion: itemFromStore.version,
}
await this.update(updateBean);
}else{
//如果本地未安装的,则同步所有字段
const updateBean: Record<string, any> = {
id: existingRecord.id,
...itemFromStore,
}
await this.update(updateBean);
}
continue;
}else{
itemFromStore.disabled = false;
await this.add(itemFromStore);
}
}
const total = Number(res?.page?.total || 0);
@@ -1586,18 +1586,6 @@ export class PluginService extends BaseService<PluginEntity> {
fullName,
},
});
// 兼容历史自开发插件:旧记录可能没有 fullName,切换为在线插件时按作者和名称复用。
if (!old && entityType === "store" && loaded.author && loaded.name) {
const legacyPlugin = await this.findOne({
where: {
author: loaded.author,
name: loaded.name,
},
});
if (legacyPlugin?.type === "custom" || !legacyPlugin?.type) {
old = legacyPlugin;
}
}
const metadata = {
input: loaded.input,
@@ -1630,16 +1618,16 @@ export class PluginService extends BaseService<PluginEntity> {
}
if (!old) {
//add
const { id } = await this.add(pluginEntity);
pluginEntity.id = id;
await super.add(pluginEntity);
} else {
if (!req.override) {
throw new Error(`插件${loaded.author}/${loaded.name}已存在`);
}
pluginEntity.id = old.id;
//update
await this.update(pluginEntity);
}
//update
await this.update(pluginEntity);
return {
id: pluginEntity.id,
};
@@ -1670,4 +1658,25 @@ export class PluginService extends BaseService<PluginEntity> {
}
);
}
isNewVersion(version: string, latestVersion: string) {
if (!latestVersion) {
return false;
}
if (latestVersion === version) {
return false;
}
//分段比较
const current = version.split(".");
const latest = latestVersion.split(".");
for (let i = 0; i < current.length; i++) {
if (parseInt(latest[i]) > parseInt(current[i])) {
return true;
} else if (parseInt(latest[i]) < parseInt(current[i])) {
return false;
}
}
return false;
}
}