Files
permit-api/src/user/user.service.ts

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 }],
});
}