refactor permissions
This commit is contained in:
@@ -0,0 +1,300 @@
|
||||
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"`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user