0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

chore(core,schemas): remove feature guard of organization api resource (#5743)

This commit is contained in:
wangsijie 2024-05-13 14:26:34 +08:00 committed by GitHub
parent 6fe6f87bc3
commit e388c66a2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 29 additions and 104 deletions

View file

@ -27,12 +27,6 @@ export const getExtraTokenClaimsForOrganizationApiResource = async (
ctx: KoaContextWithOIDC,
token: unknown
): Promise<UnknownObject | undefined> => {
const { isDevFeaturesEnabled } = EnvSet.values;
if (!isDevFeaturesEnabled) {
return;
}
const organizationId = ctx.oidc.params?.organization_id;
const resource = ctx.oidc.params?.resource;

View file

@ -35,7 +35,7 @@ import dpopValidate from 'oidc-provider/lib/helpers/validate_dpop.js';
import validatePresence from 'oidc-provider/lib/helpers/validate_presence.js';
import instance from 'oidc-provider/lib/helpers/weak_cache.js';
import { EnvSet } from '#src/env-set/index.js';
import { type EnvSet } from '#src/env-set/index.js';
import type Queries from '#src/tenants/Queries.js';
import assertThat from '#src/utils/assert-that.js';
@ -140,15 +140,11 @@ export const buildHandler: (
// The value type is `unknown`, which will swallow other type inferences. So we have to cast it
// to `Boolean` first.
const organizationId = cond(Boolean(params.organization_id) && String(params.organization_id));
if (organizationId) {
// Validate if the refresh token has the required scope from RFC 0001.
if (!refreshToken.scopes.has(UserScope.Organizations)) {
throw new InsufficientScope('refresh token missing required scope', UserScope.Organizations);
}
// Does not allow requesting resource token when requesting organization token (yet).
if (!EnvSet.values.isDevFeaturesEnabled && params.resource) {
throw new InvalidRequest('resource is not allowed when requesting organization token');
}
if (
organizationId && // Validate if the refresh token has the required scope from RFC 0001.
!refreshToken.scopes.has(UserScope.Organizations)
) {
throw new InsufficientScope('refresh token missing required scope', UserScope.Organizations);
}
/* === End RFC 0001 === */

View file

@ -3,7 +3,7 @@ import { type Resource } from '@logto/schemas';
import { trySafe, type Nullable } from '@silverhand/essentials';
import { type ResourceServer } from 'oidc-provider';
import { EnvSet } from '#src/env-set/index.js';
import { type EnvSet } from '#src/env-set/index.js';
import type Libraries from '#src/tenants/Libraries.js';
import type Queries from '#src/tenants/Queries.js';
@ -164,10 +164,8 @@ export const filterResourceScopesForTheThirdPartyApplication = async (
const userConsentResource = userConsentResources.find(
({ resource }) => resource.indicator === indicator
);
const userConsentOrganizationResources = EnvSet.values.isDevFeaturesEnabled
? includeOrganizationResourceScopes
? await getApplicationUserConsentOrganizationResourceScopes(applicationId)
: []
const userConsentOrganizationResources = includeOrganizationResourceScopes
? await getApplicationUserConsentOrganizationResourceScopes(applicationId)
: [];
const userConsentOrganizationResource = userConsentOrganizationResources.find(
({ resource }) => resource.indicator === indicator

View file

@ -5,7 +5,6 @@ import {
} from '@logto/schemas';
import { object, string, nativeEnum } from 'zod';
import { EnvSet } from '#src/env-set/index.js';
import koaGuard from '#src/middleware/koa-guard.js';
import type { ManagementApiRouter, RouterInitArgs } from '../types.js';
@ -53,15 +52,11 @@ export default function applicationUserConsentScopeRoutes<T extends ManagementAp
body,
} = ctx.guard;
// TODO @wangsijie: Remove this when feature is enabled in production
const { organizationResourceScopes, ...rest } = body;
const theBody = EnvSet.values.isDevFeaturesEnabled ? body : rest;
await validateThirdPartyApplicationById(applicationId);
await validateApplicationUserConsentScopes(theBody, tenantId);
await validateApplicationUserConsentScopes(body, tenantId);
await assignApplicationUserConsentScopes(applicationId, theBody);
await assignApplicationUserConsentScopes(applicationId, body);
ctx.status = 201;
@ -75,9 +70,7 @@ export default function applicationUserConsentScopeRoutes<T extends ManagementAp
params: object({
applicationId: string(),
}),
response: EnvSet.values.isDevFeaturesEnabled
? applicationUserConsentScopesResponseGuard
: applicationUserConsentScopesResponseGuard.omit({ organizationResourceScopes: true }),
response: applicationUserConsentScopesResponseGuard,
status: [200, 404],
}),
async (ctx, next) => {
@ -94,18 +87,12 @@ export default function applicationUserConsentScopeRoutes<T extends ManagementAp
getApplicationUserConsentScopes(applicationId),
]);
ctx.body = EnvSet.values.isDevFeaturesEnabled
? {
organizationScopes,
resourceScopes,
organizationResourceScopes,
userScopes,
}
: {
organizationScopes,
resourceScopes,
userScopes,
};
ctx.body = {
organizationScopes,
resourceScopes,
organizationResourceScopes,
userScopes,
};
return next();
}

View file

@ -13,7 +13,6 @@ import { type IRouterParamContext } from 'koa-router';
import { errors } from 'oidc-provider';
import { z } from 'zod';
import { EnvSet } from '#src/env-set/index.js';
import { consent, getMissingScopes } from '#src/libraries/session.js';
import koaGuard from '#src/middleware/koa-guard.js';
import type TenantContext from '#src/tenants/TenantContext.js';
@ -90,12 +89,13 @@ export default function consentRoutes<T extends IRouterParamContext>(
// Find the organizations granted by the user
// The user may send consent request multiple times, so we need to find the organizations again
const [, organizations] = EnvSet.values.isDevFeaturesEnabled
? await queries.applications.userConsentOrganizations.getEntities(Organizations, {
applicationId,
userId,
})
: [0, []];
const [, organizations] = await queries.applications.userConsentOrganizations.getEntities(
Organizations,
{
applicationId,
userId,
}
);
// The missingResourceScopes from the prompt details are from `getResourceServerInfo`,
// which contains resource scopes and organization resource scopes.
@ -111,10 +111,6 @@ export default function consentRoutes<T extends IRouterParamContext>(
const organizationsWithMissingResourceScopes = await Promise.all(
organizations.map(async ({ name, id }) => {
if (!EnvSet.values.isDevFeaturesEnabled) {
return { name, id };
}
const missingResourceScopes = await filterAndParseMissingResourceScopes({
resourceScopes: allMissingResourceScopes,
queries,
@ -136,10 +132,6 @@ export default function consentRoutes<T extends IRouterParamContext>(
const resourceScopesToGrant: Record<string, string[]> = Object.fromEntries(
organizationsWithMissingResourceScopes.reduce<Array<[string, string[]]>>(
(entries, { missingResourceScopes }) => {
if (!missingResourceScopes) {
return entries;
}
const organizationEntries: Array<[string, string[]]> = missingResourceScopes.map(
({ resource, scopes }) => [resource.indicator, scopes.map(({ name }) => name)]
);
@ -261,10 +253,6 @@ export default function consentRoutes<T extends IRouterParamContext>(
const organizationsWithMissingResourceScopes = await Promise.all(
organizations.map(async ({ name, id }) => {
if (!EnvSet.values.isDevFeaturesEnabled) {
return { name, id };
}
const missingResourceScopes = await filterAndParseMissingResourceScopes({
resourceScopes: allMissingResourceScopes,
queries,

View file

@ -2,7 +2,6 @@ import { ReservedResource } from '@logto/core-kit';
import { type MissingResourceScopes, type Scope, missingResourceScopesGuard } from '@logto/schemas';
import { errors } from 'oidc-provider';
import { EnvSet } from '#src/env-set/index.js';
import {
filterResourceScopesForTheThirdPartyApplication,
findResourceScopes,
@ -108,10 +107,6 @@ export const filterAndParseMissingResourceScopes = async ({
await Promise.all(
Object.entries(resourceScopes).map(
async ([resourceIndicator, missingScopes]): Promise<[string, string[]]> => {
if (!EnvSet.values.isDevFeaturesEnabled) {
return [resourceIndicator, missingScopes];
}
// Fetch the list of scopes, `findFromOrganizations` is set to false,
// so it will only search the user resource scopes.
const scopes = await findResourceScopes({

View file

@ -2,12 +2,10 @@ import {
type CreateOrganizationRole,
OrganizationRoles,
organizationRoleWithScopesGuard,
organizationRoleWithScopesGuardDeprecated,
} from '@logto/schemas';
import { generateStandardId } from '@logto/shared';
import { z } from 'zod';
import { EnvSet } from '#src/env-set/index.js';
import koaGuard from '#src/middleware/koa-guard.js';
import koaPagination from '#src/middleware/koa-pagination.js';
import koaQuotaGuard from '#src/middleware/koa-quota-guard.js';
@ -45,10 +43,7 @@ export default function organizationRoleRoutes<T extends ManagementApiRouter>(
koaPagination(),
koaGuard({
query: z.object({ q: z.string().optional() }),
// TODO @wangsijie - Remove this once the feature is ready
response: EnvSet.values.isDevFeaturesEnabled
? organizationRoleWithScopesGuard.array()
: organizationRoleWithScopesGuardDeprecated.array(),
response: organizationRoleWithScopesGuard.array(),
status: [200],
}),
async (ctx, next) => {
@ -70,19 +65,6 @@ export default function organizationRoleRoutes<T extends ManagementApiRouter>(
resourceScopeIds: string[];
};
// TODO @wangsijie - Remove this once the feature is ready
const originalCreateCard: z.ZodType<
Omit<CreateOrganizationRolePayload, 'resourceScopeIds'> & { resourceScopeIds?: string[] },
z.ZodTypeDef,
unknown
> = OrganizationRoles.createGuard
.omit({
id: true,
})
.extend({
organizationScopeIds: z.array(z.string()).default([]),
});
const createGuard: z.ZodType<CreateOrganizationRolePayload, z.ZodTypeDef, unknown> =
OrganizationRoles.createGuard
.omit({
@ -96,7 +78,7 @@ export default function organizationRoleRoutes<T extends ManagementApiRouter>(
router.post(
'/',
koaGuard({
body: EnvSet.values.isDevFeaturesEnabled ? createGuard : originalCreateCard,
body: createGuard,
response: OrganizationRoles.guard,
status: [201, 422],
}),
@ -110,8 +92,7 @@ export default function organizationRoleRoutes<T extends ManagementApiRouter>(
);
}
// TODO @wangsijie - Remove this once the feature is ready
if (EnvSet.values.isDevFeaturesEnabled && resourceScopeIds && resourceScopeIds.length > 0) {
if (resourceScopeIds.length > 0) {
await rolesResourceScopes.insert(
...resourceScopeIds.map<[string, string]>((id) => [role.id, id])
);
@ -124,9 +105,7 @@ export default function organizationRoleRoutes<T extends ManagementApiRouter>(
);
router.addRelationRoutes(rolesScopes, 'scopes');
if (EnvSet.values.isDevFeaturesEnabled) {
router.addRelationRoutes(rolesResourceScopes, 'resource-scopes');
}
router.addRelationRoutes(rolesResourceScopes, 'resource-scopes');
originalRouter.use(router.routes());
}

View file

@ -37,18 +37,6 @@ export type OrganizationRoleWithScopes = OrganizationRole & {
resourceScopes: ResourceScopeEntity[];
};
// TODO @wangsijie - Remove this once the feature is ready
export const organizationRoleWithScopesGuardDeprecated: ToZodObject<
Omit<OrganizationRoleWithScopes, 'resourceScopes'>
> = OrganizationRoles.guard.extend({
scopes: z
.object({
id: z.string(),
name: z.string(),
})
.array(),
});
export const organizationRoleWithScopesGuard: ToZodObject<OrganizationRoleWithScopes> =
OrganizationRoles.guard.extend({
scopes: z