UNPKG

burdy

Version:

Open Source Headless Platform

390 lines (389 loc) 19.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); const typeorm_1 = require("typeorm"); const user_model_1 = __importDefault(require("../models/user.model")); const user_session_model_1 = __importDefault(require("../models/user-session.model")); const jwt_1 = require("../common/jwt"); const auth_middleware_1 = __importDefault(require("../middleware/auth.middleware")); const async_middleware_1 = __importDefault(require("../middleware/async.middleware")); const bad_request_error_1 = __importDefault(require("../errors/bad-request-error")); const mail_driver_1 = require("../drivers/mail.driver"); const user_token_model_1 = __importStar(require("../models/user-token.model")); const yup = __importStar(require("yup")); const model_1 = require("../../shared/interfaces/model"); const date_fns_1 = require("date-fns"); const not_found_error_1 = __importDefault(require("../errors/not-found-error")); const orm_helpers_1 = require("../common/orm-helpers"); const lodash_1 = __importDefault(require("lodash")); const async_1 = __importDefault(require("async")); const validators_1 = __importDefault(require("../../shared/validators")); const permissions_1 = require("../../shared/features/permissions"); const hooks_1 = __importDefault(require("../../shared/features/hooks")); const site_settings_model_1 = __importDefault(require("../models/site-settings.model")); const app = (0, express_1.default)(); app.get('/loggedIn', (0, async_middleware_1.default)((req, res, next) => __awaiter(void 0, void 0, void 0, function* () { const siteSettingsRepository = (0, typeorm_1.getRepository)(site_settings_model_1.default); const initiated = yield siteSettingsRepository.findOne({ where: { key: 'initiated' }, }); if (!initiated) { throw new bad_request_error_1.default('not_initiated'); } return next(); })), (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const { user } = req.data; res.send(user); }))); app.post('/login', (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { yield req.validate({ email: validators_1.default.email() }); const { email, password } = req.body; const userRepository = (0, typeorm_1.getRepository)(user_model_1.default); const userSessionRepository = (0, typeorm_1.getRepository)(user_session_model_1.default); const user = yield userRepository.createQueryBuilder('user') .addSelect('user.password') .leftJoinAndSelect('user.groups', 'groups') .leftJoinAndSelect('user.meta', 'meta') .where('user.email = :email', { email: email.toLowerCase() }) .getOne(); yield req.validate({ email: validators_1.default.email().test('email-not-found', 'Email not found.', () => user !== undefined), password: validators_1.default.password(), }); if (user.status !== model_1.UserStatus.ACTIVE) throw new bad_request_error_1.default('inactive_user'); const result = yield user.comparePassword(password); if (!result) throw new bad_request_error_1.default('invalid_password'); const userSession = yield userSessionRepository.save({ user, expiresAt: (0, jwt_1.getExpires)(), }); const token = (0, jwt_1.sign)({ sessionId: userSession.id, userId: user.id, }); res.cookie('token', token, { maxAge: (0, jwt_1.getExpires)().getTime() * 1000, httpOnly: true, }); yield hooks_1.default.doAction('user/postLogin', user); res.send({ user, token }); }))); app.all('/logout', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const { user, session } = req.data; if (!session) throw new bad_request_error_1.default('not_logged_in'); const userSessionRepository = (0, typeorm_1.getRepository)(user_session_model_1.default); yield userSessionRepository.delete({ id: session === null || session === void 0 ? void 0 : session.id }); res.clearCookie('token'); yield hooks_1.default.doAction('user/postLogout', user); res.send(); }))); // Forgot is opened to public app.post('/forgot', (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _a; yield req.validate({ email: validators_1.default.email() }); const { email } = req.body; const userRepository = (0, typeorm_1.getRepository)(user_model_1.default); if ((_a = req.data) === null || _a === void 0 ? void 0 : _a.user) throw new bad_request_error_1.default('logged_in'); const user = yield userRepository.findOne({ where: { email: email.toLowerCase() }, }); if (!user) throw new bad_request_error_1.default('invalid_email'); yield (0, typeorm_1.getManager)().transaction((entityManager) => __awaiter(void 0, void 0, void 0, function* () { const userTokenRepository = (0, orm_helpers_1.getEnhancedRepository)(user_token_model_1.default, entityManager); const token = yield userTokenRepository.save({ expiresAt: (0, date_fns_1.addDays)(new Date(), 7), type: user_token_model_1.UserTokenType.RESET, user, }); (0, mail_driver_1.sendMail)({ subject: 'Forgot Password', from: 'test@burdy.io', to: email, html: JSON.stringify(token), }); })); res.send(); }))); app.post('/forgot/verify', (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { yield req.validate({ password: validators_1.default.password() }); const { token, password } = req.body; const userTokenRepository = (0, orm_helpers_1.getEnhancedRepository)(user_token_model_1.default); const userSessionRepository = (0, orm_helpers_1.getEnhancedRepository)(user_session_model_1.default); const userToken = yield userTokenRepository.findOne({ relations: ['user'], where: { token, type: user_token_model_1.UserTokenType.RESET }, }); if (!userToken) throw new bad_request_error_1.default('invalid_token'); const { user } = userToken; yield user.setPassword(password); yield (0, typeorm_1.getManager)().transaction((entityManager) => __awaiter(void 0, void 0, void 0, function* () { yield entityManager.save(user); yield entityManager.remove(userToken); })); userSessionRepository.delete({ user }); res.send(); }))); app.post('/forgot/reset', (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const { uuid, userId, password } = req.body; yield req.validate({ password: validators_1.default.password() }); yield (0, typeorm_1.getManager)().transaction((entityManager) => __awaiter(void 0, void 0, void 0, function* () { const userTokenRepository = (0, orm_helpers_1.getEnhancedRepository)(user_token_model_1.default, entityManager); const userToken = yield userTokenRepository.findOne({ relations: ['user'], where: { uuid, user: { id: userId }, }, }); if (!userToken) throw new bad_request_error_1.default('invalid_token'); const { user } = userToken; yield user.setPassword(password); yield user.save(); yield userToken.remove(); res.send(user); })); }))); app.get('/users', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _b, _c, _d, _e; const { search } = req.query; const userRepository = (0, typeorm_1.getRepository)(user_model_1.default); const query = userRepository.createQueryBuilder('user'); (0, orm_helpers_1.queryRelationsArray)(query, (_b = req.query) === null || _b === void 0 ? void 0 : _b.expand); if (!(0, permissions_1.hasPermissions)((_c = req === null || req === void 0 ? void 0 : req.data) === null || _c === void 0 ? void 0 : _c.user, ['all', 'users_administration'])) { query.where(`user.id = :id`, { id: (_e = (_d = req === null || req === void 0 ? void 0 : req.data) === null || _d === void 0 ? void 0 : _d.user) === null || _e === void 0 ? void 0 : _e.id }); } if (search) { query.where('user.email like :search', { search: `%${search}%` }); } if (typeof req.query.notIn === 'string') { query.where('user.id not in (:...ids)', { ids: req.query.notIn.split(','), }); } if (typeof req.query.in === 'string') { query.where('user.id in (:...ids)', { ids: req.query.in.split(',') }); } let users = yield query.getMany(); users = yield hooks_1.default.applyFilters('user/getMany', users); res.send(users); }))); app.post('/users', (0, auth_middleware_1.default)(['users_administration']), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const _f = lodash_1.default.pick(req.body, [ 'email', 'firstName', 'lastName', 'meta', 'password', 'status', 'groups', ]), { groups, meta, password } = _f, userParams = __rest(_f, ["groups", "meta", "password"]); yield req.validate({ email: validators_1.default.email().test('email-exists', 'Email taken.', () => __awaiter(void 0, void 0, void 0, function* () { var _g, _h; const userRepository = (0, typeorm_1.getRepository)(user_model_1.default); const user = yield userRepository.findOne({ where: { email: (_h = (_g = userParams.email) === null || _g === void 0 ? void 0 : _g.toLowerCase) === null || _h === void 0 ? void 0 : _h.call(_g) }, }); return user === undefined; })), password: validators_1.default.password(), }); yield (0, typeorm_1.getManager)().transaction((entityManager) => __awaiter(void 0, void 0, void 0, function* () { const userRepository = (0, orm_helpers_1.getEnhancedRepository)(user_model_1.default, entityManager); const user = yield userRepository.create(userParams); yield user.setPassword(password); user.applyMeta(meta); yield user.save(); if (Array.isArray(groups)) { yield userRepository.attach(user.id, 'groups', groups); } const userResponse = yield userRepository.findOne({ relations: ['groups', 'meta'], where: { id: user.id }, }); yield hooks_1.default.doAction('user/postCreate', userResponse); res.send(userResponse); })); }))); app.delete('/users/:id', (0, auth_middleware_1.default)(['users_administration']), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const { id } = req.params; if (id === req.data.user.id) throw new bad_request_error_1.default('cant_delete_self'); const userRepository = (0, typeorm_1.getRepository)(user_model_1.default); const user = yield userRepository.findOne(id); yield user.remove(); yield hooks_1.default.doAction('user/postDelete', user); res.send(); }))); app.delete('/users', (0, auth_middleware_1.default)(['users_administration']), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { yield req.validate({ ids: yup.array(), }); const { ids } = req.body; if (ids.includes(req.data.user.id)) throw new bad_request_error_1.default('cant_delete_self'); const userRepository = (0, typeorm_1.getRepository)(user_model_1.default); const users = yield userRepository.findByIds(ids); yield userRepository.delete(ids); yield hooks_1.default.doAction('user/postDeleteMany', users); res.send(); }))); app.get('/users/:id', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _j; const { id } = req.params; const userRepository = (0, typeorm_1.getRepository)(user_model_1.default); let user = yield userRepository.findOne({ relations: (0, orm_helpers_1.createRelationsArray)((_j = req.query) === null || _j === void 0 ? void 0 : _j.expand), where: { id }, }); if (!user) throw new not_found_error_1.default('not_found'); user = yield hooks_1.default.applyFilters('user/get', user); res.send(user); }))); app.put('/users/', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const users = req.body; const newUsers = []; yield async_1.default.each(users, (user, next) => __awaiter(void 0, void 0, void 0, function* () { const _k = lodash_1.default.pick(user, [ 'status', 'groups', 'meta', 'id', 'firstName', 'lastName' ]), { groups, meta } = _k, userParams = __rest(_k, ["groups", "meta"]); const { id } = userParams; yield (0, typeorm_1.getManager)().transaction((entityManager) => __awaiter(void 0, void 0, void 0, function* () { const userRepository = (0, orm_helpers_1.getEnhancedRepository)(user_model_1.default, entityManager); const user = yield userRepository.findOne(id, { relations: ['meta'] }); if (!user) throw new not_found_error_1.default('not_found'); const newUser = userRepository.merge(user, userParams); newUser.applyMeta(meta); if (Array.isArray(groups)) { yield userRepository.sync(id, 'groups', groups); } yield userRepository.save(newUser); const userResponse = yield userRepository.findOne({ relations: ['meta', 'groups'], where: { id: user.id }, }); newUsers.push(userResponse); })); next(); })); res.send(newUsers); }))); app.put('/users/:id', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const { id } = req.params; const _l = lodash_1.default.pick(req.body, [ 'status', 'groups', 'meta', 'firstName', 'lastName', ]), { groups, meta } = _l, userParams = __rest(_l, ["groups", "meta"]); yield (0, typeorm_1.getManager)().transaction((entityManager) => __awaiter(void 0, void 0, void 0, function* () { const userRepository = (0, orm_helpers_1.getEnhancedRepository)(user_model_1.default, entityManager); const user = yield userRepository.findOne(id, { relations: ['meta'] }); if (!user) throw new not_found_error_1.default('not_found'); const newUser = userRepository.merge(user, userParams); newUser.applyMeta(meta); if (Array.isArray(groups)) { yield userRepository.sync(id, 'groups', groups); } yield userRepository.save(newUser); const userResponse = yield userRepository.findOne({ relations: ['groups', 'meta'], where: { id }, }); res.send(userResponse); })); }))); app.post('/profile/change-password', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { yield req.validate({ password: validators_1.default.password() }); const { id } = req.data.user; const { currentPassword, password } = req.body; const userRepository = yield (0, orm_helpers_1.getEnhancedRepository)(user_model_1.default); const user = yield userRepository.createQueryBuilder('user') .addSelect('user.password') .where('user.id = :id', { id }) .getOne(); if (!user) throw new not_found_error_1.default('not_found'); const compareResult = yield user.comparePassword(currentPassword); if (!compareResult) throw new bad_request_error_1.default('wrong_password'); yield user.setPassword(password); userRepository.save(user); res.send(); }))); app.post('/users/reset-password/:id', (0, auth_middleware_1.default)(['users_administration']), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { yield req.validate({ password: validators_1.default.password() }); const { id } = req.params; const { password, notify } = req.body; const userRepository = yield (0, orm_helpers_1.getEnhancedRepository)(user_model_1.default); const userSessionRepository = yield (0, orm_helpers_1.getEnhancedRepository)(user_session_model_1.default); const user = yield userRepository.findOne(id); if (!user) throw new not_found_error_1.default('not_found'); yield user.setPassword(password); userRepository.save(user); if (notify) { // @TODO issue an email } userSessionRepository.delete({ user }); res.send(); }))); exports.default = app;