const model = require('../../models/');
const AccessControl = require('accesscontrol').AccessControl;
const createError = require('http-errors');
const base = require('./base');


/**
 * Check is user has permission.
 * @param {*} action 
 * @param {*} resource 
 * @returns 
 */
function need(action, resource) {
  return (req, res, next) => {
    (async () => {
      let ac = await getAc(req);
      let role = 'user';
      let perm = ac.permission({ role, action, resource });
      if (!perm.granted) throw createError(403, '权限不够');
      next();
    })().catch(next)
  };
}


async function readAny(req, resource) {
  if(!req.ac) throw 'ac no build';
  /**@type {AccessControl} */
  let ac = req.ac;
  return ac.can('user').readAny(resource).granted;
}

/**
 * 
 * @param {string} userId 
 * @returns {AccessControl}
 */
async function buildAc(userId) {
  let user = await model.User.findById(userId).populate('roles');

  let grants = [];
  if (['chengen', 'guoziyun'].includes(user.username)) {
    grants = base.fullGrants();
  } else {
    user.roles.forEach(role => {
      grants = grants.concat(role.grants);
    })
  }
  // console.log('grants', grants);
  grants = grantsTransform(grants);
  // console.log('grants2ac', grants);
  return new AccessControl(grants);
}


/**
 * 
 * @param {import('express').Request} req 
 * @returns {AccessControl}
 */
async function getAc(req) {
  if(req.ac) return req.ac;
  req.ac = await buildAc(req.session.user._id);
  return req.ac;
}


function grantsTransform(grants) {
  return grants.map(item => {
    let { resource, action, possession, attributes } = item;
    return {
      role: 'user',
      resource, attributes,
      action: `${action}:${possession}`,
    }
  })
}

module.exports = { need, buildAc, getAc,  readAny }
