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:
parent
e7c780dee4
commit
5f855790a4
4 changed files with 110 additions and 16 deletions
|
@ -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');
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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,
|
||||
],
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue