feat(medusa,medusa-cli): Added an invite option to the create user command, and allow seeding publishable api keys (#4192)
* feat(medusa,medusa-cli): Added an invite option to the create user command * ensure process exits for invites * addressed PR comments * allow seeding publishable api keys
This commit is contained in:
6
.changeset/tasty-walls-prove.md
Normal file
6
.changeset/tasty-walls-prove.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@medusajs/medusa-cli": patch
|
||||
"@medusajs/medusa": patch
|
||||
---
|
||||
|
||||
feat(medusa,medusa-cli): Added an invite option to the create user command, and allow seeding publishable api keys
|
||||
@@ -296,6 +296,11 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
alias: `id`,
|
||||
type: `string`,
|
||||
describe: `User's id.`,
|
||||
})
|
||||
.option(`invite`, {
|
||||
type: `boolean`,
|
||||
describe: `If flag is set, an invitation will be created instead of a new user and the invite token will be returned.`,
|
||||
default: false,
|
||||
}),
|
||||
handler: handlerP(
|
||||
getCommandHandler(`user`, (args, cmd) => {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
ProductService,
|
||||
ProductVariantService,
|
||||
RegionService,
|
||||
SalesChannelService,
|
||||
ShippingOptionService,
|
||||
ShippingProfileService,
|
||||
StoreService,
|
||||
@@ -26,6 +27,8 @@ import { ConfigModule } from "../types/global"
|
||||
import { CreateProductInput } from "../types/product"
|
||||
import { CreateProductCategoryInput } from "../types/product-category"
|
||||
import getMigrations, { getModuleSharedResources } from "./utils/get-migrations"
|
||||
import PublishableApiKeyService from "../services/publishable-api-key"
|
||||
import { SalesChannel } from "../models"
|
||||
|
||||
type SeedOptions = {
|
||||
directory: string
|
||||
@@ -101,6 +104,12 @@ const seed = async function ({ directory, migrate, seedFile }: SeedOptions) {
|
||||
const productCategoryService: ProductCategoryService = container.resolve(
|
||||
"productCategoryService"
|
||||
)
|
||||
const publishableApiKeyService: PublishableApiKeyService = container.resolve(
|
||||
"publishableApiKeyService"
|
||||
)
|
||||
const salesChannelService: SalesChannelService = container.resolve(
|
||||
"salesChannelService"
|
||||
)
|
||||
|
||||
/* eslint-disable */
|
||||
const productVariantService: ProductVariantService = container.resolve(
|
||||
@@ -122,6 +131,7 @@ const seed = async function ({ directory, migrate, seedFile }: SeedOptions) {
|
||||
categories = [],
|
||||
shipping_options,
|
||||
users,
|
||||
publishable_api_keys = [],
|
||||
} = JSON.parse(fs.readFileSync(resolvedPath, `utf-8`))
|
||||
|
||||
const gcProfile = await shippingProfileService.retrieveGiftCardDefault()
|
||||
@@ -235,6 +245,31 @@ const seed = async function ({ directory, migrate, seedFile }: SeedOptions) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let defaultSalesChannel: SalesChannel | null = null
|
||||
|
||||
try {
|
||||
defaultSalesChannel = await salesChannelService
|
||||
.withTransaction(tx)
|
||||
.retrieveDefault()
|
||||
} catch (e) {
|
||||
defaultSalesChannel = null
|
||||
}
|
||||
|
||||
for (const pak of publishable_api_keys) {
|
||||
const publishableApiKey = await publishableApiKeyService
|
||||
.withTransaction(tx)
|
||||
.create(pak, {
|
||||
loggedInUserId: "",
|
||||
})
|
||||
|
||||
// attach to default sales channel if exists
|
||||
if (defaultSalesChannel) {
|
||||
await publishableApiKeyService.addSalesChannels(publishableApiKey.id, [
|
||||
defaultSalesChannel.id,
|
||||
])
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
track("CLI_SEED_COMPLETED")
|
||||
|
||||
@@ -5,8 +5,16 @@ import express from "express"
|
||||
import { track } from "medusa-telemetry"
|
||||
|
||||
import loaders from "../loaders"
|
||||
import Logger from "../loaders/logger"
|
||||
|
||||
export default async function ({ directory, id, email, password, keepAlive }) {
|
||||
export default async function ({
|
||||
directory,
|
||||
id,
|
||||
email,
|
||||
password,
|
||||
keepAlive,
|
||||
invite,
|
||||
}) {
|
||||
track("CLI_USER", { with_id: !!id })
|
||||
const app = express()
|
||||
try {
|
||||
@@ -15,8 +23,19 @@ export default async function ({ directory, id, email, password, keepAlive }) {
|
||||
expressApp: app,
|
||||
})
|
||||
|
||||
const userService = container.resolve("userService")
|
||||
await userService.create({ id, email }, password)
|
||||
if (invite) {
|
||||
const inviteService = container.resolve("inviteService")
|
||||
await inviteService.create(email, "admin")
|
||||
const invite = await inviteService.list({
|
||||
user_email: email,
|
||||
})
|
||||
Logger.info(`
|
||||
Invite token: ${invite[0].token}
|
||||
Open the invite in Medusa Admin at: [your-admin-url]/invite?token=${invite[0].token}`)
|
||||
} else {
|
||||
const userService = container.resolve("userService")
|
||||
await userService.create({ id, email }, password)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
|
||||
@@ -177,6 +177,18 @@ class UserService extends TransactionBaseService {
|
||||
}
|
||||
|
||||
const validatedEmail = validateEmail(user.email)
|
||||
|
||||
const userEntity = await userRepo.findOne({
|
||||
where: { email: validatedEmail },
|
||||
})
|
||||
|
||||
if (userEntity) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"A user with the same email already exists."
|
||||
)
|
||||
}
|
||||
|
||||
if (password) {
|
||||
const hashedPassword = await this.hashPassword_(password)
|
||||
createData.password_hash = hashedPassword
|
||||
|
||||
Reference in New Issue
Block a user