diff --git a/src/processed/processed.service.ts b/src/processed/processed.service.ts index 9238b90..eae800e 100644 --- a/src/processed/processed.service.ts +++ b/src/processed/processed.service.ts @@ -1,8 +1,6 @@ import mongoose from "mongoose"; import { AuthenticatedUser } from "../auth"; -import { orgModel } from "../organization/organization.schema"; import { getFilterObject, getSortObject, PageQueryParams } from "../pagination"; -import { userModel } from "../user/user.schema"; import { processedFields, processedModel, diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 4d0ae06..3e5d401 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -4,8 +4,10 @@ import { deleteUser, ErrMissingOrdId, ErrOpNotValid, + ErrUserNotFound, getUser, listUsers, + resetUser, updateUser, } from "./user.service"; import { CreateUserInput, UpdateUserInput } from "./user.schema"; @@ -30,6 +32,23 @@ export async function createUserHandler( } } +export async function resetUserHandler(req: FastifyRequest, res: FastifyReply) { + const { userId } = req.params as { userId: string }; + + try { + await resetUser(userId, req.user); + return res.code(200).send({ msg: "Account reset mail sent" }); + } catch (err) { + if ( + err instanceof Error && + (err.message == ErrOpNotValid.message || + err.message == ErrUserNotFound.message) + ) + return res.code(400).send({ error: err.message }); + return err; + } +} + export async function getCurrentUserHandler( req: FastifyRequest, res: FastifyReply diff --git a/src/user/user.route.ts b/src/user/user.route.ts index 6e71456..8e16e3e 100644 --- a/src/user/user.route.ts +++ b/src/user/user.route.ts @@ -5,6 +5,7 @@ import { getCurrentUserHandler, getUserHandler, listUserHandler, + resetUserHandler, updateUserHandler, } from "./user.controller"; import { $user } from "./user.schema"; @@ -25,6 +26,15 @@ export default async function userRoutes(fastify: FastifyInstance) { createUserHandler ); + fastify.post( + "/:userId/reset", + { + config: { requiredClaims: ["user:write"] }, + preHandler: [fastify.authorize], + }, + resetUserHandler + ); + fastify.get( "/me", { diff --git a/src/user/user.service.ts b/src/user/user.service.ts index f26e81a..80459c0 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -4,6 +4,7 @@ import { CreateUserInput, UpdateUserInput, userModel } from "./user.schema"; import { sendMail } from "../utils/mail"; import { AuthenticatedUser } from "../auth"; +export const ErrUserNotFound = new Error("user not found"); export const ErrOpNotValid = new Error("operation is not valid"); export const ErrMissingOrdId = new Error( "orgId is required when role is client" @@ -57,6 +58,42 @@ export async function createUser( .populate({ path: "orgId", select: "pid name avatar" }); } +export async function resetUser(userId: string, user: AuthenticatedUser) { + if (user.role !== "superAdmin") { + throw ErrOpNotValid; + } + + const token = await generateToken(); + const userInDb = await userModel.findOneAndUpdate( + { pid: userId, tenantId: user.tenantId }, + { + $set: { + token: { + value: token, + expiry: new Date(Date.now() + 3600 * 48 * 1000), + }, + }, + }, + { new: true } + ); + + if (!userInDb) { + throw ErrUserNotFound; + } + + const sent = await sendMail( + userInDb.email, + "Quicker Permits account reset", + `Click here to reset.` + ); +} + export async function getUser(userId: string) { if (mongoose.Types.ObjectId.isValid(userId)) { return await userModel