303 lines
22 KiB
JavaScript
303 lines
22 KiB
JavaScript
module.exports = function(RED) {
|
|
var https = require('https');
|
|
var http = require('http');
|
|
var url = require('url');
|
|
|
|
// Operation definitions: operationId -> { method, pathTemplate, queryParams }
|
|
var OPERATIONS = {
|
|
// --- collective ---
|
|
'collective:list': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives' },
|
|
'collective:create': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives', body: ['name','emoji'] },
|
|
'collective:update': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{id}', body: ['emoji'] },
|
|
'collective:trash': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{id}' },
|
|
'collective:editLevel': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{id}/editLevel', body: ['level'] },
|
|
'collective:shareLevel': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{id}/shareLevel', body: ['level'] },
|
|
'collective:pageMode': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{id}/pageMode', body: ['mode'] },
|
|
// --- trash ---
|
|
'trash:list': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/trash' },
|
|
'trash:restore': { method: 'PATCH', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/trash/{id}' },
|
|
'trash:delete': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/trash/{id}', query: ['circle'] },
|
|
// --- share ---
|
|
'share:listCollectiveShares': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/shares' },
|
|
'share:createCollectiveShare': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/shares', body: ['password'] },
|
|
'share:updateCollectiveShare': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/shares/{token}', body: ['editable','password'] },
|
|
'share:deleteCollectiveShare': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/shares/{token}' },
|
|
'share:createPageShare': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{pageId}/shares', body: ['password'] },
|
|
'share:updatePageShare': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{pageId}/shares/{token}', body: ['editable','password'] },
|
|
'share:deletePageShare': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{pageId}/shares/{token}' },
|
|
// --- search ---
|
|
'search:recentPages': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/search/recent', query: ['query','limit'] },
|
|
'search:content': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/search', query: ['searchString'] },
|
|
// --- page ---
|
|
'page:list': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages' },
|
|
'page:get': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}' },
|
|
'page:create': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{parentId}', body: ['title','templateId'] },
|
|
'page:moveOrCopy': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}', body: ['parentId','title','index','copy'] },
|
|
'page:trash': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}' },
|
|
'page:touch': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/touch' },
|
|
'page:fullWidth': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/fullWidth', body: ['fullWidth'] },
|
|
'page:emoji': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/emoji', body: ['emoji'] },
|
|
'page:subpageOrder': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/subpageOrder', body: ['subpageOrder'] },
|
|
'page:moveToCollective': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/to/{newCollectiveId}', body: ['parentId','index','copy'] },
|
|
'page:addTag': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/tags/{tagId}' },
|
|
'page:removeTag': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/tags/{tagId}' },
|
|
'page:listAttachments': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/attachments' },
|
|
'page:uploadAttachment': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/attachments' },
|
|
'page:renameAttachment': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/attachments/{attachmentId}', body: ['name'] },
|
|
'page:deleteAttachment': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/attachments/{attachmentId}' },
|
|
'page:restoreAttachment': { method: 'PATCH', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/{id}/attachments/trash/{attachmentId}' },
|
|
// --- page_trash ---
|
|
'page_trash:list': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/trash' },
|
|
'page_trash:restore': { method: 'PATCH', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/trash/{id}' },
|
|
'page_trash:delete': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/trash/{id}' },
|
|
// --- template ---
|
|
'template:list': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/templates' },
|
|
'template:create': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/templates/{id}', body: ['title','parentId'] },
|
|
'template:rename': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/templates/{id}', body: ['title'] },
|
|
'template:delete': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/templates/{id}' },
|
|
'template:emoji': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/pages/templates/{id}/emoji', body: ['emoji'] },
|
|
// --- tag ---
|
|
'tag:list': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/tags' },
|
|
'tag:create': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/tags', body: ['name','color'] },
|
|
'tag:update': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/tags/{id}', body: ['name','color'] },
|
|
'tag:delete': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/tags/{id}' },
|
|
// --- collective_user_settings ---
|
|
'userSettings:pageOrder': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/userSettings/pageOrder', body: ['pageOrder'] },
|
|
'userSettings:showMembers': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/userSettings/showMembers', body: ['showMembers'] },
|
|
'userSettings:showRecentPages':{ method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/userSettings/showRecentPages', body: ['showRecentPages'] },
|
|
'userSettings:favoritePages': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/userSettings/favoritePages', body: ['favoritePages'] },
|
|
// --- session ---
|
|
'session:create': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/sessions' },
|
|
'session:sync': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/sessions', body: ['token'] },
|
|
'session:close': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/collectives/{collectiveId}/sessions', query: ['token'] },
|
|
// --- settings ---
|
|
'settings:get': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/settings/user/{key}' },
|
|
'settings:set': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/settings/user', body: ['key','value'] },
|
|
// --- public_collective ---
|
|
'public:getCollective': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}' },
|
|
// --- public_page ---
|
|
'public:listPages': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages' },
|
|
'public:getPage': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}' },
|
|
'public:createPage': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{parentId}', body: ['title','templateId'] },
|
|
'public:moveOrCopyPage': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}', body: ['parentId','title','index','copy'] },
|
|
'public:trashPage': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}' },
|
|
'public:touchPage': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/touch' },
|
|
'public:fullWidth': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/fullWidth', body: ['fullWidth'] },
|
|
'public:emoji': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/emoji', body: ['emoji'] },
|
|
'public:subpageOrder': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/subpageOrder', body: ['subpageOrder'] },
|
|
'public:addTag': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/tags/{tagId}' },
|
|
'public:removeTag': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/tags/{tagId}' },
|
|
'public:listAttachments': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/attachments' },
|
|
'public:uploadAttachment': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/attachments' },
|
|
'public:renameAttachment': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/attachments/{attachmentId}', body: ['name'] },
|
|
'public:deleteAttachment': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/attachments/{attachmentId}' },
|
|
'public:restoreAttachment': { method: 'PATCH', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/{id}/attachments/trash/{attachmentId}' },
|
|
'public:searchContent': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/search', query: ['searchString'] },
|
|
// --- public_page_trash ---
|
|
'public:listTrash': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/trash' },
|
|
'public:restoreTrash': { method: 'PATCH', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/trash/{id}' },
|
|
'public:deleteTrash': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/trash/{id}' },
|
|
// --- public_template ---
|
|
'public:listTemplates': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/pages/templates' },
|
|
// --- public_tag ---
|
|
'public:listTags': { method: 'GET', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/tags' },
|
|
'public:createTag': { method: 'POST', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/tags', body: ['name','color'] },
|
|
'public:updateTag': { method: 'PUT', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/tags/{id}', body: ['name','color'] },
|
|
'public:deleteTag': { method: 'DELETE', path: '/ocs/v2.php/apps/collectives/api/v1.0/p/collectives/{token}/tags/{id}' }
|
|
};
|
|
|
|
function CollectivesNode(config) {
|
|
RED.nodes.createNode(this, config);
|
|
var node = this;
|
|
this.configNode = RED.nodes.getNode(config.nextcloud);
|
|
this.operation = config.operation || 'collective:list';
|
|
|
|
// Path parameter fields from config
|
|
this.collectiveId = config.collectiveId;
|
|
this.pageId = config.pageId;
|
|
this.token = config.token;
|
|
this.parentId = config.parentId;
|
|
this.tagId = config.tagId;
|
|
this.attachmentId = config.attachmentId;
|
|
this.newCollectiveId = config.newCollectiveId;
|
|
this.itemId = config.itemId; // generic {id}
|
|
this.settingKey = config.settingKey;
|
|
|
|
// Body fields
|
|
this.bodyName = config.bodyName;
|
|
this.bodyEmoji = config.bodyEmoji;
|
|
this.bodyColor = config.bodyColor;
|
|
this.bodyLevel = config.bodyLevel;
|
|
this.bodyMode = config.bodyMode;
|
|
this.bodyTitle = config.bodyTitle;
|
|
this.bodyEditable = config.bodyEditable;
|
|
this.bodyPassword = config.bodyPassword;
|
|
this.bodyFullWidth = config.bodyFullWidth;
|
|
this.bodyTemplateId = config.bodyTemplateId;
|
|
this.bodyPageOrder = config.bodyPageOrder;
|
|
this.bodyShowMembers = config.bodyShowMembers;
|
|
this.bodyShowRecentPages = config.bodyShowRecentPages;
|
|
this.bodyFavoritePages = config.bodyFavoritePages;
|
|
this.bodyIndex = config.bodyIndex;
|
|
this.bodyCopy = config.bodyCopy;
|
|
this.bodySubpageOrder = config.bodySubpageOrder;
|
|
this.bodyParentId = config.bodyParentId;
|
|
this.bodyCircle = config.bodyCircle;
|
|
this.bodySearchString = config.bodySearchString;
|
|
this.bodyQuery = config.bodyQuery;
|
|
this.bodyLimit = config.bodyLimit;
|
|
this.bodyKey = config.bodyKey;
|
|
this.bodyValue = config.bodyValue;
|
|
this.bodySessionToken = config.bodySessionToken;
|
|
|
|
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;
|
|
|
|
// Build path with substituted parameters (msg overrides config)
|
|
var path = op.path;
|
|
var subs = {
|
|
'{id}': msg.itemId || node.itemId || msg.pageId || node.pageId || '',
|
|
'{collectiveId}': msg.collectiveId || node.collectiveId || '',
|
|
'{pageId}': msg.pageId || node.pageId || '',
|
|
'{parentId}': msg.parentId || node.parentId || '',
|
|
'{token}': msg.token || node.token || '',
|
|
'{tagId}': msg.tagId || node.tagId || '',
|
|
'{attachmentId}': msg.attachmentId || node.attachmentId || '',
|
|
'{newCollectiveId}': msg.newCollectiveId || node.newCollectiveId || '',
|
|
'{key}': msg.settingKey || node.settingKey || ''
|
|
};
|
|
Object.keys(subs).forEach(function(k) {
|
|
path = path.replace(k, subs[k]);
|
|
});
|
|
|
|
// Query parameters
|
|
var queryParts = [];
|
|
var queryDefs = msg.query || {};
|
|
if (op.query) {
|
|
op.query.forEach(function(q) {
|
|
var val = msg[q] !== undefined ? msg[q] : getBodyField(node, q);
|
|
if (val !== undefined && val !== '') {
|
|
queryParts.push(encodeURIComponent(q) + '=' + encodeURIComponent(val));
|
|
}
|
|
});
|
|
}
|
|
// Also handle query overrides from msg
|
|
if (typeof msg.query === 'object') {
|
|
Object.keys(msg.query).forEach(function(k) {
|
|
if (op.query && op.query.indexOf(k) === -1) {
|
|
queryParts.push(encodeURIComponent(k) + '=' + encodeURIComponent(msg.query[k]));
|
|
}
|
|
});
|
|
}
|
|
var fullUrl = baseUrl + path;
|
|
if (queryParts.length) {
|
|
fullUrl += '?' + queryParts.join('&');
|
|
}
|
|
|
|
var parsedUrl = url.parse(fullUrl);
|
|
|
|
var headers = {
|
|
'OCS-APIRequest': 'true',
|
|
'Accept': 'application/json',
|
|
'Authorization': 'Basic ' + Buffer.from(username + ':' + password).toString('base64')
|
|
};
|
|
|
|
// Build request body
|
|
var bodyObj = msg.body || {};
|
|
if (op.body) {
|
|
op.body.forEach(function(b) {
|
|
var val = msg[b] !== undefined ? msg[b] : getBodyField(node, b);
|
|
if (val !== undefined && val !== '') {
|
|
bodyObj[b] = val;
|
|
}
|
|
});
|
|
}
|
|
|
|
var bodyStr = null;
|
|
if (Object.keys(bodyObj).length > 0) {
|
|
headers['Content-Type'] = 'application/json';
|
|
bodyStr = JSON.stringify(bodyObj);
|
|
}
|
|
// Allow raw body override
|
|
if (msg.rawBody) {
|
|
bodyStr = typeof msg.rawBody === 'string' ? msg.rawBody : JSON.stringify(msg.rawBody);
|
|
if (!headers['Content-Type']) headers['Content-Type'] = 'application/json';
|
|
}
|
|
|
|
if (msg.headers && typeof msg.headers === 'object') {
|
|
Object.keys(msg.headers).forEach(function(k) {
|
|
headers[k] = msg.headers[k];
|
|
});
|
|
}
|
|
|
|
var opts = {
|
|
hostname: parsedUrl.hostname,
|
|
port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80),
|
|
path: parsedUrl.path,
|
|
method: op.method,
|
|
headers: headers,
|
|
rejectUnauthorized: false
|
|
};
|
|
|
|
var transport = parsedUrl.protocol === 'https:' ? https : http;
|
|
|
|
node.log(op.method + ' ' + fullUrl);
|
|
|
|
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 = 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 getBodyField(node, name) {
|
|
var map = {
|
|
'name': node.bodyName, 'emoji': node.bodyEmoji, 'color': node.bodyColor,
|
|
'level': node.bodyLevel, 'mode': node.bodyMode, 'title': node.bodyTitle,
|
|
'editable': node.bodyEditable, 'password': node.bodyPassword,
|
|
'fullWidth': node.bodyFullWidth, 'templateId': node.bodyTemplateId,
|
|
'pageOrder': node.bodyPageOrder, 'showMembers': node.bodyShowMembers,
|
|
'showRecentPages': node.bodyShowRecentPages, 'favoritePages': node.bodyFavoritePages,
|
|
'index': node.bodyIndex, 'copy': node.bodyCopy, 'subpageOrder': node.bodySubpageOrder,
|
|
'parentId': node.bodyParentId, 'circle': node.bodyCircle,
|
|
'searchString': node.bodySearchString, 'query': node.bodyQuery, 'limit': node.bodyLimit,
|
|
'key': node.bodyKey, 'value': node.bodyValue, 'token': node.bodySessionToken
|
|
};
|
|
return map[name];
|
|
}
|
|
|
|
RED.nodes.registerType("collectives", CollectivesNode);
|
|
}; |