diff --git a/packages/core/src/oidc/init.ts b/packages/core/src/oidc/init.ts index 0710eeb3a..ab6769d61 100644 --- a/packages/core/src/oidc/init.ts +++ b/packages/core/src/oidc/init.ts @@ -8,7 +8,6 @@ import { Provider, errors } from 'oidc-provider'; import postgresAdapter from '@/oidc/adapter'; import { findResourceByIndicator } from '@/queries/resource'; -import { findAllScopesWithResourceId } from '@/queries/scope'; import { findUserById } from '@/queries/user'; import { routes } from '@/routes/consts'; @@ -47,20 +46,18 @@ export default async function initOidc(app: Koa): Promise { // Disable the auto use of authorization_code granted resource feature // https://github.com/panva/node-oidc-provider/blob/main/docs/README.md#usegrantedresource useGrantedResource: () => false, - getResourceServerInfo: async (ctx, indicator) => { + getResourceServerInfo: async (_, indicator) => { const resourceServer = await findResourceByIndicator(indicator); if (!resourceServer) { throw new errors.InvalidTarget(); } - const { id, accessTokenTtl: accessTokenTTL } = resourceServer; - const scopes = await findAllScopesWithResourceId(id); - const scope = scopes.map(({ name }) => name).join(' '); + const { accessTokenTtl: accessTokenTTL } = resourceServer; return { accessTokenFormat: 'jwt', - scope, + scope: '', accessTokenTTL, }; }, diff --git a/packages/core/src/queries/scope.test.ts b/packages/core/src/queries/scope.test.ts deleted file mode 100644 index 94439f7ff..000000000 --- a/packages/core/src/queries/scope.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { ResourceScopes } from '@logto/schemas'; -import { createMockPool, createMockQueryResult, sql } from 'slonik'; - -import { convertToIdentifiers, convertToPrimitiveOrSql } from '@/database/utils'; -import { DeletionError } from '@/errors/SlonikError'; -import { mockScope } from '@/utils/mock'; -import { expectSqlAssert, QueryType } from '@/utils/test-utils'; - -import { findAllScopesWithResourceId, insertScope, deleteScopeById } from './scope'; - -const mockQuery: jest.MockedFunction = jest.fn(); - -jest.mock('@/database/pool', () => - createMockPool({ - query: async (sql, values) => { - return mockQuery(sql, values); - }, - }) -); - -describe('scope query', () => { - const { table, fields } = convertToIdentifiers(ResourceScopes); - - it('findAllScopesWithResourceId', async () => { - const expectSql = sql` - select ${sql.join(Object.values(fields), sql`, `)} - from ${table} - where ${fields.resourceId}=$1 - `; - - mockQuery.mockImplementationOnce(async (sql, values) => { - expectSqlAssert(sql, expectSql.sql); - expect(values).toEqual([mockScope.resourceId]); - - return createMockQueryResult([mockScope]); - }); - - await expect(findAllScopesWithResourceId(mockScope.resourceId)).resolves.toEqual([mockScope]); - }); - - it('insertScope', async () => { - const expectSql = sql` - insert into ${table} (${sql.join(Object.values(fields), sql`, `)}) - values (${sql.join( - Object.values(fields).map((_, index) => `$${index + 1}`), - sql`, ` - )}) - returning * - `; - - mockQuery.mockImplementationOnce(async (sql, values) => { - expectSqlAssert(sql, expectSql.sql); - - expect(values).toEqual( - ResourceScopes.fieldKeys.map((k) => convertToPrimitiveOrSql(k, mockScope[k])) - ); - - return createMockQueryResult([mockScope]); - }); - - await expect(insertScope(mockScope)).resolves.toEqual(mockScope); - }); - - it('deleteScopeById', async () => { - const id = 'foo'; - const expectSql = sql` - delete from ${table} - where ${fields.id}=$1 - `; - - mockQuery.mockImplementationOnce(async (sql, values) => { - expectSqlAssert(sql, expectSql.sql); - expect(values).toEqual([id]); - - return createMockQueryResult([mockScope]); - }); - - await deleteScopeById(id); - }); - - it('deleteScopeById throw error if return row count is 0', async () => { - const id = 'foo'; - const expectSql = sql` - delete from ${table} - where ${fields.id}=$1 - `; - - mockQuery.mockImplementationOnce(async (sql, values) => { - expectSqlAssert(sql, expectSql.sql); - expect(values).toEqual([id]); - - return createMockQueryResult([]); - }); - - await expect(deleteScopeById(id)).rejects.toMatchError( - new DeletionError(ResourceScopes.table, id) - ); - }); -}); diff --git a/packages/core/src/queries/scope.ts b/packages/core/src/queries/scope.ts deleted file mode 100644 index fe90ccfe8..000000000 --- a/packages/core/src/queries/scope.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ResourceScope, CreateResourceScope, ResourceScopes } from '@logto/schemas'; -import { sql } from 'slonik'; - -import { buildInsertInto } from '@/database/insert-into'; -import pool from '@/database/pool'; -import { convertToIdentifiers } from '@/database/utils'; -import { DeletionError } from '@/errors/SlonikError'; - -const { table, fields } = convertToIdentifiers(ResourceScopes); - -export const findAllScopesWithResourceId = async (resourceId: string) => - pool.any(sql` - select ${sql.join(Object.values(fields), sql`, `)} - from ${table} - where ${fields.resourceId}=${resourceId} - `); - -export const insertScope = buildInsertInto( - pool, - ResourceScopes, - { - returning: true, - } -); - -export const deleteScopeById = async (id: string) => { - const { rowCount } = await pool.query(sql` - delete from ${table} - where ${fields.id}=${id} - `); - - if (rowCount < 1) { - throw new DeletionError(ResourceScopes.table, id); - } -}; diff --git a/packages/core/src/routes/resource.test.ts b/packages/core/src/routes/resource.test.ts index 0a6ddc911..d872af63e 100644 --- a/packages/core/src/routes/resource.test.ts +++ b/packages/core/src/routes/resource.test.ts @@ -1,6 +1,6 @@ import { Resource, CreateResource } from '@logto/schemas'; -import { mockResource, mockScope } from '@/utils/mock'; +import { mockResource } from '@/utils/mock'; import { createRequester } from '@/utils/test-utils'; import resourceRoutes from './resource'; @@ -24,10 +24,6 @@ jest.mock('@/queries/resource', () => ({ deleteResourceById: jest.fn(), })); -jest.mock('@/queries/scope', () => ({ - findAllScopesWithResourceId: jest.fn(async () => [mockScope]), -})); - jest.mock('@/utils/id', () => ({ // eslint-disable-next-line unicorn/consistent-function-scoping buildIdGenerator: jest.fn(() => () => 'randomId'), @@ -83,7 +79,6 @@ describe('resource routes', () => { expect(response.status).toEqual(200); expect(response.body).toEqual({ ...mockResource, - scopes: [mockScope], }); }); @@ -102,7 +97,6 @@ describe('resource routes', () => { name, indicator, accessTokenTtl, - scopes: [mockScope], }); }); diff --git a/packages/core/src/routes/resource.ts b/packages/core/src/routes/resource.ts index 3d6c84d33..662136912 100644 --- a/packages/core/src/routes/resource.ts +++ b/packages/core/src/routes/resource.ts @@ -11,7 +11,6 @@ import { updateResourceById, deleteResourceById, } from '@/queries/resource'; -import { findAllScopesWithResourceId } from '@/queries/scope'; import { buildIdGenerator } from '@/utils/id'; import { AuthedRouter } from './types'; @@ -60,12 +59,8 @@ export default function resourceRoutes(router: T) { params: { id }, } = ctx.guard; - const [resource, scopes] = await Promise.all([ - findResourceById(id), - findAllScopesWithResourceId(id), - ]); - - ctx.body = { ...resource, scopes }; + const resource = await findResourceById(id); + ctx.body = resource; return next(); } @@ -83,12 +78,8 @@ export default function resourceRoutes(router: T) { body, } = ctx.guard; - const [scopes, resource] = await Promise.all([ - findAllScopesWithResourceId(id), - updateResourceById(id, body), - ]); - - ctx.body = { ...resource, scopes }; + const resource = await updateResourceById(id, body); + ctx.body = resource; return next(); } diff --git a/packages/core/src/utils/mock.ts b/packages/core/src/utils/mock.ts index bcc7b1bc9..3e989f44d 100644 --- a/packages/core/src/utils/mock.ts +++ b/packages/core/src/utils/mock.ts @@ -5,7 +5,6 @@ import { Application, ApplicationType, Resource, - ResourceScope, Role, Setting, SignInExperience, @@ -141,13 +140,6 @@ export const mockResource: Resource = { accessTokenTtl: 3600, }; -export const mockScope: ResourceScope = { - id: 'foo', - name: 'read:user', - description: 'read:user', - resourceId: 'logto_api', -}; - export const mockRole: Role = { name: 'admin', description: 'admin', diff --git a/packages/schemas/src/db-entries/index.ts b/packages/schemas/src/db-entries/index.ts index ad00fdbad..6ea2d5cda 100644 --- a/packages/schemas/src/db-entries/index.ts +++ b/packages/schemas/src/db-entries/index.ts @@ -5,7 +5,6 @@ export * from './application'; export * from './connector'; export * from './oidc-model-instance'; export * from './passcode'; -export * from './resource-scope'; export * from './resource'; export * from './role'; export * from './setting'; diff --git a/packages/schemas/src/db-entries/resource-scope.ts b/packages/schemas/src/db-entries/resource-scope.ts deleted file mode 100644 index 8ac901f4f..000000000 --- a/packages/schemas/src/db-entries/resource-scope.ts +++ /dev/null @@ -1,39 +0,0 @@ -// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. - -import { z } from 'zod'; - -import { GeneratedSchema, Guard } from '../foundations'; - -export type CreateResourceScope = { - id: string; - name: string; - description: string; - resourceId: string; -}; - -export type ResourceScope = { - id: string; - name: string; - description: string; - resourceId: string; -}; - -const createGuard: Guard = z.object({ - id: z.string(), - name: z.string(), - description: z.string(), - resourceId: z.string(), -}); - -export const ResourceScopes: GeneratedSchema = Object.freeze({ - table: 'resource_scopes', - tableSingular: 'resource_scope', - fields: { - id: 'id', - name: 'name', - description: 'description', - resourceId: 'resource_id', - }, - fieldKeys: ['id', 'name', 'description', 'resourceId'], - createGuard, -}); diff --git a/packages/schemas/tables/resource_scopes.sql b/packages/schemas/tables/resource_scopes.sql deleted file mode 100644 index f04104c3d..000000000 --- a/packages/schemas/tables/resource_scopes.sql +++ /dev/null @@ -1,17 +0,0 @@ -create table resource_scopes ( - id varchar(24) not null, - name varchar(64) not null, - description text not null, - resource_id varchar(24) not null, - primary key (id), - constraint fk__resource_scopes__resource_id - foreign key (resource_id) - references resources(id) - on delete cascade -); - -create unique index resource_scopes__resource_id_name -on resource_scopes ( - resource_id, - name -); \ No newline at end of file