Yuki Takei пре 7 година
родитељ
комит
3f0ada2f77

+ 1 - 4
.eslintrc.js

@@ -48,10 +48,7 @@ module.exports = {
       'error',
       'error',
       { props: false },
       { props: false },
     ],
     ],
-    'no-plusplus': [
-      'error',
-      { allowForLoopAfterthoughts: true },
-    ],
+    'no-plusplus': 'off',
     // Allow only for-of
     // Allow only for-of
     // https://qiita.com/the_red/items/0c826e97b57da6d67621
     // https://qiita.com/the_red/items/0c826e97b57da6d67621
     'no-restricted-syntax': [
     'no-restricted-syntax': [

+ 7 - 9
src/server/util/apiPaginate.js

@@ -1,5 +1,3 @@
-'use strict';
-
 const LIMIT_DEFAULT = 50;
 const LIMIT_DEFAULT = 50;
 const LIMIT_MAX = 1000;
 const LIMIT_MAX = 1000;
 
 
@@ -12,7 +10,7 @@ const parseIntValue = function(value, defaultValue, maxLimit) {
     return defaultValue;
     return defaultValue;
   }
   }
 
 
-  let v = parseInt(value);
+  const v = parseInt(value, 10);
   if (!maxLimit) {
   if (!maxLimit) {
     return v;
     return v;
   }
   }
@@ -23,22 +21,22 @@ const parseIntValue = function(value, defaultValue, maxLimit) {
 function ApiPaginate() {}
 function ApiPaginate() {}
 
 
 ApiPaginate.parseOptionsForElasticSearch = function(params) {
 ApiPaginate.parseOptionsForElasticSearch = function(params) {
-  let limit = parseIntValue(params.limit, LIMIT_DEFAULT, LIMIT_MAX);
-  let offset = parseIntValue(params.offset, OFFSET_DEFAULT);
+  const limit = parseIntValue(params.limit, LIMIT_DEFAULT, LIMIT_MAX);
+  const offset = parseIntValue(params.offset, OFFSET_DEFAULT);
 
 
   // See https://github.com/crowi/crowi/pull/293
   // See https://github.com/crowi/crowi/pull/293
   if (limit + offset > DEFAULT_MAX_RESULT_WINDOW) {
   if (limit + offset > DEFAULT_MAX_RESULT_WINDOW) {
     throw new Error(`(limit + offset) must be less than or equal to ${DEFAULT_MAX_RESULT_WINDOW}`);
     throw new Error(`(limit + offset) must be less than or equal to ${DEFAULT_MAX_RESULT_WINDOW}`);
   }
   }
 
 
-  return { limit: limit, offset: offset };
+  return { limit, offset };
 };
 };
 
 
 ApiPaginate.parseOptions = function(params) {
 ApiPaginate.parseOptions = function(params) {
-  let limit = parseIntValue(params.limit, LIMIT_DEFAULT, LIMIT_MAX);
-  let offset = parseIntValue(params.offset, OFFSET_DEFAULT);
+  const limit = parseIntValue(params.limit, LIMIT_DEFAULT, LIMIT_MAX);
+  const offset = parseIntValue(params.offset, OFFSET_DEFAULT);
 
 
-  return { limit: limit, offset: offset };
+  return { limit, offset };
 };
 };
 
 
 module.exports = ApiPaginate;
 module.exports = ApiPaginate;

+ 0 - 2
src/server/util/apiResponse.js

@@ -1,5 +1,3 @@
-'use strict';
-
 function ApiResponse() {
 function ApiResponse() {
 }
 }
 
 

+ 4 - 4
src/server/util/createGrowiPagesFromImports.js

@@ -1,6 +1,4 @@
-module.exports = crowi => {
-  'use strict';
-
+module.exports = (crowi) => {
   const Page = crowi.model('Page');
   const Page = crowi.model('Page');
 
 
   /**
   /**
@@ -15,7 +13,8 @@ module.exports = crowi => {
     const promises = [];
     const promises = [];
     const errors = [];
     const errors = [];
 
 
-    for (let page of pages) {
+    /* eslint-disable no-await-in-loop */
+    for (const page of pages) {
       const path = page.path;
       const path = page.path;
       const user = page.user;
       const user = page.user;
       const body = page.body;
       const body = page.body;
@@ -40,6 +39,7 @@ module.exports = crowi => {
         }
         }
       }
       }
     }
     }
+    /* eslint-enable no-await-in-loop */
 
 
     await Promise.all(promises);
     await Promise.all(promises);
 
 

+ 4 - 6
src/server/util/formUtil.js

