162 lines
11 KiB
JavaScript
162 lines
11 KiB
JavaScript
module.exports = function(RED) {
|
|
var https = require('https');
|
|
var http = require('http');
|
|
var url = require('url');
|
|
|
|
var OPERATIONS = {
|
|
// Tables (api v2 OCS)
|
|
'table:list': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/tables' },
|
|
'table:get': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/tables/{id}' },
|
|
'table:create': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/tables', body:['title','emoji','description','template'] },
|
|
'table:update': { method:'PUT', path:'/ocs/v2.php/apps/tables/api/2/tables/{id}', body:['title','emoji','description','archived'] },
|
|
'table:delete': { method:'DELETE', path:'/ocs/v2.php/apps/tables/api/2/tables/{id}' },
|
|
'table:scheme': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/tables/scheme/{id}' },
|
|
'table:transfer': { method:'PUT', path:'/ocs/v2.php/apps/tables/api/2/tables/{id}/transfer', body:['newOwnerUserId'] },
|
|
// Init
|
|
'init:index': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/init' },
|
|
// Columns (api v2)
|
|
'column:list': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/columns/{nodeType}/{nodeId}' },
|
|
'column:get': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/columns/{id}' },
|
|
'column:text': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/columns/text', body:['baseNodeId','title','textDefault','textMaxLength','textUnique','mandatory','baseNodeType','selectedViewIds'] },
|
|
'column:number': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/columns/number', body:['baseNodeId','title','numberDefault','numberDecimals','numberMin','numberMax','mandatory','baseNodeType'] },
|
|
'column:selection': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/columns/selection', body:['baseNodeId','title','selectionOptions','selectionDefault','mandatory','baseNodeType'] },
|
|
'column:datetime': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/columns/datetime', body:['baseNodeId','title','datetimeDefault','mandatory','baseNodeType'] },
|
|
'column:usergroup': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/columns/usergroup', body:['baseNodeId','title','usergroupDefault','usergroupMultipleItems','usergroupSelectUsers','usergroupSelectGroups','mandatory','baseNodeType'] },
|
|
// Rows (api v2)
|
|
'row:list': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/{nodeCollection}/{nodeId}/rows', query:['limit','offset'] },
|
|
'row:create': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/{nodeCollection}/{nodeId}/rows', body:['data'] },
|
|
// Generic row ops (api v1)
|
|
'row:get': { method:'GET', path:'/index.php/apps/tables/api/1/rows/{rowId}' },
|
|
'row:update': { method:'PUT', path:'/index.php/apps/tables/api/1/rows/{rowId}', body:['data'] },
|
|
'row:delete': { method:'DELETE', path:'/index.php/apps/tables/api/1/rows/{rowId}' },
|
|
// Views
|
|
'view:list': { method:'GET', path:'/index.php/apps/tables/api/1/tables/{tableId}/views' },
|
|
'view:get': { method:'GET', path:'/index.php/apps/tables/api/1/views/{viewId}' },
|
|
'view:create': { method:'POST', path:'/index.php/apps/tables/api/1/tables/{tableId}/views', body:['title','emoji'] },
|
|
'view:update': { method:'PUT', path:'/index.php/apps/tables/api/1/views/{viewId}', body:['data'] },
|
|
'view:delete': { method:'DELETE', path:'/index.php/apps/tables/api/1/views/{viewId}' },
|
|
// Shares
|
|
'share:listTable': { method:'GET', path:'/index.php/apps/tables/api/1/tables/{tableId}/shares' },
|
|
'share:listView': { method:'GET', path:'/index.php/apps/tables/api/1/views/{viewId}/shares' },
|
|
'share:create': { method:'POST', path:'/index.php/apps/tables/api/1/shares', body:['nodeId','nodeType','receiver','receiverType','permissionRead','permissionCreate','permissionUpdate','permissionDelete','permissionManage'] },
|
|
'share:update': { method:'PUT', path:'/index.php/apps/tables/api/1/shares/{shareId}', body:['permissionType','permissionValue'] },
|
|
'share:delete': { method:'DELETE', path:'/index.php/apps/tables/api/1/shares/{shareId}' },
|
|
'share:linkCreate': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/{nodeCollection}/{nodeId}/share', body:['password'] },
|
|
// Contexts
|
|
'context:list': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/contexts' },
|
|
'context:get': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/contexts/{contextId}' },
|
|
'context:create': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/contexts', body:['name','iconName','description'] },
|
|
'context:update': { method:'PUT', path:'/ocs/v2.php/apps/tables/api/2/contexts/{contextId}', body:['name','iconName','description'] },
|
|
'context:delete': { method:'DELETE', path:'/ocs/v2.php/apps/tables/api/2/contexts/{contextId}' },
|
|
// Favorites
|
|
'favorite:add': { method:'POST', path:'/ocs/v2.php/apps/tables/api/2/favorites/{nodeType}/{nodeId}' },
|
|
'favorite:remove': { method:'DELETE', path:'/ocs/v2.php/apps/tables/api/2/favorites/{nodeType}/{nodeId}' },
|
|
// Import
|
|
'import:table': { method:'POST', path:'/index.php/apps/tables/api/1/import/table/{tableId}', body:['path','createMissingColumns'] },
|
|
// Public rows
|
|
'public:rows': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/public/{token}/rows', query:['limit','offset'] },
|
|
'public:columns': { method:'GET', path:'/ocs/v2.php/apps/tables/api/2/public/{token}/columns' }
|
|
};
|
|
|
|
function TablesNode(config) {
|
|
RED.nodes.createNode(this, config);
|
|
var node = this;
|
|
this.configNode = RED.nodes.getNode(config.nextcloud);
|
|
this.operation = config.operation || 'table:list';
|
|
this.tableId = config.tableId; this.viewId = config.viewId; this.rowId = config.rowId;
|
|
this.shareId = config.shareId; this.nodeId = config.nodeId; this.nodeType = config.nodeType;
|
|
this.nodeCollection = config.nodeCollection; this.token = config.token; this.contextId = config.contextId;
|
|
this.bodyTitle = config.bodyTitle; this.bodyEmoji = config.bodyEmoji; this.bodyData = config.bodyData;
|
|
this.bodyName = config.bodyName; this.bodyReceiver = config.bodyReceiver; this.bodyReceiverType = config.bodyReceiverType;
|
|
this.bodyBaseNodeId = config.bodyBaseNodeId; this.bodyBaseNodeType = config.bodyBaseNodeType;
|
|
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
|
|
.replace(/\{id\}/g, msg.id || node.nodeId || '')
|
|
.replace(/\{tableId\}/g, msg.tableId || node.tableId || '')
|
|
.replace(/\{viewId\}/g, msg.viewId || node.viewId || '')
|
|
.replace(/\{rowId\}/g, msg.rowId || node.rowId || '')
|
|
.replace(/\{shareId\}/g, msg.shareId || node.shareId || '')
|
|
.replace(/\{nodeId\}/g, msg.nodeId || node.nodeId || '')
|
|
.replace(/\{nodeType\}/g, msg.nodeType || node.nodeType || 'table')
|
|
.replace(/\{nodeCollection\}/g, msg.nodeCollection || node.nodeCollection || 'tables')
|
|
.replace(/\{token\}/g, msg.token || node.token || '')
|
|
.replace(/\{contextId\}/g, msg.contextId || node.contextId || '');
|
|
|
|
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 = {
|
|
'Accept': 'application/json',
|
|
'Authorization': 'Basic ' + Buffer.from(username + ':' + password).toString('base64')
|
|
};
|
|
if (path.indexOf('/ocs/') === 0) headers['OCS-APIRequest'] = 'true';
|
|
|
|
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.data !== undefined) bodyObj.data = msg.data;
|
|
if (msg.body && typeof msg.body === 'object') Object.assign(bodyObj, msg.body);
|
|
|
|
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(chunk) { body += chunk; });
|
|
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 = { 'title': node.bodyTitle, 'emoji': node.bodyEmoji, 'name': node.bodyName,
|
|
'receiver': node.bodyReceiver, 'receiverType': node.bodyReceiverType,
|
|
'baseNodeId': node.bodyBaseNodeId, 'baseNodeType': node.bodyBaseNodeType,
|
|
'data': node.bodyData, 'limit': node.bodyLimit, 'offset': node.bodyOffset,
|
|
'password': node.bodyPassword, 'description': node.bodyDescription,
|
|
'template': node.bodyTemplate, 'nodeId': node.nodeId, 'nodeType': node.nodeType,
|
|
'newOwnerUserId': node.bodyNewOwnerId };
|
|
return m[name];
|
|
}
|
|
|
|
RED.nodes.registerType("tables", TablesNode);
|
|
}; |