mirror of https://github.com/node-red/node-red.git
				
				
				
			
		
			
				
	
	
		
			186 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			186 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
/**
 | 
						|
 * Copyright JS Foundation and other contributors, http://js.foundation
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 *
 | 
						|
 * Unless required by applicable law or agreed to in writing, software
 | 
						|
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
 * See the License for the specific language governing permissions and
 | 
						|
 * limitations under the License.
 | 
						|
 **/
 | 
						|
 | 
						|
const path = require("path");
 | 
						|
const semver = require("semver");
 | 
						|
const {events,i18n,log} = require("@node-red/util");
 | 
						|
var runtime;
 | 
						|
 | 
						|
function copyObjectProperties(src,dst,copyList,blockList) {
 | 
						|
    if (!src) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    if (copyList && !blockList) {
 | 
						|
        copyList.forEach(function(i) {
 | 
						|
            if (src.hasOwnProperty(i)) {
 | 
						|
                var propDescriptor = Object.getOwnPropertyDescriptor(src,i);
 | 
						|
                Object.defineProperty(dst,i,propDescriptor);
 | 
						|
            }
 | 
						|
        });
 | 
						|
    } else if (!copyList && blockList) {
 | 
						|
        for (var i in src) {
 | 
						|
            if (src.hasOwnProperty(i) && blockList.indexOf(i) === -1) {
 | 
						|
                var propDescriptor = Object.getOwnPropertyDescriptor(src,i);
 | 
						|
                Object.defineProperty(dst,i,propDescriptor);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
function requireModule(name) {
 | 
						|
    var moduleInfo = require("./index").getModuleInfo(name);
 | 
						|
    if (moduleInfo && moduleInfo.path) {
 | 
						|
        var relPath = path.relative(__dirname, moduleInfo.path);
 | 
						|
        return require(relPath);
 | 
						|
    } else {
 | 
						|
        var err = new Error(`Cannot find module '${name}'`);
 | 
						|
        err.code = "MODULE_NOT_FOUND";
 | 
						|
        throw err;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function createNodeApi(node) {
 | 
						|
    var red = {
 | 
						|
        nodes: {},
 | 
						|
        log: {},
 | 
						|
        settings: {},
 | 
						|
        events: events,
 | 
						|
        hooks: runtime.hooks,
 | 
						|
        util: runtime.util,
 | 
						|
        version: runtime.version,
 | 
						|
        require: requireModule,
 | 
						|
        comms: {
 | 
						|
            publish: function(topic,data,retain) {
 | 
						|
                events.emit("comms",{
 | 
						|
                    topic: topic,
 | 
						|
                    data: data,
 | 
						|
                    retain: retain
 | 
						|
                })
 | 
						|
            }
 | 
						|
        },
 | 
						|
        library: {
 | 
						|
            register: function(type) {
 | 
						|
                return runtime.library.register(node.id,type);
 | 
						|
            }
 | 
						|
        },
 | 
						|
        httpNode: runtime.nodeApp,
 | 
						|
        httpAdmin: runtime.adminApp,
 | 
						|
        server: runtime.server
 | 
						|
    }
 | 
						|
    copyObjectProperties(runtime.nodes,red.nodes,["createNode","getNode","eachNode","addCredentials","getCredentials","deleteCredentials" ]);
 | 
						|
    red.nodes.registerType = function(type,constructor,opts) {
 | 
						|
        runtime.nodes.registerType(node.id,type,constructor,opts);
 | 
						|
    }
 | 
						|
    red.nodes.registerSubflow = function(subflowDef) {
 | 
						|
        runtime.nodes.registerSubflow(node.id,subflowDef)
 | 
						|
    }
 | 
						|
    copyObjectProperties(log,red.log,null,["init"]);
 | 
						|
    copyObjectProperties(runtime.settings,red.settings,null,["init","load","reset"]);
 | 
						|
    if (runtime.adminApi) {
 | 
						|
        red.auth = runtime.adminApi.auth;
 | 
						|
    } else {
 | 
						|
        //TODO: runtime.adminApi is always stubbed if not enabled, so this block
 | 
						|
        // is unused - but may be needed for the unit tests
 | 
						|
        red.auth = {
 | 
						|
            needsPermission: function(v) { return function(req,res,next) {next()} }
 | 
						|
        };
 | 
						|
        // TODO: stub out httpAdmin/httpNode/server
 | 
						|
    }
 | 
						|
    red["_"] = function() {
 | 
						|
        var args = Array.prototype.slice.call(arguments, 0);
 | 
						|
        if (args[0].indexOf(":") === -1) {
 | 
						|
            args[0] = node.namespace+":"+args[0];
 | 
						|
        }
 | 
						|
        return i18n._.apply(null,args);
 | 
						|
    }
 | 
						|
    return red;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
function checkAgainstList(module,version,list) {
 | 
						|
    for (let i=0;i<list.length;i++) {
 | 
						|
        let rule = list[i];
 | 
						|
        if (rule.module.test(module)) {
 | 
						|
            if (version && rule.version) {
 | 
						|
                if (semver.satisfies(version,rule.version)) {
 | 
						|
                    return rule;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                return rule;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
function checkModuleAllowed(module,version,allowList,denyList) {
 | 
						|
    // console.log("checkModuleAllowed",module,version);//,allowList,denyList)
 | 
						|
    if (!allowList && !denyList) {
 | 
						|
        // Default to allow
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    if (allowList.length === 0 && denyList.length === 0) {
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    var allowedRule = checkAgainstList(module,version,allowList);
 | 
						|
    var deniedRule = checkAgainstList(module,version,denyList);
 | 
						|
    // console.log("A",allowedRule)
 | 
						|
    // console.log("D",deniedRule)
 | 
						|
 | 
						|
    if (allowedRule && !deniedRule) {
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    if (!allowedRule && deniedRule) {
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
    if (!allowedRule && !deniedRule) {
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
    if (allowedRule.wildcardPos !== deniedRule.wildcardPos) {
 | 
						|
        return allowedRule.wildcardPos > deniedRule.wildcardPos
 | 
						|
    } else {
 | 
						|
        // First wildcard in same position.
 | 
						|
        // Go with the longer matching rule. This isn't going to be 100%
 | 
						|
        // right, but we are deep into edge cases at this point.
 | 
						|
        return allowedRule.module.toString().length > deniedRule.module.toString().length
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
}
 | 
						|
 | 
						|
function parseModuleList(list) {
 | 
						|
    list = list || ["*"];
 | 
						|
    return list.map(rule => {
 | 
						|
        let m = /^(.+?)(?:@(.*))?$/.exec(rule);
 | 
						|
        let wildcardPos = m[1].indexOf("*");
 | 
						|
        wildcardPos = wildcardPos===-1?Infinity:wildcardPos;
 | 
						|
 | 
						|
        return {
 | 
						|
            module: new RegExp("^"+m[1].replace(/\*/g,".*")+"$"),
 | 
						|
            version: m[2],
 | 
						|
            wildcardPos: wildcardPos
 | 
						|
        }
 | 
						|
    })
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
module.exports = {
 | 
						|
    init: function(_runtime) {
 | 
						|
        runtime = _runtime;
 | 
						|
    },
 | 
						|
    createNodeApi: createNodeApi,
 | 
						|
    parseModuleList: parseModuleList,
 | 
						|
    checkModuleAllowed: checkModuleAllowed
 | 
						|
}
 |