Feat(medusa, user, core-flows): User creation with invites (#6413)

**What**
- add accept invite endpoint 

**Invite accept flow**
- authenticate using the auth endpoint to create and auth-user
- invoke accept endpoint with token and info to create user
This commit is contained in:
Philip Korsholm
2024-02-19 05:29:15 +00:00
committed by GitHub
parent 5977a38ef4
commit f6d38163bb
28 changed files with 399 additions and 40 deletions
@@ -0,0 +1,34 @@
import { acceptInviteWorkflow } from "@medusajs/core-flows"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
import { InviteWorkflow } from "@medusajs/types"
import { AdminPostInvitesInviteAcceptReq } from "../validators"
import { IUserModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
if (req.auth_user?.app_metadata?.user_id) {
const moduleService: IUserModuleService = req.scope.resolve(
ModuleRegistrationName.USER
)
const user = moduleService.retrieve(req.auth_user.app_metadata.user_id)
res.status(200).json({ user })
return
}
const workflow = acceptInviteWorkflow(req.scope)
const input = {
invite_token: req.filterableFields.token as string,
auth_user_id: req.auth_user!.id,
user: req.validatedBody as AdminPostInvitesInviteAcceptReq,
} as InviteWorkflow.AcceptInviteWorkflowInputDTO
const { result: users } = await workflow.run({ input })
// Set customer_id on session user if we are in session
if (req.session.auth_user) {
req.session.auth_user.app_metadata.user_id = users[0].id
}
res.status(200).json({ user: users[0] })
}
@@ -3,11 +3,19 @@ import {
AdminCreateInviteRequest,
AdminGetInvitesParams,
AdminGetInvitesInviteParams,
AdminPostInvitesInviteAcceptReq,
AdminPostInvitesInviteAcceptParams,
} from "./validators"
import * as QueryConfig from "./query-config"
import { MiddlewareRoute } from "../../../types/middlewares"
import { authenticate } from "../../../utils/authenticate-middleware"
export const adminInviteRoutesMiddlewares: MiddlewareRoute[] = [
{
method: "ALL",
matcher: "/admin/invites*",
middlewares: [authenticate("admin", ["session", "bearer"])],
},
{
method: ["GET"],
matcher: "/admin/invites",
@@ -23,6 +31,14 @@ export const adminInviteRoutesMiddlewares: MiddlewareRoute[] = [
matcher: "/admin/invites",
middlewares: [transformBody(AdminCreateInviteRequest)],
},
{
method: "POST",
matcher: "/admin/invites/accept",
middlewares: [
transformBody(AdminPostInvitesInviteAcceptReq),
transformQuery(AdminPostInvitesInviteAcceptParams),
],
},
{
method: ["GET"],
matcher: "/admin/invites/:id",
@@ -1,5 +1,11 @@
import { Type } from "class-transformer"
import { IsEmail, IsOptional, IsString, ValidateNested } from "class-validator"
import {
IsEmail,
IsNotEmpty,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import {
DateComparisonOperator,
FindParams,
@@ -70,3 +76,63 @@ export class AdminCreateInviteRequest {
@IsEmail()
email: string
}
/**
* Details of the use accepting the invite.
*/
export class AdminPostInvitesInviteAcceptUserReq {}
/**
* @schema AdminPostInvitesInviteAcceptReq
* type: object
* description: "The details of the invite to be accepted."
* required:
* - token
* - user
* properties:
* token:
* description: "The token of the invite to accept. This is a unique token generated when the invite was created or resent."
* type: string
* user:
* description: "The details of the user to create."
* type: object
* required:
* - first_name
* - last_name
* - password
* properties:
* first_name:
* type: string
* description: the first name of the User
* last_name:
* type: string
* description: the last name of the User
* password:
* description: The password for the User
* type: string
* format: password
*/
export class AdminPostInvitesInviteAcceptReq {
/**
* The invite's first name.
*/
@IsString()
@IsOptional()
first_name: string
/**
* The invite's last name.
*/
@IsString()
@IsOptional()
last_name: string
}
export class AdminPostInvitesInviteAcceptParams {
@IsString()
@IsNotEmpty()
token: string
@IsOptional()
expand = undefined
}