From 196e821ff262c7d91829d9633e6b23c58f0f9f0c Mon Sep 17 00:00:00 2001 From: Stevche Radevski Date: Fri, 1 Mar 2024 10:24:50 +0100 Subject: [PATCH] feat: Modify api key and sales channel link to use modules and add test (#6546) --- .../publishable-key-sales-channel.spec.ts | 105 ++++++++++++++++++ .../__tests__/api-key-module-service.spec.ts | 13 +++ packages/api-key/src/joiner-config.ts | 2 +- .../src/api-key/steps/create-api-keys.ts | 4 +- .../src/api-key/workflows/create-api-keys.ts | 2 +- .../link-modules/src/definitions/index.ts | 1 - .../publishable-api-key-sales-channel.ts | 16 ++- packages/link-modules/src/links.ts | 4 +- .../src/api-v2/admin/api-keys/[id]/route.ts | 4 +- .../medusa/src/api-v2/admin/api-keys/route.ts | 4 +- .../src/api-v2/admin/api-keys/validators.ts | 7 ++ packages/types/src/api-key/common/api-key.ts | 1 + 12 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts diff --git a/integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts b/integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts new file mode 100644 index 0000000000..7a48d8b329 --- /dev/null +++ b/integration-tests/modules/__tests__/link-modules/publishable-key-sales-channel.spec.ts @@ -0,0 +1,105 @@ +import { ModuleRegistrationName, Modules } from "@medusajs/modules-sdk" +import { + IApiKeyModuleService, + ISalesChannelModuleService, +} from "@medusajs/types" +import path from "path" +import { startBootstrapApp } from "../../../environment-helpers/bootstrap-app" +import { getContainer } from "../../../environment-helpers/use-container" +import { initDb, useDb } from "../../../environment-helpers/use-db" +import { remoteQueryObjectFromString } from "@medusajs/utils" + +jest.setTimeout(50000) + +const env = { MEDUSA_FF_MEDUSA_V2: true } + +describe("Publishable keys and sales channel link", () => { + let dbConnection + let appContainer + let shutdownServer + let apiKeyModule: IApiKeyModuleService + let scModuleService: ISalesChannelModuleService + let remoteQuery + let remoteLink + + beforeAll(async () => { + const cwd = path.resolve(path.join(__dirname, "..", "..")) + dbConnection = await initDb({ cwd, env } as any) + shutdownServer = await startBootstrapApp({ cwd, env }) + appContainer = getContainer() + apiKeyModule = appContainer.resolve(ModuleRegistrationName.API_KEY) + scModuleService = appContainer.resolve(ModuleRegistrationName.SALES_CHANNEL) + remoteQuery = appContainer.resolve("remoteQuery") + remoteLink = appContainer.resolve("remoteLink") + }) + + afterAll(async () => { + const db = useDb() + await db.shutdown() + await shutdownServer() + }) + + afterEach(async () => { + const db = useDb() + await db.teardown() + }) + + it("should query api key and sales channels link with remote query", async () => { + const salesChannel = await scModuleService.create({ + name: "Webshop", + }) + + const apiKeys = await apiKeyModule.create([ + { + title: "Api key", + type: "publishable", + created_by: "test", + }, + { + title: "Api key 2", + type: "publishable", + created_by: "test", + }, + ]) + + await remoteLink.create([ + { + [Modules.API_KEY]: { + publishable_key_id: apiKeys[0].id, + }, + [Modules.SALES_CHANNEL]: { + sales_channel_id: salesChannel.id, + }, + }, + { + [Modules.API_KEY]: { + publishable_key_id: apiKeys[1].id, + }, + [Modules.SALES_CHANNEL]: { + sales_channel_id: salesChannel.id, + }, + }, + ]) + + const queryObject = remoteQueryObjectFromString({ + entryPoint: "api_key", + variables: { + filters: { token: apiKeys[0].token }, + }, + fields: ["id", "sales_channels.id"], + }) + const keyLinks = await remoteQuery(queryObject) + + expect(keyLinks).toHaveLength(1) + expect(keyLinks).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + id: apiKeys[0].id, + sales_channels: expect.arrayContaining([ + expect.objectContaining({ id: salesChannel.id }), + ]), + }), + ]) + ) + }) +}) diff --git a/packages/api-key/integration-tests/__tests__/api-key-module-service.spec.ts b/packages/api-key/integration-tests/__tests__/api-key-module-service.spec.ts index d89a2d3783..ba888b1ad4 100644 --- a/packages/api-key/integration-tests/__tests__/api-key-module-service.spec.ts +++ b/packages/api-key/integration-tests/__tests__/api-key-module-service.spec.ts @@ -284,6 +284,19 @@ moduleIntegrationTestRunner({ expect(apiKeysInDatabase).toHaveLength(2) }) + it("should only return keys with matching token", async function () { + const created = await service.create([ + createPublishableKeyFixture, + createPublishableKeyFixture, + ]) + + const apiKeysInDatabase = await service.list({ + token: created[0].token, + }) + expect(apiKeysInDatabase).toHaveLength(1) + expect(apiKeysInDatabase[0].token).toEqual(created[0].token) + }) + it("should not return the token and salt for secret keys when listing", async function () { await service.create([createSecretKeyFixture]) diff --git a/packages/api-key/src/joiner-config.ts b/packages/api-key/src/joiner-config.ts index 559afda491..ca9c9f2fd6 100644 --- a/packages/api-key/src/joiner-config.ts +++ b/packages/api-key/src/joiner-config.ts @@ -22,7 +22,7 @@ export const joinerConfig: ModuleJoinerConfig = { linkableKeys: LinkableKeys, alias: [ { - name: ["api-key", "api-keys"], + name: ["api_key", "api_keys"], args: { entity: ApiKey.name }, }, ], diff --git a/packages/core-flows/src/api-key/steps/create-api-keys.ts b/packages/core-flows/src/api-key/steps/create-api-keys.ts index 8c75a965ff..ddf3aa57bd 100644 --- a/packages/core-flows/src/api-key/steps/create-api-keys.ts +++ b/packages/core-flows/src/api-key/steps/create-api-keys.ts @@ -3,7 +3,7 @@ import { CreateApiKeyDTO, IApiKeyModuleService } from "@medusajs/types" import { StepResponse, createStep } from "@medusajs/workflows-sdk" type CreateApiKeysStepInput = { - apiKeysData: CreateApiKeyDTO[] + api_keys: CreateApiKeyDTO[] } export const createApiKeysStepId = "create-api-keys" @@ -13,7 +13,7 @@ export const createApiKeysStep = createStep( const service = container.resolve( ModuleRegistrationName.API_KEY ) - const created = await service.create(data.apiKeysData) + const created = await service.create(data.api_keys) return new StepResponse( created, created.map((apiKey) => apiKey.id) diff --git a/packages/core-flows/src/api-key/workflows/create-api-keys.ts b/packages/core-flows/src/api-key/workflows/create-api-keys.ts index d01bc7bd20..02489e5ee3 100644 --- a/packages/core-flows/src/api-key/workflows/create-api-keys.ts +++ b/packages/core-flows/src/api-key/workflows/create-api-keys.ts @@ -2,7 +2,7 @@ import { ApiKeyDTO, CreateApiKeyDTO } from "@medusajs/types" import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk" import { createApiKeysStep } from "../steps" -type WorkflowInput = { apiKeysData: CreateApiKeyDTO[] } +type WorkflowInput = { api_keys: CreateApiKeyDTO[] } export const createApiKeysWorkflowId = "create-api-keys" export const createApiKeysWorkflow = createWorkflow( diff --git a/packages/link-modules/src/definitions/index.ts b/packages/link-modules/src/definitions/index.ts index 041a999960..aeb2f0dc1f 100644 --- a/packages/link-modules/src/definitions/index.ts +++ b/packages/link-modules/src/definitions/index.ts @@ -9,4 +9,3 @@ export * from "./product-shipping-profile" export * from "./product-variant-inventory-item" export * from "./product-variant-price-set" export * from "./publishable-api-key-sales-channel" - diff --git a/packages/link-modules/src/definitions/publishable-api-key-sales-channel.ts b/packages/link-modules/src/definitions/publishable-api-key-sales-channel.ts index a9fd53ab42..86a50db58a 100644 --- a/packages/link-modules/src/definitions/publishable-api-key-sales-channel.ts +++ b/packages/link-modules/src/definitions/publishable-api-key-sales-channel.ts @@ -1,5 +1,6 @@ import { ModuleJoinerConfig } from "@medusajs/types" import { LINKS } from "../links" +import { Modules } from "@medusajs/modules-sdk" export const PublishableApiKeySalesChannel: ModuleJoinerConfig = { serviceName: LINKS.PublishableApiKeySalesChannel, @@ -19,14 +20,14 @@ export const PublishableApiKeySalesChannel: ModuleJoinerConfig = { primaryKeys: ["id", "publishable_key_id", "sales_channel_id"], relationships: [ { - serviceName: "publishableApiKeyService", + serviceName: Modules.API_KEY, isInternalService: true, primaryKey: "id", foreignKey: "publishable_key_id", - alias: "publishable_key", + alias: "api_key", }, { - serviceName: "salesChannelService", + serviceName: Modules.SALES_CHANNEL, isInternalService: true, primaryKey: "id", foreignKey: "sales_channel_id", @@ -35,7 +36,7 @@ export const PublishableApiKeySalesChannel: ModuleJoinerConfig = { ], extends: [ { - serviceName: "publishableApiKeyService", + serviceName: Modules.API_KEY, fieldAlias: { sales_channels: "sales_channels_link.sales_channel", }, @@ -49,13 +50,16 @@ export const PublishableApiKeySalesChannel: ModuleJoinerConfig = { }, }, { - serviceName: "salesChannelService", + serviceName: Modules.SALES_CHANNEL, + fieldAlias: { + api_keys: "api_keys_link.api_key", + }, relationship: { serviceName: LINKS.PublishableApiKeySalesChannel, isInternalService: true, primaryKey: "sales_channel_id", foreignKey: "id", - alias: "publishable_keys_link", + alias: "api_keys_link", isList: true, }, }, diff --git a/packages/link-modules/src/links.ts b/packages/link-modules/src/links.ts index acf2efc8b4..5ea25bab21 100644 --- a/packages/link-modules/src/links.ts +++ b/packages/link-modules/src/links.ts @@ -41,8 +41,8 @@ export const LINKS = { "sales_channel_id" ), PublishableApiKeySalesChannel: composeLinkName( - "publishableApiKeyService", - "publishable_key_id", + Modules.API_KEY, + "api_key_id", Modules.SALES_CHANNEL, "sales_channel_id" ), diff --git a/packages/medusa/src/api-v2/admin/api-keys/[id]/route.ts b/packages/medusa/src/api-v2/admin/api-keys/[id]/route.ts index 46eb8644da..5e0cb25c9d 100644 --- a/packages/medusa/src/api-v2/admin/api-keys/[id]/route.ts +++ b/packages/medusa/src/api-v2/admin/api-keys/[id]/route.ts @@ -20,7 +20,7 @@ export const GET = async ( const variables = { id: req.params.id } const queryObject = remoteQueryObjectFromString({ - entryPoint: "api-key", + entryPoint: "api_key", variables, fields: defaultAdminApiKeyFields, }) @@ -66,7 +66,7 @@ export const DELETE = async ( res.status(200).json({ id, - object: "api-key", + object: "api_key", deleted: true, }) } diff --git a/packages/medusa/src/api-v2/admin/api-keys/route.ts b/packages/medusa/src/api-v2/admin/api-keys/route.ts index ed99b7349c..3e20b89033 100644 --- a/packages/medusa/src/api-v2/admin/api-keys/route.ts +++ b/packages/medusa/src/api-v2/admin/api-keys/route.ts @@ -15,7 +15,7 @@ export const GET = async ( const remoteQuery = req.scope.resolve("remoteQuery") const queryObject = remoteQueryObjectFromString({ - entryPoint: "api-key", + entryPoint: "api_key", variables: { filters: req.filterableFields, order: req.listConfig.order, @@ -47,7 +47,7 @@ export const POST = async ( ] const { result, errors } = await createApiKeysWorkflow(req.scope).run({ - input: { apiKeysData: input }, + input: { api_keys: input }, throwOnError: false, }) diff --git a/packages/medusa/src/api-v2/admin/api-keys/validators.ts b/packages/medusa/src/api-v2/admin/api-keys/validators.ts index a2381d3ddb..fd8d1a0d22 100644 --- a/packages/medusa/src/api-v2/admin/api-keys/validators.ts +++ b/packages/medusa/src/api-v2/admin/api-keys/validators.ts @@ -34,6 +34,13 @@ export class AdminGetApiKeysParams extends extendedFindParamsMixin({ @IsOptional() title?: string | string[] + /** + * Filter by token + */ + @IsString({ each: true }) + @IsOptional() + token?: string | string[] + /** * Filter by type */ diff --git a/packages/types/src/api-key/common/api-key.ts b/packages/types/src/api-key/common/api-key.ts index c11639d45a..00601586f2 100644 --- a/packages/types/src/api-key/common/api-key.ts +++ b/packages/types/src/api-key/common/api-key.ts @@ -17,6 +17,7 @@ export interface ApiKeyDTO { export interface FilterableApiKeyProps extends BaseFilterable { id?: string | string[] + token?: string | string[] title?: string | string[] type?: ApiKeyType }