mirror of
https://github.com/logto-io/logto.git
synced 2025-03-31 22:51:25 -05:00
refactor: remove legacy resources (#5118)
* refactor: remove legacy api resources * refactor: remove legacy resources * refactor: add alteration script * refactor(cli): adjust legacy seed test data * refactor: update alteration timestamp * refactor: update organization role name
This commit is contained in:
parent
a52a3d1663
commit
3d5786d982
12 changed files with 309 additions and 157 deletions
|
@ -41,7 +41,13 @@ import { consoleLog, getPathInModule } from '../../../utils.js';
|
|||
import { appendAdminConsoleRedirectUris, seedTenantCloudServiceApplication } from './cloud.js';
|
||||
import { seedOidcConfigs } from './oidc-config.js';
|
||||
import { seedTenantOrganizations } from './tenant-organizations.js';
|
||||
import { assignScopesToRole, createTenant, seedAdminData } from './tenant.js';
|
||||
import {
|
||||
assignScopesToRole,
|
||||
createTenant,
|
||||
seedAdminData,
|
||||
seedLegacyManagementApiUserRole,
|
||||
seedManagementApiProxyApplications,
|
||||
} from './tenant.js';
|
||||
|
||||
const getExplicitOrder = (query: string) => {
|
||||
const matched = /\/\*\s*init_order\s*=\s*([\d.]+)\s*\*\//.exec(query)?.[1];
|
||||
|
@ -159,18 +165,9 @@ export const seedTables = async (
|
|||
.map(({ id }) => id)
|
||||
);
|
||||
|
||||
// Assign all cloud API scopes to role `admin:admin`
|
||||
await assignScopesToRole(
|
||||
connection,
|
||||
adminTenantId,
|
||||
adminAdminData.role.id,
|
||||
...cloudAdditionalScopes.map(({ id }) => id)
|
||||
);
|
||||
|
||||
// FIXME: @wangsijie should not create tenant Cloud Service application in the OSS DB.
|
||||
await seedTenantCloudServiceApplication(connection, defaultTenantId);
|
||||
|
||||
await Promise.all([
|
||||
seedLegacyManagementApiUserRole(connection),
|
||||
seedTenantCloudServiceApplication(connection, defaultTenantId),
|
||||
connection.query(
|
||||
insertInto(createDefaultAdminConsoleConfig(defaultTenantId), LogtoConfigs.table)
|
||||
),
|
||||
|
@ -183,10 +180,10 @@ export const seedTables = async (
|
|||
connection.query(insertInto(createAdminTenantSignInExperience(), SignInExperiences.table)),
|
||||
connection.query(insertInto(createDefaultAdminConsoleApplication(), Applications.table)),
|
||||
updateDatabaseTimestamp(connection, latestTimestamp),
|
||||
seedTenantOrganizations(connection),
|
||||
seedManagementApiProxyApplications(connection),
|
||||
]);
|
||||
|
||||
await seedTenantOrganizations(connection);
|
||||
|
||||
consoleLog.succeed('Seed data');
|
||||
};
|
||||
|
||||
|
@ -232,13 +229,18 @@ export const seedTest = async (connection: DatabaseTransactionConnection, forLeg
|
|||
insertInto({ id: userIds[1], username: 'test2', tenantId: adminTenantId }, Users.table)
|
||||
),
|
||||
]);
|
||||
|
||||
if (forLegacy) {
|
||||
const adminTenantRole = await getManagementRole(adminTenantId);
|
||||
await assignRoleToUser(userIds[0], adminTenantRole.id);
|
||||
}
|
||||
|
||||
consoleLog.succeed('Created test users');
|
||||
|
||||
const adminTenantRole = await getManagementRole(adminTenantId);
|
||||
// The only legacy user role for Management API. Used in OSS only.
|
||||
const defaultTenantRole = await getManagementRole(defaultTenantId);
|
||||
|
||||
await Promise.all([
|
||||
assignRoleToUser(userIds[0], adminTenantRole.id),
|
||||
assignRoleToUser(userIds[0], defaultTenantRole.id),
|
||||
assignRoleToUser(userIds[1], defaultTenantRole.id),
|
||||
]);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import {
|
||||
defaultTenantId,
|
||||
adminTenantId,
|
||||
Roles,
|
||||
Applications,
|
||||
OrganizationRoles,
|
||||
TenantRole,
|
||||
getTenantScope,
|
||||
|
@ -13,32 +11,17 @@ import {
|
|||
tenantRoleScopes,
|
||||
getTenantOrganizationCreateData,
|
||||
Organizations,
|
||||
Scopes,
|
||||
Resources,
|
||||
PredefinedScope,
|
||||
RolesScopes,
|
||||
ApplicationsRoles,
|
||||
} from '@logto/schemas';
|
||||
import { getMapiProxyM2mApp, getMapiProxyRole } from '@logto/schemas/lib/types/mapi-proxy.js';
|
||||
import { convertToIdentifiers, generateStandardId } from '@logto/shared';
|
||||
import type { DatabaseTransactionConnection } from 'slonik';
|
||||
import { sql } from 'slonik';
|
||||
|
||||
import { insertInto } from '../../../database.js';
|
||||
import { consoleLog } from '../../../utils.js';
|
||||
|
||||
/**
|
||||
* Seed initial data in the admin tenant for tenant organizations:
|
||||
* Seed initial data in the admin tenant for tenant organizations (`default` and `admin`):
|
||||
*
|
||||
* - Organization roles and scopes for tenant management.
|
||||
* - Create tenant organizations for the initial tenants (`default` and `admin`).
|
||||
*
|
||||
* The following data are used for Logto Cloud, we seed them anyway for the sake of simplicity:
|
||||
*
|
||||
* - Machine-to-machine roles for Management API proxy.
|
||||
* - Assign the corresponding Management API scopes to the machine-to-machine roles.
|
||||
* - Machine-to-machine applications for Management API proxy.
|
||||
* - Assign the roles to the corresponding applications.
|
||||
*/
|
||||
export const seedTenantOrganizations = async (connection: DatabaseTransactionConnection) => {
|
||||
const tenantIds = [defaultTenantId, adminTenantId];
|
||||
|
@ -83,73 +66,4 @@ export const seedTenantOrganizations = async (connection: DatabaseTransactionCon
|
|||
)
|
||||
);
|
||||
consoleLog.succeed('Created tenant organizations');
|
||||
|
||||
/* === Cloud-specific data === */
|
||||
// Init Management API proxy roles
|
||||
await connection.query(
|
||||
insertInto(
|
||||
tenantIds.map((tenantId) => getMapiProxyRole(tenantId)),
|
||||
Roles.table
|
||||
)
|
||||
);
|
||||
consoleLog.succeed('Created Management API proxy roles');
|
||||
|
||||
// Prepare Management API scopes
|
||||
const scopes = convertToIdentifiers(Scopes, true);
|
||||
const resources = convertToIdentifiers(Resources, true);
|
||||
/** Scopes with the name {@link PredefinedScope.All} in all Management API resources. */
|
||||
const allScopes = await connection.any<{ id: string; indicator: string }>(sql`
|
||||
select ${scopes.fields.id}, ${resources.fields.indicator}
|
||||
from ${resources.table}
|
||||
join ${scopes.table} on ${scopes.fields.resourceId} = ${resources.fields.id}
|
||||
where ${resources.fields.indicator} like 'https://%.logto.app/api'
|
||||
and ${scopes.fields.name} = ${PredefinedScope.All}
|
||||
and ${resources.fields.tenantId} = ${adminTenantId}
|
||||
`);
|
||||
const assertScopeId = (forTenantId: string) => {
|
||||
const scope = allScopes.find(
|
||||
(scope) => scope.indicator === `https://${forTenantId}.logto.app/api`
|
||||
);
|
||||
if (!scope) {
|
||||
throw new Error(`Cannot find Management API scope for tenant '${forTenantId}'.`);
|
||||
}
|
||||
return scope.id;
|
||||
};
|
||||
|
||||
// Assign Management API scopes to the proxy roles
|
||||
await connection.query(
|
||||
insertInto(
|
||||
tenantIds.map((tenantId) => ({
|
||||
tenantId: adminTenantId,
|
||||
id: generateStandardId(),
|
||||
roleId: getMapiProxyRole(tenantId).id,
|
||||
scopeId: assertScopeId(tenantId),
|
||||
})),
|
||||
RolesScopes.table
|
||||
)
|
||||
);
|
||||
consoleLog.succeed('Assigned Management API scopes to the proxy roles');
|
||||
|
||||
// Create machine-to-machine applications for Management API proxy
|
||||
await connection.query(
|
||||
insertInto(
|
||||
tenantIds.map((tenantId) => getMapiProxyM2mApp(tenantId)),
|
||||
Applications.table
|
||||
)
|
||||
);
|
||||
consoleLog.succeed('Created machine-to-machine applications for Management API proxy');
|
||||
|
||||
// Assign the proxy roles to the applications
|
||||
await connection.query(
|
||||
insertInto(
|
||||
tenantIds.map((tenantId) => ({
|
||||
tenantId: adminTenantId,
|
||||
id: generateStandardId(),
|
||||
applicationId: getMapiProxyM2mApp(tenantId).id,
|
||||
roleId: getMapiProxyRole(tenantId).id,
|
||||
})),
|
||||
ApplicationsRoles.table
|
||||
)
|
||||
);
|
||||
consoleLog.succeed('Assigned the proxy roles to the applications');
|
||||
};
|
||||
|
|
|
@ -1,13 +1,29 @@
|
|||
import { createTenantMetadata } from '@logto/core-kit';
|
||||
import type { AdminData, UpdateAdminData, CreateScope, CreateRolesScope } from '@logto/schemas';
|
||||
import {
|
||||
type AdminData,
|
||||
type UpdateAdminData,
|
||||
type CreateScope,
|
||||
type CreateRolesScope,
|
||||
defaultTenantId,
|
||||
adminTenantId,
|
||||
Applications,
|
||||
ApplicationsRoles,
|
||||
getMapiProxyM2mApp,
|
||||
getMapiProxyRole,
|
||||
defaultManagementApiAdminName,
|
||||
Roles,
|
||||
PredefinedScope,
|
||||
getManagementApiResourceIndicator,
|
||||
} from '@logto/schemas';
|
||||
import { generateStandardId } from '@logto/shared';
|
||||
import { assert } from '@silverhand/essentials';
|
||||
import type { CommonQueryMethods } from 'slonik';
|
||||
import type { CommonQueryMethods, DatabaseTransactionConnection } from 'slonik';
|
||||
import { sql } from 'slonik';
|
||||
import { raw } from 'slonik-sql-tag-raw';
|
||||
|
||||
import { insertInto } from '../../../database.js';
|
||||
import { getDatabaseName } from '../../../queries/database.js';
|
||||
import { consoleLog } from '../../../utils.js';
|
||||
|
||||
export const createTenant = async (pool: CommonQueryMethods, tenantId: string) => {
|
||||
const database = await getDatabaseName(pool, true);
|
||||
|
@ -102,3 +118,72 @@ export const assignScopesToRole = async (
|
|||
)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* For each initial tenant (`default` and `admin`), create a machine-to-machine application for
|
||||
* Management API proxy and assign the corresponding proxy role to it.
|
||||
*/
|
||||
export const seedManagementApiProxyApplications = async (
|
||||
connection: DatabaseTransactionConnection
|
||||
) => {
|
||||
const tenantIds = [defaultTenantId, adminTenantId];
|
||||
|
||||
// Create machine-to-machine applications for Management API proxy
|
||||
await connection.query(
|
||||
insertInto(
|
||||
tenantIds.map((tenantId) => getMapiProxyM2mApp(tenantId)),
|
||||
Applications.table
|
||||
)
|
||||
);
|
||||
consoleLog.succeed('Created machine-to-machine applications for Management API proxy');
|
||||
|
||||
// Assign the proxy roles to the applications
|
||||
await connection.query(
|
||||
insertInto(
|
||||
tenantIds.map((tenantId) => ({
|
||||
tenantId: adminTenantId,
|
||||
id: generateStandardId(),
|
||||
applicationId: getMapiProxyM2mApp(tenantId).id,
|
||||
roleId: getMapiProxyRole(tenantId).id,
|
||||
})),
|
||||
ApplicationsRoles.table
|
||||
)
|
||||
);
|
||||
consoleLog.succeed('Assigned the proxy roles to the applications');
|
||||
};
|
||||
|
||||
/**
|
||||
* Seed the legacy user role for accessing default Management API, and assign the `all` scope to
|
||||
* it. Used in OSS only.
|
||||
*/
|
||||
export const seedLegacyManagementApiUserRole = async (
|
||||
connection: DatabaseTransactionConnection
|
||||
) => {
|
||||
const roleId = generateStandardId();
|
||||
await connection.query(
|
||||
insertInto(
|
||||
{
|
||||
tenantId: adminTenantId,
|
||||
id: roleId,
|
||||
name: defaultManagementApiAdminName,
|
||||
description: 'Legacy user role for accessing default Management API. Used in OSS only.',
|
||||
},
|
||||
Roles.table
|
||||
)
|
||||
);
|
||||
await connection.query(sql`
|
||||
insert into roles_scopes (id, role_id, scope_id, tenant_id)
|
||||
values (
|
||||
${generateStandardId()},
|
||||
${roleId},
|
||||
(
|
||||
select scopes.id from scopes
|
||||
join resources on scopes.resource_id = resources.id
|
||||
where resources.indicator = ${getManagementApiResourceIndicator(defaultTenantId)}
|
||||
and scopes.name = ${PredefinedScope.All}
|
||||
and scopes.tenant_id = ${adminTenantId}
|
||||
),
|
||||
${adminTenantId}
|
||||
);
|
||||
`);
|
||||
};
|
||||
|
|
|
@ -94,7 +94,6 @@ function Providers() {
|
|||
isCloud && [
|
||||
...Object.values(TenantScope),
|
||||
cloudApi.scopes.CreateTenant,
|
||||
cloudApi.scopes.ManageTenant,
|
||||
cloudApi.scopes.ManageTenantSelf,
|
||||
]
|
||||
),
|
||||
|
|
|
@ -4,7 +4,6 @@ import type { User } from '@logto/schemas';
|
|||
import {
|
||||
AdminTenantRole,
|
||||
SignInMode,
|
||||
getManagementApiAdminName,
|
||||
defaultTenantId,
|
||||
adminTenantId,
|
||||
InteractionEvent,
|
||||
|
@ -13,6 +12,7 @@ import {
|
|||
getTenantOrganizationId,
|
||||
getTenantRole,
|
||||
TenantRole,
|
||||
defaultManagementApiAdminName,
|
||||
} from '@logto/schemas';
|
||||
import { generateStandardId } from '@logto/shared';
|
||||
import { conditional, conditionalArray, trySafe } from '@silverhand/essentials';
|
||||
|
@ -80,8 +80,7 @@ const getInitialUserRoles = (
|
|||
) =>
|
||||
conditionalArray<string>(
|
||||
isInAdminTenant && AdminTenantRole.User,
|
||||
isCreatingFirstAdminUser && getManagementApiAdminName(defaultTenantId),
|
||||
isCreatingFirstAdminUser && isCloud && getManagementApiAdminName(adminTenantId)
|
||||
isCreatingFirstAdminUser && !isCloud && defaultManagementApiAdminName // OSS uses the legacy Management API user role
|
||||
);
|
||||
|
||||
async function handleSubmitRegister(
|
||||
|
|
|
@ -3,21 +3,16 @@
|
|||
|
||||
import type { LogtoConfig } from '@logto/node';
|
||||
import {
|
||||
cloudApiIndicator,
|
||||
CloudScope,
|
||||
PredefinedScope,
|
||||
adminTenantId,
|
||||
defaultTenantId,
|
||||
getManagementApiResourceIndicator,
|
||||
getManagementApiAdminName,
|
||||
adminConsoleApplicationId,
|
||||
InteractionEvent,
|
||||
AdminTenantRole,
|
||||
type Role,
|
||||
type User,
|
||||
RoleType,
|
||||
} from '@logto/schemas';
|
||||
import { conditionalArray } from '@silverhand/essentials';
|
||||
|
||||
import { authedAdminTenantApi as api, adminTenantApi } from '#src/api/api.js';
|
||||
import type { InteractionPayload } from '#src/api/interaction.js';
|
||||
|
@ -106,20 +101,3 @@ export const createUserWithAllRolesAndSignInToClient = async () => {
|
|||
|
||||
return { id, client };
|
||||
};
|
||||
|
||||
export const createUserAndSignInToCloudClient = async (
|
||||
userRoleType: AdminTenantRole.User | AdminTenantRole.Admin
|
||||
) => {
|
||||
const [{ id }, { username, password }] = await createUserWithRoles(
|
||||
conditionalArray<string>(
|
||||
AdminTenantRole.User,
|
||||
userRoleType === AdminTenantRole.Admin && getManagementApiAdminName(adminTenantId)
|
||||
)
|
||||
);
|
||||
const client = await initClientAndSignIn(username, password, {
|
||||
resources: [cloudApiIndicator],
|
||||
scopes: Object.values(CloudScope),
|
||||
});
|
||||
|
||||
return { id, client };
|
||||
};
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
import { generateStandardId } from '@logto/shared/universal';
|
||||
import { sql } from 'slonik';
|
||||
|
||||
import type { AlterationScript } from '../lib/types/alteration.js';
|
||||
|
||||
const alteration: AlterationScript = {
|
||||
up: async (pool) => {
|
||||
// Unassign cloud scopes accidentally assigned to the admin Management API proxy
|
||||
await pool.query(sql`
|
||||
delete from roles_scopes
|
||||
using scopes
|
||||
where roles_scopes.tenant_id = 'admin'
|
||||
and roles_scopes.role_id = 'm-admin'
|
||||
and roles_scopes.scope_id = scopes.id
|
||||
and scopes.name in ('send:sms', 'send:email', 'create:affiliate', 'manage:affiliate');
|
||||
`);
|
||||
// Delete all legacy roles in the admin tenant
|
||||
await pool.query(sql`
|
||||
delete from roles
|
||||
where tenant_id = 'admin'
|
||||
and name like '%:admin'
|
||||
and name not like 'machine:mapi:%'
|
||||
and name != 'default:admin';
|
||||
`);
|
||||
// Update default role description
|
||||
await pool.query(sql`
|
||||
update roles
|
||||
set description = 'Legacy user role for accessing default Management API. Used in OSS only.'
|
||||
where tenant_id = 'admin'
|
||||
and name = 'default:admin';
|
||||
`);
|
||||
// Delete `manage:tenant` scope from the Cloud API resource
|
||||
await pool.query(sql`
|
||||
delete from scopes
|
||||
using resources
|
||||
where scopes.tenant_id = 'admin'
|
||||
and scopes.name = 'manage:tenant'
|
||||
and scopes.resource_id = resources.id
|
||||
and resources.indicator = 'https://cloud.logto.io/api';
|
||||
`);
|
||||
},
|
||||
down: async (pool) => {
|
||||
console.log('Add `manage:tenant` scope to the Cloud API resource');
|
||||
// Add `manage:tenant` scope to the Cloud API resource
|
||||
await pool.query(sql`
|
||||
insert into scopes (tenant_id, id, name, description, resource_id)
|
||||
values ('admin', 'manage:tenant', 'manage:tenant', 'Allow managing existing tenants, including create without limitation, update, and delete.', (
|
||||
select id from resources where tenant_id = 'admin' and indicator = 'https://cloud.logto.io/api'
|
||||
));
|
||||
`);
|
||||
console.log('Update default role description');
|
||||
// Update default role description
|
||||
await pool.query(sql`
|
||||
update roles
|
||||
set description = 'Admin tenant admin role for Logto tenant default.'
|
||||
where tenant_id = 'admin'
|
||||
and name = 'default:admin';
|
||||
`);
|
||||
console.log('Add legacy roles in the admin tenant');
|
||||
// Add legacy roles in the admin tenant
|
||||
const existingTenantIds = await pool.any<{ id: string }>(sql`
|
||||
select id from tenants where id != 'default';
|
||||
`);
|
||||
await pool.query(sql`
|
||||
insert into roles (tenant_id, id, name, description)
|
||||
values ${sql.join(
|
||||
existingTenantIds.map((tenant) => {
|
||||
return sql`
|
||||
(
|
||||
'admin',
|
||||
${`${tenant.id}:admin`},
|
||||
${`${tenant.id}:admin`},
|
||||
${`Admin tenant admin role for Logto tenant ${tenant.id}.`}
|
||||
)
|
||||
`;
|
||||
}),
|
||||
sql`, `
|
||||
)};
|
||||
`);
|
||||
console.log('Restore assigned Management API scopes to the legacy roles');
|
||||
// Restore assigned Management API scopes to the legacy roles
|
||||
await pool.query(sql`
|
||||
insert into roles_scopes (tenant_id, id, role_id, scope_id)
|
||||
values ${sql.join(
|
||||
existingTenantIds.map((tenant) => {
|
||||
return sql`
|
||||
(
|
||||
'admin',
|
||||
${`${tenant.id}:admin`},
|
||||
${`${tenant.id}:admin`},
|
||||
(
|
||||
select scopes.id from scopes
|
||||
join resources on scopes.resource_id = resources.id
|
||||
and resources.indicator = ${`https://${tenant.id}.logto.app/api`}
|
||||
where scopes.tenant_id = 'admin'
|
||||
and scopes.name = 'all'
|
||||
)
|
||||
)
|
||||
`;
|
||||
}),
|
||||
sql`, `
|
||||
)};
|
||||
`);
|
||||
console.log('Assign to legacy roles to users according to the tenant organization roles');
|
||||
// Assign to legacy roles to users according to the tenant organization roles
|
||||
const adminUsersOrganizations = await pool.any<{ userId: string; organizationId: string }>(sql`
|
||||
select user_id as "userId", organization_id as "organizationId"
|
||||
from organization_role_user_relations
|
||||
where tenant_id = 'admin'
|
||||
and organization_role_id = 'admin'
|
||||
and organization_id != 't-default'
|
||||
and organization_id like 't-%';
|
||||
`);
|
||||
await pool.query(sql`
|
||||
insert into users_roles (tenant_id, id, user_id, role_id)
|
||||
values ${sql.join(
|
||||
adminUsersOrganizations.map((relation) => {
|
||||
return sql`
|
||||
(
|
||||
'admin',
|
||||
${`${relation.userId}:${relation.organizationId.slice(2)}:admin`},
|
||||
${relation.userId},
|
||||
${`${relation.organizationId.slice(2)}:admin`}
|
||||
)
|
||||
`;
|
||||
}),
|
||||
sql`, `
|
||||
)};
|
||||
`);
|
||||
console.log(
|
||||
'Assign back cloud scopes to the admin Management API proxy and the legacy admin user'
|
||||
);
|
||||
// Assign back cloud scopes to the admin Management API proxy and the legacy admin user
|
||||
await pool.query(sql`
|
||||
insert into roles_scopes (tenant_id, id, role_id, scope_id)
|
||||
values ${sql.join(
|
||||
['send:sms', 'send:email', 'create:affiliate', 'manage:affiliate', 'manage:tenant'].map(
|
||||
(scope) => {
|
||||
return sql`
|
||||
(
|
||||
'admin',
|
||||
${generateStandardId()},
|
||||
'm-admin',
|
||||
(
|
||||
select id from scopes
|
||||
where tenant_id = 'admin'
|
||||
and name = ${scope}
|
||||
)
|
||||
),
|
||||
(
|
||||
'admin',
|
||||
${generateStandardId()},
|
||||
'admin:admin',
|
||||
(
|
||||
select id from scopes
|
||||
where tenant_id = 'admin'
|
||||
and name = ${scope}
|
||||
)
|
||||
)
|
||||
`;
|
||||
}
|
||||
),
|
||||
sql`, `
|
||||
)};
|
||||
`);
|
||||
},
|
||||
};
|
||||
|
||||
export default alteration;
|
|
@ -13,8 +13,6 @@ export const cloudApiIndicator = 'https://cloud.logto.io/api';
|
|||
export enum CloudScope {
|
||||
/** The user can create a user tenant. */
|
||||
CreateTenant = 'create:tenant',
|
||||
/** The user can perform arbitrary operations on any tenant. */
|
||||
ManageTenant = 'manage:tenant',
|
||||
/** The user can update or delete its own tenants. */
|
||||
ManageTenantSelf = 'manage:tenant:self',
|
||||
SendSms = 'send:sms',
|
||||
|
@ -55,10 +53,6 @@ export const createCloudApi = (): Readonly<[UpdateAdminData, ...CreateScope[]]>
|
|||
name: AdminTenantRole.User,
|
||||
},
|
||||
},
|
||||
buildScope(
|
||||
CloudScope.ManageTenant,
|
||||
'Allow managing existing tenants, including create without limitation, update, and delete.'
|
||||
),
|
||||
buildScope(
|
||||
CloudScope.SendEmail,
|
||||
'Allow sending emails. This scope is only available to M2M application.'
|
||||
|
|
|
@ -6,10 +6,19 @@ import {
|
|||
type CreateRole,
|
||||
type CreateScope,
|
||||
} from '../db-entries/index.js';
|
||||
import { PredefinedScope, InternalRole, AdminTenantRole } from '../types/index.js';
|
||||
import {
|
||||
PredefinedScope,
|
||||
InternalRole,
|
||||
AdminTenantRole,
|
||||
getMapiProxyRole,
|
||||
} from '../types/index.js';
|
||||
|
||||
import { adminTenantId, defaultTenantId } from './tenant.js';
|
||||
|
||||
/**
|
||||
* The Management API data for a tenant. Usually used for creating a new tenant in the admin
|
||||
* tenant.
|
||||
*/
|
||||
export type AdminData = {
|
||||
resource: CreateResource;
|
||||
scopes: CreateScope[];
|
||||
|
@ -51,6 +60,10 @@ export const defaultManagementApi = Object.freeze({
|
|||
resourceId: defaultResourceId,
|
||||
},
|
||||
],
|
||||
/**
|
||||
* An internal user role for Management API of the `default` tenant.
|
||||
* @deprecated This role will be removed soon.
|
||||
*/
|
||||
role: {
|
||||
tenantId: defaultTenantId,
|
||||
/** @deprecated You should not rely on this constant. Change to something else. */
|
||||
|
@ -73,11 +86,14 @@ export function getManagementApiResourceIndicator(tenantId: string, path = 'api'
|
|||
return `https://${tenantId}.logto.app/${path}`;
|
||||
}
|
||||
|
||||
export const getManagementApiAdminName = <TenantId extends string>(tenantId: TenantId) =>
|
||||
`${tenantId}:${AdminTenantRole.Admin}` as const;
|
||||
/**
|
||||
* The fixed Management API user role for `default` tenant in the admin tenant. It is used for
|
||||
* OSS only.
|
||||
*/
|
||||
export const defaultManagementApiAdminName = `${defaultTenantId}:admin` as const;
|
||||
|
||||
/** Create a set of admin data for Management API of the given tenant ID. */
|
||||
export const createAdminData = (tenantId: string): AdminData => {
|
||||
export const createAdminData = (tenantId: string) => {
|
||||
const resourceId = generateStandardId();
|
||||
|
||||
return Object.freeze({
|
||||
|
@ -96,6 +112,7 @@ export const createAdminData = (tenantId: string): AdminData => {
|
|||
resourceId,
|
||||
},
|
||||
],
|
||||
/** @deprecated This role will be removed soon. */
|
||||
role: {
|
||||
tenantId,
|
||||
id: generateStandardId(),
|
||||
|
@ -103,11 +120,11 @@ export const createAdminData = (tenantId: string): AdminData => {
|
|||
description: `Internal admin role for Logto tenant ${defaultTenantId}.`,
|
||||
type: RoleType.MachineToMachine,
|
||||
},
|
||||
});
|
||||
} satisfies AdminData);
|
||||
};
|
||||
|
||||
/** Create a set of admin data for Management API of the given tenant ID for `admin` tenant. */
|
||||
export const createAdminDataInAdminTenant = (tenantId: string): AdminData => {
|
||||
/** Create a set of admin data for Management API of the given tenant ID for the admin tenant. */
|
||||
export const createAdminDataInAdminTenant = (tenantId: string) => {
|
||||
const resourceId = generateStandardId();
|
||||
|
||||
return Object.freeze({
|
||||
|
@ -126,17 +143,12 @@ export const createAdminDataInAdminTenant = (tenantId: string): AdminData => {
|
|||
resourceId,
|
||||
},
|
||||
],
|
||||
role: {
|
||||
tenantId: adminTenantId,
|
||||
id: generateStandardId(),
|
||||
name: getManagementApiAdminName(tenantId),
|
||||
description: `Admin tenant admin role for Logto tenant ${tenantId}.`,
|
||||
type: RoleType.User,
|
||||
},
|
||||
});
|
||||
/** The machine-to-machine role for the Management API proxy of the given tenant ID. */
|
||||
role: getMapiProxyRole(tenantId),
|
||||
} satisfies AdminData);
|
||||
};
|
||||
|
||||
export const createMeApiInAdminTenant = (): AdminData => {
|
||||
export const createMeApiInAdminTenant = () => {
|
||||
const resourceId = generateStandardId();
|
||||
|
||||
return Object.freeze({
|
||||
|
@ -162,5 +174,5 @@ export const createMeApiInAdminTenant = (): AdminData => {
|
|||
description: 'Default role for admin tenant.',
|
||||
type: RoleType.User,
|
||||
},
|
||||
});
|
||||
} satisfies AdminData);
|
||||
};
|
||||
|
|
|
@ -24,3 +24,4 @@ export * from './organization.js';
|
|||
export * from './sso-connector.js';
|
||||
export * from './tenant.js';
|
||||
export * from './tenant-organization.js';
|
||||
export * from './mapi-proxy.js';
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* This module provides utilities to manage mapi proxy.
|
||||
*/
|
||||
|
||||
import { generateStandardSecret } from '@logto/shared';
|
||||
import { generateStandardSecret } from '@logto/shared/universal';
|
||||
|
||||
import {
|
||||
RoleType,
|
||||
|
@ -21,7 +21,7 @@ import {
|
|||
type CreateApplication,
|
||||
ApplicationType,
|
||||
} from '../db-entries/index.js';
|
||||
import { adminTenantId } from '../index.js';
|
||||
import { adminTenantId } from '../seeds/tenant.js';
|
||||
|
||||
/**
|
||||
* Given a tenant ID, return the role data for the mapi proxy.
|
||||
|
|
|
@ -54,7 +54,6 @@ export enum InternalRole {
|
|||
}
|
||||
|
||||
export enum AdminTenantRole {
|
||||
Admin = 'admin',
|
||||
/** Common user role in admin tenant. */
|
||||
User = 'user',
|
||||
/** The role for machine to machine applications that represent a user tenant and send requests to Logto Cloud. */
|
||||
|
|
Loading…
Add table
Reference in a new issue