Files
dsc-api/database/migrations/1784500000000-RefactorPermissionsToCrudAndGroup.ts
T
2026-07-20 10:16:45 +03:30

301 lines
12 KiB
TypeScript

import { MigrationInterface, QueryRunner } from "typeorm";
type CrudResource = {
old: string;
group: string;
titles: { create: string; read: string; update: string; delete: string };
};
const CRUD_RESOURCES: CrudResource[] = [
{
old: "services",
group: "services",
titles: { create: "ایجاد سرویس‌ها", read: "مشاهده سرویس‌ها", update: "ویرایش سرویس‌ها", delete: "حذف سرویس‌ها" },
},
{
old: "customers",
group: "customers",
titles: { create: "ایجاد مشتریان", read: "مشاهده مشتریان", update: "ویرایش مشتریان", delete: "حذف مشتریان" },
},
{
old: "agents",
group: "representatives",
titles: { create: "ایجاد نمایندگان", read: "مشاهده نمایندگان", update: "ویرایش نمایندگان", delete: "حذف نمایندگان" },
},
{
old: "developers",
group: "users",
titles: {
create: "ایجاد توسعه‌دهندگان",
read: "مشاهده توسعه‌دهندگان",
update: "ویرایش توسعه‌دهندگان",
delete: "حذف توسعه‌دهندگان",
},
},
{
old: "invoices",
group: "financial",
titles: { create: "ایجاد صورتحساب‌ها", read: "مشاهده صورتحساب‌ها", update: "ویرایش صورتحساب‌ها", delete: "حذف صورتحساب‌ها" },
},
{
old: "transactions",
group: "financial",
titles: { create: "ایجاد تراکنش‌ها", read: "مشاهده تراکنش‌ها", update: "ویرایش تراکنش‌ها", delete: "حذف تراکنش‌ها" },
},
{
old: "discounts",
group: "financial",
titles: { create: "ایجاد تخفیف‌ها", read: "مشاهده تخفیف‌ها", update: "ویرایش تخفیف‌ها", delete: "حذف تخفیف‌ها" },
},
{
old: "admins",
group: "users",
titles: { create: "ایجاد ادمین‌ها", read: "مشاهده ادمین‌ها", update: "ویرایش ادمین‌ها", delete: "حذف ادمین‌ها" },
},
{
old: "tickets",
group: "support",
titles: { create: "ایجاد تیکت‌ها", read: "مشاهده تیکت‌ها", update: "ویرایش تیکت‌ها", delete: "حذف تیکت‌ها" },
},
{
old: "criticisms",
group: "other",
titles: { create: "ایجاد انتقادات", read: "مشاهده انتقادات", update: "ویرایش انتقادات", delete: "حذف انتقادات" },
},
{
old: "contacts_us",
group: "other",
titles: { create: "ایجاد تماس با ما", read: "مشاهده تماس با ما", update: "ویرایش تماس با ما", delete: "حذف تماس با ما" },
},
{
old: "advertisements",
group: "content",
titles: { create: "ایجاد تبلیغات", read: "مشاهده تبلیغات", update: "ویرایش تبلیغات", delete: "حذف تبلیغات" },
},
{
old: "announcements",
group: "content",
titles: { create: "ایجاد اطلاعیه‌ها", read: "مشاهده اطلاعیه‌ها", update: "ویرایش اطلاعیه‌ها", delete: "حذف اطلاعیه‌ها" },
},
{
old: "blogs",
group: "content",
titles: { create: "ایجاد بلاگ‌ها", read: "مشاهده بلاگ‌ها", update: "ویرایش بلاگ‌ها", delete: "حذف بلاگ‌ها" },
},
{
old: "learnings",
group: "content",
titles: { create: "ایجاد آموزش‌ها", read: "مشاهده آموزش‌ها", update: "ویرایش آموزش‌ها", delete: "حذف آموزش‌ها" },
},
{
old: "settings",
group: "other",
titles: { create: "ایجاد تنظیمات", read: "مشاهده تنظیمات", update: "ویرایش تنظیمات", delete: "حذف تنظیمات" },
},
{
old: "bank_accounts",
group: "financial",
titles: {
create: "ایجاد حساب‌های بانکی",
read: "مشاهده حساب‌های بانکی",
update: "ویرایش حساب‌های بانکی",
delete: "حذف حساب‌های بانکی",
},
},
{
old: "payments",
group: "financial",
titles: { create: "ایجاد پرداخت‌ها", read: "مشاهده پرداخت‌ها", update: "ویرایش پرداخت‌ها", delete: "حذف پرداخت‌ها" },
},
{
old: "support_plan",
group: "support",
titles: {
create: "ایجاد پلن پشتیبانی",
read: "مشاهده پلن پشتیبانی",
update: "ویرایش پلن پشتیبانی",
delete: "حذف پلن پشتیبانی",
},
},
{
old: "reseller",
group: "representatives",
titles: {
create: "ایجاد نمایندگی فروش",
read: "مشاهده نمایندگی فروش",
update: "ویرایش نمایندگی فروش",
delete: "حذف نمایندگی فروش",
},
},
{
old: "workspace",
group: "task_manager",
titles: { create: "ایجاد فضای کار", read: "مشاهده فضای کار", update: "ویرایش فضای کار", delete: "حذف فضای کار" },
},
{
old: "project",
group: "task_manager",
titles: { create: "ایجاد پروژه", read: "مشاهده پروژه", update: "ویرایش پروژه", delete: "حذف پروژه" },
},
{
old: "task",
group: "task_manager",
titles: { create: "ایجاد وظیفه", read: "مشاهده وظیفه", update: "ویرایش وظیفه", delete: "حذف وظیفه" },
},
{
old: "task_phase",
group: "task_manager",
titles: { create: "ایجاد فاز وظیفه", read: "مشاهده فاز وظیفه", update: "ویرایش فاز وظیفه", delete: "حذف فاز وظیفه" },
},
];
const SINGLE_PERMISSIONS: { name: string; group: string; title: string }[] = [
{ name: "logs", group: "other", title: "لاگ‌ها" },
{ name: "manage_sso_clients", group: "other", title: "مدیریت کلاینت‌های SSO" },
{ name: "dmenu", group: "products", title: "دی‌منو" },
{ name: "dkala", group: "products", title: "دی‌کالا" },
{ name: "dpage", group: "products", title: "دی‌پیج" },
{ name: "dmail", group: "products", title: "دی‌میل" },
{ name: "view_all_workspaces", group: "task_manager", title: "مشاهده همه فضاهای کار" },
{ name: "view_all_projects", group: "task_manager", title: "مشاهده همه پروژه‌ها" },
];
const NEW_ENUM_VALUES = [
...CRUD_RESOURCES.flatMap((r) => [`${r.old}_create`, `${r.old}_read`, `${r.old}_update`, `${r.old}_delete`]),
...SINGLE_PERMISSIONS.map((p) => p.name),
];
const OLD_ENUM_VALUES = [
"services",
"customers",
"agents",
"developers",
"invoices",
"transactions",
"discounts",
"admins",
"tickets",
"criticisms",
"contacts_us",
"advertisements",
"announcements",
"blogs",
"learnings",
"logs",
"settings",
"bank_accounts",
"payments",
"manage_sso_clients",
"support_plan",
"dmenu",
"dkala",
"dpage",
"dmail",
"reseller",
"workspace",
"view_all_workspaces",
"project",
"view_all_projects",
"task",
"task_phase",
];
export class RefactorPermissionsToCrudAndGroup1784500000000 implements MigrationInterface {
name = "RefactorPermissionsToCrudAndGroup1784500000000";
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`CREATE TYPE "public"."permission_group_enum" AS ENUM('services', 'customers', 'users', 'financial', 'content', 'support', 'other', 'products', 'representatives', 'task_manager')`,
);
await queryRunner.query(`ALTER TABLE "permission" ADD "group" "public"."permission_group_enum"`);
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE text USING "name"::text`);
await queryRunner.query(`DROP TYPE "public"."permission_name_enum"`);
for (const resource of CRUD_RESOURCES) {
const oldPerm = await queryRunner.query(`SELECT id FROM "permission" WHERE "name" = $1`, [resource.old]);
if (!oldPerm.length) continue;
const oldId = oldPerm[0].id as string;
const actions = ["create", "read", "update", "delete"] as const;
for (const action of actions) {
const newName = `${resource.old}_${action}`;
const title = resource.titles[action];
const inserted = await queryRunner.query(
`INSERT INTO "permission" ("id", "name", "title", "group", "createdAt", "updatedAt")
VALUES (uuid_generate_v4(), $1, $2, $3, NOW(), NOW())
RETURNING id`,
[newName, title, resource.group],
);
const newId = inserted[0].id as string;
await queryRunner.query(
`INSERT INTO "role_permission_relation" ("roleId", "permissionId")
SELECT "roleId", $1 FROM "role_permission_relation" WHERE "permissionId" = $2
ON CONFLICT ("roleId", "permissionId") DO NOTHING`,
[newId, oldId],
);
}
await queryRunner.query(`DELETE FROM "role_permission_relation" WHERE "permissionId" = $1`, [oldId]);
await queryRunner.query(`DELETE FROM "permission" WHERE "id" = $1`, [oldId]);
}
for (const perm of SINGLE_PERMISSIONS) {
await queryRunner.query(`UPDATE "permission" SET "group" = $1, "title" = COALESCE(NULLIF("title", ''), $2) WHERE "name" = $3`, [
perm.group,
perm.title,
perm.name,
]);
}
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "group" SET NOT NULL`);
const enumList = NEW_ENUM_VALUES.map((v) => `'${v}'`).join(", ");
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum" AS ENUM(${enumList})`);
await queryRunner.query(
`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum" USING "name"::"public"."permission_name_enum"`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE text USING "name"::text`);
await queryRunner.query(`DROP TYPE "public"."permission_name_enum"`);
for (const resource of CRUD_RESOURCES) {
const actions = ["create", "read", "update", "delete"];
const crudRows = await queryRunner.query(`SELECT id, name FROM "permission" WHERE "name" LIKE $1`, [`${resource.old}_%`]);
if (!crudRows.length) continue;
const inserted = await queryRunner.query(
`INSERT INTO "permission" ("id", "name", "title", "group", "createdAt", "updatedAt")
VALUES (uuid_generate_v4(), $1, $2, $3, NOW(), NOW())
RETURNING id`,
[resource.old, resource.old, resource.group],
);
const oldId = inserted[0].id as string;
for (const row of crudRows) {
await queryRunner.query(
`INSERT INTO "role_permission_relation" ("roleId", "permissionId")
SELECT "roleId", $1 FROM "role_permission_relation" WHERE "permissionId" = $2
ON CONFLICT ("roleId", "permissionId") DO NOTHING`,
[oldId, row.id],
);
await queryRunner.query(`DELETE FROM "role_permission_relation" WHERE "permissionId" = $1`, [row.id]);
await queryRunner.query(`DELETE FROM "permission" WHERE "id" = $1`, [row.id]);
}
}
const oldEnumList = OLD_ENUM_VALUES.map((v) => `'${v}'`).join(", ");
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum" AS ENUM(${oldEnumList})`);
await queryRunner.query(
`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum" USING "name"::"public"."permission_name_enum"`,
);
await queryRunner.query(`ALTER TABLE "permission" DROP COLUMN "group"`);
await queryRunner.query(`DROP TYPE "public"."permission_group_enum"`);
}
}