Previous documentation stuffed type imports with regular imports. This was fine, but either remove the unnecessary 'type' in the first import statement or import like this PR.
173 lines
4.1 KiB
Plaintext
173 lines
4.1 KiB
Plaintext
---
|
||
addHowToData: true
|
||
---
|
||
|
||
import DetailsList from '@site/src/components/DetailsList'
|
||
import ServiceLifetimeSection from '../../troubleshooting/awilix-resolution-error/_service-lifetime.md'
|
||
import CustomRegistrationSection from '../../troubleshooting/awilix-resolution-error/_custom-registration.md'
|
||
|
||
# Example: Access Logged-In User
|
||
|
||
This document gives an example of how you can use middlewares to register the logged-in user in the dependency container of your commerce application. You can then access the logged-in user in other resources, such as services.
|
||
|
||
:::tip
|
||
|
||
You can apply the same steps if you want to register the current customer.
|
||
|
||
:::
|
||
|
||
Learn more about [middlewares in its guide](./add-middleware.mdx).
|
||
|
||
## Step 1: Create the Middleware
|
||
|
||
Create the file `src/api/middlewares.ts` with the following content:
|
||
|
||
```ts title="src/api/middlewares.ts"
|
||
import {
|
||
authenticate,
|
||
} from "@medusajs/medusa"
|
||
import type {
|
||
MedusaNextFunction,
|
||
MedusaRequest,
|
||
MedusaResponse,
|
||
MiddlewaresConfig,
|
||
User,
|
||
UserService,
|
||
} from "@medusajs/medusa"
|
||
|
||
const registerLoggedInUser = async (
|
||
req: MedusaRequest,
|
||
res: MedusaResponse,
|
||
next: MedusaNextFunction
|
||
) => {
|
||
let loggedInUser: User | null = null
|
||
|
||
if (req.user && req.user.userId) {
|
||
const userService =
|
||
req.scope.resolve("userService") as UserService
|
||
loggedInUser = await userService.retrieve(req.user.userId)
|
||
}
|
||
|
||
req.scope.register({
|
||
loggedInUser: {
|
||
resolve: () => loggedInUser,
|
||
},
|
||
})
|
||
|
||
next()
|
||
}
|
||
|
||
export const config: MiddlewaresConfig = {
|
||
routes: [
|
||
{
|
||
matcher: "/admin/products",
|
||
middlewares: [authenticate(), registerLoggedInUser],
|
||
},
|
||
],
|
||
}
|
||
```
|
||
|
||
This creates a `registerLoggedInUser` middleware that handles registering the logged-in user in the dependency container.
|
||
|
||
It then applies this middleware on the `/admin/products` API Route. You can change that to be the route of any other API Route or a pattern that matches multiple routes.
|
||
|
||
---
|
||
|
||
## Step 2: Use in a Service
|
||
|
||
Access the logged-in user resource in the constructor of a service:
|
||
|
||
<!-- eslint-disable prefer-rest-params -->
|
||
|
||
```ts
|
||
import { Lifetime } from "awilix"
|
||
import {
|
||
TransactionBaseService,
|
||
User,
|
||
} from "@medusajs/medusa"
|
||
|
||
class HelloService extends TransactionBaseService {
|
||
|
||
protected readonly loggedInUser_: User | null
|
||
|
||
constructor(container, options) {
|
||
super(...arguments)
|
||
|
||
try {
|
||
this.loggedInUser_ = container.loggedInUser
|
||
} catch (e) {
|
||
// avoid errors when backend first runs
|
||
}
|
||
}
|
||
|
||
// ...
|
||
}
|
||
|
||
export default HelloService
|
||
```
|
||
|
||
If you're accessing it in an extended core service, it’s important to change the lifetime of the service to `Lifetime.SCOPED`. For example:
|
||
|
||
<!-- eslint-disable prefer-rest-params -->
|
||
|
||
```ts
|
||
import { Lifetime } from "awilix"
|
||
import {
|
||
ProductService as MedusaProductService,
|
||
User,
|
||
} from "@medusajs/medusa"
|
||
|
||
// extend core product service
|
||
class ProductService extends MedusaProductService {
|
||
// The default life time for a core service is SINGLETON
|
||
static LIFE_TIME = Lifetime.SCOPED
|
||
|
||
protected readonly loggedInUser_: User | null
|
||
|
||
constructor(container, options) {
|
||
super(...arguments)
|
||
|
||
this.loggedInUser_ = container.loggedInUser
|
||
}
|
||
}
|
||
|
||
export default ProductService
|
||
```
|
||
|
||
You can learn more about the importance of changing the service lifetime in the [Middlewares documentation](./add-middleware.mdx#note-about-services-lifetime).
|
||
|
||
---
|
||
|
||
## Step 3: Test it Out
|
||
|
||
To test out your implementation, run the following command in the root directory of the Medusa backend to transpile your changes:
|
||
|
||
```bash npm2yarn
|
||
npm run build
|
||
```
|
||
|
||
Then, run your backend with the following command:
|
||
|
||
```bash npm2yarn
|
||
npx medusa develop
|
||
```
|
||
|
||
If you try accessing the API Routes you added the middleware to, you should see your implementation working as expected.
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
<DetailsList
|
||
sections={[
|
||
{
|
||
title: 'AwilixResolutionError: Could Not Resolve X',
|
||
content: <ServiceLifetimeSection />
|
||
},
|
||
{
|
||
title: 'AwilixResolutionError: Could Not Resolve X (Custom Registration)',
|
||
content: <CustomRegistrationSection />
|
||
}
|
||
]}
|
||
/>
|