| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- const debug = require('debug')('growi:lib:middlewares');
- const md5 = require('md5');
- const entities = require('entities');
- exports.csrfKeyGenerator = function(crowi, app) {
- return function(req, res, next) {
- var csrfKey = (req.session && req.session.id) || 'anon';
- if (req.csrfToken === null) {
- req.csrfToken = crowi.getTokens().create(csrfKey);
- }
- next();
- };
- };
- exports.loginChecker = function(crowi, app) {
- return function(req, res, next) {
- var User = crowi.model('User');
- // session に user object が入ってる
- if (req.session.user && '_id' in req.session.user) {
- User.findById(req.session.user._id, function(err, userData) {
- if (err) {
- next();
- }
- else {
- req.user = req.session.user = userData;
- res.locals.user = req.user;
- next();
- }
- });
- }
- else {
- req.user = req.session.user = false;
- res.locals.user = req.user;
- next();
- }
- };
- };
- exports.loginCheckerForPassport = function(crowi, app) {
- return function(req, res, next) {
- if (req.user == null) {
- req.user = false;
- }
- res.locals.user = req.user;
- next();
- };
- };
- exports.csrfVerify = function(crowi, app) {
- return function(req, res, next) {
- var token = req.body._csrf || req.query._csrf || null;
- var csrfKey = (req.session && req.session.id) || 'anon';
- debug('req.skipCsrfVerify', req.skipCsrfVerify);
- if (req.skipCsrfVerify) {
- debug('csrf verify skipped');
- return next();
- }
- if (crowi.getTokens().verify(csrfKey, token)) {
- debug('csrf successfully verified');
- return next();
- }
- debug('csrf verification failed. return 403', csrfKey, token);
- return res.sendStatus(403);
- };
- };
- exports.swigFunctions = function(crowi, app) {
- return function(req, res, next) {
- require('../util/swigFunctions')(crowi, app, req, res.locals);
- next();
- };
- };
- exports.swigFilters = function(crowi, app, swig) {
- // define a function for Gravatar
- const generateGravatarSrc = function(user) {
- const email = user.email || '';
- const hash = md5(email.trim().toLowerCase());
- return `https://gravatar.com/avatar/${hash}`;
- };
- // define a function for uploaded picture
- const getUploadedPictureSrc = function(user) {
- if (user.image) {
- return user.image;
- }
- else {
- return '/images/icons/user.svg';
- }
- };
- return function(req, res, next) {
- swig.setFilter('path2name', function(string) {
- var name = string.replace(/(\/)$/, '');
- if (name.match(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/)) { // /.../hoge/YYYY/MM/DD 形式のページ
- return name.replace(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/, '$1');
- }
- if (name.match(/.+\/([^/]+\/\d{4}\/\d{2})$/)) { // /.../hoge/YYYY/MM 形式のページ
- return name.replace(/.+\/([^/]+\/\d{4}\/\d{2})$/, '$1');
- }
- if (name.match(/.+\/([^/]+\/\d{4})$/)) { // /.../hoge/YYYY 形式のページ
- return name.replace(/.+\/([^/]+\/\d{4})$/, '$1');
- }
- return name.replace(/.+\/(.+)?$/, '$1'); // ページの末尾を拾う
- });
- swig.setFilter('normalizeDateInPath', function(path) {
- var patterns = [
- [/20(\d{2})(\d{2})(\d{2})(.+)/g, '20$1/$2/$3/$4'],
- [/20(\d{2})(\d{2})(\d{2})/g, '20$1/$2/$3'],
- [/20(\d{2})(\d{2})(.+)/g, '20$1/$2/$3'],
- [/20(\d{2})(\d{2})/g, '20$1/$2'],
- [/20(\d{2})_(\d{1,2})_(\d{1,2})_?(.+)/g, '20$1/$2/$3/$4'],
- [/20(\d{2})_(\d{1,2})_(\d{1,2})/g, '20$1/$2/$3'],
- [/20(\d{2})_(\d{1,2})_?(.+)/g, '20$1/$2/$3'],
- [/20(\d{2})_(\d{1,2})/g, '20$1/$2'],
- ];
- for (var i = 0; i < patterns.length ; i++) {
- var mat = patterns[i][0];
- var rep = patterns[i][1];
- if (path.match(mat)) {
- return path.replace(mat, rep);
- }
- }
- return path;
- });
- swig.setFilter('datetz', function(input, format) {
- // timezone
- const swigFilters = require('swig-templates/lib/filters');
- return swigFilters.date(input, format, app.get('tzoffset'));
- });
- swig.setFilter('nl2br', function(string) {
- return string
- .replace(/\n/g, '<br>');
- });
- swig.setFilter('removeLastSlash', function(string) {
- if (string == '/') {
- return string;
- }
- return string.substr(0, string.length - 1);
- });
- swig.setFilter('presentation', function(string) {
- // 手抜き
- return string
- .replace(/[\n]+#/g, '\n\n\n#')
- .replace(/\s(https?.+(jpe?g|png|gif))\s/, '\n\n\n\n\n\n');
- });
- swig.setFilter('gravatar', generateGravatarSrc);
- swig.setFilter('uploadedpicture', getUploadedPictureSrc);
- swig.setFilter('picture', function(user) {
- if (!user) {
- return '/images/icons/user.svg';
- }
- if (user.isGravatarEnabled === true) {
- return generateGravatarSrc(user);
- }
- else {
- return getUploadedPictureSrc(user);
- }
- });
- swig.setFilter('encodeHTML', function(string) {
- return entities.encodeHTML(string);
- });
- swig.setFilter('preventXss', function(string) {
- return crowi.xss.process(string);
- });
- next();
- };
- };
- exports.adminRequired = function() {
- return function(req, res, next) {
- // check the user logged in
- // make sure that req.user isn't username/email string to login which is set by basic-auth-connect
- if (req.user != null && (req.user instanceof Object) && '_id' in req.user) {
- if (req.user.admin) {
- next();
- return;
- }
- return res.redirect('/');
- }
- return res.redirect('/login');
- };
- };
- /**
- * require login handler
- *
- * @param {any} crowi
- * @param {any} app
- * @param {boolean} isStrictly whethere strictly restricted (default true)
- */
- exports.loginRequired = function(crowi, app, isStrictly = true) {
- return function(req, res, next) {
- var User = crowi.model('User');
- // when the route is not strictly restricted
- if (!isStrictly) {
- var config = req.config;
- var Config = crowi.model('Config');
- // when allowed to read
- if (Config.isGuesstAllowedToRead(config)) {
- return next();
- }
- }
- // check the user logged in
- // make sure that req.user isn't username/email string to login which is set by basic-auth-connect
- if (req.user != null && (req.user instanceof Object) && '_id' in req.user) {
- if (req.user.status === User.STATUS_ACTIVE) {
- // Active の人だけ先に進める
- return next();
- }
- else if (req.user.status === User.STATUS_REGISTERED) {
- return res.redirect('/login/error/registered');
- }
- else if (req.user.status === User.STATUS_SUSPENDED) {
- return res.redirect('/login/error/suspended');
- }
- else if (req.user.status === User.STATUS_INVITED) {
- return res.redirect('/login/invited');
- }
- }
- // is api path
- var path = req.path || '';
- if (path.match(/^\/_api\/.+$/)) {
- return res.sendStatus(403);
- }
- req.session.jumpTo = req.originalUrl;
- return res.redirect('/login');
- };
- };
- exports.accessTokenParser = function(crowi, app) {
- return function(req, res, next) {
- // TODO: comply HTTP header of RFC6750 / Authorization: Bearer
- var accessToken = req.query.access_token || req.body.access_token || null;
- if (!accessToken) {
- return next();
- }
- var User = crowi.model('User');
- debug('accessToken is', accessToken);
- User.findUserByApiToken(accessToken)
- .then(function(userData) {
- req.user = userData;
- req.skipCsrfVerify = true;
- debug('Access token parsed: skipCsrfVerify');
- next();
- }).catch(function(err) {
- next();
- });
- };
- };
- // this is for Installer
- exports.applicationNotInstalled = function() {
- return function(req, res, next) {
- var config = req.config;
- if (Object.keys(config.crowi).length !== 1) {
- req.flash('errorMessage', 'Application already installed.');
- return res.redirect('admin'); // admin以外はadminRequiredで'/'にリダイレクトされる
- }
- return next();
- };
- };
- exports.checkSearchIndicesGenerated = function(crowi, app) {
- return function(req, res, next) {
- const searcher = crowi.getSearcher();
- // build index
- if (searcher) {
- searcher.buildIndex()
- .then((data) => {
- if (!data.errors) {
- debug('Index created.');
- }
- return searcher.addAllPages();
- })
- .catch((error) => {
- if (error.message != null && error.message.match(/index_already_exists_exception/)) {
- debug('Creating index is failed: ', error.message);
- }
- else {
- console.log(`Error while building index of Elasticsearch': ${error.message}`);
- }
- });
- }
- return next();
- };
- };
- exports.applicationInstalled = function() {
- return function(req, res, next) {
- var config = req.config;
- if (Object.keys(config.crowi).length === 1) { // app:url is set by process
- return res.redirect('/installer');
- }
- return next();
- };
- };
- exports.awsEnabled = function() {
- return function(req, res, next) {
- var config = req.config;
- if (config.crowi['aws:region'] !== '' && config.crowi['aws:bucket'] !== '' && config.crowi['aws:accessKeyId'] !== '' && config.crowi['aws:secretAccessKey'] !== '') {
- req.flash('globalError', 'AWS settings required to use this function. Please ask the administrator.');
- return res.redirect('/');
- }
- return next();
- };
- };
|