Files
api/scripts/sync-superadmin-setting-template.mjs
T
mohmdsdgandCursor 71d6f6a534 fix(settings): restrict superadmin template to can_edit=0 keys only
Superadmin was seeding all deploy_settings_const INSERT keys including
can_edit=1 entries with wrong defaults (e.g. montzar_product_id=25).
Template/catalog now follow final can_edit=0 from SQL; editable keys are
purged from setting_templates and tenant settings on boot/seed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-19 18:40:07 +03:30

125 lines
4.1 KiB
JavaScript

#!/usr/bin/env node
/**
* منبع حقیقت: khaneghi_server/database/sql/deploy_settings_const.sql
* خروجی:
* - prisma/setting-templates-from-deploy.json (فقط can_edit=0 نهایی)
* - src/program-settings/deploy-setting-catalog-keys.ts
*/
import { readFileSync, writeFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const root = join(__dirname, '..');
const sqlPath = join(
root,
'../khaneghi_server/database/sql/deploy_settings_const.sql',
);
const sql = readFileSync(sqlPath, 'utf8');
/** @type {Map<string, { key: string, value: string, title_fa: string, can_edit: number, is_active: number, description: string, type: string }>} */
const rows = new Map();
function unquote(s) {
return String(s ?? '')
.trim()
.replace(/^'/, '')
.replace(/'$/, '')
.replace(/\\'/g, "'")
.replace(/\\n/g, '\n');
}
// INSERT … SELECT 'key', 'value', …
for (const m of sql.matchAll(
/SELECT\s+'([^']+)',\s+'((?:\\'|[^'])*)',\s+'((?:\\'|[^'])*)',\s+(\d+),\s+(\d+)(?:,\s+(NULL|'(?:\\'|[^'])*'))(?:,\s+'((?:\\'|[^'])*)')?/g,
)) {
const key = m[1];
const value = unquote(`'${m[2]}'`);
const title_fa = unquote(`'${m[3]}'`);
const can_edit = Number(m[4]);
const is_active = Number(m[5]);
let description = '';
if (m[6] && m[6] !== 'NULL') description = unquote(m[6]);
const type = m[7] ? unquote(`'${m[7]}'`) : '';
rows.set(key, { key, value, title_fa, can_edit, is_active, description, type });
}
function applyCanEdit(block, value) {
const keys = [...block.matchAll(/'([^']+)'/g)].map((x) => x[1]);
for (const key of keys) {
const row = rows.get(key);
if (row) row.can_edit = value;
}
}
// UPDATE can_edit = 0/1 batches
for (const m of sql.matchAll(
/UPDATE\s+`settings`\s+SET\s+`can_edit`\s*=\s*(\d)(?:,\s*`[^`]+`\s*=[^W]+)?\s+WHERE\s+`key`\s+IN\s*\(([\s\S]*?)\)\s*;/g,
)) {
applyCanEdit(m[2], Number(m[1]));
}
for (const m of sql.matchAll(
/UPDATE\s+`settings`\s+SET\s+`can_edit`\s*=\s*(\d)\s+WHERE\s+`key`\s*=\s*'([^']+)'/g,
)) {
const row = rows.get(m[2]);
if (row) row.can_edit = Number(m[1]);
}
// zarin_* wildcard
if (/UPDATE\s+`settings`\s+SET\s+`can_edit`\s*=\s*0,\s*`is_active`\s*=\s*1\s+WHERE\s+`key`\s+LIKE\s+'zarin_%'/.test(sql)) {
for (const [key, row] of rows) {
if (key.startsWith('zarin_')) row.can_edit = 0;
}
}
// type-only UPDATE batches — enrich type when present
for (const m of sql.matchAll(
/UPDATE\s+`settings`\s+SET\s+`type`\s*=\s*'([^']+)'\s+WHERE\s+`key`\s+IN\s*\(([\s\S]*?)\)\s*;/g,
)) {
const type = m[1];
for (const key of [...m[2].matchAll(/'([^']+)'/g)].map((x) => x[1])) {
const row = rows.get(key);
if (row && type) row.type = type;
}
}
const systemRows = [...rows.values()]
.filter((r) => r.can_edit === 0)
.sort((a, b) => a.key.localeCompare(b.key));
const editableRows = [...rows.values()]
.filter((r) => r.can_edit === 1)
.sort((a, b) => a.key.localeCompare(b.key));
const jsonOut = systemRows.map((r) => ({
key: r.key,
value: r.value ?? '',
title_fa: r.title_fa ?? r.key,
can_edit: 0,
is_active: r.is_active ?? 1,
description: r.description ?? '',
type: r.type ?? '',
}));
const tsKeys = `/**
* کلیدهای can_edit=0 در deploy_settings_const.sql — فقط همین‌ها در قالب سوپرادمین.
* تولید خودکار: node scripts/sync-superadmin-setting-template.mjs
*/
export const DEPLOY_SETTING_CATALOG_KEYS = new Set<string>([
${systemRows.map((r) => ` ${JSON.stringify(r.key)},`).join('\n')}
]);
/** کلیدهای can_edit=1 — نباید در قالب/جدول settings سوپرادمین باشند */
export const DEPLOY_SETTING_EDITABLE_KEYS = new Set<string>([
${editableRows.map((r) => ` ${JSON.stringify(r.key)},`).join('\n')}
]);
`;
writeFileSync(join(root, 'prisma/setting-templates-from-deploy.json'), `${JSON.stringify(jsonOut, null, 2)}\n`);
writeFileSync(join(root, 'src/program-settings/deploy-setting-catalog-keys.ts'), `${tsKeys}\n`);
console.log(`system keys (can_edit=0): ${systemRows.length}`);
console.log(`editable keys (can_edit=1): ${editableRows.length}`);