chore: rename route from api-v2 to api (#7379)
* chore: rename route from api-v2 to api * chore: change oas references * chore: remove v2 ref
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import { revokeApiKeysWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../types/routing"
|
||||
import { AdminRevokeApiKeyType } from "../../validators"
|
||||
import { refetchApiKey } from "../../helpers"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminRevokeApiKeyType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { errors } = await revokeApiKeysWorkflow(req.scope).run({
|
||||
input: {
|
||||
selector: { id: req.params.id },
|
||||
revoke: {
|
||||
...req.validatedBody,
|
||||
revoked_by: req.auth.actor_id,
|
||||
},
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const apiKey = await refetchApiKey(
|
||||
req.params.id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ api_key: apiKey })
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import {
|
||||
deleteApiKeysWorkflow,
|
||||
updateApiKeysWorkflow,
|
||||
} from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../types/routing"
|
||||
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { refetchApiKey } from "../helpers"
|
||||
import { AdminUpdateApiKeyType } from "../validators"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const apiKey = await refetchApiKey(
|
||||
req.params.id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ api_key: apiKey })
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminUpdateApiKeyType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { result, errors } = await updateApiKeysWorkflow(req.scope).run({
|
||||
input: {
|
||||
selector: { id: req.params.id },
|
||||
update: req.validatedBody,
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const apiKey = await refetchApiKey(
|
||||
req.params.id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ api_key: apiKey })
|
||||
}
|
||||
|
||||
export const DELETE = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const id = req.params.id
|
||||
|
||||
const { errors } = await deleteApiKeysWorkflow(req.scope).run({
|
||||
input: { ids: [id] },
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
id,
|
||||
object: "api_key",
|
||||
deleted: true,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { ApiKeyType, MedusaError } from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../types/routing"
|
||||
import { refetchApiKey } from "../../helpers"
|
||||
import { LinkMethodRequest } from "@medusajs/types/src"
|
||||
import { linkSalesChannelsToApiKeyWorkflow } from "@medusajs/core-flows"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<LinkMethodRequest>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { add, remove } = req.validatedBody
|
||||
const apiKey = await refetchApiKey(req.params.id, req.scope, ["id", "type"])
|
||||
|
||||
if (apiKey.type !== ApiKeyType.PUBLISHABLE) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"Sales channels can only be associated with publishable API keys"
|
||||
)
|
||||
}
|
||||
|
||||
const { errors } = await linkSalesChannelsToApiKeyWorkflow(req.scope).run({
|
||||
input: {
|
||||
id: req.params.id,
|
||||
add,
|
||||
remove,
|
||||
},
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const updatedApiKey = await refetchApiKey(
|
||||
req.params.id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ api_key: updatedApiKey })
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MedusaContainer } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
export const refetchApiKey = async (
|
||||
apiKeyId: string,
|
||||
scope: MedusaContainer,
|
||||
fields: string[]
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "api_key",
|
||||
variables: {
|
||||
filters: { id: apiKeyId },
|
||||
},
|
||||
fields: fields,
|
||||
})
|
||||
|
||||
const apiKeys = await remoteQuery(queryObject)
|
||||
return apiKeys[0]
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import * as QueryConfig from "./query-config"
|
||||
|
||||
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
|
||||
import { authenticate } from "../../../utils/middlewares/authenticate-middleware"
|
||||
import { validateAndTransformQuery } from "../../utils/validate-query"
|
||||
import {
|
||||
AdminCreateApiKey,
|
||||
AdminGetApiKeyParams,
|
||||
AdminGetApiKeysParams,
|
||||
AdminRevokeApiKey,
|
||||
AdminUpdateApiKey,
|
||||
} from "./validators"
|
||||
import { validateAndTransformBody } from "../../utils/validate-body"
|
||||
import { createLinkBody } from "../../utils/validators"
|
||||
|
||||
export const adminApiKeyRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
{
|
||||
matcher: "/admin/api-keys*",
|
||||
middlewares: [authenticate("admin", ["bearer", "session"])],
|
||||
},
|
||||
{
|
||||
method: ["GET"],
|
||||
matcher: "/admin/api-keys",
|
||||
middlewares: [
|
||||
validateAndTransformQuery(
|
||||
AdminGetApiKeysParams,
|
||||
QueryConfig.listTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["GET"],
|
||||
matcher: "/admin/api-keys/:id",
|
||||
middlewares: [
|
||||
validateAndTransformQuery(
|
||||
AdminGetApiKeyParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/api-keys",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminCreateApiKey),
|
||||
validateAndTransformQuery(
|
||||
AdminGetApiKeyParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/api-keys/:id",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminUpdateApiKey),
|
||||
validateAndTransformQuery(
|
||||
AdminGetApiKeyParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["DELETE"],
|
||||
matcher: "/admin/api-keys/:id",
|
||||
middlewares: [],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/api-keys/:id/revoke",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminRevokeApiKey),
|
||||
validateAndTransformQuery(
|
||||
AdminGetApiKeyParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/api-keys/:id/sales-channels",
|
||||
middlewares: [
|
||||
validateAndTransformBody(createLinkBody()),
|
||||
validateAndTransformQuery(
|
||||
AdminGetApiKeyParams,
|
||||
QueryConfig.retrieveTransformQueryConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
export const defaultAdminApiKeyFields = [
|
||||
"id",
|
||||
"title",
|
||||
"token",
|
||||
"redacted",
|
||||
"type",
|
||||
"last_used_at",
|
||||
"created_at",
|
||||
"created_by",
|
||||
"revoked_at",
|
||||
"revoked_by",
|
||||
"sales_channels.id",
|
||||
"sales_channels.name",
|
||||
]
|
||||
|
||||
export const retrieveTransformQueryConfig = {
|
||||
defaults: defaultAdminApiKeyFields,
|
||||
isList: false,
|
||||
}
|
||||
|
||||
export const listTransformQueryConfig = {
|
||||
...retrieveTransformQueryConfig,
|
||||
defaultLimit: 20,
|
||||
isList: true,
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { createApiKeysWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../types/routing"
|
||||
import { AdminCreateApiKeyType } from "./validators"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "api_key",
|
||||
variables: {
|
||||
filters: req.filterableFields,
|
||||
...req.remoteQueryConfig.pagination,
|
||||
},
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
})
|
||||
|
||||
const { rows: apiKeys, metadata } = await remoteQuery(queryObject)
|
||||
|
||||
res.json({
|
||||
api_keys: apiKeys,
|
||||
count: metadata.count,
|
||||
offset: metadata.skip,
|
||||
limit: metadata.take,
|
||||
})
|
||||
}
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminCreateApiKeyType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const input = [
|
||||
{
|
||||
...req.validatedBody,
|
||||
created_by: req.auth.actor_id,
|
||||
},
|
||||
]
|
||||
|
||||
const { result, errors } = await createApiKeysWorkflow(req.scope).run({
|
||||
input: { api_keys: input },
|
||||
throwOnError: false,
|
||||
})
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
// We should not refetch the api key here, as we need to show the secret key in the response (and never again)
|
||||
// And the only time we get to see the secret, is when we create it
|
||||
res.status(200).json({ api_key: result[0] })
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { z } from "zod"
|
||||
import {
|
||||
createFindParams,
|
||||
createOperatorMap,
|
||||
createSelectParams,
|
||||
} from "../../utils/validators"
|
||||
import { ApiKeyType } from "@medusajs/utils"
|
||||
|
||||
export const AdminGetApiKeyParams = createSelectParams()
|
||||
|
||||
export type AdminGetApiKeysParamsType = z.infer<typeof AdminGetApiKeysParams>
|
||||
export const AdminGetApiKeysParams = createFindParams({
|
||||
offset: 0,
|
||||
limit: 50,
|
||||
}).merge(
|
||||
z.object({
|
||||
q: z.string().optional(),
|
||||
id: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
title: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
token: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
type: z.nativeEnum(ApiKeyType).optional(),
|
||||
created_at: createOperatorMap().optional(),
|
||||
updated_at: createOperatorMap().optional(),
|
||||
deleted_at: createOperatorMap().optional(),
|
||||
$and: z.lazy(() => AdminGetApiKeysParams.array()).optional(),
|
||||
$or: z.lazy(() => AdminGetApiKeysParams.array()).optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export type AdminCreateApiKeyType = z.infer<typeof AdminCreateApiKey>
|
||||
export const AdminCreateApiKey = z.object({
|
||||
title: z.string(),
|
||||
type: z.nativeEnum(ApiKeyType),
|
||||
})
|
||||
|
||||
export type AdminUpdateApiKeyType = z.infer<typeof AdminUpdateApiKey>
|
||||
export const AdminUpdateApiKey = z.object({
|
||||
title: z.string(),
|
||||
})
|
||||
|
||||
export type AdminRevokeApiKeyType = z.infer<typeof AdminRevokeApiKey>
|
||||
export const AdminRevokeApiKey = z.object({
|
||||
revoke_in: z.number().optional(),
|
||||
})
|
||||
Reference in New Issue
Block a user