From 3f41278a24e0321857953c5ba79a6010865b09c2 Mon Sep 17 00:00:00 2001 From: wangsijie Date: Thu, 24 Nov 2022 11:09:03 +0800 Subject: [PATCH] feat(schemas): add roles and permissions (#2494) --- packages/core/src/__mocks__/index.ts | 1 + packages/core/src/lib/user.ts | 7 ++- packages/core/src/routes/admin-user.test.ts | 6 +-- .../next-1669091623-roles-and-scopes.ts | 43 +++++++++++++++++++ packages/schemas/src/seeds/roles.ts | 1 + packages/schemas/tables/roles.sql | 12 ++++-- packages/schemas/tables/scopes.sql | 8 ++++ packages/schemas/tables/scopesroles.sql | 5 +++ 8 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 packages/schemas/alterations/next-1669091623-roles-and-scopes.ts create mode 100644 packages/schemas/tables/scopes.sql create mode 100644 packages/schemas/tables/scopesroles.sql diff --git a/packages/core/src/__mocks__/index.ts b/packages/core/src/__mocks__/index.ts index e9202fc6d..552ac3fc1 100644 --- a/packages/core/src/__mocks__/index.ts +++ b/packages/core/src/__mocks__/index.ts @@ -32,6 +32,7 @@ export const mockResource: Resource = { }; export const mockRole: Role = { + id: 'role_id', name: 'admin', description: 'admin', }; diff --git a/packages/core/src/lib/user.ts b/packages/core/src/lib/user.ts index 1e0a8bdb0..5aac5639b 100644 --- a/packages/core/src/lib/user.ts +++ b/packages/core/src/lib/user.ts @@ -13,6 +13,7 @@ import assertThat from '#src/utils/assert-that.js'; import { encryptPassword } from '#src/utils/password.js'; const userId = buildIdGenerator(12); +const roleId = buildIdGenerator(21); export const generateUserId = async (retries = 500) => pRetry( @@ -76,7 +77,11 @@ export const insertUser: typeof insertUserQuery = async ({ roleNames, ...rest }) if (missingRoleNames.length > 0) { await insertRoles( - missingRoleNames.map((name) => ({ name, description: 'User default role.' })) + missingRoleNames.map((name) => ({ + id: roleId(), + name, + description: 'User default role.', + })) ); } } diff --git a/packages/core/src/routes/admin-user.test.ts b/packages/core/src/routes/admin-user.test.ts index 8cfe016a3..9e203e21f 100644 --- a/packages/core/src/routes/admin-user.test.ts +++ b/packages/core/src/routes/admin-user.test.ts @@ -81,7 +81,7 @@ jest.mock('#src/lib/user.js', () => ({ jest.mock('#src/queries/roles.js', () => ({ findRolesByRoleNames: jest.fn( - async (): Promise => [{ name: 'admin', description: 'none' }] + async (): Promise => [{ id: 'role_id', name: 'admin', description: 'none' }] ), })); @@ -291,8 +291,8 @@ describe('adminUserRoutes', () => { const mockedFindRolesByRoleNames = findRolesByRoleNames as jest.Mock; mockedFindRolesByRoleNames.mockImplementationOnce( async (): Promise => [ - { name: 'worker', description: 'none' }, - { name: 'cleaner', description: 'none' }, + { id: 'role_id1', name: 'worker', description: 'none' }, + { id: 'role_id2', name: 'cleaner', description: 'none' }, ] ); await expect( diff --git a/packages/schemas/alterations/next-1669091623-roles-and-scopes.ts b/packages/schemas/alterations/next-1669091623-roles-and-scopes.ts new file mode 100644 index 000000000..ba5cebd78 --- /dev/null +++ b/packages/schemas/alterations/next-1669091623-roles-and-scopes.ts @@ -0,0 +1,43 @@ +import { sql } from 'slonik'; + +import type { AlterationScript } from '../lib/types/alteration.js'; + +const alteration: AlterationScript = { + up: async (pool) => { + await pool.query(sql` + -- scopes + create table scopes ( + id varchar(21) not null, + resource_id varchar(21) references resources (id) on update cascade on delete cascade, + name varchar(256) not null, + description text, + created_at timestamptz not null default(now()), + primary key (id) + ); + -- update table roles, add id and replace pkey + alter table roles add column id varchar(21); + update roles set id = name; + alter table roles alter column id set not null; + alter table roles drop constraint roles_pkey; + create unique index roles_pkey on roles using btree(id); + create unique index roles__name on roles (name); + -- roles_scopes + create table roles_scopes ( + role_id varchar(21) references roles (id) on update cascade on delete cascade, + scope_id varchar(21) references scopes (id) on update cascade on delete cascade, + constraint roles_permissison_pkey primary key (role_id, scope_id) + ); + `); + }, + down: async (pool) => { + await pool.query(sql` + drop table permissions; + alter index roles_pkey rename to roles_pkey_1; + create unique index roles_pkey on roles using btree(name) + drop index roles_pkey_1; + alter table roles drop column id; + `); + }, +}; + +export default alteration; diff --git a/packages/schemas/src/seeds/roles.ts b/packages/schemas/src/seeds/roles.ts index 27f4bd368..fc79930cd 100644 --- a/packages/schemas/src/seeds/roles.ts +++ b/packages/schemas/src/seeds/roles.ts @@ -5,6 +5,7 @@ import { UserRole } from '../types/index.js'; * Default Admin Role for Admin Console. */ export const defaultRole: Readonly = { + id: 'ac-admin-id', name: UserRole.Admin, description: 'Admin role for Logto.', }; diff --git a/packages/schemas/tables/roles.sql b/packages/schemas/tables/roles.sql index 520ddcc5b..f08ba85d1 100644 --- a/packages/schemas/tables/roles.sql +++ b/packages/schemas/tables/roles.sql @@ -1,5 +1,11 @@ create table roles ( - name varchar(128) not null, - description varchar(128) not null, - primary key (name) + id varchar(21) not null, + name varchar(128) not null, + description varchar(128) not null, + primary key (id) +); + +create unique index roles__name +on roles ( + name ); diff --git a/packages/schemas/tables/scopes.sql b/packages/schemas/tables/scopes.sql new file mode 100644 index 000000000..f4f1f406e --- /dev/null +++ b/packages/schemas/tables/scopes.sql @@ -0,0 +1,8 @@ +create table scopes ( + id varchar(21) not null, + resource_id varchar(21) references resources (id) on update cascade on delete cascade, + name varchar(256) not null, + description text, + created_at timestamptz not null default(now()), + primary key (id) +); diff --git a/packages/schemas/tables/scopesroles.sql b/packages/schemas/tables/scopesroles.sql new file mode 100644 index 000000000..b659da2f4 --- /dev/null +++ b/packages/schemas/tables/scopesroles.sql @@ -0,0 +1,5 @@ +create table roles_scopes ( + role_id varchar(21) references roles (id) on update cascade on delete cascade, + scope_id varchar(21) references scopes (id) on update cascade on delete cascade, + primary key (role_id, scope_id) +);