chore(medusa): remove PublishableAPIKeys feature flag (#3087)

This commit is contained in:
Frane Polić
2023-02-20 21:16:08 +01:00
committed by GitHub
parent 46547f29c7
commit 6c04624727
21 changed files with 58 additions and 133 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
chore(feature-flag): Remove PublishableAPIKeys feature flag
@@ -2273,17 +2273,6 @@ Object of the following format:
This section holds all events related to publishable API keys.
:::note
As of Medusa v1.6.3, Publishable API Keys are available but guarded by a feature flag. To use Publishable API Keys either:
1. Enable the `MEDUSA_FF_PUBLISHABLE_API_KEYS` environment variable;
2. Or enable the `publishable_api_keys` key in the Medusa server's settings.
You can learn more about enabling it in the [feature flags](../feature-flags/toggle.md) documentation.
:::
<table class="reference-table">
<thead>
<tr>
@@ -1,10 +1,8 @@
const path = require("path")
const { IdMap } = require("medusa-test-utils")
const startServerWithEnvironment =
require("../../../helpers/start-server-with-environment").default
const { useApi } = require("../../../helpers/use-api")
const { useDb } = require("../../../helpers/use-db")
const { useDb, initDb } = require("../../../helpers/use-db")
const adminSeeder = require("../../helpers/admin-seeder")
const {
simplePublishableApiKeyFactory,
@@ -14,6 +12,7 @@ const {
simpleProductFactory,
simpleRegionFactory,
} = require("../../factories")
const setupServer = require("../../../helpers/setup-server")
jest.setTimeout(50000)
@@ -30,22 +29,15 @@ const customerData = {
last_name: "medusa",
}
describe("[MEDUSA_FF_PUBLISHABLE_API_KEYS] Publishable API keys", () => {
describe("Publishable API keys", () => {
let medusaProcess
let dbConnection
const adminUserId = "admin_user"
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", ".."))
const [process, connection] = await startServerWithEnvironment({
cwd,
env: {
MEDUSA_FF_PUBLISHABLE_API_KEYS: true,
MEDUSA_FF_SALES_CHANNELS: true,
},
})
dbConnection = connection
medusaProcess = process
dbConnection = await initDb({ cwd })
medusaProcess = await setupServer({ cwd })
})
afterAll(async () => {
@@ -3,7 +3,7 @@ import { NextFunction, Request, Response } from "express"
import PublishableApiKeyService from "../../../services/publishable-api-key"
export type PublishableApiKeyScopes = {
sales_channel_id: string[]
sales_channel_ids: string[]
}
/**
@@ -23,7 +23,7 @@ async function validateProductSalesChannelAssociation(
"publishableApiKeyService"
)
const { sales_channel_id: salesChannelIds } =
const { sales_channel_ids: salesChannelIds } =
await publishableKeyService.getResourceScopes(pubKey)
if (
@@ -30,8 +30,8 @@ async function validateSalesChannelParam(
channelIds = !Array.isArray(channelIds) ? [channelIds] : channelIds
if (
scopes.sales_channel_id.length &&
!channelIds.every((sc) => scopes.sales_channel_id.includes(sc))
scopes.sales_channel_ids.length &&
!channelIds.every((sc) => scopes.sales_channel_ids.includes(sc))
) {
req.errors = req.errors ?? []
req.errors.push(
@@ -1,7 +1,7 @@
import { NextFunction, Request, Response } from "express"
import PublishableApiKeyService from "../../../services/publishable-api-key"
import { ProductService, ProductVariantService } from "../../../services"
import { ProductVariantService } from "../../../services"
/**
* The middleware check if requested product is assigned to a SC associated with PK in the header.
@@ -25,7 +25,7 @@ async function validateProductVariantSalesChannelAssociation(
"publishableApiKeyService"
)
const { sales_channel_id: salesChannelIds } =
const { sales_channel_ids: salesChannelIds } =
await publishableKeyService.getResourceScopes(pubKey)
if (
@@ -1,7 +1,5 @@
import { Router } from "express"
import { isFeatureFlagEnabled } from "../../../middlewares/feature-flag-enabled"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import middlewares, {
transformBody,
transformQuery,
@@ -18,11 +16,7 @@ import { GetPublishableApiKeySalesChannelsParams } from "./list-publishable-api-
const route = Router()
export default (app) => {
app.use(
"/publishable-api-keys",
isFeatureFlagEnabled(PublishableAPIKeysFeatureFlag.key),
route
)
app.use("/publishable-api-keys", route)
route.post(
"/",
@@ -22,7 +22,6 @@ import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators
import { FlagRouter } from "../../../../utils/flag-router"
import SalesChannelFeatureFlag from "../../../../loaders/feature-flags/sales-channels"
import { CartCreateProps } from "../../../../types/cart"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
/**
* @oas [post] /carts
@@ -125,21 +124,18 @@ export default async (req, res) => {
}
}
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
if (
!toCreate.sales_channel_id &&
req.publishableApiKeyScopes?.sales_channel_id.length
) {
if (req.publishableApiKeyScopes.sales_channel_id.length > 1) {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"The PublishableApiKey provided in the request header has multiple associated sales channels."
)
}
toCreate.sales_channel_id =
req.publishableApiKeyScopes.sales_channel_id[0]
if (
!toCreate.sales_channel_id &&
req.publishableApiKeyScopes?.sales_channel_ids.length
) {
if (req.publishableApiKeyScopes.sales_channel_ids.length > 1) {
throw new MedusaError(
MedusaError.Types.UNEXPECTED_STATE,
"The PublishableApiKey provided in the request header has multiple associated sales channels."
)
}
toCreate.sales_channel_id = req.publishableApiKeyScopes.sales_channel_ids[0]
}
let cart: Cart
@@ -10,7 +10,6 @@ import middlewares, {
import { StorePostCartsCartReq } from "./update-cart"
import { StorePostCartReq } from "./create-cart"
import SalesChannelFeatureFlag from "../../../../loaders/feature-flags/sales-channels"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import { extendRequestParams } from "../../../middlewares/publishable-api-key/extend-request-params"
import { validateSalesChannelParam } from "../../../middlewares/publishable-api-key/validate-sales-channel-param"
@@ -45,15 +44,10 @@ export default (app, container) => {
const createMiddlewares = [
middlewareService.usePreCartCreation(),
transformBody(StorePostCartReq),
extendRequestParams,
validateSalesChannelParam,
]
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
createMiddlewares.push(
extendRequestParams as unknown as RequestHandler,
validateSalesChannelParam as unknown as RequestHandler
)
}
route.post(
"/",
...createMiddlewares,
@@ -34,14 +34,12 @@ export default (app, container, config) => {
})
)
const featureFlagRouter = container.resolve("featureFlagRouter")
route.use(middlewares.authenticateCustomer())
authRoutes(route)
collectionRoutes(route)
customerRoutes(route, container)
productRoutes(route, featureFlagRouter)
productRoutes(route)
productTagsRoutes(route)
productTypesRoutes(route)
orderRoutes(route)
@@ -1,6 +1,5 @@
import { IsOptional, IsString } from "class-validator"
import { defaultStoreProductsRelations } from "."
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import {
CartService,
PricingService,
@@ -9,7 +8,6 @@ import {
RegionService,
} from "../../../../services"
import { PriceSelectionParams } from "../../../../types/price-selection"
import { FlagRouter } from "../../../../utils/flag-router"
import { cleanResponseData } from "../../../../utils/clean-response-data"
/**
@@ -87,11 +85,8 @@ export default async (req, res) => {
const rawProduct = await productService.retrieve(id, req.retrieveConfig)
let sales_channel_id = validated.sales_channel_id
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
if (req.publishableApiKeyScopes?.sales_channel_id.length === 1) {
sales_channel_id = req.publishableApiKeyScopes.sales_channel_id[0]
}
if (req.publishableApiKeyScopes?.sales_channel_ids.length === 1) {
sales_channel_id = req.publishableApiKeyScopes.sales_channel_ids[0]
}
let regionId = validated.region_id
@@ -3,10 +3,8 @@ import "reflect-metadata"
import { Product } from "../../../.."
import middlewares, { transformQuery } from "../../../middlewares"
import { FlagRouter } from "../../../../utils/flag-router"
import { PaginatedResponse } from "../../../../types/common"
import { extendRequestParams } from "../../../middlewares/publishable-api-key/extend-request-params"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import { validateProductSalesChannelAssociation } from "../../../middlewares/publishable-api-key/validate-product-sales-channel-association"
import { validateSalesChannelParam } from "../../../middlewares/publishable-api-key/validate-sales-channel-param"
import { StoreGetProductsParams } from "./list-products"
@@ -14,17 +12,10 @@ import { StoreGetProductsProductParams } from "./get-product"
const route = Router()
export default (app, featureFlagRouter: FlagRouter) => {
app.use("/products", route)
export default (app) => {
app.use("/products", extendRequestParams, validateSalesChannelParam, route)
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
route.use(
"/",
extendRequestParams as unknown as RequestHandler,
validateSalesChannelParam as unknown as RequestHandler
)
route.use("/:id", validateProductSalesChannelAssociation)
}
route.use("/:id", validateProductSalesChannelAssociation)
route.get(
"/",
@@ -105,6 +96,7 @@ export const allowedStoreProductsRelations = [
...defaultStoreProductsRelations,
"variants.title",
"variants.prices.amount",
"sales_channels",
]
export * from "./list-products"
@@ -19,8 +19,6 @@ import { PriceSelectionParams } from "../../../../types/price-selection"
import { FeatureFlagDecorators } from "../../../../utils/feature-flag-decorators"
import { optionalBooleanMapper } from "../../../../utils/validators/is-boolean"
import { IsType } from "../../../../utils/validators/is-type"
import { FlagRouter } from "../../../../utils/flag-router"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import { cleanResponseData } from "../../../../utils/clean-response-data"
import { Cart, Product } from "../../../../models"
@@ -202,13 +200,12 @@ export default async (req, res) => {
// get only published products for store endpoint
filterableFields["status"] = ["published"]
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
if (req.publishableApiKeyScopes?.sales_channel_id.length) {
filterableFields.sales_channel_id =
filterableFields.sales_channel_id ||
req.publishableApiKeyScopes.sales_channel_id
if (req.publishableApiKeyScopes?.sales_channel_ids.length) {
filterableFields.sales_channel_id =
filterableFields.sales_channel_id ||
req.publishableApiKeyScopes.sales_channel_ids
if (!listConfig.relations.includes("listConfig.relations")) {
listConfig.relations.push("sales_channels")
}
}
@@ -10,8 +10,6 @@ import { PriceSelectionParams } from "../../../../types/price-selection"
import { defaultStoreVariantRelations } from "."
import { validator } from "../../../../utils/validator"
import { IsOptional, IsString } from "class-validator"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import { FlagRouter } from "../../../../utils/flag-router"
/**
* @oas [get] /variants/{variant_id}
@@ -82,11 +80,8 @@ export default async (req, res) => {
})
let sales_channel_id = validated.sales_channel_id
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
if (req.publishableApiKeyScopes?.sales_channel_id.length === 1) {
sales_channel_id = req.publishableApiKeyScopes.sales_channel_id[0]
}
if (req.publishableApiKeyScopes?.sales_channel_ids.length === 1) {
sales_channel_id = req.publishableApiKeyScopes.sales_channel_ids[0]
}
let regionId = validated.region_id
@@ -1,8 +1,7 @@
import { Router } from "express"
import { ProductVariant } from "../../../../"
import { RequestHandler, Router } from "express"
import middlewares from "../../../middlewares"
import { featureFlagRouter } from "../../../../loaders/feature-flags"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import { extendRequestParams } from "../../../middlewares/publishable-api-key/extend-request-params"
import { validateSalesChannelParam } from "../../../middlewares/publishable-api-key/validate-sales-channel-param"
import { validateProductVariantSalesChannelAssociation } from "../../../middlewares/publishable-api-key/validate-variant-sales-channel-association"
@@ -10,16 +9,9 @@ import { validateProductVariantSalesChannelAssociation } from "../../../middlewa
const route = Router()
export default (app) => {
app.use("/variants", route)
app.use("/variants", extendRequestParams, validateSalesChannelParam, route)
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
route.use(
"/",
extendRequestParams as unknown as RequestHandler,
validateSalesChannelParam as unknown as RequestHandler
)
route.use("/:id", validateProductVariantSalesChannelAssociation)
}
route.use("/:id", validateProductVariantSalesChannelAssociation)
route.get("/", middlewares.wrap(require("./list-variants").default))
route.get("/:id", middlewares.wrap(require("./get-variant").default))
@@ -15,8 +15,6 @@ import { PriceSelectionParams } from "../../../../types/price-selection"
import { FilterableProductVariantProps } from "../../../../types/product-variant"
import { validator } from "../../../../utils/validator"
import { IsType } from "../../../../utils/validators/is-type"
import PublishableAPIKeysFeatureFlag from "../../../../loaders/feature-flags/publishable-api-keys"
import { FlagRouter } from "../../../../utils/flag-router"
/**
* @oas [get] /variants
@@ -129,11 +127,9 @@ export default async (req, res) => {
}
let sales_channel_id = validated.sales_channel_id
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
if (featureFlagRouter.isFeatureEnabled(PublishableAPIKeysFeatureFlag.key)) {
if (req.publishableApiKeyScopes?.sales_channel_id.length === 1) {
sales_channel_id = req.publishableApiKeyScopes.sales_channel_id[0]
}
if (req.publishableApiKeyScopes?.sales_channel_ids.length === 1) {
sales_channel_id = req.publishableApiKeyScopes.sales_channel_ids[0]
}
const pricingService: PricingService = req.scope.resolve("pricingService")
@@ -1,9 +1,5 @@
import { MigrationInterface, QueryRunner } from "typeorm"
import PublishableAPIKeysFeatureFlag from "../loaders/feature-flags/publishable-api-keys"
export const featureFlag = PublishableAPIKeysFeatureFlag.key
export class publishableApiKey1667815005070 implements MigrationInterface {
name = "publishableApiKey1667815005070"
@@ -1,9 +1,6 @@
import { PrimaryColumn } from "typeorm"
import { Entity, PrimaryColumn } from "typeorm"
import { FeatureFlagEntity } from "../utils/feature-flag-decorators"
import PublishableAPIKeysFeatureFlag from "../loaders/feature-flags/publishable-api-keys"
@FeatureFlagEntity(PublishableAPIKeysFeatureFlag.key)
@Entity()
export class PublishableApiKeySalesChannel {
@PrimaryColumn()
sales_channel_id: string
@@ -1,12 +1,9 @@
import { BeforeInsert, Column } from "typeorm"
import { BeforeInsert, Column, Entity } from "typeorm"
import { BaseEntity } from "../interfaces"
import { resolveDbType } from "../utils/db-aware-column"
import { generateEntityId } from "../utils"
import { FeatureFlagEntity } from "../utils/feature-flag-decorators"
import PublishableAPIKeysFeatureFlag from "../loaders/feature-flags/publishable-api-keys"
import { generateEntityId, resolveDbType } from "../utils"
@FeatureFlagEntity(PublishableAPIKeysFeatureFlag.key)
@Entity()
export class PublishableApiKey extends BaseEntity {
@Column({ type: "varchar", nullable: true })
created_by: string | null
@@ -326,7 +326,7 @@ class PublishableApiKeyService extends TransactionBaseService {
*/
async getResourceScopes(
publishableApiKeyId: string
): Promise<{ sales_channel_id: string[] }> {
): Promise<{ sales_channel_ids: string[] }> {
const pubKeySalesChannelRepo = this.activeManager_.withRepository(
this.publishableApiKeySalesChannelRepository_
)
@@ -337,7 +337,7 @@ class PublishableApiKeyService extends TransactionBaseService {
})
return {
sales_channel_id: salesChannels.map(
sales_channel_ids: salesChannels.map(
({ sales_channel_id }) => sales_channel_id
),
}