@topgroup/diginext
Version:
A BUILD SERVER & CLI to deploy apps to any Kubernetes clusters.
277 lines (276 loc) • 15.7 kB
JavaScript
"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;