UNPKG

@topgroup/diginext

Version:

A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.

277 lines (276 loc) 15.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const bcrypt_1 = __importDefault(require("bcrypt")); const express_1 = __importDefault(require("express")); // eslint-disable-next-line import/no-extraneous-dependencies const google_auth_library_1 = require("google-auth-library"); const lodash_1 = require("lodash"); const mongoose_1 = require("mongoose"); const app_config_1 = require("../../../app.config"); const entities_1 = require("../../../entities"); const interfaces_1 = require("../../../interfaces"); const passports_1 = require("../../../modules/passports"); const mongodb_1 = require("../../../plugins/mongodb"); const services_1 = require("../../../services"); const client = new google_auth_library_1.OAuth2Client(process.env.GOOGLE_CLIENT_ID); const router = express_1.default.Router(); /** * Basic auth - REGISTER: /api/v1/register */ router.post("/register", async (req, res) => { const { name, email, password, workspace: wsId } = req.body; // const { DB } = await import("../../../modules/api/DB"); const userSvc = new services_1.UserService(); const wsSvc = new services_1.WorkspaceService(); // validation if (!email) return res.json((0, interfaces_1.respondFailure)(`Email is required.`)); if (!password) return res.json((0, interfaces_1.respondFailure)(`Password is required.`)); try { let workspace; let workspaceId; const existingUser = await userSvc.findOne({ email }, { populate: ["workspaces", "roles"] }); if (existingUser) { if (wsId) { workspace = await wsSvc.findOne({ _id: wsId }); workspaceId = mongodb_1.MongoDB.toString(workspace._id); // validation if (!workspace) return res.json((0, interfaces_1.respondFailure)(`Invalid workspace.`)); if (!workspace.public && !existingUser.workspaces.map((ws) => mongodb_1.MongoDB.toString(ws._id)).includes(wsId)) return res.json((0, interfaces_1.respondFailure)(`You need invitation to access this private workspace.`)); // return res.json(respondFailure(`Workspace ID `)); } else { return res.json((0, interfaces_1.respondFailure)(`Invalid credentials.`)); } } // Hash the password const hashedPassword = await bcrypt_1.default.hash(password, 10); // auto-generated name const userName = name || email.split("@")[0]; // Create/update a new user let newUser; if (existingUser) { // <-- invited user const updateData = { name: userName, password: hashedPassword }; // await console.log("REGISTER > updateData :>> ", updateData); // TODO: NOT SURE WHY THE FIRST LINE IS NOT WORKING!!! ---> DEBUG LATER // const updatedUser = await userSvc.updateOne({ _id: existingUser._id }, updateData, { populate: ["workspaces", "roles"] }); const userModel = (0, mongoose_1.model)("users", entities_1.userSchema, "users"); await userModel.updateOne({ _id: existingUser._id }, updateData); const updatedUser = await userSvc.findOne({ _id: existingUser._id }, { populate: ["workspaces", "roles"] }); // console.log("REGISTER > updatedUser :>> ", updatedUser); newUser = updatedUser; } else { newUser = await userSvc.create({ name: userName, email, password: hashedPassword }, { populate: ["workspaces", "roles"] }); } // console.log("REGISTER > newUser :>> ", newUser); // sign JWT and redirect const userId = mongodb_1.MongoDB.toString(newUser._id); let access_token; let refresh_token; let redirectUrl = req.query.state || app_config_1.Config.BASE_URL; const originUrl = new URL(redirectUrl).origin; if (newUser.workspaces && newUser.workspaces.length === 1) { // if this user only have 1 workspace -> make it active! workspace = newUser.workspaces[0]; workspaceId = mongodb_1.MongoDB.toString(workspace._id); // active role const activeRoleId = newUser.roles[0]._id; // sign JWT const { accessToken, refreshToken } = await (0, passports_1.generateJWT)(userId, { expiresIn: process.env.JWT_EXPIRE_TIME || "2d", workspaceId }); const tokenInfo = await (0, passports_1.extractAccessTokenInfo)({ access_token: accessToken, refresh_token: refreshToken }, { id: userId, workspaceId, exp: Date.now() + 172800000 }); // update tokens to user info newUser = await userSvc.updateOne({ _id: newUser._id }, { token: tokenInfo.token, activeWorkspace: workspaceId, activeRole: activeRoleId }, { populate: ["roles", "workspaces", "activeRole", "activeWorkspace"] }); access_token = accessToken; refresh_token = refreshToken; // assign JWT access token to cookie and request headers: res.cookie("x-auth-cookie", access_token); res.cookie("refresh_token", refresh_token); res.header("Authorization", `Bearer ${access_token}`); return res.json((0, interfaces_1.respondSuccess)({ data: { user: newUser, access_token, refresh_token } })); } // if this user has no workspaces or multiple workspaces -> select one! console.warn("this user has no workspaces or multiple workspaces -> select one!"); // sign JWT (without "workspaceId") const { accessToken, refreshToken } = await await (0, passports_1.generateJWT)(userId, { expiresIn: process.env.JWT_EXPIRE_TIME || "2d" }); const tokenInfo = await (0, passports_1.extractAccessTokenInfo)({ access_token: accessToken, refresh_token: refreshToken }, { id: userId, exp: Date.now() + 172800000 }); // update tokens to user info newUser = await userSvc.updateOne({ _id: newUser._id }, { token: tokenInfo.token }, { populate: ["workspaces", "roles"] }); access_token = accessToken; refresh_token = refreshToken; // assign JWT access token to cookie and request headers: res.cookie("x-auth-cookie", access_token); res.cookie("refresh_token", refresh_token); res.header("Authorization", `Bearer ${access_token}`); return res.json((0, interfaces_1.respondSuccess)({ data: { user: newUser, access_token, refresh_token } })); } catch (error) { console.error("Error during registration:", error); return res.json((0, interfaces_1.respondFailure)("Internal server error")); } }); /** * Basic auth - LOGIN: /api/v1/login */ router.post("/login", // recaptcha.middleware.verify, async (req, res) => { const { email, password } = req.body; const userSvc = new services_1.UserService(); // validation if (!email) return res.json((0, interfaces_1.respondFailure)(`Email is required.`)); if (!password) return res.json((0, interfaces_1.respondFailure)(`Password is required.`)); try { let user = await userSvc.findOne({ email }, { populate: ["workspaces", "roles"] }); if (!user) return res.json((0, interfaces_1.respondFailure)("Invalid credentials")); // account was authenticated by other methods if (!user.password) return res.json((0, interfaces_1.respondFailure)("This account is using other authentication method.")); // Compare the provided password with the stored hashed password const passwordMatch = await bcrypt_1.default.compare(password, user.password); if (!passwordMatch) { return res.json((0, interfaces_1.respondFailure)("Invalid credentials.")); } // sign JWT and redirect const userId = mongodb_1.MongoDB.toString(user._id); let workspace; let workspaceId; let redirectUrl = req.query.state || app_config_1.Config.BASE_URL; const originUrl = new URL(redirectUrl).origin; if (user.workspaces && user.workspaces.length === 1) { // if this user only have 1 workspace -> make it active! workspace = user.workspaces[0]; workspaceId = mongodb_1.MongoDB.toString(workspace._id); // active role const activeRoleId = user.roles[0]._id; // sign JWT const { accessToken, refreshToken } = await (0, passports_1.generateJWT)(userId, { expiresIn: process.env.JWT_EXPIRE_TIME || "2d", workspaceId }); const tokenInfo = await (0, passports_1.extractAccessTokenInfo)({ access_token: accessToken, refresh_token: refreshToken }, { id: userId, exp: Date.now() + 172800000 }); // update current user user = await userSvc.updateOne({ _id: user._id }, { token: tokenInfo.token, activeWorkspace: workspaceId, activeRole: activeRoleId }, { populate: ["roles", "workspaces", "activeRole", "activeWorkspace"] }); // assign JWT access token to cookie and request headers: res.cookie("x-auth-cookie", accessToken); res.cookie("refresh_token", refreshToken); res.header("Authorization", `Bearer ${accessToken}`); return res.json((0, interfaces_1.respondSuccess)({ data: { user, access_token: accessToken, refresh_token: refreshToken } })); } // if this user has no workspaces or multiple workspaces -> select one! console.log("this user has no workspaces or multiple workspaces -> select one!"); const { accessToken, refreshToken } = await (0, passports_1.generateJWT)(userId, { expiresIn: process.env.JWT_EXPIRE_TIME || "2d" }); const tokenInfo = await (0, passports_1.extractAccessTokenInfo)({ access_token: accessToken, refresh_token: refreshToken }, { id: userId, exp: Date.now() + 172800000 }); user = await userSvc.updateOne({ _id: user._id }, { token: tokenInfo.token }); // assign JWT access token to cookie and request headers: res.cookie("x-auth-cookie", accessToken); res.cookie("refresh_token", refreshToken); res.header("Authorization", `Bearer ${accessToken}`); return res.json((0, interfaces_1.respondSuccess)({ data: { user, access_token: accessToken, refresh_token: refreshToken } })); } catch (error) { console.error("Error during login:", error); return res.json((0, interfaces_1.respondFailure)("Internal server error")); } }); router.post("/login/google", async (req, res) => { const { token } = req.body; try { const userGoogle = await client.verifyIdToken({ idToken: token, audience: process.env.GOOGLE_CLIENT_ID, }); const payload = userGoogle.getPayload(); const userid = payload.sub; try { const userSvc = new services_1.UserService(); let user = await userSvc.findOne({ email: payload.email }, { populate: ["roles"] }); if (user) { const updateData = {}; if (user.image != payload.picture) updateData.image = payload.picture; if (user.name != payload.given_name + payload.family_name) updateData.name = payload.given_name + payload.family_name; if (!(0, lodash_1.isEmpty)(updateData)) user = await userSvc.updateOne({ _id: user._id }, updateData); return res.json((0, interfaces_1.respondSuccess)({ data: { user } })); } const provider = { name: "google", user_id: userid, access_token: token, }; const newUser = await userSvc.create({ providers: [provider], name: payload.given_name + payload.family_name, email: payload.email, image: payload.picture, verified: payload.email_verified, isActive: true, }); let access_token; let refresh_token; let workspace; let workspaceId; if (newUser.workspaces && newUser.workspaces.length === 1) { // if this user only have 1 workspace -> make it active! workspace = newUser.workspaces[0]; workspaceId = mongodb_1.MongoDB.toString(workspace._id); // active role const activeRoleId = newUser.roles[0]._id; // sign JWT const { accessToken, refreshToken } = await (0, passports_1.generateJWT)(newUser._id.toString(), { expiresIn: process.env.JWT_EXPIRE_TIME || "2d", workspaceId, }); const tokenInfo = await (0, passports_1.extractAccessTokenInfo)({ access_token: accessToken, refresh_token: refreshToken }, { id: newUser._id.toString(), workspaceId, exp: Date.now() + 172800000 }); // update tokens to user info await userSvc.updateOne({ _id: newUser._id }, { token: tokenInfo.token, activeWorkspace: workspaceId, activeRole: activeRoleId }, { populate: ["roles", "workspaces", "activeRole", "activeWorkspace"] }); access_token = accessToken; refresh_token = refreshToken; console.log("resfrest_token 1: " + refreshToken); return res.json((0, interfaces_1.respondSuccess)({ data: { user: newUser, access_token, refresh_token } })); } // if this user has no workspaces or multiple workspaces -> select one! console.warn("this user has no workspaces or multiple workspaces -> select one!"); const { accessToken, refreshToken } = await (0, passports_1.generateJWT)(newUser._id.toString(), { expiresIn: process.env.JWT_EXPIRE_TIME || "2d" }); const tokenInfo = await (0, passports_1.extractAccessTokenInfo)({ access_token: accessToken, refresh_token: refreshToken }, { id: newUser._id.toString(), exp: Date.now() + 172800000 }); // update tokens to user info const userUpdate = await userSvc.updateOne({ _id: newUser._id }, { token: tokenInfo.token }, { populate: ["workspaces", "roles"] }); access_token = accessToken; refresh_token = refreshToken; console.log("resfrest_token: " + refreshToken); return res.json((0, interfaces_1.respondSuccess)({ data: { user: userUpdate, access_token, refresh_token } })); } catch (error) { console.error("Error during login:", error); return res.json((0, interfaces_1.respondFailure)("Internal server error")); } } catch (error) { console.error("Error authenticating with Google:", error); res.status(401).json({ error: "Authentication failed" }); } }); router.post("/generate-access-token", async (req, res) => { const { workspaceId, userId } = req.body; try { const { accessToken: access_token, refreshToken: refresh_token } = await (0, passports_1.generateJWT)(userId, { expiresIn: process.env.JWT_EXPIRE_TIME || "2d", workspaceId, }); return res.json((0, interfaces_1.respondSuccess)({ data: { access_token, refresh_token } })); } catch (error) { console.error("Error authenticating generate:", error); res.status(401).json({ error: "Authentication failed" }); } }); exports.default = router;