0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor: remove tenant owner role (#5145)

This commit is contained in:
Gao Sun 2023-12-26 10:37:43 +08:00 committed by GitHub
parent e7c780dee4
commit 5f855790a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 16 deletions

View file

@ -280,9 +280,9 @@ export const seedTest = async (connection: DatabaseTransactionConnection, forLeg
);
await Promise.all([
assignOrganizationRole(userIds[0], adminTenantId, TenantRole.Owner),
assignOrganizationRole(userIds[0], defaultTenantId, TenantRole.Owner),
assignOrganizationRole(userIds[1], defaultTenantId, TenantRole.Owner),
assignOrganizationRole(userIds[0], adminTenantId, TenantRole.Admin),
assignOrganizationRole(userIds[0], defaultTenantId, TenantRole.Admin),
assignOrganizationRole(userIds[1], defaultTenantId, TenantRole.Admin),
]);
consoleLog.succeed('Assigned tenant organization membership and roles to the test users');
};

View file

@ -145,7 +145,7 @@ async function handleSubmitRegister(
await queries.organizations.relations.users.insert([organizationId, id]);
await queries.organizations.relations.rolesUsers.insert([
organizationId,
getTenantRole(TenantRole.Owner).id,
getTenantRole(TenantRole.Admin).id,
id,
]);
}

View file

@ -0,0 +1,94 @@
import { ConsoleLog } from '@logto/shared';
import { sql } from 'slonik';
import type { AlterationScript } from '../lib/types/alteration.js';
const consoleLog = new ConsoleLog();
/**
* This script update the following in the admin tenant:
*
* - Remove `owner` organization role.
* - Add `manage:tenant` scope to `admin` organization role.
* - Add `delete:data` scope to `member` organization role.
* - Update descriptions accordingly.
*/
const alteration: AlterationScript = {
up: async (pool) => {
// Update existing owner to admin.
await pool.query(sql`
update organization_role_user_relations
set organization_role_id = 'admin'
where tenant_id = 'admin'
and organization_role_id = 'owner';
`);
await pool.query(sql`
delete from organization_roles
where tenant_id = 'admin'
and name = 'owner';
`);
await pool.query(sql`
insert into organization_role_scope_relations (tenant_id, organization_role_id, organization_scope_id)
values
('admin', 'admin', 'manage-tenant'),
('admin', 'member', 'delete-data');
`);
await pool.query(sql`
update organization_roles
set description = 'Admin of the tenant, who has all permissions.'
where tenant_id = 'admin'
and name = 'admin';
`);
await pool.query(sql`
update organization_roles
set description = 'Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings.'
where tenant_id = 'admin'
and name = 'member';
`);
},
down: async (pool) => {
// Add back owner role
await pool.query(sql`
insert into organization_roles (tenant_id, id, name, description)
values
('admin', 'owner', 'owner', 'Owner of the tenant, who has all permissions.');
`);
// Insert scope relations
await pool.query(sql`
insert into organization_role_scope_relations (tenant_id, organization_role_id, organization_scope_id)
values
('admin', 'owner', 'read-data'),
('admin', 'owner', 'write-data'),
('admin', 'owner', 'delete-data'),
('admin', 'owner', 'invite-member'),
('admin', 'owner', 'remove-member'),
('admin', 'owner', 'update-member-role'),
('admin', 'owner', 'manage-tenant');
`);
// Remove added scopes
await pool.query(sql`
delete from organization_role_scope_relations
where tenant_id = 'admin'
and (organization_role_id = 'admin' and organization_scope_id = 'manage-tenant')
or (organization_role_id = 'member' and organization_scope_id = 'delete-data');
`);
// Update descriptions
await pool.query(sql`
update organization_roles
set description = 'Admin of the tenant, who has all permissions except managing the tenant settings.'
where tenant_id = 'admin'
and name = 'admin';
`);
await pool.query(sql`
update organization_roles
set description = 'Member of the tenant, who has limited permissions on reading and writing the tenant data.'
where tenant_id = 'admin'
and name = 'member';
`);
consoleLog.warn(
'Original owners are not restored since the owner role has more permissions than admin, and we cannot tell which users are the original owners.'
);
},
};
export default alteration;

View file

@ -110,20 +110,16 @@ const tenantScopeDescriptions: Readonly<Record<TenantScope, string>> = Object.fr
* Should sync JSDoc descriptions with {@link tenantRoleDescriptions}.
*/
export enum TenantRole {
/** Owner of the tenant, who has all permissions. */
Owner = 'owner',
/** Admin of the tenant, who has all permissions except managing the tenant settings. */
/** Admin of the tenant, who has all permissions. */
Admin = 'admin',
/** Member of the tenant, who has limited permissions on reading and writing the tenant data. */
/** Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings. */
Member = 'member',
}
const tenantRoleDescriptions: Readonly<Record<TenantRole, string>> = Object.freeze({
[TenantRole.Owner]: 'Owner of the tenant, who has all permissions.',
[TenantRole.Admin]:
'Admin of the tenant, who has all permissions except managing the tenant settings.',
[TenantRole.Admin]: 'Admin of the tenant, who has all permissions.',
[TenantRole.Member]:
'Member of the tenant, who has limited permissions on reading and writing the tenant data.',
'Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings.',
});
/**
@ -138,7 +134,7 @@ const tenantRoleDescriptions: Readonly<Record<TenantRole, string>> = Object.free
* tenantId: 'admin',
* id: 'member',
* name: 'member',
* description: 'Member of the tenant, who has limited permissions on reading and writing the tenant data.',
* description: 'Member of the tenant, who has permissions to operate the tenant data, but not the tenant settings.',
* });
* ```
*
@ -158,7 +154,11 @@ export const getTenantRole = (role: TenantRole): Readonly<OrganizationRole> =>
*/
export const tenantRoleScopes: Readonly<Record<TenantRole, Readonly<TenantScope[]>>> =
Object.freeze({
[TenantRole.Owner]: allTenantScopes,
[TenantRole.Admin]: allTenantScopes.filter((scope) => scope !== TenantScope.ManageTenant),
[TenantRole.Member]: [TenantScope.ReadData, TenantScope.WriteData, TenantScope.InviteMember],
[TenantRole.Admin]: allTenantScopes,
[TenantRole.Member]: [
TenantScope.ReadData,
TenantScope.WriteData,
TenantScope.DeleteData,
TenantScope.InviteMember,
],
});