module.exports = function(RED) { var https = require('https'); var http = require('http'); var url = require('url'); var OPERATIONS = { 'widgets:list': { method:'GET', path:'/ocs/v2.php/apps/dashboard/api/v1/widgets' }, 'widgetItems:v1': { method:'GET', path:'/ocs/v2.php/apps/dashboard/api/v1/widget-items', query:['sinceIds','limit'] }, 'widgetItems:v2': { method:'GET', path:'/ocs/v2.php/apps/dashboard/api/v2/widget-items', query:['sinceIds','limit'] }, 'layout:get': { method:'GET', path:'/ocs/v2.php/apps/dashboard/api/v3/layout' }, 'layout:update': { method:'POST', path:'/ocs/v2.php/apps/dashboard/api/v3/layout', body:['layout'] }, 'statuses:get': { method:'GET', path:'/ocs/v2.php/apps/dashboard/api/v3/statuses' }, 'statuses:update': { method:'POST', path:'/ocs/v2.php/apps/dashboard/api/v3/statuses', body:['statuses'] } }; function DashboardNode(config) { RED.nodes.createNode(this, config); var node = this; this.configNode = RED.nodes.getNode(config.nextcloud); this.operation = config.operation || 'widgets:list'; this.bodySinceIds = config.bodySinceIds; this.bodyLimit = config.bodyLimit; this.bodyLayout = config.bodyLayout; this.bodyStatuses = config.bodyStatuses; if (!this.configNode) { node.error("No Nextcloud configuration node selected"); return; } node.on('input', function(msg) { var op = OPERATIONS[msg.operation || node.operation]; if (!op) { node.error("Unknown operation: " + (msg.operation || node.operation), msg); return; } var baseUrl = (node.configNode.baseUrl || '').replace(/\/+$/, ''); var username = node.configNode.credentials.username; var password = node.configNode.credentials.password; var path = op.path; var queryParts = []; if (op.query) { op.query.forEach(function(q) { var v = msg[q] !== undefined ? msg[q] : getField(node, q); if (v !== undefined && v !== '') queryParts.push(encodeURIComponent(q) + '=' + encodeURIComponent(v)); }); } var fullUrl = baseUrl + path + (queryParts.length ? '?' + queryParts.join('&') : ''); var parsedUrl = url.parse(fullUrl); var headers = { 'OCS-APIRequest':'true','Accept':'application/json', 'Authorization':'Basic '+Buffer.from(username+':'+password).toString('base64') }; var bodyObj = {}; if (op.body) { op.body.forEach(function(b) { var v = msg[b] !== undefined ? msg[b] : getField(node, b); if (v !== undefined && v !== '') bodyObj[b] = v; }); } if (msg.layout && Array.isArray(msg.layout)) bodyObj.layout = msg.layout; if (msg.statuses && Array.isArray(msg.statuses)) bodyObj.statuses = msg.statuses; var bodyStr = null; if (Object.keys(bodyObj).length > 0) { headers['Content-Type']='application/json'; bodyStr=JSON.stringify(bodyObj); } var opts = { hostname:parsedUrl.hostname, port:parsedUrl.port||(parsedUrl.protocol==='https:'?443:80), path:parsedUrl.path, method:op.method, headers:headers, rejectUnauthorized:false }; node.log(op.method+' '+fullUrl); var transport = parsedUrl.protocol==='https:'?https:http; var req = transport.request(opts, function(res) { var body=''; res.on('data',function(c){body+=c;}); res.on('end',function(){ msg.statusCode=res.statusCode; msg.operation=msg.operation||node.operation; try{msg.payload=JSON.parse(body);}catch(e){msg.payload=body;} node.send(msg); }); }); req.on('error',function(err){msg.error=err.message;node.error(op.method+' '+fullUrl+' — '+err.message,msg);}); if(bodyStr) req.write(bodyStr); req.end(); }); } function getField(node,name) { var m={ 'sinceIds':node.bodySinceIds,'limit':node.bodyLimit,'layout':node.bodyLayout,'statuses':node.bodyStatuses }; return m[name]; } RED.nodes.registerType("dashboard", DashboardNode); };