burdy
Version:
Open Source Headless Platform
390 lines (389 loc) • 19.4 kB
JavaScript
"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;