From 03fc9e18e98c5d2ad7753ecbb06797f65521b792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frane=20Poli=C4=87?= <16856471+fPolic@users.noreply.github.com> Date: Wed, 16 Nov 2022 05:35:22 +0100 Subject: [PATCH] feat(medusa, medusa-js, medusa-react): PublishableApiKey "update" endpoint & add "title" property (#2609) **What** - update PK endpoint - medusa-js/react implementation - add a title property to the entity - update the migration file - pass a title on create - list PKs by title - update the client libs with new param signatures - change id prefix to: "pk_" --- .../__tests__/admin/publishable-api-key.js | 77 ++++++++++++++- .../api/__tests__/admin/sales-channels.js | 1 - .../factories/simple-price-list-factory.ts | 1 - .../simple-publishable-api-key-factory.ts | 8 +- .../resources/admin/publishable-api-keys.ts | 13 ++- packages/medusa-react/mocks/handlers/admin.ts | 12 +++ .../admin/publishable-api-keys/mutations.ts | 37 ++++++- .../publishable-api-keys/mutations.test.ts | 36 ++++++- .../create-publishable-api-key.ts | 19 +++- .../admin/publishable-api-keys/index.ts | 16 ++- .../list-publishable-api-keys.ts | 8 +- .../update-publishable-api-key.ts | 97 +++++++++++++++++++ .../1667815005070-publishable_api_key.ts | 2 +- .../medusa/src/models/publishable-api-key.ts | 7 +- .../services/__tests__/publishable-api-key.ts | 23 ++++- .../src/services/publishable-api-key.ts | 56 +++++++++-- .../medusa/src/types/publishable-api-key.ts | 7 ++ 17 files changed, 390 insertions(+), 30 deletions(-) create mode 100644 packages/medusa/src/api/routes/admin/publishable-api-keys/update-publishable-api-key.ts create mode 100644 packages/medusa/src/types/publishable-api-key.ts diff --git a/integration-tests/api/__tests__/admin/publishable-api-key.js b/integration-tests/api/__tests__/admin/publishable-api-key.js index e905290fe7..518c59da29 100644 --- a/integration-tests/api/__tests__/admin/publishable-api-key.js +++ b/integration-tests/api/__tests__/admin/publishable-api-key.js @@ -82,9 +82,15 @@ describe("[MEDUSA_FF_PUBLISHABLE_API_KEYS] Publishable API keys", () => { beforeEach(async () => { await adminSeeder(dbConnection) - await simplePublishableApiKeyFactory(dbConnection, {}) - await simplePublishableApiKeyFactory(dbConnection, {}) - await simplePublishableApiKeyFactory(dbConnection, {}) + await simplePublishableApiKeyFactory(dbConnection, { + title: "just a title", + }) + await simplePublishableApiKeyFactory(dbConnection, { + title: "special title 1", + }) + await simplePublishableApiKeyFactory(dbConnection, { + title: "special title 2", + }) }) afterEach(async () => { @@ -105,6 +111,30 @@ describe("[MEDUSA_FF_PUBLISHABLE_API_KEYS] Publishable API keys", () => { expect(response.data.offset).toBe(0) expect(response.data.publishable_api_keys).toHaveLength(2) }) + + it("list publishable keys with query search", async () => { + const api = useApi() + + const response = await api.get( + `/admin/publishable-api-keys?q=special`, + adminHeaders + ) + + expect(response.data.count).toBe(2) + expect(response.data.limit).toBe(20) + expect(response.data.offset).toBe(0) + expect(response.data.publishable_api_keys).toHaveLength(2) + expect(response.data.publishable_api_keys).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + title: "special title 1", + }), + expect.objectContaining({ + title: "special title 2", + }), + ]) + ) + }) }) describe("POST /admin/publishable-api-keys", () => { @@ -122,7 +152,7 @@ describe("[MEDUSA_FF_PUBLISHABLE_API_KEYS] Publishable API keys", () => { const response = await api.post( `/admin/publishable-api-keys`, - {}, + { title: "Store api key" }, adminHeaders ) @@ -130,6 +160,45 @@ describe("[MEDUSA_FF_PUBLISHABLE_API_KEYS] Publishable API keys", () => { expect(response.data.publishable_api_key).toMatchObject({ created_by: "admin_user", id: expect.any(String), + title: "Store api key", + revoked_by: null, + revoked_at: null, + created_at: expect.any(String), + updated_at: expect.any(String), + }) + }) + }) + + describe("POST /admin/publishable-api-keys/:id", () => { + const pubKeyId = IdMap.getId("pubkey-get-id-update") + + beforeEach(async () => { + await adminSeeder(dbConnection) + + await simplePublishableApiKeyFactory(dbConnection, { + id: pubKeyId, + title: "Initial key title", + }) + }) + + afterEach(async () => { + const db = useDb() + return await db.teardown() + }) + + it("update a publishable key", async () => { + const api = useApi() + + const response = await api.post( + `/admin/publishable-api-keys/${pubKeyId}`, + { title: "Changed title" }, + adminHeaders + ) + + expect(response.status).toBe(200) + expect(response.data.publishable_api_key).toMatchObject({ + id: pubKeyId, + title: "Changed title", revoked_by: null, revoked_at: null, created_at: expect.any(String), diff --git a/integration-tests/api/__tests__/admin/sales-channels.js b/integration-tests/api/__tests__/admin/sales-channels.js index 50f3fffdfa..80b8955f83 100644 --- a/integration-tests/api/__tests__/admin/sales-channels.js +++ b/integration-tests/api/__tests__/admin/sales-channels.js @@ -9,7 +9,6 @@ const adminSeeder = require("../../helpers/admin-seeder") const { simpleSalesChannelFactory, simpleProductFactory, - simpleCartFactory, } = require("../../factories") const { simpleOrderFactory } = require("../../factories") const orderSeeder = require("../../helpers/order-seeder") diff --git a/integration-tests/api/factories/simple-price-list-factory.ts b/integration-tests/api/factories/simple-price-list-factory.ts index b122919aa6..c1f1d30dfc 100644 --- a/integration-tests/api/factories/simple-price-list-factory.ts +++ b/integration-tests/api/factories/simple-price-list-factory.ts @@ -3,7 +3,6 @@ import { MoneyAmount, PriceListType, PriceListStatus, - CustomerGroup, } from "@medusajs/medusa" import faker from "faker" import { Connection } from "typeorm" diff --git a/integration-tests/api/factories/simple-publishable-api-key-factory.ts b/integration-tests/api/factories/simple-publishable-api-key-factory.ts index 672e708610..048d64d6d4 100644 --- a/integration-tests/api/factories/simple-publishable-api-key-factory.ts +++ b/integration-tests/api/factories/simple-publishable-api-key-factory.ts @@ -1,4 +1,6 @@ +import faker from "faker" import { Connection } from "typeorm" + import { PublishableApiKey } from "@medusajs/medusa" export type PublishableApiKeyData = { @@ -6,6 +8,7 @@ export type PublishableApiKeyData = { revoked_at?: Date revoked_by?: string created_by?: string + title?: string } export const simplePublishableApiKeyFactory = async ( @@ -14,7 +17,10 @@ export const simplePublishableApiKeyFactory = async ( ): Promise => { const manager = connection.manager - const pubKey = manager.create(PublishableApiKey, data) + const pubKey = manager.create(PublishableApiKey, { + ...data, + title: data.title || `${faker.commerce.department()} API key`, + }) return await manager.save(pubKey) } diff --git a/packages/medusa-js/src/resources/admin/publishable-api-keys.ts b/packages/medusa-js/src/resources/admin/publishable-api-keys.ts index ed839bca9e..1234dc0194 100644 --- a/packages/medusa-js/src/resources/admin/publishable-api-keys.ts +++ b/packages/medusa-js/src/resources/admin/publishable-api-keys.ts @@ -5,6 +5,8 @@ import { AdminPublishableApiKeysRes, GetPublishableApiKeysParams, AdminPublishableApiKeysListRes, + AdminPostPublishableApiKeysReq, + AdminPostPublishableApiKeysPublishableApiKeyReq, } from "@medusajs/medusa" import { ResponsePromise } from "../../typings" @@ -41,13 +43,22 @@ class AdminPublishableApiKeyResource extends BaseResource { } create( - payload: {}, + payload: AdminPostPublishableApiKeysReq, customHeaders: Record = {} ): ResponsePromise { const path = `/admin/publishable-api-keys` return this.client.request("POST", path, payload, {}, customHeaders) } + update( + id: string, + payload: AdminPostPublishableApiKeysPublishableApiKeyReq, + customHeaders: Record = {} + ) { + const path = `/admin/publishable-api-keys/${id}` + return this.client.request("POST", path, payload, {}, customHeaders) + } + delete( id: string, customHeaders: Record = {} diff --git a/packages/medusa-react/mocks/handlers/admin.ts b/packages/medusa-react/mocks/handlers/admin.ts index e280ae5a3f..8319022996 100644 --- a/packages/medusa-react/mocks/handlers/admin.ts +++ b/packages/medusa-react/mocks/handlers/admin.ts @@ -980,6 +980,18 @@ export const adminHandlers = [ ) }), + rest.post("/admin/publishable-api-keys/:id", (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + publishable_api_key: { + ...fixtures.get("publishable_api_key"), + ...(req.body as any), + }, + }) + ) + }), + rest.post("/admin/publishable-api-keys/", (req, res, ctx) => { return res( ctx.status(200), diff --git a/packages/medusa-react/src/hooks/admin/publishable-api-keys/mutations.ts b/packages/medusa-react/src/hooks/admin/publishable-api-keys/mutations.ts index ab2bb1048a..51ea95a625 100644 --- a/packages/medusa-react/src/hooks/admin/publishable-api-keys/mutations.ts +++ b/packages/medusa-react/src/hooks/admin/publishable-api-keys/mutations.ts @@ -4,6 +4,8 @@ import { Response } from "@medusajs/medusa-js" import { AdminPublishableApiKeyDeleteRes, AdminPublishableApiKeysRes, + AdminPostPublishableApiKeysPublishableApiKeyReq, + AdminPostPublishableApiKeysReq, } from "@medusajs/medusa" import { buildOptions } from "../../utils/buildOptions" @@ -11,16 +13,47 @@ import { useMedusa } from "../../../contexts" import { adminPublishableApiKeysKeys } from "." export const useAdminCreatePublishableApiKey = ( - options?: UseMutationOptions, Error, {}> + options?: UseMutationOptions< + Response, + Error, + AdminPostPublishableApiKeysReq + > ) => { const { client } = useMedusa() const queryClient = useQueryClient() return useMutation( - (payload: {}) => client.admin.publishableApiKeys.create(payload), + (payload: AdminPostPublishableApiKeysReq) => + client.admin.publishableApiKeys.create(payload), buildOptions(queryClient, [adminPublishableApiKeysKeys.lists()], options) ) } +export const useAdminUpdatePublishableApiKey = ( + id: string, + options?: UseMutationOptions< + Response, + Error, + AdminPostPublishableApiKeysPublishableApiKeyReq + > +) => { + const { client } = useMedusa() + const queryClient = useQueryClient() + + return useMutation( + (payload: AdminPostPublishableApiKeysPublishableApiKeyReq) => + client.admin.publishableApiKeys.update(id, payload), + buildOptions( + queryClient, + [ + adminPublishableApiKeysKeys.lists(), + adminPublishableApiKeysKeys.detail(id), + adminPublishableApiKeysKeys.details(), + ], + options + ) + ) +} + export const useAdminDeletePublishableApiKey = ( id: string, options?: UseMutationOptions< diff --git a/packages/medusa-react/test/hooks/admin/publishable-api-keys/mutations.test.ts b/packages/medusa-react/test/hooks/admin/publishable-api-keys/mutations.test.ts index 96182e0538..fd0ffe91b5 100644 --- a/packages/medusa-react/test/hooks/admin/publishable-api-keys/mutations.test.ts +++ b/packages/medusa-react/test/hooks/admin/publishable-api-keys/mutations.test.ts @@ -1,12 +1,13 @@ import { renderHook } from "@testing-library/react-hooks" -import { createWrapper } from "../../../utils" import { useAdminDeletePublishableApiKey, useAdminRevokePublishableApiKey, + useAdminUpdatePublishableApiKey, + useAdminCreatePublishableApiKey, } from "../../../../src" +import { createWrapper } from "../../../utils" import { fixtures } from "../../../../mocks/data" -import { useAdminCreatePublishableApiKey } from "../../../../src" describe("useAdminCreatePublishableApiKey hook", () => { test("Created a publishable api key", async () => { @@ -17,7 +18,7 @@ describe("useAdminCreatePublishableApiKey hook", () => { } ) - result.current.mutate({}) + result.current.mutate({ title: "Mandatory title" }) await waitFor(() => result.current.isSuccess) @@ -25,6 +26,7 @@ describe("useAdminCreatePublishableApiKey hook", () => { expect(result.current.data).toEqual( expect.objectContaining({ publishable_api_key: { + title: "Mandatory title", ...fixtures.get("publishable_api_key"), }, }) @@ -32,6 +34,34 @@ describe("useAdminCreatePublishableApiKey hook", () => { }) }) +describe("useAdminUpdatePublishableApiKey hook", () => { + test("updates an publishable key and returns it", async () => { + const pubKey = { + title: "changed title", + } + + const { result, waitFor } = renderHook( + () => + useAdminUpdatePublishableApiKey(fixtures.get("publishable_api_key").id), + { + wrapper: createWrapper(), + } + ) + + result.current.mutate(pubKey) + + await waitFor(() => result.current.isSuccess) + + expect(result.current.data.response.status).toEqual(200) + expect(result.current.data.publishable_api_key).toEqual( + expect.objectContaining({ + ...fixtures.get("publishable_api_key"), + ...pubKey, + }) + ) + }) +}) + describe("useAdminRevokePublishableApiKey hook", () => { test("Revoke a publishable api key", async () => { const id = "pubkey_1234" diff --git a/packages/medusa/src/api/routes/admin/publishable-api-keys/create-publishable-api-key.ts b/packages/medusa/src/api/routes/admin/publishable-api-keys/create-publishable-api-key.ts index 26ed81da05..1a33c43a5b 100644 --- a/packages/medusa/src/api/routes/admin/publishable-api-keys/create-publishable-api-key.ts +++ b/packages/medusa/src/api/routes/admin/publishable-api-keys/create-publishable-api-key.ts @@ -1,5 +1,6 @@ import { Request, Response } from "express" import { EntityManager } from "typeorm" +import { IsString } from "class-validator" import PublishableApiKeyService from "../../../../services/publishable-api-key" @@ -8,6 +9,16 @@ import PublishableApiKeyService from "../../../../services/publishable-api-key" * operationId: "PostPublishableApiKeys" * summary: "Create a PublishableApiKey" * description: "Creates a PublishableApiKey." + * requestBody: + * content: + * application/json: + * schema: + * required: + * - title + * properties: + * title: + * description: A title for the publishable api key + * type: string * x-authenticated: true * x-codeSamples: * - lang: JavaScript @@ -59,14 +70,20 @@ export default async (req: Request, res: Response) => { ) as PublishableApiKeyService const manager = req.scope.resolve("manager") as EntityManager + const data = req.validatedBody as AdminPostPublishableApiKeysReq const loggedInUserId = (req.user?.id ?? req.user?.userId) as string const pubKey = await manager.transaction(async (transactionManager) => { return await publishableApiKeyService .withTransaction(transactionManager) - .create({ loggedInUserId }) + .create(data, { loggedInUserId }) }) return res.status(200).json({ publishable_api_key: pubKey }) } + +export class AdminPostPublishableApiKeysReq { + @IsString() + title: string +} diff --git a/packages/medusa/src/api/routes/admin/publishable-api-keys/index.ts b/packages/medusa/src/api/routes/admin/publishable-api-keys/index.ts index 22eb25a5f3..c53d5635b6 100644 --- a/packages/medusa/src/api/routes/admin/publishable-api-keys/index.ts +++ b/packages/medusa/src/api/routes/admin/publishable-api-keys/index.ts @@ -2,10 +2,15 @@ import { Router } from "express" import { isFeatureFlagEnabled } from "../../../middlewares/feature-flag-enabled" import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys" -import middlewares, { transformQuery } from "../../../middlewares" +import middlewares, { + transformBody, + transformQuery, +} from "../../../middlewares" import { GetPublishableApiKeysParams } from "./list-publishable-api-keys" import { PublishableApiKey } from "../../../../models" import { DeleteResponse, PaginatedResponse } from "../../../../types/common" +import { AdminPostPublishableApiKeysReq } from "./create-publishable-api-key" +import { AdminPostPublishableApiKeysPublishableApiKeyReq } from "./update-publishable-api-key" const route = Router() @@ -18,6 +23,7 @@ export default (app) => { route.post( "/", + transformBody(AdminPostPublishableApiKeysReq), middlewares.wrap(require("./create-publishable-api-key").default) ) @@ -26,6 +32,12 @@ export default (app) => { middlewares.wrap(require("./get-publishable-api-key").default) ) + route.post( + "/:id", + transformBody(AdminPostPublishableApiKeysPublishableApiKeyReq), + middlewares.wrap(require("./update-publishable-api-key").default) + ) + route.delete( "/:id", middlewares.wrap(require("./delete-publishable-api-key").default) @@ -54,3 +66,5 @@ export type AdminPublishableApiKeysListRes = PaginatedResponse & { export type AdminPublishableApiKeyDeleteRes = DeleteResponse export * from "./list-publishable-api-keys" +export * from "./create-publishable-api-key" +export * from "./update-publishable-api-key" diff --git a/packages/medusa/src/api/routes/admin/publishable-api-keys/list-publishable-api-keys.ts b/packages/medusa/src/api/routes/admin/publishable-api-keys/list-publishable-api-keys.ts index 3bd657867d..239eb86130 100644 --- a/packages/medusa/src/api/routes/admin/publishable-api-keys/list-publishable-api-keys.ts +++ b/packages/medusa/src/api/routes/admin/publishable-api-keys/list-publishable-api-keys.ts @@ -11,7 +11,7 @@ import PublishableApiKeyService from "../../../../services/publishable-api-key" * description: "List PublishableApiKeys." * x-authenticated: true * parameters: - * - (query) order_id {string} List publishable keys by id. + * - (query) q {string} Query used for searching publishable api keys by title. * - (query) limit=20 {number} The number of items in the response * - (query) offset=0 {number} The offset of items in response * - (query) expand {string} Comma separated list of relations to include in the results. @@ -84,4 +84,8 @@ export default async (req: Request, res: Response) => { export class GetPublishableApiKeysParams extends extendedFindParamsMixin({ limit: 20, offset: 0, -}) {} +}) { + @IsString() + @IsOptional() + q?: string +} diff --git a/packages/medusa/src/api/routes/admin/publishable-api-keys/update-publishable-api-key.ts b/packages/medusa/src/api/routes/admin/publishable-api-keys/update-publishable-api-key.ts new file mode 100644 index 0000000000..db33752d19 --- /dev/null +++ b/packages/medusa/src/api/routes/admin/publishable-api-keys/update-publishable-api-key.ts @@ -0,0 +1,97 @@ +import { Request, Response } from "express" +import { IsOptional, IsString } from "class-validator" +import { EntityManager } from "typeorm" + +import PublishableApiKeyService from "../../../../services/publishable-api-key" + +/** + * @oas [post] /publishable-api-key/{id} + * operationId: "PostPublishableApiKysPublishableApiKey" + * summary: "Updates a PublishableApiKey" + * description: "Updates a PublishableApiKey." + * x-authenticated: true + * parameters: + * - (path) id=* {string} The ID of the PublishableApiKey. + * requestBody: + * content: + * application/json: + * schema: + * properties: + * title: + * description: A title to update for the key. + * type: string + * x-codeSamples: + * - lang: JavaScript + * label: JS Client + * source: | + * import Medusa from "@medusajs/medusa-js" + * const medusa = new Medusa({ baseUrl: MEDUSA_BACKEND_URL, maxRetries: 3 }) + * // must be previously logged in or use api token + * medusa.admin.publishableApiKey.update(publishable_key_id, { + * title: "new title" + * }) + * .then(({ publishable_api_key }) => { + * console.log(publishable_api_key.id) + * }) + * - lang: Shell + * label: cURL + * source: | + * curl --location --request POST 'https://medusa-url.com/admin/publishable-api-key/{id}' \ + * --header 'Authorization: Bearer {api_token}' \ + * --header 'Content-Type: application/json' \ + * --data-raw '{ + * "title": "updated title" + * }' + * security: + * - api_token: [] + * - cookie_auth: [] + * tags: + * - PublishableApiKey + * responses: + * 200: + * description: OK + * content: + * application/json: + * schema: + * properties: + * publishable_api_key: + * $ref: "#/components/schemas/publishable_api_key" + * "400": + * $ref: "#/components/responses/400_error" + * "401": + * $ref: "#/components/responses/unauthorized" + * "404": + * $ref: "#/components/responses/not_found_error" + * "409": + * $ref: "#/components/responses/invalid_state_error" + * "422": + * $ref: "#/components/responses/invalid_request_error" + * "500": + * $ref: "#/components/responses/500_error" + */ +export default async (req: Request, res: Response) => { + const { id } = req.params + const { validatedBody } = req as { + validatedBody: AdminPostPublishableApiKeysPublishableApiKeyReq + } + + const publishableApiKeysService: PublishableApiKeyService = req.scope.resolve( + "publishableApiKeyService" + ) + + const manager: EntityManager = req.scope.resolve("manager") + + const updatedKey = await manager.transaction(async (transactionManager) => { + return await publishableApiKeysService + .withTransaction(transactionManager) + .update(id, validatedBody) + }) + + res.status(200).json({ publishable_api_key: updatedKey }) +} + +export class AdminPostPublishableApiKeysPublishableApiKeyReq { + @IsString() + @IsOptional() + title?: string +} diff --git a/packages/medusa/src/migrations/1667815005070-publishable_api_key.ts b/packages/medusa/src/migrations/1667815005070-publishable_api_key.ts index 857a028890..5d8baab4aa 100644 --- a/packages/medusa/src/migrations/1667815005070-publishable_api_key.ts +++ b/packages/medusa/src/migrations/1667815005070-publishable_api_key.ts @@ -12,7 +12,7 @@ export class publishableApiKey1667815005070 implements MigrationInterface { `CREATE TABLE "publishable_api_key_sales_channel" ("sales_channel_id" character varying NOT NULL, "publishable_key_id" character varying NOT NULL, CONSTRAINT "PK_68eaeb14bdac8954460054c567c" PRIMARY KEY ("sales_channel_id", "publishable_key_id"))` ) await queryRunner.query( - `CREATE TABLE "publishable_api_key" ("id" character varying NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "created_by" character varying, "revoked_by" character varying, "revoked_at" TIMESTAMP WITH TIME ZONE, CONSTRAINT "PK_9e613278673a87de92c606b4494" PRIMARY KEY ("id"))` + `CREATE TABLE "publishable_api_key" ("id" character varying NOT NULL, "created_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updated_at" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "created_by" character varying, "revoked_by" character varying, "revoked_at" TIMESTAMP WITH TIME ZONE, "title" character varying NOT NULL, CONSTRAINT "PK_9e613278673a87de92c606b4494" PRIMARY KEY ("id"))` ) } diff --git a/packages/medusa/src/models/publishable-api-key.ts b/packages/medusa/src/models/publishable-api-key.ts index e5a9b413c5..e0f1f65f76 100644 --- a/packages/medusa/src/models/publishable-api-key.ts +++ b/packages/medusa/src/models/publishable-api-key.ts @@ -17,9 +17,12 @@ export class PublishableApiKey extends BaseEntity { @Column({ type: resolveDbType("timestamptz"), nullable: true }) revoked_at?: Date + @Column() + title: string + @BeforeInsert() private beforeInsert(): void { - this.id = generateEntityId(this.id, "pubkey") + this.id = generateEntityId(this.id, "pk") } } @@ -32,7 +35,7 @@ export class PublishableApiKey extends BaseEntity { * id: * type: string * description: The key's ID - * example: pak_01G1G5V27GYX4QXNARRQCW1N8T + * example: pk_01G1G5V27GYX4QXNARRQCW1N8T * created_by: * type: string * description: "The unique identifier of the user that created the key." diff --git a/packages/medusa/src/services/__tests__/publishable-api-key.ts b/packages/medusa/src/services/__tests__/publishable-api-key.ts index a71e1116f3..3cdb1a1a86 100644 --- a/packages/medusa/src/services/__tests__/publishable-api-key.ts +++ b/packages/medusa/src/services/__tests__/publishable-api-key.ts @@ -48,13 +48,17 @@ describe("PublishableApiKeyService", () => { }) it("should create a publishable api key and call the repository with the right arguments as well as the event bus service", async () => { - await publishableApiKeyService.create({ - loggedInUserId: IdMap.getId("admin_user"), - }) + await publishableApiKeyService.create( + { title: "API key title" }, + { + loggedInUserId: IdMap.getId("admin_user"), + } + ) expect(publishableApiKeyRepository.create).toHaveBeenCalledTimes(1) expect(publishableApiKeyRepository.create).toHaveBeenCalledWith({ created_by: IdMap.getId("admin_user"), + title: "API key title", }) expect(EventBusServiceMock.emit).toHaveBeenCalledTimes(1) expect(EventBusServiceMock.emit).toHaveBeenCalledWith( @@ -63,6 +67,19 @@ describe("PublishableApiKeyService", () => { ) }) + it("should update a publishable api key", async () => { + await publishableApiKeyService.update(pubKeyToRetrieve.id, { + title: "new title", + }) + + expect(publishableApiKeyRepository.save).toHaveBeenLastCalledWith( + expect.objectContaining({ + id: pubKeyToRetrieve.id, + title: "new title", + }) + ) + }) + it("should revoke a publishable api key", async () => { await publishableApiKeyService.revoke("id", { loggedInUserId: IdMap.getId("admin_user"), diff --git a/packages/medusa/src/services/publishable-api-key.ts b/packages/medusa/src/services/publishable-api-key.ts index f171d937e7..4b87543646 100644 --- a/packages/medusa/src/services/publishable-api-key.ts +++ b/packages/medusa/src/services/publishable-api-key.ts @@ -1,4 +1,4 @@ -import { EntityManager } from "typeorm" +import { EntityManager, ILike } from "typeorm" import { MedusaError } from "medusa-core-utils" import { PublishableApiKeyRepository } from "../repositories/publishable-api-key" @@ -6,7 +6,11 @@ import { FindConfig, Selector } from "../types/common" import { PublishableApiKey } from "../models" import { TransactionBaseService } from "../interfaces" import EventBusService from "./event-bus" -import { buildQuery } from "../utils" +import { buildQuery, isDefined, isString } from "../utils" +import { + CreatePublishableApiKeyInput, + UpdatePublishableApiKeyInput, +} from "../types/publishable-api-key" type InjectedDependencies = { manager: EntityManager @@ -45,17 +49,22 @@ class PublishableApiKeyService extends TransactionBaseService { /** * Create a PublishableApiKey record. * - * @params context - key creation context object + * @param data - partial data for creating the entity + * @param context - key creation context object */ - async create(context: { - loggedInUserId: string - }): Promise { + async create( + data: CreatePublishableApiKeyInput, + context: { + loggedInUserId: string + } + ): Promise { return await this.atomicPhase_(async (manager) => { const publishableApiKeyRepo = manager.getCustomRepository( this.publishableApiKeyRepository_ ) const publishableApiKey = publishableApiKeyRepo.create({ + ...data, created_by: context.loggedInUserId, }) @@ -122,7 +131,7 @@ class PublishableApiKeyService extends TransactionBaseService { * @return an array containing publishable API keys and a total count of records that matches the query */ async listAndCount( - selector: Selector, + selector: Selector & { q?: string }, config: FindConfig = { skip: 0, take: 20, @@ -133,11 +142,44 @@ class PublishableApiKeyService extends TransactionBaseService { this.publishableApiKeyRepository_ ) + let q + if (isString(selector.q)) { + q = selector.q + delete selector.q + } + const query = buildQuery(selector, config) + if (q) { + query.where.title = ILike(`%${q}%`) + } + return await pubKeyRepo.findAndCount(query) } + async update( + publishableApiKeyId: string, + data: UpdatePublishableApiKeyInput + ): Promise { + { + return await this.atomicPhase_(async (manager) => { + const publishableApiKeyRepository = manager.getCustomRepository( + this.publishableApiKeyRepository_ + ) + + const pubKey = await this.retrieve(publishableApiKeyId) + + for (const key of Object.keys(data)) { + if (isDefined(data[key])) { + pubKey[key] = data[key] + } + } + + return await publishableApiKeyRepository.save(pubKey) + }) + } + } + /** * Delete Publishable API key. * diff --git a/packages/medusa/src/types/publishable-api-key.ts b/packages/medusa/src/types/publishable-api-key.ts new file mode 100644 index 0000000000..9e529c9965 --- /dev/null +++ b/packages/medusa/src/types/publishable-api-key.ts @@ -0,0 +1,7 @@ +export type CreatePublishableApiKeyInput = { + title: string +} + +export type UpdatePublishableApiKeyInput = { + title?: string +}