54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
import { CreationAttributes } from "@sequelize/core"
|
|
import { isNil, random } from "lodash"
|
|
|
|
import { User } from "@/models"
|
|
import BaseService from "@/services/base-service"
|
|
|
|
export type UserCreationAttributes = Partial<CreationAttributes<User>>
|
|
|
|
export class CreateService extends BaseService {
|
|
constructor(private attributes: UserCreationAttributes) {
|
|
super()
|
|
}
|
|
|
|
async perform(): Promise<User> {
|
|
const { email, auth0Subject, roles, ...optionalAttributes } = this.attributes
|
|
|
|
if (isNil(email)) {
|
|
throw new Error("Email is required")
|
|
}
|
|
|
|
if (isNil(auth0Subject)) {
|
|
throw new Error("Auth0 Subject is required")
|
|
}
|
|
|
|
const [emailLocalPart] = email.split("@")
|
|
/**
|
|
* Yep, if we don't have enough data, your name becomes your email split randomly.
|
|
* This way we can at least have a first name and last name,
|
|
* and the first and last name are likely to be distinct.
|
|
*/
|
|
const randomSplit = random(1, emailLocalPart.length - 2)
|
|
const [firstNameFallback, lastNameFallback] = emailLocalPart.includes(".")
|
|
? emailLocalPart.split(".")
|
|
: [emailLocalPart.slice(0, randomSplit), emailLocalPart.slice(randomSplit)]
|
|
const { firstName, lastName } = optionalAttributes
|
|
const firstNameOrFallback = firstName || firstNameFallback
|
|
const lastNameOrFallback = lastName || lastNameFallback
|
|
|
|
const user = await User.create({
|
|
...optionalAttributes,
|
|
email,
|
|
auth0Subject: auth0Subject,
|
|
firstName: firstNameOrFallback,
|
|
lastName: lastNameOrFallback,
|
|
displayName: `${firstNameOrFallback} ${lastNameOrFallback}`,
|
|
roles: roles ?? [User.Roles.USER],
|
|
})
|
|
|
|
return user
|
|
}
|
|
}
|
|
|
|
export default CreateService
|