feat: Destroy session + introduce http config (#7336)
This commit is contained in:
@@ -12,7 +12,10 @@ const adminHeaders = {
|
||||
jest.setTimeout(30000)
|
||||
|
||||
medusaIntegrationTestRunner({
|
||||
env: { MEDUSA_FF_MEDUSA_V2: true },
|
||||
force_modules_migration: true,
|
||||
env: {
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
},
|
||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||
let container
|
||||
|
||||
@@ -58,21 +61,48 @@ medusaIntegrationTestRunner({
|
||||
)
|
||||
})
|
||||
|
||||
// TODO: Remove in V2, as this is no longer supported
|
||||
it("creates admin JWT token correctly", async () => {
|
||||
breaking(async () => {
|
||||
const response = await api
|
||||
.post("/admin/auth/token", {
|
||||
email: "admin@medusa.js",
|
||||
password: "secret_password",
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.access_token).toEqual(expect.any(String))
|
||||
it("should test the entire authentication lifecycle", async () => {
|
||||
// sign in
|
||||
const response = await api.post("/auth/admin/emailpass", {
|
||||
email: "admin@medusa.js",
|
||||
password: "secret_password",
|
||||
})
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data).toEqual({ token: expect.any(String) })
|
||||
|
||||
const headers = {
|
||||
headers: { ["authorization"]: `Bearer ${response.data.token}` },
|
||||
}
|
||||
|
||||
// convert token to session
|
||||
const cookieRequest = await api.post("/auth/session", {}, headers)
|
||||
expect(cookieRequest.status).toEqual(200)
|
||||
|
||||
// extract cookie
|
||||
const [cookie] = cookieRequest.headers["set-cookie"][0].split(";")
|
||||
|
||||
const cookieHeader = {
|
||||
headers: { Cookie: cookie },
|
||||
}
|
||||
|
||||
// perform cookie authenticated request
|
||||
const authedRequest = await api.get(
|
||||
"/admin/products?limit=1",
|
||||
cookieHeader
|
||||
)
|
||||
expect(authedRequest.status).toEqual(200)
|
||||
|
||||
// sign out
|
||||
const signOutRequest = await api.delete("/auth/session", cookieHeader)
|
||||
expect(signOutRequest.status).toEqual(200)
|
||||
|
||||
// attempt to perform authenticated request
|
||||
const unAuthedRequest = await api
|
||||
.get("/admin/products?limit=1", cookieHeader)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(unAuthedRequest.response.status).toEqual(401)
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
@@ -24,10 +24,12 @@ module.exports = {
|
||||
redis_url: redisUrl,
|
||||
database_url: DB_URL,
|
||||
database_type: "postgres",
|
||||
jwt_secret: "test",
|
||||
cookie_secret: "test",
|
||||
http_compression: {
|
||||
enabled: enableResponseCompression,
|
||||
http: {
|
||||
compression: {
|
||||
enabled: enableResponseCompression,
|
||||
},
|
||||
jwtSecret: "test",
|
||||
cookieSecret: "test",
|
||||
},
|
||||
},
|
||||
featureFlags: {
|
||||
@@ -39,75 +41,70 @@ module.exports = {
|
||||
options: { ttl: cacheTTL },
|
||||
},
|
||||
workflows: true,
|
||||
// We don't want to load the modules if v2 is not enabled, as they run data operations and migrations on load.
|
||||
...(enableMedusaV2
|
||||
? {
|
||||
[Modules.AUTH]: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
resolve: "@medusajs/auth",
|
||||
options: {
|
||||
providers: [
|
||||
{
|
||||
name: "emailpass",
|
||||
scopes: {
|
||||
admin: {},
|
||||
store: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
[Modules.AUTH]: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
resolve: "@medusajs/auth",
|
||||
options: {
|
||||
providers: [
|
||||
{
|
||||
name: "emailpass",
|
||||
scopes: {
|
||||
admin: {},
|
||||
store: {},
|
||||
},
|
||||
},
|
||||
[Modules.USER]: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
resolve: "@medusajs/user",
|
||||
],
|
||||
},
|
||||
},
|
||||
[Modules.USER]: {
|
||||
scope: "internal",
|
||||
resources: "shared",
|
||||
resolve: "@medusajs/user",
|
||||
options: {
|
||||
jwt_secret: "test",
|
||||
},
|
||||
},
|
||||
[Modules.CACHE]: {
|
||||
resolve: "@medusajs/cache-inmemory",
|
||||
options: { ttl: 0 }, // Cache disabled
|
||||
},
|
||||
[Modules.STOCK_LOCATION]: {
|
||||
resolve: "@medusajs/stock-location-next",
|
||||
options: {},
|
||||
},
|
||||
[Modules.INVENTORY]: {
|
||||
resolve: "@medusajs/inventory-next",
|
||||
options: {},
|
||||
},
|
||||
[Modules.FILE]: {
|
||||
resolve: "@medusajs/file",
|
||||
options: {
|
||||
providers: [
|
||||
{
|
||||
resolve: "@medusajs/file-local-next",
|
||||
options: {
|
||||
jwt_secret: "test",
|
||||
config: {
|
||||
local: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
[Modules.CACHE]: {
|
||||
resolve: "@medusajs/cache-inmemory",
|
||||
options: { ttl: 0 }, // Cache disabled
|
||||
},
|
||||
[Modules.STOCK_LOCATION]: {
|
||||
resolve: "@medusajs/stock-location-next",
|
||||
options: {},
|
||||
},
|
||||
[Modules.INVENTORY]: {
|
||||
resolve: "@medusajs/inventory-next",
|
||||
options: {},
|
||||
},
|
||||
[Modules.FILE]: {
|
||||
resolve: "@medusajs/file",
|
||||
options: {
|
||||
providers: [
|
||||
{
|
||||
resolve: "@medusajs/file-local-next",
|
||||
options: {
|
||||
config: {
|
||||
local: {},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
[Modules.PRODUCT]: true,
|
||||
[Modules.PRICING]: true,
|
||||
[Modules.PROMOTION]: true,
|
||||
[Modules.CUSTOMER]: true,
|
||||
[Modules.SALES_CHANNEL]: true,
|
||||
[Modules.CART]: true,
|
||||
[Modules.WORKFLOW_ENGINE]: true,
|
||||
[Modules.REGION]: true,
|
||||
[Modules.API_KEY]: true,
|
||||
[Modules.STORE]: true,
|
||||
[Modules.TAX]: true,
|
||||
[Modules.CURRENCY]: true,
|
||||
[Modules.PAYMENT]: true,
|
||||
[Modules.FULFILLMENT]: true,
|
||||
}
|
||||
: {}),
|
||||
],
|
||||
},
|
||||
},
|
||||
[Modules.PRODUCT]: true,
|
||||
[Modules.PRICING]: true,
|
||||
[Modules.PROMOTION]: true,
|
||||
[Modules.CUSTOMER]: true,
|
||||
[Modules.SALES_CHANNEL]: true,
|
||||
[Modules.CART]: true,
|
||||
[Modules.WORKFLOW_ENGINE]: true,
|
||||
[Modules.REGION]: true,
|
||||
[Modules.API_KEY]: true,
|
||||
[Modules.STORE]: true,
|
||||
[Modules.TAX]: true,
|
||||
[Modules.CURRENCY]: true,
|
||||
[Modules.PAYMENT]: true,
|
||||
[Modules.FULFILLMENT]: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ medusaIntegrationTestRunner({
|
||||
const authService: IAuthModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.AUTH
|
||||
)
|
||||
const { jwt_secret } =
|
||||
const { http } =
|
||||
appContainer.resolve("configModule").projectConfig
|
||||
const authUser = await authService.create({
|
||||
entity_id: "store_user",
|
||||
@@ -42,7 +42,7 @@ medusaIntegrationTestRunner({
|
||||
scope: "store",
|
||||
})
|
||||
|
||||
const token = jwt.sign(authUser, jwt_secret)
|
||||
const token = jwt.sign(authUser, http.jwtSecret)
|
||||
|
||||
const response = await api.post(
|
||||
`/store/customers`,
|
||||
|
||||
@@ -7,7 +7,7 @@ export const createAuthenticatedCustomer = async (
|
||||
appContainer: MedusaContainer,
|
||||
customerData: Partial<CreateCustomerDTO> = {}
|
||||
) => {
|
||||
const { jwt_secret } = appContainer.resolve("configModule").projectConfig
|
||||
const { http } = appContainer.resolve("configModule").projectConfig
|
||||
const authService = appContainer.resolve(ModuleRegistrationName.AUTH)
|
||||
const customerModuleService = appContainer.resolve(
|
||||
ModuleRegistrationName.CUSTOMER
|
||||
@@ -27,7 +27,7 @@ export const createAuthenticatedCustomer = async (
|
||||
app_metadata: { customer_id: customer.id },
|
||||
})
|
||||
|
||||
const token = jwt.sign(authUser, jwt_secret)
|
||||
const token = jwt.sign(authUser, http.jwtSecret)
|
||||
|
||||
return { customer, authUser, jwt: token }
|
||||
}
|
||||
|
||||
@@ -38,8 +38,10 @@ module.exports = {
|
||||
projectConfig: {
|
||||
database_url: DB_URL,
|
||||
database_type: "postgres",
|
||||
jwt_secret: "test",
|
||||
cookie_secret: "test",
|
||||
http: {
|
||||
jwtSecret: "test",
|
||||
cookieSecret: "test",
|
||||
},
|
||||
},
|
||||
featureFlags: {
|
||||
medusa_v2: enableMedusaV2,
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
UIMatch,
|
||||
useLocation,
|
||||
useMatches,
|
||||
useNavigate,
|
||||
} from "react-router-dom"
|
||||
|
||||
import { Skeleton } from "../../common/skeleton"
|
||||
@@ -27,6 +28,8 @@ import { useMe } from "../../../hooks/api/users"
|
||||
import { useSearch } from "../../../providers/search-provider"
|
||||
import { useSidebar } from "../../../providers/sidebar-provider"
|
||||
import { useTheme } from "../../../providers/theme-provider"
|
||||
import { useLogout } from "../../../hooks/api/auth"
|
||||
import { queryClient } from "../../../lib/medusa"
|
||||
|
||||
export const Shell = ({ children }: PropsWithChildren) => {
|
||||
return (
|
||||
@@ -200,20 +203,19 @@ const ThemeToggle = () => {
|
||||
}
|
||||
|
||||
const Logout = () => {
|
||||
// const navigate = useNavigate()
|
||||
// const { mutateAsync: logoutMutation } = useAdminDeleteSession()
|
||||
const navigate = useNavigate()
|
||||
const { mutateAsync: logoutMutation } = useLogout()
|
||||
|
||||
const handleLayout = async () => {
|
||||
// await logoutMutation(undefined, {
|
||||
// onSuccess: () => {
|
||||
// /**
|
||||
// * When the user logs out, we want to clear the query cache
|
||||
// */
|
||||
// queryClient.clear()
|
||||
// navigate("/login")
|
||||
// },
|
||||
// })
|
||||
// noop
|
||||
await logoutMutation(undefined, {
|
||||
onSuccess: () => {
|
||||
/**
|
||||
* When the user logs out, we want to clear the query cache
|
||||
*/
|
||||
queryClient.clear()
|
||||
navigate("/login")
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -14,3 +14,10 @@ export const useEmailPassLogin = (
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
export const useLogout = (options?: UseMutationOptions<void, Error>) => {
|
||||
return useMutation({
|
||||
mutationFn: () => sdk.auth.logout(),
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -30,4 +30,12 @@ export class Auth {
|
||||
this.client.setToken(token)
|
||||
}
|
||||
}
|
||||
|
||||
logout = async () => {
|
||||
await this.client.fetch("/auth/session", {
|
||||
method: "DELETE",
|
||||
})
|
||||
|
||||
this.client.clearToken()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,28 @@ export class Client {
|
||||
this.setToken_(token)
|
||||
}
|
||||
|
||||
clearToken() {
|
||||
this.clearToken_()
|
||||
}
|
||||
|
||||
protected clearToken_() {
|
||||
const { storageMethod, storageKey } = this.getTokenStorageInfo_()
|
||||
switch (storageMethod) {
|
||||
case "local": {
|
||||
window.localStorage.removeItem(storageKey)
|
||||
break
|
||||
}
|
||||
case "session": {
|
||||
window.sessionStorage.removeItem(storageKey)
|
||||
break
|
||||
}
|
||||
case "memory": {
|
||||
this.token = ""
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected initClient(): ClientFetch {
|
||||
const defaultHeaders = new Headers({
|
||||
"content-type": "application/json",
|
||||
|
||||
@@ -67,7 +67,7 @@ type SessionOptions = {
|
||||
*/
|
||||
saveUninitialized?: boolean
|
||||
/**
|
||||
* The secret to sign the session ID cookie. By default, the value of `cookie_secret` is used.
|
||||
* The secret to sign the session ID cookie. By default, the value of `http.cookieSecret` is used.
|
||||
* Refer to [express-session’s documentation](https://www.npmjs.com/package/express-session#secret) for details.
|
||||
*/
|
||||
secret?: string
|
||||
@@ -111,193 +111,6 @@ export type HttpCompressionOptions = {
|
||||
* Essential configurations related to the Medusa backend, such as database and CORS configurations.
|
||||
*/
|
||||
export type ProjectConfigOptions = {
|
||||
/**
|
||||
* The Medusa backend’s API Routes are protected by Cross-Origin Resource Sharing (CORS). So, only allowed URLs or URLs matching a specified pattern can send requests to the backend’s API Routes.
|
||||
*
|
||||
* `store_cors` is a string used to specify the accepted URLs or patterns for store API Routes. It can either be one accepted origin, or a comma-separated list of accepted origins.
|
||||
*
|
||||
* Every origin in that list must either be:
|
||||
*
|
||||
* 1. A URL. For example, `http://localhost:8000`. The URL must not end with a backslash;
|
||||
* 2. Or a regular expression pattern that can match more than one origin. For example, `.example.com`. The regex pattern that the backend tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`.
|
||||
*
|
||||
* @example
|
||||
* Some example values of common use cases:
|
||||
*
|
||||
* ```bash
|
||||
* # Allow different ports locally starting with 800
|
||||
* STORE_CORS=/http:\/\/localhost:800\d+$/
|
||||
*
|
||||
* # Allow any origin ending with vercel.app. For example, storefront.vercel.app
|
||||
* STORE_CORS=/vercel\.app$/
|
||||
*
|
||||
* # Allow all HTTP requests
|
||||
* STORE_CORS=/http:\/\/.+/
|
||||
* ```
|
||||
*
|
||||
* Then, set the configuration in `medusa-config.js`:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* store_cors: process.env.STORE_CORS,
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you’re adding the value directly within `medusa-config.js`, make sure to add an extra escaping `/` for every backslash in the pattern. For example:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* store_cors: "/vercel\\.app$/",
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
store_cors?: string
|
||||
/**
|
||||
* The Medusa backend’s API Routes are protected by Cross-Origin Resource Sharing (CORS). So, only allowed URLs or URLs matching a specified pattern can send requests to the backend’s API Routes.
|
||||
*
|
||||
* `admin_cors` is a string used to specify the accepted URLs or patterns for admin API Routes. It can either be one accepted origin, or a comma-separated list of accepted origins.
|
||||
*
|
||||
* Every origin in that list must either be:
|
||||
*
|
||||
* 1. A URL. For example, `http://localhost:7001`. The URL must not end with a backslash;
|
||||
* 2. Or a regular expression pattern that can match more than one origin. For example, `.example.com`. The regex pattern that the backend tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`.
|
||||
*
|
||||
* @example
|
||||
* Some example values of common use cases:
|
||||
*
|
||||
* ```bash
|
||||
* # Allow different ports locally starting with 700
|
||||
* ADMIN_CORS=/http:\/\/localhost:700\d+$/
|
||||
*
|
||||
* # Allow any origin ending with vercel.app. For example, admin.vercel.app
|
||||
* ADMIN_CORS=/vercel\.app$/
|
||||
*
|
||||
* # Allow all HTTP requests
|
||||
* ADMIN_CORS=/http:\/\/.+/
|
||||
* ```
|
||||
*
|
||||
* Then, set the configuration in `medusa-config.js`:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* admin_cors: process.env.ADMIN_CORS,
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you’re adding the value directly within `medusa-config.js`, make sure to add an extra escaping `/` for every backslash in the pattern. For example:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* admin_cors: "/http:\\/\\/localhost:700\\d+$/",
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
admin_cors?: string
|
||||
/**
|
||||
* The Medusa backend’s API Routes are protected by Cross-Origin Resource Sharing (CORS). So, only allowed URLs or URLs matching a specified pattern can send requests to the backend’s API Routes.
|
||||
*
|
||||
* `auth_cors` is a string used to specify the accepted URLs or patterns for API Routes starting with `/auth`. It can either be one accepted origin, or a comma-separated list of accepted origins.
|
||||
*
|
||||
* Every origin in that list must either be:
|
||||
*
|
||||
* 1. A URL. For example, `http://localhost:7001`. The URL must not end with a backslash;
|
||||
* 2. Or a regular expression pattern that can match more than one origin. For example, `.example.com`. The regex pattern that the backend tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`.
|
||||
*
|
||||
* @example
|
||||
* Some example values of common use cases:
|
||||
*
|
||||
* ```bash
|
||||
* # Allow different ports locally starting with 700
|
||||
* AUTH_CORS=/http:\/\/localhost:700\d+$/
|
||||
*
|
||||
* # Allow any origin ending with vercel.app. For example, admin.vercel.app
|
||||
* AUTH_CORS=/vercel\.app$/
|
||||
*
|
||||
* # Allow all HTTP requests
|
||||
* AUTH_CORS=/http:\/\/.+/
|
||||
* ```
|
||||
*
|
||||
* Then, set the configuration in `medusa-config.js`:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* auth_cors: process.env.AUTH_CORS,
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you’re adding the value directly within `medusa-config.js`, make sure to add an extra escaping `/` for every backslash in the pattern. For example:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* auth_cors: "/http:\\/\\/localhost:700\\d+$/",
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
auth_cors?: string
|
||||
/**
|
||||
* A random string used to create cookie tokens. Although this configuration option is not required, it’s highly recommended to set it for better security.
|
||||
*
|
||||
* In a development environment, if this option is not set, the default secret is `supersecret` However, in production, if this configuration is not set, an error is thrown and
|
||||
* the backend crashes.
|
||||
*
|
||||
* @example
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* cookie_secret: process.env.COOKIE_SECRET ||
|
||||
* "supersecret",
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
cookie_secret?: string
|
||||
|
||||
/**
|
||||
* A random string used to create authentication tokens. Although this configuration option is not required, it’s highly recommended to set it for better security.
|
||||
*
|
||||
* In a development environment, if this option is not set the default secret is `supersecret` However, in production, if this configuration is not set an error, an
|
||||
* error is thrown and the backend crashes.
|
||||
*
|
||||
* @example
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* jwt_secret: process.env.JWT_SECRET ||
|
||||
* "supersecret",
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
jwt_secret?: string
|
||||
|
||||
/**
|
||||
* The name of the database to connect to. If specified in `database_url`, then it’s not required to include it.
|
||||
*
|
||||
@@ -562,6 +375,7 @@ export type ProjectConfigOptions = {
|
||||
session_options?: SessionOptions
|
||||
|
||||
/**
|
||||
* @deprecated - use `http.compression` instead
|
||||
* Configure HTTP compression from the application layer. If you have access to the HTTP server, the recommended approach would be to enable it there.
|
||||
* However, some platforms don't offer access to the HTTP layer and in those cases, this is a good alternative.
|
||||
*
|
||||
@@ -624,6 +438,268 @@ export type ProjectConfigOptions = {
|
||||
* ```
|
||||
*/
|
||||
worker_mode?: "shared" | "worker" | "server"
|
||||
|
||||
/**
|
||||
* Configure the application's http-specific settings
|
||||
*
|
||||
* @example
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* cookieSecret: "some-super-secret",
|
||||
* compression: { ... },
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
http: {
|
||||
/**
|
||||
* A random string used to create authentication tokens in the http layer. Although this configuration option is not required, it’s highly recommended to set it for better security.
|
||||
*
|
||||
* In a development environment, if this option is not set the default secret is `supersecret` However, in production, if this configuration is not set an error, an
|
||||
* error is thrown and the backend crashes.
|
||||
*
|
||||
* @example
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* cookieSecret: "supersecret"
|
||||
* }
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
jwtSecret?: string
|
||||
/**
|
||||
* The expiration time for the JWT token. If not provided, the default value is `24h`.
|
||||
*
|
||||
* @example
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* jwtExpiresIn: "2d"
|
||||
* }
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
jwtExpiresIn?: string
|
||||
/**
|
||||
* A random string used to create cookie tokens in the http layer. Although this configuration option is not required, it’s highly recommended to set it for better security.
|
||||
*
|
||||
* In a development environment, if this option is not set, the default secret is `supersecret` However, in production, if this configuration is not set, an error is thrown and
|
||||
* the backend crashes.
|
||||
*
|
||||
* @example
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* cookieSecret: "supersecret"
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
cookieSecret?: string
|
||||
/**
|
||||
* The Medusa backend’s API Routes are protected by Cross-Origin Resource Sharing (CORS). So, only allowed URLs or URLs matching a specified pattern can send requests to the backend’s API Routes.
|
||||
*
|
||||
* `cors` is a string used to specify the accepted URLs or patterns for API Routes starting with `/auth`. It can either be one accepted origin, or a comma-separated list of accepted origins.
|
||||
*
|
||||
* Every origin in that list must either be:
|
||||
*
|
||||
* 1. A URL. For example, `http://localhost:7001`. The URL must not end with a backslash;
|
||||
* 2. Or a regular expression pattern that can match more than one origin. For example, `.example.com`. The regex pattern that the backend tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`.
|
||||
*
|
||||
* @example
|
||||
* Some example values of common use cases:
|
||||
*
|
||||
* ```bash
|
||||
* # Allow different ports locally starting with 700
|
||||
* AUTH_CORS=/http:\/\/localhost:700\d+$/
|
||||
*
|
||||
* # Allow any origin ending with vercel.app. For example, admin.vercel.app
|
||||
* AUTH_CORS=/vercel\.app$/
|
||||
*
|
||||
* # Allow all HTTP requests
|
||||
* AUTH_CORS=/http:\/\/.+/
|
||||
* ```
|
||||
*
|
||||
* Then, set the configuration in `medusa-config.js`:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* authCors: process.env.AUTH_CORS
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you’re adding the value directly within `medusa-config.js`, make sure to add an extra escaping `/` for every backslash in the pattern. For example:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* authCors: "/http:\\/\\/localhost:700\\d+$/",
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
authCors: string
|
||||
/**
|
||||
*
|
||||
* Configure HTTP compression from the application layer. If you have access to the HTTP server, the recommended approach would be to enable it there.
|
||||
* However, some platforms don't offer access to the HTTP layer and in those cases, this is a good alternative.
|
||||
*
|
||||
* Its value is an object that has the following properties:
|
||||
*
|
||||
* If you enable HTTP compression and you want to disable it for specific API Routes, you can pass in the request header `"x-no-compression": true`.
|
||||
*
|
||||
* @example
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* compression: {
|
||||
* enabled: true,
|
||||
* level: 6,
|
||||
* memLevel: 8,
|
||||
* threshold: 1024,
|
||||
* }
|
||||
* },
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
compression?: HttpCompressionOptions
|
||||
/**
|
||||
* The Medusa backend’s API Routes are protected by Cross-Origin Resource Sharing (CORS). So, only allowed URLs or URLs matching a specified pattern can send requests to the backend’s API Routes.
|
||||
*
|
||||
* `store_cors` is a string used to specify the accepted URLs or patterns for store API Routes. It can either be one accepted origin, or a comma-separated list of accepted origins.
|
||||
*
|
||||
* Every origin in that list must either be:
|
||||
*
|
||||
* 1. A URL. For example, `http://localhost:8000`. The URL must not end with a backslash;
|
||||
* 2. Or a regular expression pattern that can match more than one origin. For example, `.example.com`. The regex pattern that the backend tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`.
|
||||
*
|
||||
* @example
|
||||
* Some example values of common use cases:
|
||||
*
|
||||
* ```bash
|
||||
* # Allow different ports locally starting with 800
|
||||
* STORE_CORS=/http:\/\/localhost:800\d+$/
|
||||
*
|
||||
* # Allow any origin ending with vercel.app. For example, storefront.vercel.app
|
||||
* STORE_CORS=/vercel\.app$/
|
||||
*
|
||||
* # Allow all HTTP requests
|
||||
* STORE_CORS=/http:\/\/.+/
|
||||
* ```
|
||||
*
|
||||
* Then, set the configuration in `medusa-config.js`:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* storeCors: process.env.STORE_CORS,
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you’re adding the value directly within `medusa-config.js`, make sure to add an extra escaping `/` for every backslash in the pattern. For example:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* storeCors: "/vercel\\.app$/",
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
storeCors: string
|
||||
/**
|
||||
* The Medusa backend’s API Routes are protected by Cross-Origin Resource Sharing (CORS). So, only allowed URLs or URLs matching a specified pattern can send requests to the backend’s API Routes.
|
||||
*
|
||||
* `admin_cors` is a string used to specify the accepted URLs or patterns for admin API Routes. It can either be one accepted origin, or a comma-separated list of accepted origins.
|
||||
*
|
||||
* Every origin in that list must either be:
|
||||
*
|
||||
* 1. A URL. For example, `http://localhost:7001`. The URL must not end with a backslash;
|
||||
* 2. Or a regular expression pattern that can match more than one origin. For example, `.example.com`. The regex pattern that the backend tests for is `^([\/~@;%#'])(.*?)\1([gimsuy]*)$`.
|
||||
*
|
||||
* @example
|
||||
* Some example values of common use cases:
|
||||
*
|
||||
* ```bash
|
||||
* # Allow different ports locally starting with 700
|
||||
* ADMIN_CORS=/http:\/\/localhost:700\d+$/
|
||||
*
|
||||
* # Allow any origin ending with vercel.app. For example, admin.vercel.app
|
||||
* ADMIN_CORS=/vercel\.app$/
|
||||
*
|
||||
* # Allow all HTTP requests
|
||||
* ADMIN_CORS=/http:\/\/.+/
|
||||
* ```
|
||||
*
|
||||
* Then, set the configuration in `medusa-config.js`:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* adminCors: process.env.ADMIN_CORS,
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you’re adding the value directly within `medusa-config.js`, make sure to add an extra escaping `/` for every backslash in the pattern. For example:
|
||||
*
|
||||
* ```js title="medusa-config.js"
|
||||
* module.exports = {
|
||||
* projectConfig: {
|
||||
* http: {
|
||||
* adminCors: process.env.ADMIN_CORS,
|
||||
* }
|
||||
* // ...
|
||||
* },
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
adminCors: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,19 +53,28 @@ export const POST = async (
|
||||
userData: req.validatedBody,
|
||||
authUserId: req.auth.auth_user_id,
|
||||
},
|
||||
throwOnError: false,
|
||||
}
|
||||
|
||||
const { errors } = await createUserAccountWorkflow(req.scope).run(input)
|
||||
|
||||
if (Array.isArray(errors) && errors[0]) {
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const { result } = await createUserAccountWorkflow(req.scope).run(input)
|
||||
const user = await refetchUser(
|
||||
req.auth.auth_user_id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
const { jwt_secret } = req.scope.resolve(
|
||||
const { http } = req.scope.resolve(
|
||||
ContainerRegistrationKeys.CONFIG_MODULE
|
||||
).projectConfig
|
||||
const token = jwt.sign(user, jwt_secret)
|
||||
|
||||
const token = jwt.sign(user, http.jwtSecret, {
|
||||
expiresIn: http.jwtExpiresIn,
|
||||
})
|
||||
|
||||
res.status(200).json({ user, token })
|
||||
}
|
||||
|
||||
@@ -25,9 +25,11 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||
const { success, error, authUser, successRedirectUrl } = authResult
|
||||
|
||||
if (success) {
|
||||
const { jwt_secret } = req.scope.resolve("configModule").projectConfig
|
||||
const { http } = req.scope.resolve("configModule").projectConfig
|
||||
|
||||
const token = jwt.sign(authUser, jwt_secret)
|
||||
const { jwtSecret, jwtExpiresIn } = http
|
||||
|
||||
const token = jwt.sign(authUser, jwtSecret, { expiresIn: jwtExpiresIn })
|
||||
|
||||
if (successRedirectUrl) {
|
||||
const url = new URL(successRedirectUrl!)
|
||||
|
||||
@@ -30,8 +30,11 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
|
||||
}
|
||||
|
||||
if (success) {
|
||||
const { jwt_secret } = req.scope.resolve("configModule").projectConfig
|
||||
const token = jwt.sign(authUser, jwt_secret)
|
||||
const { http } = req.scope.resolve("configModule").projectConfig
|
||||
|
||||
const token = jwt.sign(authUser, http.jwtSecret, {
|
||||
expiresIn: http.jwtExpiresIn,
|
||||
})
|
||||
|
||||
return res.status(200).json({ token })
|
||||
}
|
||||
|
||||
@@ -7,6 +7,11 @@ export const authRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
matcher: "/auth/session",
|
||||
middlewares: [authenticate(/.*/, "bearer")],
|
||||
},
|
||||
{
|
||||
method: ["DELETE"],
|
||||
matcher: "/auth/session",
|
||||
middlewares: [authenticate(/.*/, ["session"])],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/auth/:scope/:auth_provider/callback",
|
||||
|
||||
@@ -11,3 +11,11 @@ export const POST = async (
|
||||
|
||||
res.status(200).json({ user: req.auth })
|
||||
}
|
||||
|
||||
export const DELETE = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
req.session.destroy()
|
||||
res.json({ success: true })
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ConfigModule } from "@medusajs/types"
|
||||
import { getConfigFile, isDefined } from "medusa-core-utils"
|
||||
import logger from "./logger"
|
||||
import { ConfigModule } from "@medusajs/types"
|
||||
|
||||
const isProduction = ["production", "prod"].includes(process.env.NODE_ENV || "")
|
||||
|
||||
@@ -18,47 +18,55 @@ export const handleConfigError = (error: Error): void => {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
export default (rootDirectory: string): ConfigModule => {
|
||||
const { configModule, error } = getConfigFile<ConfigModule>(
|
||||
rootDirectory,
|
||||
`medusa-config`
|
||||
)
|
||||
const buildHttpConfig = (projectConfig: ConfigModule["projectConfig"]) => {
|
||||
const http = projectConfig.http ?? {}
|
||||
|
||||
if (error) {
|
||||
handleConfigError(error)
|
||||
http.jwtExpiresIn = http?.jwtExpiresIn ?? "1d"
|
||||
http.authCors = http.authCors ?? ""
|
||||
http.storeCors = http.storeCors ?? ""
|
||||
http.adminCors = http.adminCors ?? ""
|
||||
|
||||
http.jwtSecret = http?.jwtSecret ?? process.env.JWT_SECRET
|
||||
|
||||
if (!http.jwtSecret) {
|
||||
errorHandler(
|
||||
`[medusa-config] ⚠️ http.jwtSecret not found.${
|
||||
isProduction ? "" : "Using default 'supersecret'."
|
||||
}`
|
||||
)
|
||||
|
||||
http.jwtSecret = "supersecret"
|
||||
}
|
||||
|
||||
if (!configModule?.projectConfig?.redis_url) {
|
||||
http.cookieSecret =
|
||||
projectConfig.http?.cookieSecret ?? process.env.COOKIE_SECRET
|
||||
|
||||
if (!http.cookieSecret) {
|
||||
errorHandler(
|
||||
`[medusa-config] ⚠️ http.cookieSecret not found.${
|
||||
isProduction ? "" : " Using default 'supersecret'."
|
||||
}`
|
||||
)
|
||||
|
||||
http.cookieSecret = "supersecret"
|
||||
}
|
||||
|
||||
return http
|
||||
}
|
||||
|
||||
const normalizeProjectConfig = (
|
||||
projectConfig: ConfigModule["projectConfig"]
|
||||
) => {
|
||||
if (!projectConfig?.redis_url) {
|
||||
console.log(
|
||||
`[medusa-config] ⚠️ redis_url not found. A fake redis instance will be used.`
|
||||
)
|
||||
}
|
||||
|
||||
const jwt_secret =
|
||||
configModule?.projectConfig?.jwt_secret ?? process.env.JWT_SECRET
|
||||
if (!jwt_secret) {
|
||||
errorHandler(
|
||||
`[medusa-config] ⚠️ jwt_secret not found.${
|
||||
isProduction
|
||||
? ""
|
||||
: " fallback to either cookie_secret or default 'supersecret'."
|
||||
}`
|
||||
)
|
||||
}
|
||||
projectConfig.http = buildHttpConfig(projectConfig)
|
||||
|
||||
const cookie_secret =
|
||||
configModule?.projectConfig?.cookie_secret ?? process.env.COOKIE_SECRET
|
||||
if (!cookie_secret) {
|
||||
errorHandler(
|
||||
`[medusa-config] ⚠️ cookie_secret not found.${
|
||||
isProduction
|
||||
? ""
|
||||
: " fallback to either cookie_secret or default 'supersecret'."
|
||||
}`
|
||||
)
|
||||
}
|
||||
let worker_mode = projectConfig?.worker_mode
|
||||
|
||||
let worker_mode = configModule?.projectConfig?.worker_mode
|
||||
if (!isDefined(worker_mode)) {
|
||||
const env = process.env.MEDUSA_WORKER_MODE
|
||||
if (isDefined(env)) {
|
||||
@@ -71,12 +79,25 @@ export default (rootDirectory: string): ConfigModule => {
|
||||
}
|
||||
|
||||
return {
|
||||
projectConfig: {
|
||||
jwt_secret: jwt_secret ?? "supersecret",
|
||||
cookie_secret: cookie_secret ?? "supersecret",
|
||||
...configModule?.projectConfig,
|
||||
worker_mode,
|
||||
},
|
||||
...projectConfig,
|
||||
worker_mode,
|
||||
}
|
||||
}
|
||||
|
||||
export default (rootDirectory: string): ConfigModule => {
|
||||
const { configModule, error } = getConfigFile<ConfigModule>(
|
||||
rootDirectory,
|
||||
`medusa-config`
|
||||
)
|
||||
|
||||
if (error) {
|
||||
handleConfigError(error)
|
||||
}
|
||||
|
||||
const projectConfig = normalizeProjectConfig(configModule.projectConfig)
|
||||
|
||||
return {
|
||||
projectConfig,
|
||||
admin: configModule?.admin ?? {},
|
||||
modules: configModule.modules ?? {},
|
||||
featureFlags: configModule?.featureFlags ?? {},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ConfigModule } from "@medusajs/types"
|
||||
import createStore from "connect-redis"
|
||||
import cookieParser from "cookie-parser"
|
||||
import { Express } from "express"
|
||||
import session from "express-session"
|
||||
import morgan from "morgan"
|
||||
import Redis from "ioredis"
|
||||
import { ConfigModule } from "@medusajs/types"
|
||||
import morgan from "morgan"
|
||||
|
||||
type Options = {
|
||||
app: Express
|
||||
@@ -28,14 +28,14 @@ export default async ({
|
||||
sameSite = "none"
|
||||
}
|
||||
|
||||
const { cookie_secret, session_options } = configModule.projectConfig
|
||||
const { http, session_options } = configModule.projectConfig
|
||||
const sessionOpts = {
|
||||
name: session_options?.name ?? "connect.sid",
|
||||
resave: session_options?.resave ?? true,
|
||||
rolling: session_options?.rolling ?? false,
|
||||
saveUninitialized: session_options?.saveUninitialized ?? true,
|
||||
proxy: true,
|
||||
secret: session_options?.secret ?? cookie_secret,
|
||||
secret: session_options?.secret ?? http?.cookieSecret,
|
||||
cookie: {
|
||||
sameSite,
|
||||
secure,
|
||||
|
||||
@@ -4,11 +4,13 @@ export const storeGlobalMiddlewareMock = jest.fn()
|
||||
|
||||
export const config = {
|
||||
projectConfig: {
|
||||
store_cors: "http://localhost:8000",
|
||||
admin_cors: "http://localhost:7001",
|
||||
database_logging: false,
|
||||
jwt_secret: "supersecret",
|
||||
cookie_secret: "superSecret",
|
||||
http: {
|
||||
storeCors: "http://localhost:8000",
|
||||
adminCors: "http://localhost:7001",
|
||||
jwtSecret: "supersecret",
|
||||
cookieSecret: "superSecret",
|
||||
},
|
||||
},
|
||||
featureFlags: {},
|
||||
plugins: [],
|
||||
|
||||
@@ -124,7 +124,7 @@ export const createServer = async (rootDir) => {
|
||||
user_id: opts.adminSession.userId || opts.adminSession.jwt?.userId,
|
||||
domain: "admin",
|
||||
},
|
||||
config.projectConfig.jwt_secret
|
||||
config.projectConfig.http.jwtSecret
|
||||
)
|
||||
|
||||
headers.Authorization = `Bearer ${token}`
|
||||
@@ -137,7 +137,7 @@ export const createServer = async (rootDir) => {
|
||||
opts.clientSession.jwt?.customer_id,
|
||||
domain: "store",
|
||||
},
|
||||
config.projectConfig.jwt_secret
|
||||
config.projectConfig.http.jwtSecret
|
||||
)
|
||||
|
||||
headers.Authorization = `Bearer ${token}`
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { ConfigModule } from "@medusajs/types"
|
||||
import { promiseAll, wrapHandler } from "@medusajs/utils"
|
||||
import cors from "cors"
|
||||
import { type Express, json, Router, text, urlencoded } from "express"
|
||||
import { Router, json, text, urlencoded, type Express } from "express"
|
||||
import { readdir } from "fs/promises"
|
||||
import { parseCorsOrigins } from "medusa-core-utils"
|
||||
import { extname, join, sep } from "path"
|
||||
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
|
||||
import {
|
||||
authenticateCustomer,
|
||||
authenticateLegacy,
|
||||
errorHandler,
|
||||
requireCustomerAuthentication,
|
||||
} from "../../../utils/middlewares"
|
||||
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
|
||||
import logger from "../../logger"
|
||||
import {
|
||||
AsyncRouteHandler,
|
||||
GlobalMiddlewareDescriptor,
|
||||
HTTP_METHODS,
|
||||
MiddlewareRoute,
|
||||
MiddlewaresConfig,
|
||||
MiddlewareVerb,
|
||||
MiddlewaresConfig,
|
||||
ParserConfigArgs,
|
||||
RouteConfig,
|
||||
RouteDescriptor,
|
||||
RouteVerb,
|
||||
} from "./types"
|
||||
import { ConfigModule } from "@medusajs/types"
|
||||
|
||||
const log = ({
|
||||
activityId,
|
||||
@@ -610,7 +610,7 @@ export class RoutesLoader {
|
||||
descriptor.route,
|
||||
cors({
|
||||
origin: parseCorsOrigins(
|
||||
this.configModule.projectConfig.admin_cors || ""
|
||||
this.configModule.projectConfig.http.adminCors
|
||||
),
|
||||
credentials: true,
|
||||
})
|
||||
@@ -625,7 +625,7 @@ export class RoutesLoader {
|
||||
descriptor.route,
|
||||
cors({
|
||||
origin: parseCorsOrigins(
|
||||
this.configModule.projectConfig.auth_cors || ""
|
||||
this.configModule.projectConfig.http.authCors
|
||||
),
|
||||
credentials: true,
|
||||
})
|
||||
@@ -640,7 +640,7 @@ export class RoutesLoader {
|
||||
descriptor.route,
|
||||
cors({
|
||||
origin: parseCorsOrigins(
|
||||
this.configModule.projectConfig.store_cors || ""
|
||||
this.configModule.projectConfig.http.storeCors
|
||||
),
|
||||
credentials: true,
|
||||
})
|
||||
|
||||
@@ -3,9 +3,6 @@ import {
|
||||
MedusaAppMigrateDown,
|
||||
MedusaAppMigrateUp,
|
||||
MedusaAppOutput,
|
||||
MedusaModule,
|
||||
MODULE_PACKAGE_NAMES,
|
||||
Modules,
|
||||
ModulesDefinition,
|
||||
} from "@medusajs/modules-sdk"
|
||||
import {
|
||||
@@ -188,29 +185,6 @@ export const loadMedusaApp = async (
|
||||
injectedDependencies,
|
||||
})
|
||||
|
||||
// TODO: Remove this and make it more dynamic on ensuring all modules are loaded.
|
||||
const requiredModuleKeys = [Modules.PRODUCT, Modules.PRICING]
|
||||
|
||||
const missingPackages: string[] = []
|
||||
|
||||
for (const requiredModuleKey of requiredModuleKeys) {
|
||||
const isModuleInstalled = MedusaModule.isInstalled(requiredModuleKey)
|
||||
|
||||
if (!isModuleInstalled) {
|
||||
missingPackages.push(
|
||||
MODULE_PACKAGE_NAMES[requiredModuleKey] || requiredModuleKey
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (missingPackages.length) {
|
||||
throw new Error(
|
||||
`Medusa requires the following packages/module registration: (${missingPackages.join(
|
||||
", "
|
||||
)})`
|
||||
)
|
||||
}
|
||||
|
||||
if (!config.registerInContainer) {
|
||||
return medusaApp
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export default async ({
|
||||
|
||||
// After a user has authenticated a JWT will be placed on a cookie, all
|
||||
// calls will be authenticated based on the JWT
|
||||
const { jwt_secret } = configModule.projectConfig
|
||||
const { http } = configModule.projectConfig
|
||||
passport.use(
|
||||
"admin-session",
|
||||
new CustomStrategy(async (req, done) => {
|
||||
@@ -97,7 +97,7 @@ export default async ({
|
||||
new JWTStrategy(
|
||||
{
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: jwt_secret,
|
||||
secretOrKey: http.jwtSecret,
|
||||
},
|
||||
(token, done) => {
|
||||
if (token.domain !== "admin") {
|
||||
@@ -121,7 +121,7 @@ export default async ({
|
||||
new JWTStrategy(
|
||||
{
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: jwt_secret,
|
||||
secretOrKey: http.jwtSecret,
|
||||
},
|
||||
(token, done) => {
|
||||
if (token.domain !== "store") {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { PaymentWebhookEvents } from "@medusajs/utils"
|
||||
import { IPaymentModuleService, ProviderWebhookPayload } from "@medusajs/types"
|
||||
import { SubscriberArgs, SubscriberConfig } from "../types/subscribers"
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IPaymentModuleService, ProviderWebhookPayload } from "@medusajs/types"
|
||||
import { PaymentWebhookEvents } from "@medusajs/utils"
|
||||
import { SubscriberArgs, SubscriberConfig } from "../types/subscribers"
|
||||
|
||||
type SerializedBuffer = {
|
||||
data: ArrayBuffer
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import { Request, Response, NextFunction } from "express"
|
||||
import { HttpCompressionOptions, ProjectConfigOptions } from "@medusajs/types"
|
||||
import compression from "compression"
|
||||
import { Logger } from "@medusajs/types"
|
||||
import {
|
||||
ProjectConfigOptions,
|
||||
HttpCompressionOptions,
|
||||
} from "@medusajs/types"
|
||||
import { Request, Response } from "express"
|
||||
|
||||
export function shouldCompressResponse(req: Request, res: Response) {
|
||||
const logger: Logger = req.scope.resolve("logger")
|
||||
const { projectConfig } = req.scope.resolve("configModule")
|
||||
const { enabled } = compressionOptions(projectConfig)
|
||||
|
||||
@@ -27,9 +22,10 @@ export function shouldCompressResponse(req: Request, res: Response) {
|
||||
export function compressionOptions(
|
||||
config: ProjectConfigOptions
|
||||
): HttpCompressionOptions {
|
||||
const responseCompressionOptions = config.http_compression ?? {}
|
||||
const responseCompressionOptions = config.http.compression ?? {}
|
||||
|
||||
responseCompressionOptions.enabled = responseCompressionOptions.enabled ?? false
|
||||
responseCompressionOptions.enabled =
|
||||
responseCompressionOptions.enabled ?? false
|
||||
responseCompressionOptions.level = responseCompressionOptions.level ?? 6
|
||||
responseCompressionOptions.memLevel = responseCompressionOptions.memLevel ?? 8
|
||||
responseCompressionOptions.threshold =
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { ApiKeyDTO, AuthUserDTO, IApiKeyModuleService } from "@medusajs/types"
|
||||
import {
|
||||
ApiKeyDTO,
|
||||
AuthUserDTO,
|
||||
ConfigModule,
|
||||
IApiKeyModuleService,
|
||||
} from "@medusajs/types"
|
||||
import { stringEqualsOrRegexMatch } from "@medusajs/utils"
|
||||
import { NextFunction, RequestHandler } from "express"
|
||||
import jwt, { JwtPayload } from "jsonwebtoken"
|
||||
@@ -55,10 +60,11 @@ export const authenticate = (
|
||||
)
|
||||
|
||||
if (!authUser) {
|
||||
const { jwt_secret } = req.scope.resolve("configModule").projectConfig
|
||||
const { http } =
|
||||
req.scope.resolve<ConfigModule>("configModule").projectConfig
|
||||
authUser = getAuthUserFromJwtToken(
|
||||
req.headers.authorization,
|
||||
jwt_secret,
|
||||
http.jwtSecret!,
|
||||
authTypes,
|
||||
authScope
|
||||
)
|
||||
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
import { AuthUserService } from "@services"
|
||||
import Scrypt from "scrypt-kdf"
|
||||
|
||||
const EXPIRATION = "1d"
|
||||
|
||||
class EmailPasswordProvider extends AbstractAuthModuleProvider {
|
||||
public static PROVIDER = "emailpass"
|
||||
public static DISPLAY_NAME = "Email/Password Authentication"
|
||||
|
||||
Reference in New Issue
Block a user