@@ -1,13 +1,12 @@
-'use strict';
+
 
 
 module.exports = {
 module.exports = {
-  normalizeCRLFFilter: function(value) {
+  normalizeCRLFFilter(value) {
     return value
     return value
       .replace(/\r\n/g, '\n')
       .replace(/\r\n/g, '\n')
-      .replace(/\r/g, '\n')
-    ;
+      .replace(/\r/g, '\n');
   },
   },
-  stringToArrayFilter: function(value) {
+  stringToArrayFilter(value) {
     if (!value || value === '') {
     if (!value || value === '') {
       return [];
       return [];
     }
     }
@@ -15,4 +14,3 @@ module.exports = {
     return value.split('\n');
     return value.split('\n');
   },
   },
 };
 };
-

+ 3 - 3
src/server/util/getToday.js

@@ -4,9 +4,9 @@
 
 
 module.exports = function() {
 module.exports = function() {
   const today = new Date();
   const today = new Date();
-  const month = ('0' + (today.getMonth() + 1)).slice(-2);
-  const day = ('0' + today.getDate()).slice(-2);
-  const dateString = today.getFullYear() + '/' + month + '/' + day;
+  const month = (`0${today.getMonth() + 1}`).slice(-2);
+  const day = (`0${today.getDate()}`).slice(-2);
+  const dateString = `${today.getFullYear()}/${month}/${day}`;
 
 
   return dateString;
   return dateString;
 };
 };

+ 10 - 13
src/server/util/googleAuth.js

@@ -7,25 +7,22 @@ const { GoogleApis } = require('googleapis');
  */
  */
 
 
 module.exports = function(crowi) {
 module.exports = function(crowi) {
-  'use strict';
-
-  const google = new GoogleApis()
-    , config = crowi.getConfig()
-    , lib = {}
-    ;
+  const google = new GoogleApis();
+  const config = crowi.getConfig();
 
 
+  const lib = {};
   function createOauth2Client(url) {
   function createOauth2Client(url) {
     return new google.auth.OAuth2(
     return new google.auth.OAuth2(
       config.crowi['google:clientId'],
       config.crowi['google:clientId'],
       config.crowi['google:clientSecret'],
       config.crowi['google:clientSecret'],
-      url
+      url,
     );
     );
   }
   }
 
 
   lib.createAuthUrl = function(req, callback) {
   lib.createAuthUrl = function(req, callback) {
     const callbackUrl = urljoin(crowi.configManager.getSiteUrl(), '/google/callback');
     const callbackUrl = urljoin(crowi.configManager.getSiteUrl(), '/google/callback');
     const oauth2Client = createOauth2Client(callbackUrl);
     const oauth2Client = createOauth2Client(callbackUrl);
-    google.options({auth: oauth2Client});
+    google.options({ auth: oauth2Client });
 
 
     const redirectUrl = oauth2Client.generateAuthUrl({
     const redirectUrl = oauth2Client.generateAuthUrl({
       access_type: 'offline',
       access_type: 'offline',
@@ -38,7 +35,7 @@ module.exports = function(crowi) {
   lib.handleCallback = function(req, callback) {
   lib.handleCallback = function(req, callback) {
     const callbackUrl = urljoin(crowi.configManager.getSiteUrl(), '/google/callback');
     const callbackUrl = urljoin(crowi.configManager.getSiteUrl(), '/google/callback');
     const oauth2Client = createOauth2Client(callbackUrl);
     const oauth2Client = createOauth2Client(callbackUrl);
-    google.options({auth: oauth2Client});
+    google.options({ auth: oauth2Client });
 
 
     const code = req.session.googleAuthCode || null;
     const code = req.session.googleAuthCode || null;
 
 
@@ -47,7 +44,7 @@ module.exports = function(crowi) {
     }
     }
 
 
     debug('Request googleToken by auth code', code);
     debug('Request googleToken by auth code', code);
-    oauth2Client.getToken(code, function(err, tokens) {
+    oauth2Client.getToken(code, (err, tokens) => {
       debug('Result of google.getToken()', err, tokens);
       debug('Result of google.getToken()', err, tokens);
       if (err) {
       if (err) {
         return callback(new Error('[googleAuth.handleCallback] Error to get token.'), null);
         return callback(new Error('[googleAuth.handleCallback] Error to get token.'), null);
@@ -56,14 +53,14 @@ module.exports = function(crowi) {
       oauth2Client.credentials = tokens;
       oauth2Client.credentials = tokens;
 
 
       const oauth2 = google.oauth2('v2');
       const oauth2 = google.oauth2('v2');
-      oauth2.userinfo.get({}, function(err, response) {
+      oauth2.userinfo.get({}, (err, response) => {
         debug('Response of oauth2.userinfo.get', err, response);
         debug('Response of oauth2.userinfo.get', err, response);
         if (err) {
         if (err) {
           return callback(new Error('[googleAuth.handleCallback] Error while proceccing userinfo.get.'), null);
           return callback(new Error('[googleAuth.handleCallback] Error while proceccing userinfo.get.'), null);
         }
         }
 
 
-        let data = response.data;
-        data.user_id = data.id;           // This is for B.C. (tokeninfo をつかっている前提のコードに対してのもの)
+        const data = response.data;
+        data.user_id = data.id; // This is for B.C. (tokeninfo をつかっている前提のコードに対してのもの)
         return callback(null, data);
         return callback(null, data);
       });
       });
     });
     });

+ 3 - 3
src/server/util/i18nUserSettingDetector.js

@@ -1,7 +1,7 @@
 module.exports = {
 module.exports = {
   name: 'userSettingDetector',
   name: 'userSettingDetector',
 
 
-  lookup: function(req, res, options) {
+  lookup(req, res, options) {
     // return null if
     // return null if
     //  1. user doesn't logged in
     //  1. user doesn't logged in
     //  2. req.user is username/email string to login which is set by basic-auth-connect
     //  2. req.user is username/email string to login which is set by basic-auth-connect
@@ -11,7 +11,7 @@ module.exports = {
     return req.user.lang || null;
     return req.user.lang || null;
   },
   },
 
 
-  cacheUserlanguage: function(req, res, lng, options) {
+  cacheUserlanguage(req, res, lng, options) {
     // nothing to do
     // nothing to do
-  }
+  },
 };
 };

+ 16 - 14
src/server/util/importer.js

@@ -1,15 +1,17 @@
 /**
 /**
  * importer
  * importer
  */
  */
-module.exports = crowi => {
-  'use strict';
 
 
+/* eslint-disable no-use-before-define */
+
+module.exports = (crowi) => {
   const logger = require('@alias/logger')('growi:util:importer');
   const logger = require('@alias/logger')('growi:util:importer');
   const esa = require('esa-nodejs');
   const esa = require('esa-nodejs');
   const config = crowi.getConfig();
   const config = crowi.getConfig();
   const createGrowiPages = require('./createGrowiPagesFromImports')(crowi);
   const createGrowiPages = require('./createGrowiPagesFromImports')(crowi);
   const restQiitaAPIService = crowi.getRestQiitaAPIService();
   const restQiitaAPIService = crowi.getRestQiitaAPIService();
-  let importer = {};
+
+  const importer = {};
   let esaClient = {};
   let esaClient = {};
 
 
   /**
   /**
@@ -34,7 +36,7 @@ module.exports = crowi => {
   /**
   /**
    * Import page data from esa to GROWI
    * Import page data from esa to GROWI
    */
    */
-  importer.importDataFromEsa = user => {
+  importer.importDataFromEsa = (user) => {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
       const firstPage = 1;
       const firstPage = 1;
       const errors = importPostsFromEsa(firstPage, user, []);
       const errors = importPostsFromEsa(firstPage, user, []);
@@ -49,12 +51,12 @@ module.exports = crowi => {
    */
    */
   const importPostsFromEsa = (pageNum, user, errors) => {
   const importPostsFromEsa = (pageNum, user, errors) => {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
-      esaClient.api.posts({page: pageNum, per_page: 100}, async(err, res) => {
+      esaClient.api.posts({ page: pageNum, per_page: 100 }, async(err, res) => {
         const nextPage = res.body.next_page;
         const nextPage = res.body.next_page;
         const postsReceived = res.body.posts;
         const postsReceived = res.body.posts;
 
 
         if (err) {
         if (err) {
-          reject(`error in page ${pageNum}: ${err}`);
+          reject(new Error(`error in page ${pageNum}: ${err}`));
         }
         }
 
 
         const data = convertEsaDataForGrowi(postsReceived, user);
         const data = convertEsaDataForGrowi(postsReceived, user);
@@ -83,9 +85,9 @@ module.exports = crowi => {
    * @param {string} pageNum default value is '1'
    * @param {string} pageNum default value is '1'
    */
    */
   const importPostsFromQiita = async(pageNum, user, errors) => {
   const importPostsFromQiita = async(pageNum, user, errors) => {
-    const per_page = '100';
-    const res = await restQiitaAPIService.getQiitaPages(pageNum, per_page);
-    const next = pageNum * per_page;
+    const perPage = '100';
+    const res = await restQiitaAPIService.getQiitaPages(pageNum, perPage);
+    const next = pageNum * perPage;
     const postsReceived = res.pages;
     const postsReceived = res.pages;
     const pageTotal = res.total;
     const pageTotal = res.total;
     const data = convertQiitaDataForGrowi(postsReceived, user);
     const data = convertQiitaDataForGrowi(postsReceived, user);
@@ -103,7 +105,7 @@ module.exports = crowi => {
    */
    */
   const convertEsaDataForGrowi = (pages, user) => {
   const convertEsaDataForGrowi = (pages, user) => {
     const basePage = '';
     const basePage = '';
-    const data = pages.map(post => {
+    const data = pages.map((post) => {
       const category = post.category;
       const category = post.category;
       const name = post.name;
       const name = post.name;
 
 
@@ -122,7 +124,7 @@ module.exports = crowi => {
       return {
       return {
         path: `${basePage}/${path}`,
         path: `${basePage}/${path}`,
         body: post.body_md,
         body: post.body_md,
-        user: user,
+        user,
       };
       };
     });
     });
 
 
@@ -134,14 +136,14 @@ module.exports = crowi => {
    */
    */
   const convertQiitaDataForGrowi = (pages, user) => {
   const convertQiitaDataForGrowi = (pages, user) => {
     const basePage = '';
     const basePage = '';
-    const data = pages.map(post => {
+    const data = pages.map((post) => {
       const title = post.title;
       const title = post.title;
-      let path = title;
+      const path = title;
 
 
       return {
       return {
         path: `${basePage}/${path}`,
         path: `${basePage}/${path}`,
         body: post.body,
         body: post.body,
-        user: user,
+        user,
       };
       };
     });
     });
 
 

+ 34 - 42
src/server/util/mailer.js

@@ -3,58 +3,51 @@
  */
  */
 
 
 module.exports = function(crowi) {
 module.exports = function(crowi) {
-  'use strict';
-
-  var debug = require('debug')('growi:lib:mailer')
-    , nodemailer = require('nodemailer')
-    , swig = require('swig-templates')
-    , Config = crowi.model('Config')
-    , config = crowi.getConfig()
-    , mailConfig = {}
-    , mailer = {}
-    ;
+  const debug = require('debug')('growi:lib:mailer');
+  const nodemailer = require('nodemailer');
+  const swig = require('swig-templates');
+  const Config = crowi.model('Config');
+  const config = crowi.getConfig();
+  const mailConfig = {};
 
 
+  let mailer = {};
 
 
   function createSMTPClient(option) {
   function createSMTPClient(option) {
-    var client;
-
     debug('createSMTPClient option', option);
     debug('createSMTPClient option', option);
     if (!option) {
     if (!option) {
-      option = {
+      option = { // eslint-disable-line no-param-reassign
         host: config.crowi['mail:smtpHost'],
         host: config.crowi['mail:smtpHost'],
         port: config.crowi['mail:smtpPort'],
         port: config.crowi['mail:smtpPort'],
       };
       };
 
 
       if (config.crowi['mail:smtpUser'] && config.crowi['mail:smtpPassword']) {
       if (config.crowi['mail:smtpUser'] && config.crowi['mail:smtpPassword']) {
-        option.auth =  {
+        option.auth = {
           user: config.crowi['mail:smtpUser'],
           user: config.crowi['mail:smtpUser'],
-          pass: config.crowi['mail:smtpPassword']
+          pass: config.crowi['mail:smtpPassword'],
         };
         };
       }
       }
       if (option.port === 465) {
       if (option.port === 465) {
         option.secure = true;
         option.secure = true;
       }
       }
     }
     }
-    option.tls = {rejectUnauthorized: false};
+    option.tls = { rejectUnauthorized: false };
 
 
-    client = nodemailer.createTransport(option);
+    const client = nodemailer.createTransport(option);
 
 
     debug('mailer set up for SMTP', client);
     debug('mailer set up for SMTP', client);
     return client;
     return client;
   }
   }
 
 
   function createSESClient(option) {
   function createSESClient(option) {
-    var client;
-
     if (!option) {
     if (!option) {
-      option = {
+      option = { // eslint-disable-line no-param-reassign
         accessKeyId: config.crowi['aws:accessKeyId'],
         accessKeyId: config.crowi['aws:accessKeyId'],
-        secretAccessKey: config.crowi['aws:secretAccessKey']
+        secretAccessKey: config.crowi['aws:secretAccessKey'],
       };
       };
     }
     }
 
 
-    var ses = require('nodemailer-ses-transport');
-    client = nodemailer.createTransport(ses(option));
+    const ses = require('nodemailer-ses-transport');
+    const client = nodemailer.createTransport(ses(option));
 
 
     debug('mailer set up for SES', client);
     debug('mailer set up for SES', client);
     return client;
     return client;
@@ -70,7 +63,6 @@ module.exports = function(crowi) {
     ) {
     ) {
       // SMTP 設定がある場合はそれを優先
       // SMTP 設定がある場合はそれを優先
       mailer = createSMTPClient();
       mailer = createSMTPClient();
-
     }
     }
     else if (config.crowi['aws:accessKeyId'] && config.crowi['aws:secretAccessKey']) {
     else if (config.crowi['aws:accessKeyId'] && config.crowi['aws:secretAccessKey']) {
       // AWS 設定がある場合はSESを設定
       // AWS 設定がある場合はSESを設定
@@ -81,20 +73,21 @@ module.exports = function(crowi) {
     }
     }
 
 
     mailConfig.from = config.crowi['mail:from'];
     mailConfig.from = config.crowi['mail:from'];
-    mailConfig.subject = Config.appTitle(config)  + 'からのメール';
+    mailConfig.subject = `${Config.appTitle(config)}からのメール`;
 
 
     debug('mailer initialized');
     debug('mailer initialized');
   }
   }
 
 
   function setupMailConfig(overrideConfig) {
   function setupMailConfig(overrideConfig) {
-    var c = overrideConfig
-      , mc = {}
-      ;
+    const c = overrideConfig;
+
+
+    let mc = {};
     mc = mailConfig;
     mc = mailConfig;
 
 
-    mc.to      = c.to;
-    mc.from    = c.from || mailConfig.from;
-    mc.text    = c.text;
+    mc.to = c.to;
+    mc.from = c.from || mailConfig.from;
+    mc.text = c.text;
     mc.subject = c.subject || mailConfig.subject;
     mc.subject = c.subject || mailConfig.subject;
 
 
     return mc;
     return mc;
@@ -102,33 +95,32 @@ module.exports = function(crowi) {
 
 
   function send(config, callback) {
   function send(config, callback) {
     if (mailer) {
     if (mailer) {
-      var templateVars = config.vars || {};
+      const templateVars = config.vars || {};
       return swig.renderFile(
       return swig.renderFile(
         config.template,
         config.template,
         templateVars,
         templateVars,
-        function(err, output) {
+        (err, output) => {
           if (err) {
           if (err) {
             throw err;
             throw err;
           }
           }
 
 
           config.text = output;
           config.text = output;
           return mailer.sendMail(setupMailConfig(config), callback);
           return mailer.sendMail(setupMailConfig(config), callback);
-        }
+        },
       );
       );
     }
     }
-    else {
-      debug('Mailer is not completed to set up. Please set up SMTP or AWS setting.');
-      return callback(new Error('Mailer is not completed to set up. Please set up SMTP or AWS setting.'), null);
-    }
+
+    debug('Mailer is not completed to set up. Please set up SMTP or AWS setting.');
+    return callback(new Error('Mailer is not completed to set up. Please set up SMTP or AWS setting.'), null);
   }
   }
 
 
 
 
   initialize();
   initialize();
 
 
   return {
   return {
-    createSMTPClient: createSMTPClient,
-    createSESClient: createSESClient,
-    mailer: mailer,
-    send: send,
+    createSMTPClient,
+    createSESClient,
+    mailer,
+    send,
   };
   };
 };
 };

+ 42 - 41
src/server/util/middlewares.js

@@ -7,7 +7,7 @@ const entities = require('entities');
 
 
 exports.csrfKeyGenerator = function(crowi, app) {
 exports.csrfKeyGenerator = function(crowi, app) {
   return function(req, res, next) {
   return function(req, res, next) {
-    var csrfKey = (req.session && req.session.id) || 'anon';
+    const csrfKey = (req.session && req.session.id) || 'anon';
 
 
     if (req.csrfToken === null) {
     if (req.csrfToken === null) {
       req.csrfToken = crowi.getTokens().create(csrfKey);
       req.csrfToken = crowi.getTokens().create(csrfKey);
@@ -28,7 +28,8 @@ exports.loginChecker = function(crowi, app) {
         user = await User.findById(req.session.user._id).populate(User.IMAGE_POPULATION);
         user = await User.findById(req.session.user._id).populate(User.IMAGE_POPULATION);
       }
       }
 
 
-      req.user = req.session.user = user;
+      req.user = user;
+      req.session.user = user;
       res.locals.user = req.user;
       res.locals.user = req.user;
       next();
       next();
     }
     }
@@ -47,8 +48,8 @@ exports.loginCheckerForPassport = function(crowi, app) {
 
 
 exports.csrfVerify = function(crowi, app) {
 exports.csrfVerify = function(crowi, app) {
   return function(req, res, next) {
   return function(req, res, next) {
-    var token = req.body._csrf || req.query._csrf || null;
-    var csrfKey = (req.session && req.session.id) || 'anon';
+    const token = req.body._csrf || req.query._csrf || null;
+    const csrfKey = (req.session && req.session.id) || 'anon';
 
 
     debug('req.skipCsrfVerify', req.skipCsrfVerify);
     debug('req.skipCsrfVerify', req.skipCsrfVerify);
     if (req.skipCsrfVerify) {
     if (req.skipCsrfVerify) {
@@ -74,7 +75,6 @@ exports.swigFunctions = function(crowi, app) {
 };
 };
 
 
 exports.swigFilters = function(crowi, app, swig) {
 exports.swigFilters = function(crowi, app, swig) {
-
   // define a function for Gravatar
   // define a function for Gravatar
   const generateGravatarSrc = function(user) {
   const generateGravatarSrc = function(user) {
     const email = user.email || '';
     const email = user.email || '';
@@ -87,18 +87,17 @@ exports.swigFilters = function(crowi, app, swig) {
     if (user.image) {
     if (user.image) {
       return user.image;
       return user.image;
     }
     }
-    else if (user.imageAttachment != null) {
+    if (user.imageAttachment != null) {
       return user.imageAttachment.filePathProxied;
       return user.imageAttachment.filePathProxied;
     }
     }
-    else {
-      return '/images/icons/user.svg';
-    }
+
+    return '/images/icons/user.svg';
   };
   };
 
 
 
 
   return function(req, res, next) {
   return function(req, res, next) {
-    swig.setFilter('path2name', function(string) {
-      var name = string.replace(/(\/)$/, '');
+    swig.setFilter('path2name', (string) => {
+      const name = string.replace(/(\/)$/, '');
 
 
       if (name.match(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/)) { // /.../hoge/YYYY/MM/DD 形式のページ
       if (name.match(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/)) { // /.../hoge/YYYY/MM/DD 形式のページ
         return name.replace(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/, '$1');
         return name.replace(/.+\/([^/]+\/\d{4}\/\d{2}\/\d{2})$/, '$1');
@@ -113,8 +112,8 @@ exports.swigFilters = function(crowi, app, swig) {
       return name.replace(/.+\/(.+)?$/, '$1'); // ページの末尾を拾う
       return name.replace(/.+\/(.+)?$/, '$1'); // ページの末尾を拾う
     });
     });
 
 
-    swig.setFilter('normalizeDateInPath', function(path) {
-      var patterns = [
+    swig.setFilter('normalizeDateInPath', (path) => {
+      const 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/$4'],
         [/20(\d{2})(\d{2})(\d{2})/g, '20$1/$2/$3'],
         [/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/$3'],
@@ -125,9 +124,9 @@ exports.swigFilters = function(crowi, app, swig) {
         [/20(\d{2})_(\d{1,2})/g, '20$1/$2'],
         [/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];
+      for (let i = 0; i < patterns.length; i++) {
+        const mat = patterns[i][0];
+        const rep = patterns[i][1];
         if (path.match(mat)) {
         if (path.match(mat)) {
           return path.replace(mat, rep);
           return path.replace(mat, rep);
         }
         }
@@ -136,22 +135,22 @@ exports.swigFilters = function(crowi, app, swig) {
       return path;
       return path;
     });
     });
 
 
-    swig.setFilter('datetz', function(input, format) {
+    swig.setFilter('datetz', (input, format) => {
       // timezone
       // timezone
       const swigFilters = require('swig-templates/lib/filters');
       const swigFilters = require('swig-templates/lib/filters');
       return swigFilters.date(input, format, app.get('tzoffset'));
       return swigFilters.date(input, format, app.get('tzoffset'));
     });
     });
 
 
-    swig.setFilter('nl2br', function(string) {
+    swig.setFilter('nl2br', (string) => {
       return string
       return string
         .replace(/\n/g, '<br>');
         .replace(/\n/g, '<br>');
     });
     });
 
 
-    swig.setFilter('removeTrailingSlash', function(string) {
+    swig.setFilter('removeTrailingSlash', (string) => {
       return pathUtils.removeTrailingSlash(string);
       return pathUtils.removeTrailingSlash(string);
     });
     });
 
 
-    swig.setFilter('presentation', function(string) {
+    swig.setFilter('presentation', (string) => {
       // 手抜き
       // 手抜き
       return string
       return string
         .replace(/\s(https?.+(jpe?g|png|gif))\s/, '\n\n\n![]($1)\n\n\n');
         .replace(/\s(https?.+(jpe?g|png|gif))\s/, '\n\n\n![]($1)\n\n\n');
@@ -160,7 +159,7 @@ exports.swigFilters = function(crowi, app, swig) {
     swig.setFilter('gravatar', generateGravatarSrc);
     swig.setFilter('gravatar', generateGravatarSrc);
     swig.setFilter('uploadedpicture', getUploadedPictureSrc);
     swig.setFilter('uploadedpicture', getUploadedPictureSrc);
 
 
-    swig.setFilter('picture', function(user) {
+    swig.setFilter('picture', (user) => {
       if (!user) {
       if (!user) {
         return '/images/icons/user.svg';
         return '/images/icons/user.svg';
       }
       }
@@ -168,20 +167,19 @@ exports.swigFilters = function(crowi, app, swig) {
       if (user.isGravatarEnabled === true) {
       if (user.isGravatarEnabled === true) {
         return generateGravatarSrc(user);
         return generateGravatarSrc(user);
       }
       }
-      else {
-        return getUploadedPictureSrc(user);
-      }
+
+      return getUploadedPictureSrc(user);
     });
     });
 
 
-    swig.setFilter('encodeHTML', function(string) {
+    swig.setFilter('encodeHTML', (string) => {
       return entities.encodeHTML(string);
       return entities.encodeHTML(string);
     });
     });
 
 
-    swig.setFilter('preventXss', function(string) {
+    swig.setFilter('preventXss', (string) => {
       return crowi.xss.process(string);
       return crowi.xss.process(string);
     });
     });
 
 
-    swig.setFilter('slice', function(list, start, end) {
+    swig.setFilter('slice', (list, start, end) => {
       return list.slice(start, end);
       return list.slice(start, end);
     });
     });
 
 
@@ -213,12 +211,12 @@ exports.adminRequired = function() {
  */
  */
 exports.loginRequired = function(crowi, app, isStrictly = true) {
 exports.loginRequired = function(crowi, app, isStrictly = true) {
   return function(req, res, next) {
   return function(req, res, next) {
-    var User = crowi.model('User');
+    const User = crowi.model('User');
 
 
     // when the route is not strictly restricted
     // when the route is not strictly restricted
     if (!isStrictly) {
     if (!isStrictly) {
-      var config = req.config;
-      var Config = crowi.model('Config');
+      const config = req.config;
+      const Config = crowi.model('Config');
 
 
       // when allowed to read
       // when allowed to read
       if (Config.isGuestAllowedToRead(config)) {
       if (Config.isGuestAllowedToRead(config)) {
@@ -233,19 +231,19 @@ exports.loginRequired = function(crowi, app, isStrictly = true) {
         // Active の人だけ先に進める
         // Active の人だけ先に進める
         return next();
         return next();
       }
       }
-      else if (req.user.status === User.STATUS_REGISTERED) {
+      if (req.user.status === User.STATUS_REGISTERED) {
         return res.redirect('/login/error/registered');
         return res.redirect('/login/error/registered');
       }
       }
-      else if (req.user.status === User.STATUS_SUSPENDED) {
+      if (req.user.status === User.STATUS_SUSPENDED) {
         return res.redirect('/login/error/suspended');
         return res.redirect('/login/error/suspended');
       }
       }
-      else if (req.user.status === User.STATUS_INVITED) {
+      if (req.user.status === User.STATUS_INVITED) {
         return res.redirect('/login/invited');
         return res.redirect('/login/invited');
       }
       }
     }
     }
 
 
     // is api path
     // is api path
-    var path = req.path || '';
+    const path = req.path || '';
     if (path.match(/^\/_api\/.+$/)) {
     if (path.match(/^\/_api\/.+$/)) {
       return res.sendStatus(403);
       return res.sendStatus(403);
     }
     }
@@ -258,22 +256,22 @@ exports.loginRequired = function(crowi, app, isStrictly = true) {
 exports.accessTokenParser = function(crowi, app) {
 exports.accessTokenParser = function(crowi, app) {
   return function(req, res, next) {
   return function(req, res, next) {
     // TODO: comply HTTP header of RFC6750 / Authorization: Bearer
     // TODO: comply HTTP header of RFC6750 / Authorization: Bearer
-    var accessToken = req.query.access_token || req.body.access_token || null;
+    const accessToken = req.query.access_token || req.body.access_token || null;
     if (!accessToken) {
     if (!accessToken) {
       return next();
       return next();
     }
     }
 
 
-    var User = crowi.model('User');
+    const User = crowi.model('User');
 
 
     debug('accessToken is', accessToken);
     debug('accessToken is', accessToken);
     User.findUserByApiToken(accessToken)
     User.findUserByApiToken(accessToken)
-    .then(function(userData) {
+    .then((userData) => {
       req.user = userData;
       req.user = userData;
       req.skipCsrfVerify = true;
       req.skipCsrfVerify = true;
       debug('Access token parsed: skipCsrfVerify');
       debug('Access token parsed: skipCsrfVerify');
 
 
       next();
       next();
-    }).catch(function(err) {
+    }).catch((err) => {
       next();
       next();
     });
     });
   };
   };
@@ -295,7 +293,7 @@ exports.applicationNotInstalled = function() {
 
 
 exports.applicationInstalled = function() {
 exports.applicationInstalled = function() {
   return function(req, res, next) {
   return function(req, res, next) {
-    var config = req.config;
+    const config = req.config;
 
 
     if (Object.keys(config.crowi).length === 0) {
     if (Object.keys(config.crowi).length === 0) {
       return res.redirect('/installer');
       return res.redirect('/installer');
@@ -307,8 +305,11 @@ exports.applicationInstalled = function() {
 
 
 exports.awsEnabled = function() {
 exports.awsEnabled = function() {
   return function(req, res, next) {
   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'] !== '') {
+    const 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.');
       req.flash('globalError', 'AWS settings required to use this function. Please ask the administrator.');
       return res.redirect('/');
       return res.redirect('/');
     }
     }

+ 107 - 95
src/server/util/search.js

@@ -52,7 +52,7 @@ function SearchClient(crowi, esUri) {
 
 
   this.registerUpdateEvent();
   this.registerUpdateEvent();
 
 
-  this.mappingFile = crowi.resourceDir + 'search/mappings.json';
+  this.mappingFile = `${crowi.resourceDir}search/mappings.json`;
 }
 }
 
 
 SearchClient.prototype.getInfo = function() {
 SearchClient.prototype.getInfo = function() {
@@ -100,10 +100,10 @@ SearchClient.prototype.shouldIndexed = function(page) {
 SearchClient.prototype.parseUri = function(uri) {
 SearchClient.prototype.parseUri = function(uri) {
   let indexName = 'crowi';
   let indexName = 'crowi';
   let host = uri;
   let host = uri;
-  let m;
-  if ((m = uri.match(/^(https?:\/\/[^/]+)\/(.+)$/))) {
-    host = m[1];
-    indexName = m[2];
+  const match = uri.match(/^(https?:\/\/[^/]+)\/(.+)$/);
+  if (match) {
+    host = match[1];
+    indexName = match[2];
   }
   }
 
 
   return {
   return {
@@ -131,7 +131,7 @@ SearchClient.prototype.deleteIndex = function(uri) {
 function generateDocContentsRelatedToRestriction(page) {
 function generateDocContentsRelatedToRestriction(page) {
   let grantedUserIds = null;
   let grantedUserIds = null;
   if (page.grantedUsers != null && page.grantedUsers.length > 0) {
   if (page.grantedUsers != null && page.grantedUsers.length > 0) {
-    grantedUserIds = page.grantedUsers.map(user => {
+    grantedUserIds = page.grantedUsers.map((user) => {
       const userId = (user._id == null) ? user : user._id;
       const userId = (user._id == null) ? user : user._id;
       return userId.toString();
       return userId.toString();
     });
     });
@@ -155,7 +155,7 @@ SearchClient.prototype.prepareBodyForUpdate = function(body, page) {
     throw new Error('Body must be an array.');
     throw new Error('Body must be an array.');
   }
   }
 
 
-  let command = {
+  const command = {
     update: {
     update: {
       _index: this.indexName,
       _index: this.indexName,
       _type: 'pages',
       _type: 'pages',
@@ -186,7 +186,7 @@ SearchClient.prototype.prepareBodyForCreate = function(body, page) {
     throw new Error('Body must be an array.');
     throw new Error('Body must be an array.');
   }
   }
 
 
-  let command = {
+  const command = {
     index: {
     index: {
       _index: this.indexName,
       _index: this.indexName,
       _type: 'pages',
       _type: 'pages',
@@ -217,7 +217,7 @@ SearchClient.prototype.prepareBodyForDelete = function(body, page) {
     throw new Error('Body must be an array.');
     throw new Error('Body must be an array.');
   }
   }
 
 
-  let command = {
+  const command = {
     delete: {
     delete: {
       _index: this.indexName,
       _index: this.indexName,
       _type: 'pages',
       _type: 'pages',
@@ -232,42 +232,46 @@ SearchClient.prototype.addPages = async function(pages) {
   const Bookmark = this.crowi.model('Bookmark');
   const Bookmark = this.crowi.model('Bookmark');
   const body = [];
   const body = [];
 
 
+  /* eslint-disable no-await-in-loop */
   for (const page of pages) {
   for (const page of pages) {
     page.bookmarkCount = await Bookmark.countByPageId(page._id);
     page.bookmarkCount = await Bookmark.countByPageId(page._id);
     this.prepareBodyForCreate(body, page);
     this.prepareBodyForCreate(body, page);
   }
   }
+  /* eslint-enable no-await-in-loop */
 
 
   logger.debug('addPages(): Sending Request to ES', body);
   logger.debug('addPages(): Sending Request to ES', body);
   return this.client.bulk({
   return this.client.bulk({
-    body: body,
+    body,
   });
   });
 };
 };
 
 
 SearchClient.prototype.updatePages = function(pages) {
 SearchClient.prototype.updatePages = function(pages) {
-  let self = this;
-  let body = [];
+  const self = this;
+  const body = [];
 
 
-  pages.map(function(page) {
+  pages.map((page) => {
     self.prepareBodyForUpdate(body, page);
     self.prepareBodyForUpdate(body, page);
+    return;
   });
   });
 
 
   logger.debug('updatePages(): Sending Request to ES', body);
   logger.debug('updatePages(): Sending Request to ES', body);
   return this.client.bulk({
   return this.client.bulk({
-    body: body,
+    body,
   });
   });
 };
 };
 
 
 SearchClient.prototype.deletePages = function(pages) {
 SearchClient.prototype.deletePages = function(pages) {
-  let self = this;
-  let body = [];
+  const self = this;
+  const body = [];
 
 
-  pages.map(function(page) {
+  pages.map((page) => {
     self.prepareBodyForDelete(body, page);
     self.prepareBodyForDelete(body, page);
+    return;
   });
   });
 
 
   logger.debug('deletePages(): Sending Request to ES', body);
   logger.debug('deletePages(): Sending Request to ES', body);
   return this.client.bulk({
   return this.client.bulk({
-    body: body,
+    body,
   });
   });
 };
 };
 
 
@@ -283,22 +287,22 @@ SearchClient.prototype.addAllPages = async function() {
   let total = 0;
   let total = 0;
 
 
   return new Promise((resolve, reject) => {
   return new Promise((resolve, reject) => {
-    const bulkSend = body => {
+    const bulkSend = (body) => {
       self.client
       self.client
         .bulk({
         .bulk({
-          body: body,
+          body,
           requestTimeout: Infinity,
           requestTimeout: Infinity,
         })
         })
-        .then(res => {
+        .then((res) => {
           logger.info('addAllPages add anyway (items, errors, took): ', (res.items || []).length, res.errors, res.took, 'ms');
           logger.info('addAllPages add anyway (items, errors, took): ', (res.items || []).length, res.errors, res.took, 'ms');
         })
         })
-        .catch(err => {
+        .catch((err) => {
           logger.error('addAllPages error on add anyway: ', err);
           logger.error('addAllPages error on add anyway: ', err);
         });
         });
     };
     };
 
 
     cursor
     cursor
-      .eachAsync(async doc => {
+      .eachAsync(async(doc) => {
         if (!doc.creator || !doc.revision || !self.shouldIndexed(doc)) {
         if (!doc.creator || !doc.revision || !self.shouldIndexed(doc)) {
           // debug('Skipped', doc.path);
           // debug('Skipped', doc.path);
           skipped++;
           skipped++;
@@ -328,7 +332,7 @@ SearchClient.prototype.addAllPages = async function() {
 
 
         resolve();
         resolve();
       })
       })
-      .catch(e => {
+      .catch((e) => {
         logger.error('Error wile iterating cursor.eachAsync()', e);
         logger.error('Error wile iterating cursor.eachAsync()', e);
         reject(e);
         reject(e);
       });
       });
@@ -348,7 +352,7 @@ SearchClient.prototype.search = async function(query) {
     const result = await this.client.indices.validateQuery({
     const result = await this.client.indices.validateQuery({
       explain: true,
       explain: true,
       body: {
       body: {
-        query: query.body.query
+        query: query.body.query,
       },
       },
     });
     });
     logger.debug('ES returns explanations: ', result.explanations);
     logger.debug('ES returns explanations: ', result.explanations);
@@ -365,11 +369,10 @@ SearchClient.prototype.search = async function(query) {
       total: result.hits.total,
       total: result.hits.total,
       results: result.hits.hits.length,
       results: result.hits.hits.length,
     },
     },
-    data: result.hits.hits.map(function(elm) {
+    data: result.hits.hits.map((elm) => {
       return { _id: elm._id, _score: elm._score, _source: elm._source };
       return { _id: elm._id, _score: elm._score, _source: elm._source };
     }),
     }),
   };
   };
-
 };
 };
 
 
 SearchClient.prototype.createSearchQuerySortedByUpdatedAt = function(option) {
 SearchClient.prototype.createSearchQuerySortedByUpdatedAt = function(option) {
@@ -380,7 +383,7 @@ SearchClient.prototype.createSearchQuerySortedByUpdatedAt = function(option) {
   }
   }
 
 
   // default is only id field, sorted by updated_at
   // default is only id field, sorted by updated_at
-  let query = {
+  const query = {
     index: this.indexName,
     index: this.indexName,
     type: 'pages',
     type: 'pages',
     body: {
     body: {
@@ -401,7 +404,7 @@ SearchClient.prototype.createSearchQuerySortedByScore = function(option) {
   }
   }
 
 
   // sort by score
   // sort by score
-  let query = {
+  const query = {
     index: this.indexName,
     index: this.indexName,
     type: 'pages',
     type: 'pages',
     body: {
     body: {
@@ -426,7 +429,7 @@ SearchClient.prototype.initializeBoolQuery = function(query) {
     query.body.query.bool = {};
     query.body.query.bool = {};
   }
   }
 
 
-  const isInitialized = query => !!query && Array.isArray(query);
+  const isInitialized = (query) => { return !!query && Array.isArray(query) };
 
 
   if (!isInitialized(query.body.query.bool.filter)) {
   if (!isInitialized(query.body.query.bool.filter)) {
     query.body.query.bool.filter = [];
     query.body.query.bool.filter = [];
@@ -441,10 +444,10 @@ SearchClient.prototype.initializeBoolQuery = function(query) {
 };
 };
 
 
 SearchClient.prototype.appendCriteriaForQueryString = function(query, queryString) {
 SearchClient.prototype.appendCriteriaForQueryString = function(query, queryString) {
-  query = this.initializeBoolQuery(query);
+  query = this.initializeBoolQuery(query); // eslint-disable-line no-param-reassign
 
 
   // parse
   // parse
-  let parsedKeywords = this.parseQueryString(queryString);
+  const parsedKeywords = this.parseQueryString(queryString);
 
 
   if (parsedKeywords.match.length > 0) {
   if (parsedKeywords.match.length > 0) {
     const q = {
     const q = {
@@ -462,15 +465,15 @@ SearchClient.prototype.appendCriteriaForQueryString = function(query, queryStrin
       multi_match: {
       multi_match: {
         query: parsedKeywords.not_match.join(' '),
         query: parsedKeywords.not_match.join(' '),
         fields: ['path.ja', 'path.en', 'body.ja', 'body.en'],
         fields: ['path.ja', 'path.en', 'body.ja', 'body.en'],
-        operator: 'or'
+        operator: 'or',
       },
       },
     };
     };
     query.body.query.bool.must_not.push(q);
     query.body.query.bool.must_not.push(q);
   }
   }
 
 
   if (parsedKeywords.phrase.length > 0) {
   if (parsedKeywords.phrase.length > 0) {
-    let phraseQueries = [];
-    parsedKeywords.phrase.forEach(function(phrase) {
+    const phraseQueries = [];
+    parsedKeywords.phrase.forEach((phrase) => {
       phraseQueries.push({
       phraseQueries.push({
         multi_match: {
         multi_match: {
           query: phrase, // each phrase is quoteted words
           query: phrase, // each phrase is quoteted words
@@ -488,8 +491,8 @@ SearchClient.prototype.appendCriteriaForQueryString = function(query, queryStrin
   }
   }
 
 
   if (parsedKeywords.not_phrase.length > 0) {
   if (parsedKeywords.not_phrase.length > 0) {
-    let notPhraseQueries = [];
-    parsedKeywords.not_phrase.forEach(function(phrase) {
+    const notPhraseQueries = [];
+    parsedKeywords.not_phrase.forEach((phrase) => {
       notPhraseQueries.push({
       notPhraseQueries.push({
         multi_match: {
         multi_match: {
           query: phrase, // each phrase is quoteted words
           query: phrase, // each phrase is quoteted words
@@ -507,19 +510,18 @@ SearchClient.prototype.appendCriteriaForQueryString = function(query, queryStrin
   }
   }
 
 
   if (parsedKeywords.prefix.length > 0) {
   if (parsedKeywords.prefix.length > 0) {
-    const queries = parsedKeywords.prefix.map(path => {
+    const queries = parsedKeywords.prefix.map((path) => {
       return { prefix: { 'path.raw': path } };
       return { prefix: { 'path.raw': path } };
     });
     });
     query.body.query.bool.filter.push({ bool: { should: queries } });
     query.body.query.bool.filter.push({ bool: { should: queries } });
   }
   }
 
 
   if (parsedKeywords.not_prefix.length > 0) {
   if (parsedKeywords.not_prefix.length > 0) {
-    const queries = parsedKeywords.not_prefix.map(path => {
+    const queries = parsedKeywords.not_prefix.map((path) => {
       return { prefix: { 'path.raw': path } };
       return { prefix: { 'path.raw': path } };
     });
     });
     query.body.query.bool.filter.push({ bool: { must_not: queries } });
     query.body.query.bool.filter.push({ bool: { must_not: queries } });
   }
   }
-
 };
 };
 
 
 SearchClient.prototype.filterPagesByViewer = async function(query, user, userGroups) {
 SearchClient.prototype.filterPagesByViewer = async function(query, user, userGroups) {
@@ -529,10 +531,12 @@ SearchClient.prototype.filterPagesByViewer = async function(query, user, userGro
   const showPagesRestrictedByOwner = !Config.hidePagesRestrictedByOwnerInList(config);
   const showPagesRestrictedByOwner = !Config.hidePagesRestrictedByOwnerInList(config);
   const showPagesRestrictedByGroup = !Config.hidePagesRestrictedByGroupInList(config);
   const showPagesRestrictedByGroup = !Config.hidePagesRestrictedByGroupInList(config);
 
 
-  query = this.initializeBoolQuery(query);
+  query = this.initializeBoolQuery(query); // eslint-disable-line no-param-reassign
 
 
   const Page = this.crowi.model('Page');
   const Page = this.crowi.model('Page');
-  const { GRANT_PUBLIC, GRANT_RESTRICTED, GRANT_SPECIFIED, GRANT_OWNER, GRANT_USER_GROUP } = Page;
+  const {
+    GRANT_PUBLIC, GRANT_RESTRICTED, GRANT_SPECIFIED, GRANT_OWNER, GRANT_USER_GROUP,
+  } = Page;
 
 
   const grantConditions = [
   const grantConditions = [
     { term: { grant: GRANT_PUBLIC } },
     { term: { grant: GRANT_PUBLIC } },
@@ -541,12 +545,14 @@ SearchClient.prototype.filterPagesByViewer = async function(query, user, userGro
   // ensure to hit to GRANT_RESTRICTED pages that the user specified at own
   // ensure to hit to GRANT_RESTRICTED pages that the user specified at own
   if (user != null) {
   if (user != null) {
     grantConditions.push(
     grantConditions.push(
-      { bool: {
-        must: [
-          { term: { grant: GRANT_RESTRICTED } },
-          { term: { granted_users: user._id.toString() } }
-        ]
-      } }
+      {
+        bool: {
+          must: [
+            { term: { grant: GRANT_RESTRICTED } },
+            { term: { granted_users: user._id.toString() } },
+          ],
+        },
+      },
     );
     );
   }
   }
 
 
@@ -558,18 +564,22 @@ SearchClient.prototype.filterPagesByViewer = async function(query, user, userGro
   }
   }
   else if (user != null) {
   else if (user != null) {
     grantConditions.push(
     grantConditions.push(
-      { bool: {
-        must: [
-          { term: { grant: GRANT_SPECIFIED } },
-          { term: { granted_users: user._id.toString() } }
-        ]
-      } },
-      { bool: {
-        must: [
-          { term: { grant: GRANT_OWNER } },
-          { term: { granted_users: user._id.toString() } }
-        ]
-      } },
+      {
+        bool: {
+          must: [
+            { term: { grant: GRANT_SPECIFIED } },
+            { term: { granted_users: user._id.toString() } },
+          ],
+        },
+      },
+      {
+        bool: {
+          must: [
+            { term: { grant: GRANT_OWNER } },
+            { term: { granted_users: user._id.toString() } },
+          ],
+        },
+      },
     );
     );
   }
   }
 
 
@@ -579,14 +589,16 @@ SearchClient.prototype.filterPagesByViewer = async function(query, user, userGro
     );
     );
   }
   }
   else if (userGroups != null && userGroups.length > 0) {
   else if (userGroups != null && userGroups.length > 0) {
-    const userGroupIds = userGroups.map(group => group._id.toString() );
+    const userGroupIds = userGroups.map((group) => { return group._id.toString() });
     grantConditions.push(
     grantConditions.push(
-      { bool: {
-        must: [
-          { term: { grant: GRANT_USER_GROUP } },
-          { terms: { granted_group: userGroupIds } }
-        ]
-      } },
+      {
+        bool: {
+          must: [
+            { term: { grant: GRANT_USER_GROUP } },
+            { terms: { granted_group: userGroupIds } },
+          ],
+        },
+      },
     );
     );
   }
   }
 
 
@@ -594,21 +606,21 @@ SearchClient.prototype.filterPagesByViewer = async function(query, user, userGro
 };
 };
 
 
 SearchClient.prototype.filterPortalPages = function(query) {
 SearchClient.prototype.filterPortalPages = function(query) {
-  query = this.initializeBoolQuery(query);
+  query = this.initializeBoolQuery(query); // eslint-disable-line no-param-reassign
 
 
   query.body.query.bool.must_not.push(this.queries.USER);
   query.body.query.bool.must_not.push(this.queries.USER);
   query.body.query.bool.filter.push(this.queries.PORTAL);
   query.body.query.bool.filter.push(this.queries.PORTAL);
 };
 };
 
 
 SearchClient.prototype.filterPublicPages = function(query) {
 SearchClient.prototype.filterPublicPages = function(query) {
-  query = this.initializeBoolQuery(query);
+  query = this.initializeBoolQuery(query); // eslint-disable-line no-param-reassign
 
 
   query.body.query.bool.must_not.push(this.queries.USER);
   query.body.query.bool.must_not.push(this.queries.USER);
   query.body.query.bool.filter.push(this.queries.PUBLIC);
   query.body.query.bool.filter.push(this.queries.PUBLIC);
 };
 };
 
 
 SearchClient.prototype.filterUserPages = function(query) {
 SearchClient.prototype.filterUserPages = function(query) {
-  query = this.initializeBoolQuery(query);
+  query = this.initializeBoolQuery(query); // eslint-disable-line no-param-reassign
 
 
   query.body.query.bool.filter.push(this.queries.USER);
   query.body.query.bool.filter.push(this.queries.USER);
 };
 };
@@ -632,14 +644,14 @@ SearchClient.prototype.appendFunctionScore = function(query, queryString) {
   const User = this.crowi.model('User');
   const User = this.crowi.model('User');
   const count = User.count({}) || 1;
   const count = User.count({}) || 1;
 
 
-  const minScore = queryString.length * 0.1 - 1;    // increase with length
+  const minScore = queryString.length * 0.1 - 1; // increase with length
   logger.debug('min_score: ', minScore);
   logger.debug('min_score: ', minScore);
 
 
   query.body.query = {
   query.body.query = {
     function_score: {
     function_score: {
       query: { ...query.body.query },
       query: { ...query.body.query },
-      //// disable min_score -- 2019.02.28 Yuki Takei
-      //// more precise adjustment is needed...
+      // // disable min_score -- 2019.02.28 Yuki Takei
+      // // more precise adjustment is needed...
       // min_score: minScore,
       // min_score: minScore,
       field_value_factor: {
       field_value_factor: {
         field: 'bookmark_count',
         field: 'bookmark_count',
@@ -670,24 +682,24 @@ SearchClient.prototype.searchKeyword = async function(queryString, user, userGro
 };
 };
 
 
 SearchClient.prototype.parseQueryString = function(queryString) {
 SearchClient.prototype.parseQueryString = function(queryString) {
-  let matchWords = [];
-  let notMatchWords = [];
-  let phraseWords = [];
-  let notPhraseWords = [];
-  let prefixPaths = [];
-  let notPrefixPaths = [];
+  const matchWords = [];
+  const notMatchWords = [];
+  const phraseWords = [];
+  const notPhraseWords = [];
+  const prefixPaths = [];
+  const notPrefixPaths = [];
 
 
   queryString.trim();
   queryString.trim();
-  queryString = queryString.replace(/\s+/g, ' ');
+  queryString = queryString.replace(/\s+/g, ' '); // eslint-disable-line no-param-reassign
 
 
   // First: Parse phrase keywords
   // First: Parse phrase keywords
-  let phraseRegExp = new RegExp(/(-?"[^"]+")/g);
-  let phrases = queryString.match(phraseRegExp);
+  const phraseRegExp = new RegExp(/(-?"[^"]+")/g);
+  const phrases = queryString.match(phraseRegExp);
 
 
   if (phrases !== null) {
   if (phrases !== null) {
-    queryString = queryString.replace(phraseRegExp, '');
+    queryString = queryString.replace(phraseRegExp, ''); // eslint-disable-line no-param-reassign
 
 
-    phrases.forEach(function(phrase) {
+    phrases.forEach((phrase) => {
       phrase.trim();
       phrase.trim();
       if (phrase.match(/^-/)) {
       if (phrase.match(/^-/)) {
         notPhraseWords.push(phrase.replace(/^-/, ''));
         notPhraseWords.push(phrase.replace(/^-/, ''));
@@ -699,7 +711,7 @@ SearchClient.prototype.parseQueryString = function(queryString) {
   }
   }
 
 
   // Second: Parse other keywords (include minus keywords)
   // Second: Parse other keywords (include minus keywords)
-  queryString.split(' ').forEach(function(word) {
+  queryString.split(' ').forEach((word) => {
     if (word === '') {
     if (word === '') {
       return;
       return;
     }
     }
@@ -748,10 +760,10 @@ SearchClient.prototype.syncPageCreated = function(page, user, bookmarkCount = 0)
 
 
   page.bookmarkCount = bookmarkCount;
   page.bookmarkCount = bookmarkCount;
   this.addPages([page])
   this.addPages([page])
-    .then(function(res) {
+    .then((res) => {
       debug('ES Response', res);
       debug('ES Response', res);
     })
     })
-    .catch(function(err) {
+    .catch((err) => {
       logger.error('ES Error', err);
       logger.error('ES Error', err);
     });
     });
 };
 };
@@ -761,10 +773,10 @@ SearchClient.prototype.syncPageUpdated = function(page, user, bookmarkCount = 0)
   // TODO delete
   // TODO delete
   if (!this.shouldIndexed(page)) {
   if (!this.shouldIndexed(page)) {
     this.deletePages([page])
     this.deletePages([page])
-      .then(function(res) {
+      .then((res) => {
         debug('deletePages: ES Response', res);
         debug('deletePages: ES Response', res);
       })
       })
-      .catch(function(err) {
+      .catch((err) => {
         logger.error('deletePages:ES Error', err);
         logger.error('deletePages:ES Error', err);
       });
       });
 
 
@@ -773,10 +785,10 @@ SearchClient.prototype.syncPageUpdated = function(page, user, bookmarkCount = 0)
 
 
   page.bookmarkCount = bookmarkCount;
   page.bookmarkCount = bookmarkCount;
   this.updatePages([page])
   this.updatePages([page])
-    .then(function(res) {
+    .then((res) => {
       debug('ES Response', res);
       debug('ES Response', res);
     })
     })
-    .catch(function(err) {
+    .catch((err) => {
       logger.error('ES Error', err);
       logger.error('ES Error', err);
     });
     });
 };
 };
@@ -785,10 +797,10 @@ SearchClient.prototype.syncPageDeleted = function(page, user) {
   debug('SearchClient.syncPageDeleted', page.path);
   debug('SearchClient.syncPageDeleted', page.path);
 
 
   this.deletePages([page])
   this.deletePages([page])
-    .then(function(res) {
+    .then((res) => {
       debug('deletePages: ES Response', res);
       debug('deletePages: ES Response', res);
     })
     })
-    .catch(function(err) {
+    .catch((err) => {
       logger.error('deletePages:ES Error', err);
       logger.error('deletePages:ES Error', err);
     });
     });
 };
 };
@@ -801,8 +813,8 @@ SearchClient.prototype.syncBookmarkChanged = async function(pageId) {
 
 
   page.bookmarkCount = bookmarkCount;
   page.bookmarkCount = bookmarkCount;
   this.updatePages([page])
   this.updatePages([page])
-    .then(res => debug('ES Response', res))
-    .catch(err => logger.error('ES Error', err));
+    .then((res) => { return debug('ES Response', res) })
+    .catch((err) => { return logger.error('ES Error', err) });
 };
 };
 
 
 module.exports = SearchClient;
 module.exports = SearchClient;

+ 25 - 30
src/server/util/slack.js

@@ -5,19 +5,20 @@ const urljoin = require('url-join');
  * slack
  * slack
  */
  */
 
 
+/* eslint-disable no-use-before-define */
+
 module.exports = function(crowi) {
 module.exports = function(crowi) {
-  'use strict';
+  const config = crowi.getConfig();
+  const Config = crowi.model('Config');
+  const Slack = require('slack-node');
 
 
-  const config = crowi.getConfig(),
-    Config = crowi.model('Config'),
-    Slack = require('slack-node'),
-    slack = {};
+  const slack = {};
 
 
   const postWithIwh = function(messageObj) {
   const postWithIwh = function(messageObj) {
     return new Promise((resolve, reject) => {
     return new Promise((resolve, reject) => {
       const client = new Slack();
       const client = new Slack();
       client.setWebhook(config.notification['slack:incomingWebhookUrl']);
       client.setWebhook(config.notification['slack:incomingWebhookUrl']);
-      client.webhook(messageObj, function(err, res) {
+      client.webhook(messageObj, (err, res) => {
         if (err) {
         if (err) {
           debug('Post error', err, res);
           debug('Post error', err, res);
           debug('Sent data to slack is:', messageObj);
           debug('Sent data to slack is:', messageObj);
@@ -35,7 +36,7 @@ module.exports = function(crowi) {
       if (messageObj.attachments != null) {
       if (messageObj.attachments != null) {
         messageObj.attachments = JSON.stringify(messageObj.attachments);
         messageObj.attachments = JSON.stringify(messageObj.attachments);
       }
       }
-      client.api('chat.postMessage', messageObj, function(err, res) {
+      client.api('chat.postMessage', messageObj, (err, res) => {
         if (err) {
         if (err) {
           debug('Post error', err, res);
           debug('Post error', err, res);
           debug('Sent data to slack is:', messageObj);
           debug('Sent data to slack is:', messageObj);
@@ -49,20 +50,17 @@ module.exports = function(crowi) {
   const convertMarkdownToMarkdown = function(body) {
   const convertMarkdownToMarkdown = function(body) {
     const url = crowi.configManager.getSiteUrl();
     const url = crowi.configManager.getSiteUrl();
 
 
-    body = body
+    return body
       .replace(/\n\*\s(.+)/g, '\n• $1')
       .replace(/\n\*\s(.+)/g, '\n• $1')
       .replace(/#{1,}\s?(.+)/g, '\n*$1*')
       .replace(/#{1,}\s?(.+)/g, '\n*$1*')
       .replace(/(\[(.+)\]\((https?:\/\/.+)\))/g, '<$3|$2>')
       .replace(/(\[(.+)\]\((https?:\/\/.+)\))/g, '<$3|$2>')
-      .replace(/(\[(.+)\]\((\/.+)\))/g, '<' + url + '$3|$2>')
-    ;
-
-    return body;
+      .replace(/(\[(.+)\]\((\/.+)\))/g, `<${url}$3|$2>`);
   };
   };
 
 
   const prepareAttachmentTextForCreate = function(page, user) {
   const prepareAttachmentTextForCreate = function(page, user) {
     let body = page.revision.body;
     let body = page.revision.body;
     if (body.length > 2000) {
     if (body.length > 2000) {
-      body = body.substr(0, 2000) + '...';
+      body = `${body.substr(0, 2000)}...`;
     }
     }
 
 
     return convertMarkdownToMarkdown(body);
     return convertMarkdownToMarkdown(body);
@@ -72,11 +70,9 @@ module.exports = function(crowi) {
     const diff = require('diff');
     const diff = require('diff');
     let diffText = '';
     let diffText = '';
 
 
-    diff.diffLines(previousRevision.body, page.revision.body).forEach(function(line) {
+    diff.diffLines(previousRevision.body, page.revision.body).forEach((line) => {
       debug('diff line', line);
       debug('diff line', line);
-      /* eslint-disable no-unused-vars */
-      const value = line.value.replace(/\r\n|\r/g, '\n');
-      /* eslint-enable */
+      const value = line.value.replace(/\r\n|\r/g, '\n'); // eslint-disable-line no-unused-vars
       if (line.added) {
       if (line.added) {
         diffText += `${line.value} ... :lower_left_fountain_pen:`;
         diffText += `${line.value} ... :lower_left_fountain_pen:`;
       }
       }
@@ -88,7 +84,7 @@ module.exports = function(crowi) {
         }
         }
       }
       }
       else {
       else {
-        //diffText += '...\n';
+        // diffText += '...\n';
       }
       }
     });
     });
 
 
@@ -100,22 +96,21 @@ module.exports = function(crowi) {
   const prepareAttachmentTextForComment = function(comment) {
   const prepareAttachmentTextForComment = function(comment) {
     let body = comment.comment;
     let body = comment.comment;
     if (body.length > 2000) {
     if (body.length > 2000) {
-      body = body.substr(0, 2000) + '...';
+      body = `${body.substr(0, 2000)}...`;
     }
     }
 
 
     if (comment.isMarkdown) {
     if (comment.isMarkdown) {
       return convertMarkdownToMarkdown(body);
       return convertMarkdownToMarkdown(body);
     }
     }
-    else {
-      return body;
-    }
+
+    return body;
   };
   };
 
 
   const prepareSlackMessageForPage = function(page, user, channel, updateType, previousRevision) {
   const prepareSlackMessageForPage = function(page, user, channel, updateType, previousRevision) {
     const url = crowi.configManager.getSiteUrl();
     const url = crowi.configManager.getSiteUrl();
     let body = page.revision.body;
     let body = page.revision.body;
 
 
-    if (updateType == 'create') {
+    if (updateType === 'create') {
       body = prepareAttachmentTextForCreate(page, user);
       body = prepareAttachmentTextForCreate(page, user);
     }
     }
     else {
     else {
@@ -124,7 +119,7 @@ module.exports = function(crowi) {
 
 
     const attachment = {
     const attachment = {
       color: '#263a3c',
       color: '#263a3c',
-      author_name: '@' + user.username,
+      author_name: `@${user.username}`,
       author_link: urljoin(url, 'user', user.username),
       author_link: urljoin(url, 'user', user.username),
       author_icon: user.image,
       author_icon: user.image,
       title: page.path,
       title: page.path,
@@ -137,7 +132,7 @@ module.exports = function(crowi) {
     }
     }
 
 
     const message = {
     const message = {
-      channel: '#' + channel,
+      channel: `#${channel}`,
       username: Config.appTitle(config),
       username: Config.appTitle(config),
       text: getSlackMessageTextForPage(page.path, user, updateType),
       text: getSlackMessageTextForPage(page.path, user, updateType),
       attachments: [attachment],
       attachments: [attachment],
@@ -152,7 +147,7 @@ module.exports = function(crowi) {
 
 
     const attachment = {
     const attachment = {
       color: '#263a3c',
       color: '#263a3c',
-      author_name: '@' + user.username,
+      author_name: `@${user.username}`,
       author_link: urljoin(url, 'user', user.username),
       author_link: urljoin(url, 'user', user.username),
       author_icon: user.image,
       author_icon: user.image,
       text: body,
       text: body,
@@ -163,7 +158,7 @@ module.exports = function(crowi) {
     }
     }
 
 
     const message = {
     const message = {
-      channel: '#' + channel,
+      channel: `#${channel}`,
       username: Config.appTitle(config),
       username: Config.appTitle(config),
       text: getSlackMessageTextForComment(path, user),
       text: getSlackMessageTextForComment(path, user),
       attachments: [attachment],
       attachments: [attachment],
@@ -177,7 +172,7 @@ module.exports = function(crowi) {
     const url = crowi.configManager.getSiteUrl();
     const url = crowi.configManager.getSiteUrl();
 
 
     const pageUrl = `<${urljoin(url, path)}|${path}>`;
     const pageUrl = `<${urljoin(url, path)}|${path}>`;
-    if (updateType == 'create') {
+    if (updateType === 'create') {
       text = `:rocket: ${user.username} created a new page! ${pageUrl}`;
       text = `:rocket: ${user.username} created a new page! ${pageUrl}`;
     }
     }
     else {
     else {
@@ -215,7 +210,7 @@ module.exports = function(crowi) {
         debug('posting message with IncomingWebhook');
         debug('posting message with IncomingWebhook');
         return postWithIwh(messageObj);
         return postWithIwh(messageObj);
       }
       }
-      else if (Config.hasSlackToken(config)) {
+      if (Config.hasSlackToken(config)) {
         debug('posting message with Web API');
         debug('posting message with Web API');
         return postWithWebApi(messageObj);
         return postWithWebApi(messageObj);
       }
       }
@@ -226,7 +221,7 @@ module.exports = function(crowi) {
         debug('posting message with Web API');
         debug('posting message with Web API');
         return postWithWebApi(messageObj);
         return postWithWebApi(messageObj);
       }
       }
-      else if (Config.hasSlackIwhUrl(config)) {
+      if (Config.hasSlackIwhUrl(config)) {
         debug('posting message with IncomingWebhook');
         debug('posting message with IncomingWebhook');
         return postWithIwh(messageObj);
         return postWithIwh(messageObj);
       }
       }

+ 39 - 43
src/server/util/swigFunctions.js

@@ -1,13 +1,11 @@
 module.exports = function(crowi, app, req, locals) {
 module.exports = function(crowi, app, req, locals) {
-  const debug = require('debug')('growi:lib:swigFunctions')
-    , stringWidth = require('string-width')
-    , Page = crowi.model('Page')
-    , Config = crowi.model('Config')
-    , User = crowi.model('User')
-    , passportService = crowi.passportService
-    , cdnResourcesService = crowi.cdnResourcesService
-  ;
-
+  const debug = require('debug')('growi:lib:swigFunctions');
+  const stringWidth = require('string-width');
+  const Page = crowi.model('Page');
+  const Config = crowi.model('Config');
+  const User = crowi.model('User');
+  const passportService = crowi.passportService;
+  const cdnResourcesService = crowi.cdnResourcesService;
   debug('initializing swigFunctions');
   debug('initializing swigFunctions');
 
 
   locals.nodeVersion = function() {
   locals.nodeVersion = function() {
@@ -30,13 +28,13 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.getAppTitleFontSize = function(appTitle) {
   locals.getAppTitleFontSize = function(appTitle) {
-    let appTitleWidth = stringWidth(appTitle);
+    const appTitleWidth = stringWidth(appTitle);
     let fontSize = 22;
     let fontSize = 22;
     if (appTitleWidth < 13) { /* do nothing */ }
     if (appTitleWidth < 13) { /* do nothing */ }
     else if (appTitleWidth < 21) {
     else if (appTitleWidth < 21) {
       fontSize -= 3 * (Math.floor((appTitleWidth - 13) / 3) + 1);
       fontSize -= 3 * (Math.floor((appTitleWidth - 13) / 3) + 1);
     }
     }
-    else  {
+    else {
       fontSize = 11;
       fontSize = 11;
     }
     }
     return fontSize;
     return fontSize;
@@ -123,7 +121,7 @@ module.exports = function(crowi, app, req, locals) {
    * return true if enabled and strategy has been setup successfully
    * return true if enabled and strategy has been setup successfully
    */
    */
   locals.isLdapSetup = function() {
   locals.isLdapSetup = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isEnabledPassport(config) && Config.isEnabledPassportLdap(config) && passportService.isLdapStrategySetup;
     return Config.isEnabledPassport(config) && Config.isEnabledPassportLdap(config) && passportService.isLdapStrategySetup;
   };
   };
 
 
@@ -131,7 +129,7 @@ module.exports = function(crowi, app, req, locals) {
    * return true if enabled but strategy has some problem
    * return true if enabled but strategy has some problem
    */
    */
   locals.isLdapSetupFailed = function() {
   locals.isLdapSetupFailed = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isEnabledPassport(config) && Config.isEnabledPassportLdap(config) && !passportService.isLdapStrategySetup;
     return Config.isEnabledPassport(config) && Config.isEnabledPassportLdap(config) && !passportService.isLdapStrategySetup;
   };
   };
 
 
@@ -156,22 +154,22 @@ module.exports = function(crowi, app, req, locals) {
       return false;
       return false;
     }
     }
 
 
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return config.crowi['google:clientId'] && config.crowi['google:clientSecret'];
     return config.crowi['google:clientId'] && config.crowi['google:clientSecret'];
   };
   };
 
 
   locals.passportGoogleLoginEnabled = function() {
   locals.passportGoogleLoginEnabled = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return locals.isEnabledPassport() && config.crowi['security:passport-google:isEnabled'];
     return locals.isEnabledPassport() && config.crowi['security:passport-google:isEnabled'];
   };
   };
 
 
   locals.passportGitHubLoginEnabled = function() {
   locals.passportGitHubLoginEnabled = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return locals.isEnabledPassport() && config.crowi['security:passport-github:isEnabled'];
     return locals.isEnabledPassport() && config.crowi['security:passport-github:isEnabled'];
   };
   };
 
 
   locals.passportTwitterLoginEnabled = function() {
   locals.passportTwitterLoginEnabled = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return locals.isEnabledPassport() && config.crowi['security:passport-twitter:isEnabled'];
     return locals.isEnabledPassport() && config.crowi['security:passport-twitter:isEnabled'];
   };
   };
 
 
@@ -187,17 +185,17 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.isEnabledPlugins = function() {
   locals.isEnabledPlugins = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isEnabledPlugins(config);
     return Config.isEnabledPlugins(config);
   };
   };
 
 
   locals.isEnabledLinebreaks = function() {
   locals.isEnabledLinebreaks = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isEnabledLinebreaks(config);
     return Config.isEnabledLinebreaks(config);
   };
   };
 
 
   locals.isEnabledLinebreaksInComments = function() {
   locals.isEnabledLinebreaksInComments = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isEnabledLinebreaksInComments(config);
     return Config.isEnabledLinebreaksInComments(config);
   };
   };
 
 
@@ -206,12 +204,12 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.pageBreakSeparator = function() {
   locals.pageBreakSeparator = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.pageBreakSeparator(config);
     return Config.pageBreakSeparator(config);
   };
   };
 
 
   locals.pageBreakCustomSeparator = function() {
   locals.pageBreakCustomSeparator = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.pageBreakCustomSeparator(config);
     return Config.pageBreakCustomSeparator(config);
   };
   };
 
 
@@ -220,12 +218,12 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.customHeader = function() {
   locals.customHeader = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.customHeader(config);
     return Config.customHeader(config);
   };
   };
 
 
   locals.theme = function() {
   locals.theme = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.theme(config);
     return Config.theme(config);
   };
   };
 
 
@@ -235,42 +233,42 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.behaviorType = function() {
   locals.behaviorType = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.behaviorType(config);
     return Config.behaviorType(config);
   };
   };
 
 
   locals.layoutType = function() {
   locals.layoutType = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.layoutType(config);
     return Config.layoutType(config);
   };
   };
 
 
   locals.highlightJsStyle = function() {
   locals.highlightJsStyle = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.highlightJsStyle(config);
     return Config.highlightJsStyle(config);
   };
   };
 
 
   locals.highlightJsStyleBorder = function() {
   locals.highlightJsStyleBorder = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.highlightJsStyleBorder(config);
     return Config.highlightJsStyleBorder(config);
   };
   };
 
 
   locals.isEnabledTimeline = function() {
   locals.isEnabledTimeline = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isEnabledTimeline(config);
     return Config.isEnabledTimeline(config);
   };
   };
 
 
   locals.isUploadable = function() {
   locals.isUploadable = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isUploadable(config);
     return Config.isUploadable(config);
   };
   };
 
 
   locals.isEnabledAttachTitleHeader = function() {
   locals.isEnabledAttachTitleHeader = function() {
-    let config = crowi.getConfig();
+    const config = crowi.getConfig();
     return Config.isEnabledAttachTitleHeader(config);
     return Config.isEnabledAttachTitleHeader(config);
   };
   };
 
 
   locals.parentPath = function(path) {
   locals.parentPath = function(path) {
-    if (path == '/') {
+    if (path === '/') {
       return path;
       return path;
     }
     }
 
 
@@ -278,7 +276,7 @@ module.exports = function(crowi, app, req, locals) {
       return path;
       return path;
     }
     }
 
 
-    return path + '/';
+    return `${path}/`;
   };
   };
 
 
   locals.isUserPageList = function(path) {
   locals.isUserPageList = function(path) {
@@ -290,7 +288,7 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.isTopPage = function() {
   locals.isTopPage = function() {
-    let path = req.path || '';
+    const path = req.path || '';
     if (path === '/') {
     if (path === '/') {
       return true;
       return true;
     }
     }
@@ -299,7 +297,7 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.isTrashPage = function() {
   locals.isTrashPage = function() {
-    let path = req.path || '';
+    const path = req.path || '';
     if (path.match(/^\/trash\/.*/)) {
     if (path.match(/^\/trash\/.*/)) {
       return true;
       return true;
     }
     }
@@ -308,8 +306,8 @@ module.exports = function(crowi, app, req, locals) {
   };
   };
 
 
   locals.isDeletablePage = function() {
   locals.isDeletablePage = function() {
-    let Page = crowi.model('Page');
-    let path = req.path || '';
+    const Page = crowi.model('Page');
+    const path = req.path || '';
 
 
     return Page.isDeletableName(path);
     return Page.isDeletableName(path);
   };
   };
@@ -318,11 +316,11 @@ module.exports = function(crowi, app, req, locals) {
     if (!user || !user.username) {
     if (!user || !user.username) {
       return '';
       return '';
     }
     }
-    return '/user/' + user.username;
+    return `/user/${user.username}`;
   };
   };
 
 
   locals.css = {
   locals.css = {
-    grant: function(pageData) {
+    grant(pageData) {
       if (!pageData) {
       if (!pageData) {
         return '';
         return '';
       }
       }
@@ -332,7 +330,7 @@ module.exports = function(crowi, app, req, locals) {
           return 'grant-public';
           return 'grant-public';
         case Page.GRANT_RESTRICTED:
         case Page.GRANT_RESTRICTED:
           return 'grant-restricted';
           return 'grant-restricted';
-        //case Page.GRANT_SPECIFIED:
+        // case Page.GRANT_SPECIFIED:
         //  return 'grant-specified';
         //  return 'grant-specified';
         //  break;
         //  break;
         case Page.GRANT_OWNER:
         case Page.GRANT_OWNER:
@@ -342,9 +340,7 @@ module.exports = function(crowi, app, req, locals) {
       }
       }
       return '';
       return '';
     },
     },
-    userStatus: function(user) {
-      //debug('userStatus', user._id, user.usename, user.status);
-
+    userStatus(user) {
       switch (user.status) {
       switch (user.status) {
         case User.STATUS_REGISTERED:
         case User.STATUS_REGISTERED:
           return 'label-info';
           return 'label-info';