134 lines
3.4 KiB
TypeScript
134 lines
3.4 KiB
TypeScript
import mongoose from "mongoose";
|
|
import { generateId, generateToken } from "../utils/id";
|
|
import { CreateUserInput, UpdateUserInput, userModel } from "./user.schema";
|
|
import { sendMail } from "../utils/mail";
|
|
import { AuthenticatedUser } from "../auth";
|
|
|
|
export const ErrOpNotValid = new Error("operation is not valid");
|
|
export const ErrMissingOrdId = new Error(
|
|
"orgId is required when role is client"
|
|
);
|
|
|
|
export async function createUser(
|
|
input: CreateUserInput,
|
|
user: AuthenticatedUser
|
|
) {
|
|
if (
|
|
input.role === "superAdmin" ||
|
|
(input.role == "admin" && user.role != "superAdmin")
|
|
) {
|
|
throw ErrOpNotValid;
|
|
}
|
|
|
|
if (input.role == "client" && !input.orgId) {
|
|
throw ErrMissingOrdId;
|
|
}
|
|
|
|
const token = await generateToken();
|
|
|
|
const newUser = await userModel.create({
|
|
tenantId: user.tenantId,
|
|
pid: generateId(),
|
|
name: input.firstName + " " + input.lastName,
|
|
createdAt: new Date(),
|
|
createdBy: user.userId,
|
|
token: {
|
|
value: token,
|
|
expiry: new Date(Date.now() + 3600 * 48 * 1000),
|
|
},
|
|
status: "invited",
|
|
...input,
|
|
});
|
|
|
|
const sent = await sendMail(
|
|
input.email,
|
|
"You have been invited to Quicker Permtis.",
|
|
`Click <a href="${
|
|
process.env.SERVER_DOMAIN +
|
|
"/auth/webauthn/register?token=" +
|
|
token +
|
|
"&email=" +
|
|
newUser.email
|
|
}">here</a> to register.`
|
|
);
|
|
|
|
return userModel
|
|
.findOne({ pid: newUser.pid })
|
|
.populate({ path: "orgId", select: "pid name avatar" });
|
|
}
|
|
|
|
export async function getUser(userId: string) {
|
|
if (mongoose.Types.ObjectId.isValid(userId)) {
|
|
return await userModel
|
|
.findById(userId)
|
|
.populate({ path: "orgId", select: "_id pid name" });
|
|
}
|
|
|
|
return await userModel
|
|
.findOne({
|
|
$and: [{ pid: userId }],
|
|
})
|
|
.populate({ path: "orgId", select: "_id pid name" });
|
|
}
|
|
|
|
export async function getUserWithoutPopulate(userId: string) {
|
|
return await userModel.findById(userId);
|
|
}
|
|
|
|
export async function getUserByToken(token: string) {
|
|
return await userModel.findOne({ "token.value": token });
|
|
}
|
|
|
|
export async function getUserByEmail(email: string) {
|
|
return await userModel.findOne({ email: email });
|
|
}
|
|
|
|
export async function listUsers(tenantId: string) {
|
|
return await userModel
|
|
.find({ $and: [{ tenantId: tenantId }, { dev: { $ne: true } }] })
|
|
.select(
|
|
"_id pid orgId firstName lastName name email role avatar status createdAt createdBy lastLogin"
|
|
)
|
|
.populate({ path: "orgId", select: "_id pid name avatar" });
|
|
}
|
|
|
|
export async function updateUser(
|
|
userId: string,
|
|
input: UpdateUserInput,
|
|
user: AuthenticatedUser
|
|
) {
|
|
if (
|
|
input.role === "superAdmin" ||
|
|
(input.role == "admin" && user.role != "superAdmin")
|
|
) {
|
|
throw ErrOpNotValid;
|
|
}
|
|
return await userModel
|
|
.findOneAndUpdate({ pid: userId }, input, {
|
|
new: true,
|
|
})
|
|
.select(
|
|
"_id pid orgId firstName lastName name email role avatar status createdAt createdBy lastLogin"
|
|
)
|
|
.populate({ path: "orgId", select: "_id pid name avatar" });
|
|
}
|
|
|
|
export async function updateUserInternal(
|
|
userId: string,
|
|
input: UpdateUserInput
|
|
) {
|
|
return await userModel
|
|
.findOneAndUpdate({ pid: userId }, input, {
|
|
new: true,
|
|
})
|
|
.select(
|
|
"_id pid orgId firstName lastName name email role avatar status createdAt createdBy lastLogin"
|
|
);
|
|
}
|
|
|
|
export async function deleteUser(userId: string, tenantId: string) {
|
|
return await userModel.deleteOne({
|
|
$and: [{ pid: userId }, { tenantId: tenantId }],
|
|
});
|
|
}
|