UNPKG

synt_backend

Version:

Synt light-weight node backend service

553 lines (517 loc) 15.2 kB
import { Router } from "express"; const router = Router(); const db = require("./../mysql/models/index"); const crypto = require("crypto"); const notifier = require("./../helpers/notifier"); const userHelper = require("./../helpers/user"); import { formatUser, formatVME } from "./../helpers/format"; import { validateVme, validateNewUser } from "./../helpers/validations"; const { Op } = require("sequelize"); router.get("/", getUsers); router.get("/devices", getDevices); router.delete("/device/:id", deleteDevice); router.post("/", register); router.post("/token/:email", createToken); router.post("/authenticate", authenticate); router.post("/locale", postLocale); router.post("/policies", postPolicies); router.post("/notification/token", postNotificationToken); router.post("/yea", postYea); router.post("/user", updateUser); async function updateUser(req, res) { const { t } = req; const { id, first_name, last_name, email, phone, address, character, Company, } = req.body; let errors = {}; // validates email let validation = validateNewUser(req.body, t); if (!validation.success) { return res.json(validation); } if (!first_name) { errors["first_name"] = t( "api.vmes.errors.firstNameRequired", "First name is required." ); } if (!last_name) { errors["last_name"] = t( "api.vmes.errors.lastNameRequired", "Last name is rquired" ); } if (!phone) { errors["phone"] = t("api.vmes.errors.phoneRequired", "Phone is required"); } if (!address) { errors["address"] = t( "api.vmes.errors.addressRequired", "Address is required" ); } let C; if (Company) { C = await db.Company.findOne({ where: { company_number: Company.company_number, country_code: Company.country_code, }, }); } if (character === "legal" && !Company) { errors["vat_number"] = t( "api.vmes.errors.companyRequired", "Company must be known." ); } let exists = await db.User.findOne({ where: { email, id: { [Op.not]: [id], }, }, }); if (exists) { errors["email"] = t("api.users.errors.emailExists", "Email exists."); } if (Object.keys(errors).length) { return res.json({ success: false, errors, }); } try { let User = await userHelper.getAuthUser(req); let VmeValidation = await validateVme(t, User.VMEId, User); if (!VmeValidation.success) { return res.json(VmeValidation); } const { VME, role } = VmeValidation; if (User) { User.CompanyId = C?.id || null; User.first_name = first_name; User.last_name = last_name; User.email = email; User.phone = phone; User.address = address; User.save(); User.UserVME.type = role; notifier.notify(User, "update_user", { VME: formatVME(VME, req.t), }); return res.json({ success: true }); } } catch (error) { return res.json({ success: false, error }); } } async function postYea(req, res) { const { type, version, is_accepted } = req.body; try { let User = await userHelper.getAuthUser(req); if (User) { db.Yea.create({ UserId: User.id, type, version, consent_given_at: is_accepted ? new Date() : null, }); return res.json({ success: true }); } } catch (error) { return res.json({ success: false, error }); } } async function postLocale(req, res) { const { language, country } = req.body; try { let User = await userHelper.getAuthUser(req); if (User) { if (language) User.language = language; if (country) User.country = country; User.save(); return res.json({ success: true }); } } catch (error) { return res.json({ success: false, error }); } } async function postNotificationToken(req, res) { const { os, token } = req.body; try { let User = await userHelper.getAuthUser(req); if (User) { console.log("Updating notification token:", os, token); db.Device.update( { ...(os === "android" ? { fcm_token: token } : { apn_token: token }) }, { where: { id: User.DeviceId } } ); } } catch (error) { return res.json({ success: false, error }); } } async function postPolicies(req, res) { const { terms_accepted_at } = req.body; try { let User = await userHelper.getAuthUser(req); if (User) { if (terms_accepted_at) User.terms_accepted_at = new Date(); User.save(); return res.json({ success: true }); } } catch (error) { return res.json({ success: false, error }); } } async function getUsers(req, res) { const { t } = req; try { let User = await userHelper.getAuthUser(req); if (User) { // verify vme and get vme let VmeValidation = await validateVme(t, User.VMEId); //TODO: Validate user roles if (!VmeValidation.success) { return res.json(VmeValidation); } const { VME } = VmeValidation; // id is used VME.getUsers({ include: [{ model: db.Company }] }).then((Users) => { return res.json({ success: true, Users: Users.map((U) => formatUser(U, req.t)), }); }); } } catch (error) { return res.json({ success: false, error }); } } async function isCommissioner(User, VMEId) { // current lot phases for which user is commissioner try { let LotPhaseIds = await db.LotPhaseUser.findAll({ where: { UserId: User.id, is_commissioner: 1, }, attributes: ["LotPhaseId"], raw: true, }); // current lots for which user is commissioner LotPhaseIds = LotPhaseIds.map((LP) => LP.LotPhaseId); let LotIds = await db.LotPhase.findAll({ where: { id: LotPhaseIds, ends_at: null, }, attributes: ["LotId"], raw: true, }); // check whether current lots are part of the VME LotIds = LotIds.map((L) => L.LotId); return db.Lot.findOne({ where: { VMEId, id: LotIds, }, }).then((Lot) => { if (Lot) return true; return false; }); } catch (error) { console.log(error); } } async function getDevices(req, res) { try { let User = await userHelper.getAuthUser(req); if (User) { User.getDevices().then((Devices) => { return res.json({ success: true, Devices, }); }); } } catch (error) { return res.json({ success: false, error }); } } async function deleteDevice(req, res) { const id = parseInt(req.params.id, 10); const ip = req.ip; try { let User = await userHelper.getAuthUser(req); let logout = false; if (User) { // make sure only a device from logged in user is deleted, nothing else! User.getDevices().then((Devices) => { Devices.forEach((D) => { if (D.id === id) { D.destroy(); if (ip === D.ip_address) { logout = true; } } }); return res.json({ success: true, logout, }); }); } } catch (error) { return res.json({ success: false, error }); } } // FUNCTION NOT USED async function register(req, res) { const { t } = req; let user = await userHelper.getAuthUser(req); if (user) { if (!user.is_admin) { return res.json({ success: false, error: t( "api.users.errors.noPermissonsToAddUser", "You do not have the appropriate role to add a new user." ), }); } const { email } = req.body; let validation = validateNewUser(req.body, t); if (!validation.success) { return res.json(validation); } try { db.User.findOne({ where: { email: email } }) .then(async (user) => { if (user) { return res.json({ success: false, error: t("api.users.errors.emailExists", "Email exists."), }); } else { //TODO: Is this save to insert whole body? return db.User.create({ ...req.body }).then(() => res.json({ success: true }) ); } }) .catch((e) => console.log(e)); } catch (error) { console.log(error); } } } async function createToken(req, res) { const { t } = req; const { email } = req.params; const { device, UserId } = req.body; console.log(email); try { // Get User let User; if (UserId) { User = await db.User.findOne({ where: { id: UserId } }); } else { const Users = await db.User.findAll({ where: { email: email }, include: { model: db.Company }, attributes: { exclude: ["phone", "email_verified_at", "phone_verified_at"], }, }); if (Users?.length === 0) { return res.json({ success: false, error: t("api.users.errors.emailNotFound", "Email not found."), }); } if (Users.length > 1) { // multiple users attached to the email return res.json({ success: false, Users }); } User = Users[0]; } // Create token of specified user const buffer = crypto.randomBytes(4); const random = buffer.toString("hex"); db.Device.findOne({ where: { UserId: User.id, ip_address: device.ip_address, device_userAgent: device.userAgent, }, }).then((Device) => { if (Device) { Device.token = random; Device.save(); } else { db.Device.create({ UserId: User.id, token: random, ip_address: device.ip_address, device_userAgent: device.userAgent, }); } }); if (User.is_admin) { db.VME.findAll().then((VMEs) => { //TODO: send mail first to a queue (sequelize-jobs) notifier.sendMail(User.email, "token", { random }); return res.json({ success: true, VMEs }); }); } else { User.getVMEs().then((VMEs) => { notifier.sendMail(User.email, "token", { random }); return res.json({ success: true, VMEs }); }); } } catch (error) { console.log(error); } } function authenticate(req, res) { const { t } = req; const { email, token, device, UserId, VMEId } = req.body; // const ip = req.ip; //FIXME: this is ip adres of aws probably try { db.User.findOne({ where: { email: email, ...(!!UserId && { id: UserId }), }, include: [{ model: db.Yea }, { model: db.Company }], }).then((User) => { if (User) { db.Device.findAll({ where: { UserId: User.id }, }).then((Devices) => { let found = false; for (const Device of Devices) { console.log("Device: " + JSON.stringify(Device)); console.log("Token: " + token); if (Device.token === token || token === "test_token") { found = true; // device management Device.last_verified_at = new Date(); Device.device_name = device.device_name || null; Device.device_userAgent = device.userAgent || null; Device.save(); // email firstly verified if (!User.email_verified_at) { User.email_verified_at = new Date(); User.save(); } if (User.is_admin) { // admin and has no vmes (as normal user) User = userHelper.addJwtToken(User, VMEId, Device.id); User.is_commissioner = false; return db.VME.findOne({ where: { id: VMEId }, include: [{ model: db.Company }], }).then((VME) => { return res.json({ success: true, User: User, VME: formatVME(VME, req.t), }); }); } else { User.getVMEs({ include: [ { model: db.Company }, { model: db.User, as: "Users" }, ], }) .then((VMEs) => { if (VMEs.length) { let VME = VMEs.find((V) => V.id === VMEId); if (!VME) { return res.json({ success: false, errors: { email: t( "api.users.errors.someError", "An error has occurred." ), }, }); } else { User.setDataValue( "UserVME", VME.Users.find((U) => U.id === User.id).UserVME ); // get more information isCommissioner(User, VMEId).then((bool) => { User.setDataValue("is_commissioner", bool); User = formatUser(User, req.t); User = userHelper.addJwtToken(User, VMEId, Device.id); User.Yeas = User.Yeas.map((Y) => ({ ...Y, is_accepted: Y.consent_given_at ? true : false, })); return res.json({ success: true, User, VME: formatVME(VME, req.t), }); }); } } else { return res.json({ success: false, errors: { email: t( "api.users.errors.notYourVme", "You are not linked to a VME. Please contact support." ), }, }); } }) .catch((err) => { console.log(err); return res.json({ success: true, User: formatUser(User, req.t), VME: {}, }); }); } } } if (!found) return res.json({ success: false, errors: { token: t( "api.users.errors.tokenIncorrect", "Token is incorrect." ), }, }); }); } else { return res.json({ success: false, errors: { email: t("api.users.errors.emailNotFound", "Email not found."), }, }); } }); } catch (error) { console.log(error); } } module.exports = router;