auth.js 4.64 KB
/**
 * 认证中间件
 * @author h1bomb
 */


var _= require('lodash');
var ipaddr = require('ipaddr.js');
var options=require('../staticConfig.js').staticDir;

var author=require("../stub/service/auth");

/**
 * 不需要权限校验配置
 */
var guestAccessList = {
    "POST:/login":true,
    "GET:/logout":true
}

var NO_AUTH = '没有权限!';

var WEBSITE = 2;

var CSS_FILE = '/dist/index.css';

var STATIC_PATH = '';

var env = process.env.NODE_ENV || 'development';

//设置对于环境环境
if(env!=='development') {
    CSS_FILE = options[env].path+'/index.css';
    STATIC_PATH = options[env].path;
}


/**
 * 认证中间件
 * @param  {Object} req  请求对象
 * @param  {Object} res  响应对象
 * @param  {Function} next 执行下个中间件
 * @return {void}       无返回
 */
module.exports = function(req, res, next) {

    //方法名称
    var method = req.method;

    function nextRedirect(method,path){
        //进行白名单验证和session验证
        if(guestAccessList[method+":"+path]||req.session.user) {
            //判断是否已存在appendData
            if(!res.appendData) {
                res.appendData = _.cloneDeep(req.session.user);
            } else {
                res.appendData = _.merge({},res.appendData,req.session.user);
            }

            //添加当前菜单激活
            addActiveMenu(req,res);
            
            //添加管理员信息到http头
            if(req.session.user) {
                appendAdminInfo(req,req.session.user.auth);
            }
            
            next();
        } else {
            req.app.logger.log('info',"CurentView:Login");
            //如果是登陆界面不加载布局
            res.render('pages/login',{layout:false,cssfile:CSS_FILE,path:STATIC_PATH});
        }
    }

    function filterOriginalUrl(path){
        if(!/\.\w+/.test(path)){
            return path.replace(/\?.+/,'');
        }
        return "";
    }
    //访问路由路径
    var path = req.route?req.route.path:filterOriginalUrl(req.originalUrl);
    if(req.session.user) {
        if(guestAccessList[method+":"+path]){
            nextRedirect(method,path);
            return;
        }
        /*判断权限*/
        if(path&&req.session.user.allRight[path]){
            author.validateAuthor(req.session.user.auth.pid,req.session.user.auth.role_id,path,function(data){
                if(data.code!=200){
                    // res.status(403);
                    if(!req.xhr){
                        res.render('error/error_nolayout',{message:NO_AUTH,layout:false,cssfile:CSS_FILE});
                    }else{
                        res.json({code:201,message:"没有权限!"});
                    }
                    return;
                }
                nextRedirect(method,path);
            });
        }else{
            nextRedirect(method,path);
        }
    }else{
        nextRedirect(method,path);
    }
    
}

/**
 * 添加当前激活的菜单
 * @param {Object} req 请求对象
 * @param {Object} res 返回对象
 */
function addActiveMenu(req,res) {
    var curUrl = req.originalUrl;
    var lastOpen = req.headers['referer'];
    var hasActive = false;
    if(!res.appendData||!res.appendData.menu) {
        return;
    }
    var menu = _.cloneDeep(res.appendData.menu);
    
    function loop(list,condition) {
        _.forEach(menu,function(v,k) {
            _.forEach(v.menu,function(val,key) {
                if(condition(val.href,curUrl)) {
                    v.active = 'active';
                    val.active = 'active';
                    hasActive = true;
                }
            });
        });
    }

    loop(menu,function(url) { return url === curUrl;});

    if(!hasActive && lastOpen) {
        loop(menu,function(url) { return lastOpen.indexOf(url)>-1;});
    }
    res.appendData.menu = menu;
}

/**
 * 检查路径是否没有权限
 * @param  {String} path
 * @param {Object} req
 * @return {Boolean}
 */
function checkPath(path,req) {
    var right = req.session.user.noRight;
    var ret = true;
    _.forEach(right,function(v,k){
        if(path.indexOf(k)>-1) {
            ret = false;
            return;
        }
    });
    return ret;
}

/**
 * 附加管理员的信息
 * @param  {Request} req  请求对象
 * @param  {Number} uid  用户ID
 * @param  {String} name 用户名
 * @return {Object}      用户信息对象
 */
function appendAdminInfo(req,auth) {
    var ipObject = ipaddr.process(req.ip).octets;
    var ip = ipObject?ipObject.join('.'):req.ip;
    req._yoheaders = {
        'x-user-id':auth.pid,
        'x-user-name':auth.account,
        'x-site-type':WEBSITE,
        'x-client-ip':ip,
        'x-shop-id':auth.shopId
    };
}