@@ -252,7 +252,7 @@ ${systemRows.map((r) => ` ${JSON.stringify(r.key)},`).join('\n')}
|
||||
|
||||
/**
|
||||
* کلیدهایی که سوپرادمین مالکشان نیست (مالک: دیتابیس هر نصب).
|
||||
* در هر بوت با purgeEditableFromSuperAdmin از قالب و ردیف همهٔ پروژهها حذف میشوند.
|
||||
* در هر بوت از قالب حذف میشوند؛ از ردیف هر پروژه فقط با دکمهٔ صفحهٔ تنظیمات همان پروژه.
|
||||
*/
|
||||
export const DEPLOY_SETTING_EDITABLE_KEYS = new Set<string>([
|
||||
${editableRows.map((r) => ` ${JSON.stringify(r.key)},`).join('\n')}
|
||||
|
||||
@@ -20,7 +20,8 @@ export const DEPLOY_SETTING_CATALOG_KEYS = new Set<string>([
|
||||
|
||||
/**
|
||||
* کلیدهایی که سوپرادمین مالکشان نیست (مالک: دیتابیس هر نصب).
|
||||
* در هر بوت با purgeEditableFromSuperAdmin از قالب و ردیف همهٔ پروژهها حذف میشوند.
|
||||
* در هر بوت از قالب حذف میشوند؛ از ردیف هر پروژه فقط با دکمهٔ
|
||||
* «حذف تنظیمات غیر دسترسی» در صفحهٔ تنظیمات همان پروژه.
|
||||
*/
|
||||
export const DEPLOY_SETTING_EDITABLE_KEYS = new Set<string>([
|
||||
"about_software",
|
||||
|
||||
@@ -46,4 +46,14 @@ export class ProgramSettingsController {
|
||||
user.id,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* بعد از restore لوکال: فقط کلیدهای «دسترسی مشتری به قابلیتها» روی این پروژه
|
||||
* در سوپرادمین میمانند؛ بقیه از جدول settings همین tenant حذف میشوند.
|
||||
*/
|
||||
@Post('purge-non-owned')
|
||||
@RequirePermissions('khanegi:write')
|
||||
purgeNonOwned(@Param('tenantId') tenantId: string, @CurrentUser() user: { id: string }) {
|
||||
return this.programSettings.purgeNonOwnedFromTenant(tenantId, user.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,11 +70,10 @@ export class ProgramSettingsService implements OnModuleInit {
|
||||
if (result.seeded) {
|
||||
this.logger.log(`setting_templates seeded (${result.count} keys)`);
|
||||
}
|
||||
const purged = await this.purgeEditableFromSuperAdmin();
|
||||
if (purged.templates || purged.settings) {
|
||||
this.logger.log(
|
||||
`purged can_edit=1 from superadmin (templates=${purged.templates}, settings=${purged.settings})`,
|
||||
);
|
||||
// فقط قالب: حذف ردیف پروژهها دونه به دونه با دکمهٔ صفحهٔ تنظیمات همان پروژه
|
||||
const purged = await this.purgeNonOwnedTemplates();
|
||||
if (purged.templates) {
|
||||
this.logger.log(`purged non-owned keys from setting_templates (templates=${purged.templates})`);
|
||||
}
|
||||
await this.seedEmptyKhanegiTenants();
|
||||
} catch (error: any) {
|
||||
@@ -599,25 +598,79 @@ export class ProgramSettingsService implements OnModuleInit {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** حذف can_edit=1 از قالب و همهٔ پروژههای خانگی در DB سوپرادمین */
|
||||
async purgeEditableFromSuperAdmin() {
|
||||
const keys = [...DEPLOY_SETTING_EDITABLE_KEYS];
|
||||
if (!keys.length) return { templates: 0, settings: 0 };
|
||||
/**
|
||||
* قالب سوپرادمین فقط کلیدهای مالکیت سوپرادمین (دسترسی مشتری) میماند.
|
||||
* ردیف پروژهها را پاک نمیکند — آن کار با purgeNonOwnedFromTenant است.
|
||||
*/
|
||||
async purgeNonOwnedTemplates() {
|
||||
const keep = [...DEPLOY_SETTING_CATALOG_KEYS];
|
||||
if (!keep.length) return { templates: 0 };
|
||||
|
||||
const result = await this.prisma.$transaction(async (tx: any) => {
|
||||
const templates = await tx.settingTemplate.deleteMany({
|
||||
where: { key: { in: keys } },
|
||||
});
|
||||
const settings = await tx.setting.deleteMany({
|
||||
where: { key: { in: keys } },
|
||||
});
|
||||
return { templates: templates.count, settings: settings.count };
|
||||
const templates = await this.prisma.settingTemplate.deleteMany({
|
||||
where: { NOT: { key: { in: keep } } },
|
||||
});
|
||||
|
||||
if (result.templates || result.settings) {
|
||||
if (templates.count) {
|
||||
this.replicaWatch.kick();
|
||||
}
|
||||
return result;
|
||||
return { templates: templates.count };
|
||||
}
|
||||
|
||||
/** سازگاری با اندپوینت قدیمی seed/purge-editable — فقط قالب */
|
||||
async purgeEditableFromSuperAdmin() {
|
||||
const templates = await this.purgeNonOwnedTemplates();
|
||||
return { templates: templates.templates, settings: 0 };
|
||||
}
|
||||
|
||||
/**
|
||||
* بعد از restore لوکال روی همان نصب: همهٔ تنظیمات این پروژه در DB سوپرادمین
|
||||
* که خارج از «دسترسی مشتری به قابلیتها»اند حذف میشوند.
|
||||
*/
|
||||
async purgeNonOwnedFromTenant(tenantId: string, userId?: string) {
|
||||
const tenant = await this.requireKhanegiTenant(tenantId);
|
||||
const keep = [...DEPLOY_SETTING_CATALOG_KEYS];
|
||||
|
||||
const before = await this.prisma.setting.findMany({
|
||||
where: {
|
||||
tenantId,
|
||||
NOT: { key: { in: keep } },
|
||||
},
|
||||
select: { key: true },
|
||||
});
|
||||
const removedKeys = before.map((row: { key: string }) => row.key).sort();
|
||||
|
||||
const deleted = await this.prisma.setting.deleteMany({
|
||||
where: {
|
||||
tenantId,
|
||||
NOT: { key: { in: keep } },
|
||||
},
|
||||
});
|
||||
|
||||
await this.audit.log({
|
||||
action: 'tenant.program_settings.purge_non_owned',
|
||||
entityType: 'tenant_program_settings',
|
||||
entityId: tenantId,
|
||||
tenantId,
|
||||
userId,
|
||||
after: {
|
||||
removed: deleted.count,
|
||||
keys: removedKeys,
|
||||
kept: keep,
|
||||
} as Prisma.InputJsonValue,
|
||||
});
|
||||
|
||||
if (deleted.count) {
|
||||
this.replicaWatch.kick();
|
||||
}
|
||||
|
||||
const items = await this.listTenantRows(tenantId);
|
||||
return {
|
||||
tenant: this.tenantMeta(tenant),
|
||||
removed: deleted.count,
|
||||
removedKeys,
|
||||
items,
|
||||
count: items.length,
|
||||
};
|
||||
}
|
||||
|
||||
private deployCatalogCanEditMap() {
|
||||
|
||||
Reference in New Issue
Block a user