process.env.NODE_ENV === "development" ? require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` }) : require("dotenv").config(); const { SystemSettings } = require("../models/systemSettings"); const { Telemetry } = require("../models/telemetry"); const { User } = require("../models/user"); const { reqBody, makeJWT } = require("../utils/http"); const bcrypt = require("bcrypt"); function authenticationEndpoints(app) { if (!app) return; app.get("/auth/auto-onboard", async (_, response) => { try { const completeSetup = (await User.count({ role: "admin" })) > 0; if (completeSetup) { response.status(200).json({ completed: true }); return; } const onboardingUser = await User.get({ role: "root" }); if (!onboardingUser) { response.status(200).json({ completed: true }); return; } await Telemetry.sendTelemetry("onboarding_complete"); // Have to send here since we have no other hooks. response.status(200).json({ valid: true, user: onboardingUser, token: makeJWT( { id: onboardingUser.id, email: onboardingUser.email }, "1hr" ), message: null, }); } catch (e) { console.log(e.message, e); response.sendStatus(500).end(); } }); app.post("/auth/login", async (request, response) => { try { const { email, password } = reqBody(request); if (!email || !password) { response.status(200).json({ user: null, valid: false, token: null, message: "[002] No email or password provided.", }); return; } if (email === process.env.SYS_EMAIL) { const completeSetup = (await User.count({ role: "admin" })) > 0; if (completeSetup) { response.status(200).json({ user: null, valid: false, token: null, message: "[004] Invalid login credentials.", }); return; } } const existingUser = await User.get({ email: email }); if (!existingUser) { response.status(200).json({ user: null, valid: false, token: null, message: "[001] Invalid login credentials.", }); return; } if (!bcrypt.compareSync(password, existingUser.password)) { response.status(200).json({ user: null, valid: false, token: null, message: "[002] Invalid login credentials.", }); return; } await Telemetry.sendTelemetry("login_event"); response.status(200).json({ valid: true, user: existingUser, token: makeJWT( { id: existingUser.id, email: existingUser.email }, "30d" ), message: null, }); return; } catch (e) { console.log(e.message, e); response.sendStatus(500).end(); } }); app.post("/auth/create-account", async (request, response) => { try { const { email, password } = reqBody(request); if (!email || !password) { response.status(200).json({ user: null, valid: false, token: null, message: "[002] No email or password provided.", }); return; } const adminCount = await User.count({ role: "admin" }); if (adminCount === 0) { response.status(200).json({ user: null, valid: false, token: null, message: "[000] System setup has not been completed - account creation disabled.", }); return; } const existingUser = await User.get({ email }); if (!!existingUser) { response.status(200).json({ user: null, valid: false, token: null, message: "[001] Account already exists by this email - use another.", }); return; } const allowingAccounts = await SystemSettings.get({ label: "allow_account_creation", }); if ( !!allowingAccounts && allowingAccounts.value !== null && allowingAccounts.value === "false" ) { response.status(200).json({ user: null, valid: false, token: null, message: "[003] Access denied.", }); return; } const domainRestriction = await SystemSettings.get({ label: "account_creation_domain_scope", }); if (domainRestriction && domainRestriction.value) { const emailDomain = email.substring(email.lastIndexOf("@") + 1); if (emailDomain !== domainRestriction.value) { response.status(200).json({ user: null, valid: false, token: null, message: "[003] Invalid account creation values.", }); return; } } const { user, message } = await User.create({ email, password }); if (!user) { response.status(200).json({ user: null, valid: false, token: null, message, }); return; } await User.addToAllOrgs(user.id); await Telemetry.sendTelemetry("login_event"); response.status(200).json({ user, valid: true, token: makeJWT({ id: user.id, email: user.email }, "30d"), message: null, }); return; } catch (e) { console.log(e.message, e); response.sendStatus(500).end(); } }); app.post("/auth/transfer-root", async (request, response) => { try { const { email, password } = reqBody(request); if (!email || !password) { response.status(200).json({ user: null, valid: false, token: null, message: "[002] No email or password provided.", }); return; } const adminCount = await User.count({ role: "admin" }); if (adminCount > 0) { response.status(200).json({ user: null, valid: false, token: null, message: "[000] System setup has already been completed - you cannot do this again.", }); return; } const existingUser = await User.get({ email }); if (!!existingUser) { response.status(200).json({ user: null, valid: false, token: null, message: "[001] Account already exists by this email - use another.", }); return; } const { user, message } = await User.create({ email, password, role: "admin", }); if (!user) { response.status(200).json({ user: null, valid: false, token: null, message, }); return; } response.status(200).json({ user, valid: true, token: makeJWT({ id: user.id, email: user.email }, "30d"), message: null, }); return; } catch (e) { console.log(e.message, e); response.sendStatus(500).end(); } }); } module.exports = { authenticationEndpoints };