// src/controllers/auth.ts // Copyright (C) 2026 Robert Colbert // All Rights Reserved // import env from "../config/env.js"; import { NextFunction, Request, Response } from "express"; import { DtpController } from "../lib/controller.js"; import UserService from "../services/user.js"; import SessionService, { SessionType } from "../services/session.js"; export class AuthController extends DtpController { get name(): string { return "AuthController"; } get slug(): string { return "auth"; } get route(): string { return "/auth"; } constructor() { super(); } async start(): Promise { this.router.post("/sign-up", this.postSignUp.bind(this)); this.router.post("/sign-in", this.postSignIn.bind(this)); this.router.post("/renew-token", this.postRenewToken.bind(this)); this.router.get("/welcome", this.getWelcomeView.bind(this)); this.router.get("/sign-up", this.getSignUpForm.bind(this)); this.router.get("/sign-in", this.getSignInForm.bind(this)); this.router.get("/sign-out", this.getSignOut.bind(this)); } async postSignUp( req: Request, res: Response, next: NextFunction ): Promise { try { const user = await UserService.create( req.body.email, req.body.password, req.body.displayName ); req.session.user = { _id: user._id, email: user.email, displayName: user.displayName, flags: user.flags, }; const token = await SessionService.createJsonWebToken(user); req.session.token = token; req.session.type = SessionType.WEB; req.session.save((err: Error) => { if (err) { return next(err); } res.status(201).json({ success: true, user: { _id: user._id.toString(), email: user.email, displayName: user.displayName, flags: user.flags, }, token, }); }); } catch (error) { this.log.error("failed to process new user sign-up", { error }); return next(error); } } async postSignIn( req: Request, res: Response, next: NextFunction ): Promise { try { const user = await UserService.authenticate( req.body.email, req.body.password ); req.session.user = { _id: user._id, email: user.email, displayName: user.displayName, flags: user.flags, }; const token = await SessionService.createJsonWebToken(user); req.session.token = token; req.session.type = SessionType.WEB; req.session.save((err: Error) => { if (err) { return next(err); } res.status(200).json({ success: true, user: { _id: user._id.toString(), email: user.email, displayName: user.displayName, flags: user.flags, }, token, }); }); } catch (error) { return next(error); } } async postRenewToken(req: Request, res: Response): Promise { try { const user = await SessionService.verifyJsonWebToken(req.body.token); const token = await SessionService.createJsonWebToken(user); req.session.token = token; res.status(200).json({ success: true, token }); } catch (error) { this.log.error("failed to process token renewal", { error }); res.status((error as Error).statusCode || 500).json({ success: false, message: (error as Error).message, }); } } async getWelcomeView(_req: Request, res: Response): Promise { res.status(200).json({ success: true, message: "Welcome to DTP Web Application", }); } async getSignUpForm(_req: Request, res: Response): Promise { res.status(200).json({ success: true, form: "sign-up", }); } async getSignInForm(_req: Request, res: Response): Promise { res.status(200).json({ success: true, form: "sign-in", }); } async getSignOut( req: Request, res: Response, next: NextFunction ): Promise { if (req.session.token) { try { await SessionService.revokeJsonWebToken(req.session.token); } catch (error) { this.log.error("failed to revoke JSON Web Token", { error }); } } req.session.destroy((err: Error) => { if (err) { this.log.error("failed to destroy user session", { error: err }); return next(err); } res.status(200).json({ success: true, message: "Signed out successfully" }); }); } } export default AuthController;