diff --git a/src/command/userCommand.ts b/src/command/userCommand.ts index 634a993..b61b578 100644 --- a/src/command/userCommand.ts +++ b/src/command/userCommand.ts @@ -15,6 +15,11 @@ export interface UpdateUserCommand { lastname: string; } +export interface TransferUserOwnerCommand { + fromId: number; + toId: number; +} + export interface UpdateUserRolesCommand { id: number; roleIds: Array; diff --git a/src/command/userCommandHandler.ts b/src/command/userCommandHandler.ts index 876db24..a88979b 100644 --- a/src/command/userCommandHandler.ts +++ b/src/command/userCommandHandler.ts @@ -2,7 +2,13 @@ import { EntityManager } from "typeorm"; import { dataSource } from "../data-source"; import { user } from "../entity/user"; import InternalException from "../exceptions/internalException"; -import { CreateUserCommand, DeleteUserCommand, UpdateUserCommand, UpdateUserRolesCommand } from "./userCommand"; +import { + CreateUserCommand, + DeleteUserCommand, + TransferUserOwnerCommand, + UpdateUserCommand, + UpdateUserRolesCommand, +} from "./userCommand"; import UserService from "../service/userService"; export default abstract class UserCommandHandler { @@ -90,6 +96,38 @@ export default abstract class UserCommandHandler { return await manager.createQueryBuilder().relation(user, "roles").of(userId).remove(roleId); } + /** + * @description transfer ownership + * @param TransferUserOwnerCommand + * @returns {Promise} + */ + static async transferOwnership(transferOwnership: TransferUserOwnerCommand): Promise { + return await dataSource.manager + .transaction(async (manager) => { + manager + .createQueryBuilder() + .update(user) + .set({ + isOwner: false, + }) + .where("id = :id", { id: transferOwnership.fromId }) + .execute(); + + manager + .createQueryBuilder() + .update(user) + .set({ + isOwner: true, + }) + .where("id = :id", { id: transferOwnership.toId }) + .execute(); + }) + .then(() => {}) + .catch((err) => { + throw new InternalException("Failed transfering ownership", err); + }); + } + /** * @description delete user * @param DeleteUserCommand diff --git a/src/controller/userController.ts b/src/controller/userController.ts index 2bfc0f2..ebea67a 100644 --- a/src/controller/userController.ts +++ b/src/controller/userController.ts @@ -5,8 +5,9 @@ import InternalException from "../exceptions/internalException"; import { CLUB_NAME } from "../env.defaults"; import UserService from "../service/userService"; import UserFactory from "../factory/admin/user"; -import { UpdateUserCommand } from "../command/userCommand"; +import { TransferUserOwnerCommand, UpdateUserCommand } from "../command/userCommand"; import UserCommandHandler from "../command/userCommandHandler"; +import ForbiddenRequestException from "../exceptions/forbiddenRequestException"; /** * @description get my by id @@ -70,6 +71,30 @@ export async function verifyMyTotp(req: Request, res: Response): Promise { res.sendStatus(204); } +/** + * @description transferOwnership + * @param req {Request} Express req object + * @param res {Response} Express res object + * @returns {Promise<*>} + */ +export async function transferOwnership(req: Request, res: Response): Promise { + const userId = parseInt(req.userId); + let toId = req.body.toId; + + let { isOwner } = await UserService.getById(userId); + if (!isOwner) { + throw new ForbiddenRequestException("Action only allowed to owner."); + } + + let transfer: TransferUserOwnerCommand = { + toId: toId, + fromId: userId, + }; + await UserCommandHandler.transferOwnership(transfer); + + res.sendStatus(204); +} + /** * @description update my data * @param req {Request} Express req object diff --git a/src/routes/user.ts b/src/routes/user.ts index 47e8e7c..d196e16 100644 --- a/src/routes/user.ts +++ b/src/routes/user.ts @@ -1,5 +1,5 @@ import express from "express"; -import { getMeById, getMyTotp, updateMe, verifyMyTotp } from "../controller/userController"; +import { getMeById, getMyTotp, transferOwnership, updateMe, verifyMyTotp } from "../controller/userController"; var router = express.Router({ mergeParams: true }); @@ -15,6 +15,10 @@ router.post("/verify", async (req, res) => { await verifyMyTotp(req, res); }); +router.put("/transferOwner", async (req, res) => { + await transferOwnership(req, res); +}); + router.patch("/me", async (req, res) => { await updateMe(req, res); });