const createError = require('http-errors');
const models = require('../../models');


function checkLogin(req, res, next) {
  if (!req.session) {
    next(createError(500, 'session服务异常'));
  } else if (!req.session.user) {
    next(createError(401, '请先登录'));
  } else {
    next();
  }
}


async function checkPermission(permission, req) {
  if (!req.session)
    throw createError(500, 'session服务异常');
  if (!req.session.user)
    throw createError(401, '请先登录');

  await checkAndUpdateAuth(req);

  let auth = req.session.auth;
  if (!auth)
    throw createError(401, '权限不够');

  if (permission && !auth.isSuper) {
    let p = auth.permissions.find(x => {
      return x == permission;
    })
    if (!p) throw createError(401, '权限不够')
  }
}

/**
 * 检测用户是否有某项
 * @param {String} permission 
 */
function checkAdmin(permission) {
  return function (req, res, next) {
    (async function () {
      await checkPermission(permission, req);
      next();
    })().catch(next);
  }
}


/**
 * Update session auth.
 * 有效期1分钟
 * @param {Request} req 
 */
async function checkAndUpdateAuth(req) {
  let user = req.session.user;
  let auth = req.session.auth;
  auth = await buildAuth(user);
  req.session.auth = auth;
}

/**
 * Build auth from database.
 * @param {*} user 
 * @param {*} dealerId 
 */
async function buildAuth(_user) {
  let auth = {};
  if (!_user) return auth;
  let user = await models.User.findById(_user._id) 
    .populate('roles');

  let permissions = user.roles.reduce((ps, role) => {
    ps = ps.concat(role.permissions);
    return ps;
  }, []);

  let roles = user.roles; 

  let isSuper = permissions.includes('*');

  auth = { permissions, roles, isSuper };
  auth.ts = new Date().getTime();
  return auth;
}


module.exports = {
  checkLogin,
  checkAdmin,
  checkPermission,
  checkAndUpdateAuth,
}
