@medusajs/user 2.22.0-snapshot-20261020204851 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +75 -0
- package/README.md +87 -2
- package/package.json +8 -4
package/AGENTS.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# @medusajs/user
|
|
2
|
+
|
|
3
|
+
Commerce module for admin users and user invites, including signing and validating JWT invite tokens. Authentication itself lives in the Auth Module. Registered as `Modules.USER` (`"user"`).
|
|
4
|
+
|
|
5
|
+
## Using this package
|
|
6
|
+
|
|
7
|
+
- Loaded by default through `defineConfig` (`@medusajs/medusa/user`), which passes the options from `projectConfig.http` (`jwtSecret` or `JWT_SECRET`, `jwtOptions`, `jwtVerifyOptions`, `jwtPublicKey`). Override only to change invite behavior:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
module.exports = defineConfig({
|
|
11
|
+
modules: [
|
|
12
|
+
{
|
|
13
|
+
resolve: "@medusajs/medusa/user",
|
|
14
|
+
options: {
|
|
15
|
+
jwt_secret: process.env.JWT_SECRET,
|
|
16
|
+
valid_duration: 60 * 60 * 24, // invite TTL in seconds
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
})
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- Options read by the service constructor: `jwt_secret` (required, the module throws `INVALID_DATA` without it), `jwt_public_key`, `jwt_options` (jsonwebtoken `SignOptions`), `jwt_verify_options`, `valid_duration` (seconds; falls back to `jwt_options.expiresIn`, then 24 hours).
|
|
24
|
+
- In apps, prefer the core-flows workflows: `createUsersWorkflow`, `updateUsersWorkflow`, `deleteUsersWorkflow`, `createUserAccountWorkflow`, `removeUserAccountWorkflow`, `createInvitesWorkflow`, `acceptInviteWorkflow`, `refreshInviteTokensWorkflow`, `deleteInvitesWorkflow`, and RBAC ones (`assignUserRolesWorkflow`, `removeUserRolesWorkflow`).
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { Modules } from "@medusajs/framework/utils"
|
|
28
|
+
import type { IUserModuleService } from "@medusajs/framework/types"
|
|
29
|
+
|
|
30
|
+
const userModuleService: IUserModuleService = container.resolve(Modules.USER)
|
|
31
|
+
const invite = await userModuleService.validateInviteToken(token)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Data models (`src/models`)
|
|
35
|
+
|
|
36
|
+
- `User` (`user_`): `first_name`, `last_name`, `email` (unique among non-deleted), `avatar_url`, `metadata`.
|
|
37
|
+
- `Invite` (`invite_`): `email` (unique among non-deleted), `accepted`, `token`, `expires_at`, `metadata`.
|
|
38
|
+
|
|
39
|
+
### Service methods (`src/services/user-module.ts`)
|
|
40
|
+
|
|
41
|
+
Generated CRUD for both models, plus:
|
|
42
|
+
|
|
43
|
+
- `validateInviteToken(token)`: verifies the JWT, loads the invite, and checks the token matches the stored one and is not expired.
|
|
44
|
+
- `refreshInviteTokens(inviteIds)`: issues new tokens and `expires_at`.
|
|
45
|
+
- Overridden `createUsers`, `updateUsers`, `createInvites` (generates token and expiry), `updateInvites`.
|
|
46
|
+
|
|
47
|
+
### Events and links
|
|
48
|
+
|
|
49
|
+
- Internal CRUD events plus `user.user.invite.token_generated` (`UserEvents.INVITE_TOKEN_GENERATED` from `@medusajs/framework/utils`), emitted by `createInvites`, `updateInvites`, and `refreshInviteTokens`.
|
|
50
|
+
- Workflow events: `user.created|updated|deleted` (`UserWorkflowEvents`) and `invite.created|accepted|deleted|resent` (`InviteWorkflowEvents`).
|
|
51
|
+
- Module links: `user-rbac-role` (`user_rbac_role`) and `invite-rbac-role` (`invite_rbac_role`) to the RBAC Module.
|
|
52
|
+
|
|
53
|
+
Docs: https://docs.medusajs.com/resources/commerce-modules/user.md, https://docs.medusajs.com/resources/commerce-modules/user/module-options.md, https://docs.medusajs.com/resources/commerce-modules/user/user-creation-flows.md, https://docs.medusajs.com/resources/commerce-modules/user/invite-user-subscriber.md
|
|
54
|
+
|
|
55
|
+
## Architecture
|
|
56
|
+
|
|
57
|
+
- Tokens are signed in `generateToken` with `jwt_secret` and `jwt_options` (a random `jwtid` per token unless set). Verification uses `jwt_public_key ?? jwt_secret` and `jwt_verify_options ?? jwt_options`; a single `algorithm` option is converted to `algorithms` for verification.
|
|
58
|
+
- `getExpiresAt` in `src/utils/utils.ts` accepts seconds (number) or a timespan string.
|
|
59
|
+
|
|
60
|
+
## Development
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
cd packages/modules/user
|
|
64
|
+
yarn build
|
|
65
|
+
yarn test
|
|
66
|
+
yarn test:integration # integration-tests/__tests__/{user,invite}.spec.ts (needs Postgres, DB_* env vars)
|
|
67
|
+
yarn migration:create # after any change in src/models
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Gotchas
|
|
71
|
+
|
|
72
|
+
- The constructor's second parameter is named `moduleDeclaration` but holds the module options; option keys are snake_case.
|
|
73
|
+
- A refreshed (resent) invite invalidates earlier tokens: `validateInviteToken` rejects any token not equal to the stored `invite.token`.
|
|
74
|
+
- `createInvites` throws `INVALID_DATA` when a user with the email already exists.
|
|
75
|
+
- `updateInvites` emits `INVITE_TOKEN_GENERATED` on every update, even when the token didn't change.
|
package/README.md
CHANGED
|
@@ -1,3 +1,88 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://www.medusajs.com">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/59018053/229103275-b5e482bb-4601-46e6-8142-244f531cebdb.svg">
|
|
5
|
+
<source media="(prefers-color-scheme: light)" srcset="https://user-images.githubusercontent.com/59018053/229103726-e5b529a3-9b3f-4970-8a1f-c6af37f087bf.svg">
|
|
6
|
+
<img alt="Medusa logo" src="https://user-images.githubusercontent.com/59018053/229103726-e5b529a3-9b3f-4970-8a1f-c6af37f087bf.svg">
|
|
7
|
+
</picture>
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
<h1 align="center">
|
|
11
|
+
@medusajs/user
|
|
12
|
+
</h1>
|
|
2
13
|
|
|
3
|
-
|
|
14
|
+
<h4 align="center">
|
|
15
|
+
<a href="https://docs.medusajs.com">Documentation</a> |
|
|
16
|
+
<a href="https://www.medusajs.com">Website</a>
|
|
17
|
+
</h4>
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
Building blocks for digital commerce
|
|
21
|
+
</p>
|
|
22
|
+
<p align="center">
|
|
23
|
+
<a href="https://github.com/medusajs/medusa/blob/develop/LICENSE">
|
|
24
|
+
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Medusa is released under the MIT license." />
|
|
25
|
+
</a>
|
|
26
|
+
<a href="https://github.com/medusajs/medusa/blob/develop/CONTRIBUTING.md">
|
|
27
|
+
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" alt="PRs welcome!" />
|
|
28
|
+
</a>
|
|
29
|
+
<a href="https://discord.gg/xpCwq3Kfn8">
|
|
30
|
+
<img src="https://img.shields.io/badge/chat-on%20discord-7289DA.svg" alt="Discord Chat" />
|
|
31
|
+
</a>
|
|
32
|
+
<a href="https://twitter.com/intent/follow?screen_name=medusajs">
|
|
33
|
+
<img src="https://img.shields.io/twitter/follow/medusajs.svg?label=Follow%20@medusajs" alt="Follow @medusajs" />
|
|
34
|
+
</a>
|
|
35
|
+
</p>
|
|
36
|
+
|
|
37
|
+
User Module for Medusa: manages admin users and invites, including generating and validating invite tokens. It's installed and registered by default with `@medusajs/medusa`, which passes it the JWT settings from your project config, so Medusa applications use it through the `Modules.USER` service rather than installing this package directly.
|
|
38
|
+
|
|
39
|
+
## At a glance
|
|
40
|
+
|
|
41
|
+
| | |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| Package | `@medusajs/user` |
|
|
44
|
+
| Type | Commerce Module |
|
|
45
|
+
| Module key | `Modules.USER` (`"user"`) |
|
|
46
|
+
| Registered by default | Yes |
|
|
47
|
+
| Import from | `@medusajs/medusa/user` |
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
No installation needed. The module ships with `@medusajs/medusa` and is registered by `defineConfig`.
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
To customize the module's options, such as the invite token's validity, register it in `medusa-config.ts`:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { defineConfig } from "@medusajs/framework/utils"
|
|
59
|
+
|
|
60
|
+
module.exports = defineConfig({
|
|
61
|
+
// ...
|
|
62
|
+
modules: [
|
|
63
|
+
{
|
|
64
|
+
resolve: "@medusajs/medusa/user",
|
|
65
|
+
options: {
|
|
66
|
+
jwt_secret: process.env.JWT_SECRET,
|
|
67
|
+
valid_duration: 60 * 60 * 24,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Configuration
|
|
75
|
+
|
|
76
|
+
| Option | Type | Description | Default |
|
|
77
|
+
| --- | --- | --- | --- |
|
|
78
|
+
| `jwt_secret` | `string` | Secret used to sign invite tokens (or the private key when using asymmetric signing). Required: the module throws on startup if it's missing. | `projectConfig.http.jwtSecret`, then the `JWT_SECRET` environment variable (set by `defineConfig`) |
|
|
79
|
+
| `jwt_public_key` | `string` | Public key used to verify invite tokens when using asymmetric signing. | `projectConfig.http.jwtPublicKey` (set by `defineConfig`) |
|
|
80
|
+
| `valid_duration` | `number` | How long an invite token is valid, in seconds. | `jwt_options.expiresIn`, then `86400` (24 hours) |
|
|
81
|
+
| `jwt_options` | `object` | [jsonwebtoken](https://github.com/auth0/node-jsonwebtoken) sign options, such as `algorithm`. | `projectConfig.http.jwtOptions` (set by `defineConfig`) |
|
|
82
|
+
| `jwt_verify_options` | `object` | jsonwebtoken verify options, such as `algorithms`. Falls back to `jwt_options` when not set. | `projectConfig.http.jwtVerifyOptions` (set by `defineConfig`) |
|
|
83
|
+
|
|
84
|
+
## Resources
|
|
85
|
+
|
|
86
|
+
- [User Module](https://docs.medusajs.com/resources/commerce-modules/user)
|
|
87
|
+
- [Module Options](https://docs.medusajs.com/resources/commerce-modules/user/module-options)
|
|
88
|
+
- [User Creation Flows](https://docs.medusajs.com/resources/commerce-modules/user/user-creation-flows)
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@medusajs/user",
|
|
3
|
-
"version": "2.22.0
|
|
3
|
+
"version": "2.22.0",
|
|
4
4
|
"description": "Medusa Users module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
|
+
"AGENTS.md",
|
|
9
10
|
"!dist/**/__tests__",
|
|
10
11
|
"!dist/**/__mocks__",
|
|
11
12
|
"!dist/**/__fixtures__"
|
|
12
13
|
],
|
|
14
|
+
"llms": "https://docs.medusajs.com/llms.txt",
|
|
15
|
+
"llmsFull": "https://docs.medusajs.com/llms-full.txt",
|
|
16
|
+
"mcpServer": "https://docs.medusajs.com/mcp",
|
|
13
17
|
"engines": {
|
|
14
18
|
"node": ">=22.22.0"
|
|
15
19
|
},
|
|
@@ -39,13 +43,13 @@
|
|
|
39
43
|
"orm:cache:clear": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts MIKRO_ORM_ALLOW_GLOBAL_CLI=true medusa-mikro-orm cache:clear"
|
|
40
44
|
},
|
|
41
45
|
"devDependencies": {
|
|
42
|
-
"@medusajs/framework": "2.22.0
|
|
43
|
-
"@medusajs/test-utils": "2.22.0
|
|
46
|
+
"@medusajs/framework": "2.22.0",
|
|
47
|
+
"@medusajs/test-utils": "2.22.0"
|
|
44
48
|
},
|
|
45
49
|
"dependencies": {
|
|
46
50
|
"jsonwebtoken": "^9.0.2"
|
|
47
51
|
},
|
|
48
52
|
"peerDependencies": {
|
|
49
|
-
"@medusajs/framework": "2.22.0
|
|
53
|
+
"@medusajs/framework": "2.22.0"
|
|
50
54
|
}
|
|
51
55
|
}
|