|
|
// 引入Node.js的path模块,用于处理文件路径相关操作
|
|
|
var path = require('path');
|
|
|
// 原本要引入的roles控制器模块,此处被注释掉了,可能后续会按需启用
|
|
|
// var roles_controller = require("../controllers/roles");
|
|
|
|
|
|
// 再次引入path模块,前面的引入语句重复了,但在Node.js中不会有实质影响,可考虑优化掉重复引入的情况
|
|
|
var path = require("path");
|
|
|
|
|
|
// 创建一个全局对象service_caches,用于缓存服务相关的模块或数据,初始为空对象
|
|
|
global.service_caches = {};
|
|
|
|
|
|
// 创建一个全局变量service_auth_fn,用于存储全局验证函数,初始值为null
|
|
|
global.service_auth_fn = null;
|
|
|
|
|
|
/**
|
|
|
* Invocation函数用于构造一个回调对象格式,主要用于在调用服务的具体方法时进行权限验证等相关操作。
|
|
|
*
|
|
|
* @param {[type]} serviceName 服务名称,用于标识具体是哪个服务。
|
|
|
* @param {[type]} actionName 动作名称(方法名),对应服务模块里具体的函数名称。
|
|
|
* @param {[type]} serviceModule 服务模块,即通过require加载进来的包含具体业务逻辑函数的模块对象。
|
|
|
* @param {[type]} origFunc 原始方法,也就是服务模块里未经包装的原始业务逻辑函数。
|
|
|
*/
|
|
|
function Invocation(serviceName, actionName, serviceModule, origFunc) {
|
|
|
// 返回一个新的函数,这个函数会接收一些参数(此处未在形参中体现,在调用时会传入),并返回另一个函数作为真正的回调函数
|
|
|
return function () {
|
|
|
var origArguments = arguments;
|
|
|
return function (req, res, next) {
|
|
|
// 判断全局验证函数是否存在,如果存在则进行权限验证流程
|
|
|
if (global.service_auth_fn) {
|
|
|
global.service_auth_fn(req, res, next, serviceName, actionName, function (pass) {
|
|
|
// 如果权限验证通过(pass为true),则执行原始的业务逻辑函数
|
|
|
if (pass) {
|
|
|
origFunc.apply(serviceModule, origArguments);
|
|
|
} else {
|
|
|
// 如果权限验证失败,向客户端返回相应的错误信息,状态码为401表示未授权
|
|
|
res.sendResult(null, 401, "权限验证失败");
|
|
|
}
|
|
|
});
|
|
|
} else {
|
|
|
// 如果全局验证函数不存在,直接返回权限验证失败的错误信息给客户端
|
|
|
res.sendResult(null, 401, "权限验证失败");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 定义一个函数用于获取服务对象,它是模块对外暴露的接口之一
|
|
|
module.exports.getService = function (serviceName) {
|
|
|
// 先检查全局缓存中是否已经存在指定名称的服务对象,如果存在则直接返回缓存中的服务对象
|
|
|
if (global.service_caches[serviceName]) {
|
|
|
return global.service_caches[serviceName];
|
|
|
}
|
|
|
|
|
|
// 构建服务模块的文件路径,通过拼接当前工作目录、"services"文件夹以及服务名称来确定具体路径
|
|
|
var servicePath = path.join(process.cwd(), "services", serviceName);
|
|
|
|
|
|
// 通过require加载对应的服务模块,如果模块不存在则返回null并在控制台打印提示信息
|
|
|
var serviceModule = require(servicePath);
|
|
|
if (!serviceModule) {
|
|
|
console.log("模块没有被发现");
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
// 在全局缓存对象中为当前服务名称创建一个空对象,用于后续存储该服务的具体方法相关的回调对象等信息
|
|
|
global.service_caches[serviceName] = {};
|
|
|
|
|
|
// 打印一些提示信息,表明正在拦截指定名称的服务,方便调试和查看流程
|
|
|
console.log("*****************************************");
|
|
|
console.log("拦截服务 => %s", serviceName);
|
|
|
console.log("*****************************************");
|
|
|
|
|
|
// 遍历服务模块里的所有属性(通常是方法)
|
|
|
for (actionName in serviceModule) {
|
|
|
// 检查属性对应的是否是一个函数(即服务模块里有效的业务逻辑函数)
|
|
|
if (serviceModule && serviceModule[actionName] && typeof (serviceModule[actionName]) == "function") {
|
|
|
var origFunc = serviceModule[actionName];
|
|
|
// 使用Invocation函数构造该方法对应的回调对象,并将其存储到全局缓存对象中对应的服务和方法名下
|
|
|
global.service_caches[serviceName][actionName] = Invocation(serviceName, actionName, serviceModule, origFunc);
|
|
|
console.log("action => %s", actionName);
|
|
|
}
|
|
|
}
|
|
|
// 打印一些分割线和空行,用于在控制台输出中更清晰地区分不同服务的处理情况,此处注释掉了打印全局缓存对象的语句
|
|
|
// console.log(global.service_caches);
|
|
|
console.log("*****************************************\n");
|
|
|
return global.service_caches[serviceName];
|
|
|
}
|
|
|
|
|
|
// 定义一个函数用于设置全局验证函数,它也是模块对外暴露的接口,供外部传入具体的验证函数
|
|
|
module.exports.setAuthFn = function (authFn) {
|
|
|
global.service_auth_fn = authFn;
|
|
|
} |