mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
Feature/multi tenant (#377)
* [feature] Add tenantManager * [fix] Fix export * [schema] Change schema for tenants * [de] For auth * [config] Remove unused secret.browser param to unify with multitenancy * [feature] Add OperationContext to store state of request * [log] Remove docId and userId from log message * [feature] Add OperationContext class * [feature] For logging * [feature] Add content to some methods * [feature] For multitenancy * [feature] For multitenancy * [feature] For multitenancy * [feature] For multitenancy * [feature] For multitenancy * [feature] For multitenancy * [feature] Move all tenant logic to tenantManager * [feature] Fix reading of tenant license * [feature] Move tenant logic to EditorData interface * [feature] Use context in SQL queries * [feature] Refactoring * [feature] Fix editorDataMemory * [feature] Fix before merge
This commit is contained in:
@ -97,6 +97,13 @@
|
|||||||
"privateKeyOld": "MIIEowIBAAKCAQEAqnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/wIDAQABAoIBAQCKtUSBs8tNYrGTQTlBHXrwpkDg+u7WSZt5sEcfnkxA39BLtlHU8gGO0E9Ihr8GAL+oWjUsEltJ9GTtN8CJ9lFdPVS8sTiCZR/YQOggmFRZTJyVzMrkXgF7Uwwiu3+KxLiTOZx9eRhfDBlTD8W9fXaegX2i2Xp2ohUhBHthEBLdaZTWFi5Sid/Y0dDzBeP6UIJorZ5D+1ybaeIVHjndpwNsIEUGUxPFLrkeiU8Rm4MJ9ahxfywcP7DjQoPGY9Ge5cBhpxfzERWf732wUD6o3+L9tvOBU00CLVjULbGZKTVE2FJMyXK9jr6Zor9Mkhomp6/8Agkr9rp+TPyelFGYEz8hAoGBAOEc09CrL3eYBkhNEcaMQzxBLvOGpg8kaDX5SaArHfl9+U9yzRqss4ARECanp9HuHfjMQo7iejao0ngDjL7BNMSaH74QlSsPOY2iOm8Qvx8/zb7g4h9r1zLjFZb3mpSA4snRZvvdiZ9ugbuVPmhXnDzRRMg45MibJeeOTJNylofRAoGBAMHfF/WutqKDoX25qZo9m74W4bttOj6oIDk1N4/c6M1Z1v/aptYSE06bkWngj9P46kqjaay4hgMtzyGruc5aojPx5MHHf5bo14+Jv4NzYtR2llrUxO+UJX7aCfUYXI7RC93GUmhpeQ414j7SNAXec58d7e+ETw+6cHiAWO4uOSTPAoGATPq5qDLR4Zi4FUNdn8LZPyKfNqHF6YmupT5hIgd8kZO1jKiaYNPL8jBjkIRmjBBcaXcYD5p85nImvumf2J9jNxPpZOpwyC/Fo5xlVROp97qu1eY7DTmodntXJ6/2SXAlnZQhHmHsrPtyG752f+HtyJJbbgiem8cKWDu+DfHybfECgYBbSLo1WiBwgN4nHqZ3E48jgA6le5azLeKOTTpuKKwNFMIhEkj//t7MYn+jhLL0Mf3PSwZU50Vidc1To1IHkbFSGBGIFHFFEzl8QnXEZS4hr/y3o/teezj0c6HAn8nlDRUzRVBEDXWMdV6kCcGpCccTIrqHzpqTY0vV0UkOTQFnDQKBgAxSEhm/gtCYJIMCBe+KBJT9uECV5xDQopTTjsGOkd4306EN2dyPOIlAfwM6K/0qWisa0Ei5i8TbRRuBeTTdLEYLqXCJ7fj5tdD1begBdSVtHQ2WHqzPJSuImTkFi9NXxd1XUyZFM3y6YQvlssSuL7QSxUIEtZHnrJTt3QDd10dj",
|
"privateKeyOld": "MIIEowIBAAKCAQEAqnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/wIDAQABAoIBAQCKtUSBs8tNYrGTQTlBHXrwpkDg+u7WSZt5sEcfnkxA39BLtlHU8gGO0E9Ihr8GAL+oWjUsEltJ9GTtN8CJ9lFdPVS8sTiCZR/YQOggmFRZTJyVzMrkXgF7Uwwiu3+KxLiTOZx9eRhfDBlTD8W9fXaegX2i2Xp2ohUhBHthEBLdaZTWFi5Sid/Y0dDzBeP6UIJorZ5D+1ybaeIVHjndpwNsIEUGUxPFLrkeiU8Rm4MJ9ahxfywcP7DjQoPGY9Ge5cBhpxfzERWf732wUD6o3+L9tvOBU00CLVjULbGZKTVE2FJMyXK9jr6Zor9Mkhomp6/8Agkr9rp+TPyelFGYEz8hAoGBAOEc09CrL3eYBkhNEcaMQzxBLvOGpg8kaDX5SaArHfl9+U9yzRqss4ARECanp9HuHfjMQo7iejao0ngDjL7BNMSaH74QlSsPOY2iOm8Qvx8/zb7g4h9r1zLjFZb3mpSA4snRZvvdiZ9ugbuVPmhXnDzRRMg45MibJeeOTJNylofRAoGBAMHfF/WutqKDoX25qZo9m74W4bttOj6oIDk1N4/c6M1Z1v/aptYSE06bkWngj9P46kqjaay4hgMtzyGruc5aojPx5MHHf5bo14+Jv4NzYtR2llrUxO+UJX7aCfUYXI7RC93GUmhpeQ414j7SNAXec58d7e+ETw+6cHiAWO4uOSTPAoGATPq5qDLR4Zi4FUNdn8LZPyKfNqHF6YmupT5hIgd8kZO1jKiaYNPL8jBjkIRmjBBcaXcYD5p85nImvumf2J9jNxPpZOpwyC/Fo5xlVROp97qu1eY7DTmodntXJ6/2SXAlnZQhHmHsrPtyG752f+HtyJJbbgiem8cKWDu+DfHybfECgYBbSLo1WiBwgN4nHqZ3E48jgA6le5azLeKOTTpuKKwNFMIhEkj//t7MYn+jhLL0Mf3PSwZU50Vidc1To1IHkbFSGBGIFHFFEzl8QnXEZS4hr/y3o/teezj0c6HAn8nlDRUzRVBEDXWMdV6kCcGpCccTIrqHzpqTY0vV0UkOTQFnDQKBgAxSEhm/gtCYJIMCBe+KBJT9uECV5xDQopTTjsGOkd4306EN2dyPOIlAfwM6K/0qWisa0Ei5i8TbRRuBeTTdLEYLqXCJ7fj5tdD1begBdSVtHQ2WHqzPJSuImTkFi9NXxd1XUyZFM3y6YQvlssSuL7QSxUIEtZHnrJTt3QDd10dj",
|
||||||
"refreshLockInterval": "10m"
|
"refreshLockInterval": "10m"
|
||||||
},
|
},
|
||||||
|
"tenants": {
|
||||||
|
"baseDir": "",
|
||||||
|
"baseDomain": "",
|
||||||
|
"filenameSecret": "secret.key",
|
||||||
|
"filenameLicense": "license.lic",
|
||||||
|
"defaultTetant": "tetant"
|
||||||
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"CoAuthoring": {
|
"CoAuthoring": {
|
||||||
"server": {
|
"server": {
|
||||||
@ -200,8 +207,7 @@
|
|||||||
"allowMetaIPAddress": true
|
"allowMetaIPAddress": true
|
||||||
},
|
},
|
||||||
"secret": {
|
"secret": {
|
||||||
"browser": {"string": "secret", "file": "", "tenants": {}},
|
"inbox": {"string": "secret", "file": ""},
|
||||||
"inbox": {"string": "secret", "file": "", "tenants": {}},
|
|
||||||
"outbox": {"string": "secret", "file": ""},
|
"outbox": {"string": "secret", "file": ""},
|
||||||
"session": {"string": "secret", "file": ""}
|
"session": {"string": "secret", "file": ""}
|
||||||
},
|
},
|
||||||
@ -213,9 +219,6 @@
|
|||||||
"outbox": false
|
"outbox": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browser": {
|
|
||||||
"secretFromInbox": true
|
|
||||||
},
|
|
||||||
"inbox": {
|
"inbox": {
|
||||||
"header": "Authorization",
|
"header": "Authorization",
|
||||||
"prefix": "Bearer ",
|
"prefix": "Bearer ",
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"type": "console",
|
"type": "console",
|
||||||
"layout": {
|
"layout": {
|
||||||
"type": "pattern",
|
"type": "pattern",
|
||||||
"pattern": "%[[%d] [%p] %c -%] %.10000m"
|
"pattern": "%[[%d] [%p] [%X{TENANT}] [%X{DOCID}] [%X{USERID}] %c -%] %.10000m"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"type": "console",
|
"type": "console",
|
||||||
"layout": {
|
"layout": {
|
||||||
"type": "pattern",
|
"type": "pattern",
|
||||||
"pattern": "[%d] [%p] %c - %.10000m"
|
"pattern": "[%d] [%p] [%X{TENANT}] [%X{DOCID}] [%X{USERID}] %c - %.10000m"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
var config = require('config');
|
var config = require('config');
|
||||||
var container = require('rhea');
|
var container = require('rhea');
|
||||||
var logger = require('./logger');
|
var logger = require('./logger');
|
||||||
|
const operationContext = require('./operationContext');
|
||||||
|
|
||||||
const cfgRabbitSocketOptions = config.get('activemq.connectOptions');
|
const cfgRabbitSocketOptions = config.get('activemq.connectOptions');
|
||||||
|
|
||||||
@ -45,20 +46,20 @@ function connetPromise(reconnectOnConnectionError, closeCallback) {
|
|||||||
let conn = container.create_container().connect(cfgRabbitSocketOptions);
|
let conn = container.create_container().connect(cfgRabbitSocketOptions);
|
||||||
let isConnected = false;
|
let isConnected = false;
|
||||||
conn.on('connection_open', function(context) {
|
conn.on('connection_open', function(context) {
|
||||||
logger.debug('[AMQP] connected');
|
operationContext.global.logger.debug('[AMQP] connected');
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
resolve(conn);
|
resolve(conn);
|
||||||
});
|
});
|
||||||
conn.on('connection_error', function(context) {
|
conn.on('connection_error', function(context) {
|
||||||
//todo
|
//todo
|
||||||
logger.debug('[AMQP] connection_error %s', context.error);
|
operationContext.global.logger.debug('[AMQP] connection_error %s', context.error);
|
||||||
});
|
});
|
||||||
conn.on('connection_close', function() {
|
conn.on('connection_close', function() {
|
||||||
//todo
|
//todo
|
||||||
logger.debug('[AMQP] conn close');
|
operationContext.global.logger.debug('[AMQP] conn close');
|
||||||
});
|
});
|
||||||
conn.on('disconnected', function(context) {
|
conn.on('disconnected', function(context) {
|
||||||
logger.error('[AMQP] disconnected %s', context.error && context.error.stack);
|
operationContext.global.logger.error('[AMQP] disconnected %s', context.error && context.error.stack);
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
closeCallback();
|
closeCallback();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -708,6 +708,7 @@ CMailMergeSendData.prototype.setIsJsonKey = function(v) {
|
|||||||
};
|
};
|
||||||
function TaskQueueData(data) {
|
function TaskQueueData(data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
|
this['ctx'] = data['ctx'];
|
||||||
this['cmd'] = new InputCommand(data['cmd'], true);
|
this['cmd'] = new InputCommand(data['cmd'], true);
|
||||||
this['toFile'] = data['toFile'];
|
this['toFile'] = data['toFile'];
|
||||||
this['fromOrigin'] = data['fromOrigin'];
|
this['fromOrigin'] = data['fromOrigin'];
|
||||||
@ -718,6 +719,7 @@ function TaskQueueData(data) {
|
|||||||
this['dataKey'] = data['dataKey'];
|
this['dataKey'] = data['dataKey'];
|
||||||
this['visibilityTimeout'] = data['visibilityTimeout'];
|
this['visibilityTimeout'] = data['visibilityTimeout'];
|
||||||
} else {
|
} else {
|
||||||
|
this['ctx'] = undefined;
|
||||||
this['cmd'] = undefined;
|
this['cmd'] = undefined;
|
||||||
this['toFile'] = undefined;
|
this['toFile'] = undefined;
|
||||||
this['fromOrigin'] = undefined;
|
this['fromOrigin'] = undefined;
|
||||||
@ -730,6 +732,12 @@ function TaskQueueData(data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TaskQueueData.prototype = {
|
TaskQueueData.prototype = {
|
||||||
|
getCtx : function() {
|
||||||
|
return this['ctx'];
|
||||||
|
},
|
||||||
|
setCtx : function(data) {
|
||||||
|
return this['ctx'] = data;
|
||||||
|
},
|
||||||
getCmd : function() {
|
getCmd : function() {
|
||||||
return this['cmd'];
|
return this['cmd'];
|
||||||
},
|
},
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
exports.DOC_ID_PATTERN = '0-9-.a-zA-Z_=';
|
exports.DOC_ID_PATTERN = '0-9-.a-zA-Z_=';
|
||||||
exports.DOC_ID_REGEX = new RegExp("^[" + exports.DOC_ID_PATTERN + "]*$", 'i');
|
exports.DOC_ID_REGEX = new RegExp("^[" + exports.DOC_ID_PATTERN + "]*$", 'i');
|
||||||
exports.DOC_ID_REPLACE_REGEX = new RegExp("[^" + exports.DOC_ID_PATTERN + "]", 'g');
|
exports.DOC_ID_REPLACE_REGEX = new RegExp("[^" + exports.DOC_ID_PATTERN + "]", 'g');
|
||||||
|
exports.DOC_ID_SOCKET_PATTERN = new RegExp("^/doc/([" + exports.DOC_ID_PATTERN + "]*)/c.+", 'i');
|
||||||
exports.DOC_ID_MAX_LENGTH = 240;
|
exports.DOC_ID_MAX_LENGTH = 240;
|
||||||
exports.USER_ID_MAX_LENGTH = 240;//255-240=15 symbols to make user id unique
|
exports.USER_ID_MAX_LENGTH = 240;//255-240=15 symbols to make user id unique
|
||||||
exports.USER_NAME_MAX_LENGTH = 255;
|
exports.USER_NAME_MAX_LENGTH = 255;
|
||||||
@ -46,6 +47,8 @@ exports.ONLY_OFFICE_URL_PARAM = 'ooname';
|
|||||||
exports.DISPLAY_PREFIX = 'display';
|
exports.DISPLAY_PREFIX = 'display';
|
||||||
exports.CHANGES_NAME = 'changes';
|
exports.CHANGES_NAME = 'changes';
|
||||||
exports.VIEWER_ONLY = /^(?:(pdf|djvu|xps|oxps))$/;
|
exports.VIEWER_ONLY = /^(?:(pdf|djvu|xps|oxps))$/;
|
||||||
|
exports.DEFAULT_DOC_ID = 'docId';
|
||||||
|
exports.DEFAULT_USER_ID = 'userId';
|
||||||
|
|
||||||
exports.RIGHTS = {
|
exports.RIGHTS = {
|
||||||
None : 0,
|
None : 0,
|
||||||
|
|||||||
@ -34,7 +34,6 @@
|
|||||||
|
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var constants = require('./constants');
|
var constants = require('./constants');
|
||||||
var logger = require('./logger');
|
|
||||||
|
|
||||||
function getImageFormatBySignature(buffer) {
|
function getImageFormatBySignature(buffer) {
|
||||||
var length = buffer.length;
|
var length = buffer.length;
|
||||||
@ -500,7 +499,7 @@ exports.getStringFromFormat = function(format) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
exports.getImageFormat = function(buffer, optExt) {
|
exports.getImageFormat = function(ctx, buffer, optExt) {
|
||||||
var format = constants.AVS_OFFICESTUDIO_FILE_UNKNOWN;
|
var format = constants.AVS_OFFICESTUDIO_FILE_UNKNOWN;
|
||||||
try {
|
try {
|
||||||
//signature
|
//signature
|
||||||
@ -519,8 +518,7 @@ exports.getImageFormat = function(buffer, optExt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
logger.error(optExt);
|
ctx.logger.error('error getImageFormat ext=%s: %s', optExt, e.stack);
|
||||||
logger.error('error getImageFormat:\r\n%s', e.stack);
|
|
||||||
}
|
}
|
||||||
return format;
|
return format;
|
||||||
};
|
};
|
||||||
@ -540,7 +538,6 @@ exports.isPresentationFormat = function(format) {
|
|||||||
format === constants.AVS_OFFICESTUDIO_FILE_TEAMLAB_PPTY;
|
format === constants.AVS_OFFICESTUDIO_FILE_TEAMLAB_PPTY;
|
||||||
};
|
};
|
||||||
exports.isOOXFormat = function(format) {
|
exports.isOOXFormat = function(format) {
|
||||||
console.log('isOOXFormat'+format);
|
|
||||||
return constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX === format
|
return constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX === format
|
||||||
|| constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCM === format
|
|| constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCM === format
|
||||||
|| constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOTX === format
|
|| constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOTX === format
|
||||||
|
|||||||
@ -73,7 +73,9 @@ if (config.get('log.options.replaceConsole')) {
|
|||||||
console.error = logger.error.bind(logger);
|
console.error = logger.error.bind(logger);
|
||||||
console.debug = logger.debug.bind(logger);
|
console.debug = logger.debug.bind(logger);
|
||||||
}
|
}
|
||||||
|
exports.getLogger = function (){
|
||||||
|
return log4js.getLogger.apply(log4js, Array.prototype.slice.call(arguments));
|
||||||
|
};
|
||||||
exports.trace = function (){
|
exports.trace = function (){
|
||||||
return logger.trace.apply(logger, Array.prototype.slice.call(arguments));
|
return logger.trace.apply(logger, Array.prototype.slice.call(arguments));
|
||||||
};
|
};
|
||||||
|
|||||||
91
Common/sources/operationContext.js
Normal file
91
Common/sources/operationContext.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright Ascensio System SIA 2010-2019
|
||||||
|
*
|
||||||
|
* This program is a free software product. You can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||||
|
* version 3 as published by the Free Software Foundation. In accordance with
|
||||||
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||||
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||||
|
* of any third-party rights.
|
||||||
|
*
|
||||||
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||||
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
*
|
||||||
|
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
||||||
|
* street, Riga, Latvia, EU, LV-1050.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of the Program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU AGPL version 3.
|
||||||
|
*
|
||||||
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||||
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||||
|
* grant you any rights under trademark law for use of our trademarks.
|
||||||
|
*
|
||||||
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||||
|
* well as technical writing content are licensed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||||
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const utils = require('./utils');
|
||||||
|
const logger = require('./logger');
|
||||||
|
const constants = require('./constants');
|
||||||
|
const tenantManager = require('./tenantManager');
|
||||||
|
|
||||||
|
function Context(){
|
||||||
|
this.logger = logger.getLogger('nodeJS');
|
||||||
|
this.initDefault();
|
||||||
|
}
|
||||||
|
Context.prototype.init = function(tenant, docId, userId) {
|
||||||
|
this.setTenant(tenant);
|
||||||
|
this.setDocId(docId);
|
||||||
|
this.setUserId(userId);
|
||||||
|
};
|
||||||
|
Context.prototype.initDefault = function() {
|
||||||
|
this.init(tenantManager.getDefautTenant(), constants.DEFAULT_DOC_ID, constants.DEFAULT_USER_ID);
|
||||||
|
};
|
||||||
|
Context.prototype.initFromConnection = function(conn) {
|
||||||
|
let tenant = tenantManager.getTenantByConnection(this, conn);
|
||||||
|
let docId = conn.docid;
|
||||||
|
if (!docId) {
|
||||||
|
const docIdParsed = constants.DOC_ID_SOCKET_PATTERN.exec(conn.url);
|
||||||
|
if (docIdParsed && 1 < docIdParsed.length) {
|
||||||
|
docId = docIdParsed[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let userId = conn.user?.id;
|
||||||
|
this.init(tenant, docId || this.docId, userId || this.userId);
|
||||||
|
};
|
||||||
|
Context.prototype.initFromRequest = function(req) {
|
||||||
|
let tenant = tenantManager.getTenantByRequest(this, req);
|
||||||
|
this.init(tenant, this.docId, this.userId);
|
||||||
|
};
|
||||||
|
Context.prototype.initFromTaskQueueData = function(task) {
|
||||||
|
let ctx = task.getCtx();
|
||||||
|
this.init(ctx.tenant, ctx.docId, ctx.userId);
|
||||||
|
};
|
||||||
|
Context.prototype.initFromPubSub = function(data) {
|
||||||
|
let ctx = data.ctx;
|
||||||
|
this.init(ctx.tenant, ctx.docId, ctx.userId);
|
||||||
|
};
|
||||||
|
|
||||||
|
Context.prototype.setTenant = function(tenant) {
|
||||||
|
this.tenant = tenant;
|
||||||
|
this.logger.addContext('TENANT', tenant);
|
||||||
|
};
|
||||||
|
Context.prototype.setDocId = function(docId) {
|
||||||
|
this.docId = docId;
|
||||||
|
this.logger.addContext('DOCID', docId);
|
||||||
|
};
|
||||||
|
Context.prototype.setUserId = function(userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
this.logger.addContext('USERID', userId);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.Context = Context;
|
||||||
|
exports.global = new Context();
|
||||||
@ -34,6 +34,7 @@
|
|||||||
var config = require('config');
|
var config = require('config');
|
||||||
var amqp = require('amqplib/callback_api');
|
var amqp = require('amqplib/callback_api');
|
||||||
var logger = require('./logger');
|
var logger = require('./logger');
|
||||||
|
const operationContext = require('./operationContext');
|
||||||
|
|
||||||
var cfgRabbitUrl = config.get('rabbitmq.url');
|
var cfgRabbitUrl = config.get('rabbitmq.url');
|
||||||
var cfgRabbitSocketOptions = config.get('rabbitmq.socketOptions');
|
var cfgRabbitSocketOptions = config.get('rabbitmq.socketOptions');
|
||||||
@ -45,7 +46,7 @@ function connetPromise(reconnectOnConnectionError, closeCallback) {
|
|||||||
function startConnect() {
|
function startConnect() {
|
||||||
amqp.connect(cfgRabbitUrl, cfgRabbitSocketOptions, function(err, conn) {
|
amqp.connect(cfgRabbitUrl, cfgRabbitSocketOptions, function(err, conn) {
|
||||||
if (null != err) {
|
if (null != err) {
|
||||||
logger.error('[AMQP] %s', err.stack);
|
operationContext.global.logger.error('[AMQP] %s', err.stack);
|
||||||
if (reconnectOnConnectionError) {
|
if (reconnectOnConnectionError) {
|
||||||
setTimeout(startConnect, RECONNECT_TIMEOUT);
|
setTimeout(startConnect, RECONNECT_TIMEOUT);
|
||||||
} else {
|
} else {
|
||||||
@ -53,16 +54,16 @@ function connetPromise(reconnectOnConnectionError, closeCallback) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
conn.on('error', function(err) {
|
conn.on('error', function(err) {
|
||||||
logger.error('[AMQP] conn error', err.stack);
|
operationContext.global.logger.error('[AMQP] conn error', err.stack);
|
||||||
});
|
});
|
||||||
var closeEventCallback = function() {
|
var closeEventCallback = function() {
|
||||||
//in some case receive multiple close events
|
//in some case receive multiple close events
|
||||||
conn.removeListener('close', closeEventCallback);
|
conn.removeListener('close', closeEventCallback);
|
||||||
logger.debug('[AMQP] conn close');
|
operationContext.global.logger.debug('[AMQP] conn close');
|
||||||
closeCallback();
|
closeCallback();
|
||||||
};
|
};
|
||||||
conn.on('close', closeEventCallback);
|
conn.on('close', closeEventCallback);
|
||||||
logger.debug('[AMQP] connected');
|
operationContext.global.logger.debug('[AMQP] connected');
|
||||||
resolve(conn);
|
resolve(conn);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -33,84 +33,99 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
var logger = require('./logger');
|
|
||||||
|
|
||||||
var storage = require('./' + config.get('storage.name'));
|
var storage = require('./' + config.get('storage.name'));
|
||||||
function getStoragePath(strPath) {
|
var tenantManager = require('./tenantManager');
|
||||||
return strPath.replace(/\\/g, '/');
|
|
||||||
|
function getStoragePath(ctx, strPath) {
|
||||||
|
return tenantManager.getTenantPathPrefix(ctx) + strPath.replace(/\\/g, '/')
|
||||||
}
|
}
|
||||||
exports.headObject = function(strPath) {
|
|
||||||
return storage.headObject(getStoragePath(strPath));
|
exports.headObject = function(ctx, strPath) {
|
||||||
|
return storage.headObject(getStoragePath(ctx, strPath));
|
||||||
};
|
};
|
||||||
exports.getObject = function(strPath) {
|
exports.getObject = function(ctx, strPath) {
|
||||||
return storage.getObject(getStoragePath(strPath));
|
return storage.getObject(getStoragePath(ctx, strPath));
|
||||||
};
|
};
|
||||||
exports.createReadStream = function(strPath) {
|
exports.createReadStream = function(ctx, strPath) {
|
||||||
return storage.createReadStream(getStoragePath(strPath));
|
return storage.createReadStream(getStoragePath(ctx, strPath));
|
||||||
};
|
};
|
||||||
exports.putObject = function(strPath, buffer, contentLength) {
|
exports.putObject = function(ctx, strPath, buffer, contentLength) {
|
||||||
return storage.putObject(getStoragePath(strPath), buffer, contentLength);
|
return storage.putObject(getStoragePath(ctx, strPath), buffer, contentLength);
|
||||||
};
|
};
|
||||||
exports.uploadObject = function(strPath, filePath) {
|
exports.uploadObject = function(ctx, strPath, filePath) {
|
||||||
return storage.uploadObject(strPath, filePath);
|
return storage.uploadObject(getStoragePath(ctx, strPath), filePath);
|
||||||
};
|
};
|
||||||
exports.copyObject = function(sourceKey, destinationKey) {
|
exports.copyObject = function(ctx, sourceKey, destinationKey) {
|
||||||
return storage.copyObject(sourceKey, destinationKey);
|
let storageSrc = getStoragePath(ctx, sourceKey);
|
||||||
|
let storageDst = getStoragePath(ctx, destinationKey);
|
||||||
|
return storage.copyObject(storageSrc, storageDst);
|
||||||
};
|
};
|
||||||
exports.copyPath = function(sourcePath, destinationPath) {
|
exports.copyPath = function(ctx, sourcePath, destinationPath) {
|
||||||
return exports.listObjects(getStoragePath(sourcePath)).then(function(list) {
|
let storageSrc = getStoragePath(ctx, sourcePath);
|
||||||
|
let storageDst = getStoragePath(ctx, destinationPath);
|
||||||
|
return storage.listObjects(storageSrc).then(function(list) {
|
||||||
return Promise.all(list.map(function(curValue) {
|
return Promise.all(list.map(function(curValue) {
|
||||||
return exports.copyObject(curValue, destinationPath + '/' + exports.getRelativePath(sourcePath, curValue));
|
return storage.copyObject(curValue, storageDst + '/' + exports.getRelativePath(storageSrc, curValue));
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.listObjects = function(strPath) {
|
exports.listObjects = function(ctx, strPath) {
|
||||||
return storage.listObjects(getStoragePath(strPath)).catch(function(e) {
|
let prefix = getStoragePath(ctx, "");
|
||||||
logger.error('storage.listObjects:\r\n%s', e.stack);
|
return storage.listObjects(getStoragePath(ctx, strPath)).then(function(list) {
|
||||||
|
return list.map((currentValue) => {
|
||||||
|
return currentValue.substring(prefix.length);
|
||||||
|
});
|
||||||
|
}).catch(function(e) {
|
||||||
|
ctx.logger.error('storage.listObjects: %s', e.stack);
|
||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.deleteObject = function(strPath) {
|
exports.deleteObject = function(ctx, strPath) {
|
||||||
return storage.deleteObject(getStoragePath(strPath));
|
return storage.deleteObject(getStoragePath(ctx, strPath));
|
||||||
};
|
};
|
||||||
exports.deleteObjects = function(strPaths) {
|
exports.deleteObjects = function(ctx, strPaths) {
|
||||||
var StoragePaths = strPaths.map(function(curValue) {
|
var StoragePaths = strPaths.map(function(curValue) {
|
||||||
return getStoragePath(curValue);
|
return getStoragePath(ctx, curValue);
|
||||||
});
|
});
|
||||||
return storage.deleteObjects(StoragePaths);
|
return storage.deleteObjects(StoragePaths);
|
||||||
};
|
};
|
||||||
exports.deletePath = function(strPath) {
|
exports.deletePath = function(ctx, strPath) {
|
||||||
return exports.listObjects(getStoragePath(strPath)).then(function(list) {
|
let storageSrc = getStoragePath(ctx, strPath);
|
||||||
return exports.deleteObjects(list);
|
return storage.listObjects(storageSrc).then(function(list) {
|
||||||
|
return storage.deleteObjects(list);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.getSignedUrl = function(baseUrl, strPath, urlType, optFilename, opt_creationDate) {
|
exports.getSignedUrl = function(ctx, baseUrl, strPath, urlType, optFilename, opt_creationDate) {
|
||||||
return storage.getSignedUrl(baseUrl, getStoragePath(strPath), urlType, optFilename, opt_creationDate);
|
return storage.getSignedUrl(baseUrl, getStoragePath(ctx, strPath), urlType, optFilename, opt_creationDate);
|
||||||
};
|
};
|
||||||
exports.getSignedUrls = function(baseUrl, strPath, urlType, opt_creationDate) {
|
exports.getSignedUrls = function(ctx, baseUrl, strPath, urlType, opt_creationDate) {
|
||||||
return exports.listObjects(getStoragePath(strPath)).then(function(list) {
|
let storageSrc = getStoragePath(ctx, strPath);
|
||||||
|
return storage.listObjects(storageSrc).then(function(list) {
|
||||||
return Promise.all(list.map(function(curValue) {
|
return Promise.all(list.map(function(curValue) {
|
||||||
return exports.getSignedUrl(baseUrl, curValue, urlType, undefined, opt_creationDate);
|
return storage.getSignedUrl(baseUrl, curValue, urlType, undefined, opt_creationDate);
|
||||||
})).then(function(urls) {
|
})).then(function(urls) {
|
||||||
var outputMap = {};
|
var outputMap = {};
|
||||||
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
||||||
outputMap[exports.getRelativePath(strPath, list[i])] = urls[i];
|
outputMap[exports.getRelativePath(storageSrc, list[i])] = urls[i];
|
||||||
}
|
}
|
||||||
return outputMap;
|
return outputMap;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.getSignedUrlsArrayByArray = function(baseUrl, list, urlType) {
|
exports.getSignedUrlsArrayByArray = function(ctx, baseUrl, list, urlType) {
|
||||||
return Promise.all(list.map(function(curValue) {
|
return Promise.all(list.map(function(curValue) {
|
||||||
return exports.getSignedUrl(baseUrl, curValue, urlType, undefined);
|
let storageSrc = getStoragePath(ctx, curValue);
|
||||||
|
return storage.getSignedUrl(baseUrl, storageSrc, urlType, undefined);
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
exports.getSignedUrlsByArray = function(baseUrl, list, optPath, urlType) {
|
exports.getSignedUrlsByArray = function(ctx, baseUrl, list, optPath, urlType) {
|
||||||
return exports.getSignedUrlsArrayByArray(baseUrl, list, urlType).then(function(urls) {
|
return exports.getSignedUrlsArrayByArray(ctx, baseUrl, list, urlType).then(function(urls) {
|
||||||
var outputMap = {};
|
var outputMap = {};
|
||||||
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
||||||
if (optPath) {
|
if (optPath) {
|
||||||
outputMap[exports.getRelativePath(optPath, list[i])] = urls[i];
|
let storageSrc = getStoragePath(ctx, optPath);
|
||||||
|
outputMap[exports.getRelativePath(storageSrc, list[i])] = urls[i];
|
||||||
} else {
|
} else {
|
||||||
outputMap[list[i]] = urls[i];
|
outputMap[list[i]] = urls[i];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@ var rabbitMQCore = require('./rabbitMQCore');
|
|||||||
var activeMQCore = require('./activeMQCore');
|
var activeMQCore = require('./activeMQCore');
|
||||||
const logger = require('./logger');
|
const logger = require('./logger');
|
||||||
const commonDefines = require('./commondefines');
|
const commonDefines = require('./commondefines');
|
||||||
|
const operationContext = require('./operationContext');
|
||||||
|
|
||||||
const cfgMaxRedeliveredCount = config.get('FileConverter.converter.maxRedeliveredCount');
|
const cfgMaxRedeliveredCount = config.get('FileConverter.converter.maxRedeliveredCount');
|
||||||
const cfgQueueType = config.get('queue.type');
|
const cfgQueueType = config.get('queue.type');
|
||||||
@ -253,7 +254,7 @@ function clear(taskqueue) {
|
|||||||
function* pushBackRedeliveredRabbit(taskqueue, message, ack) {
|
function* pushBackRedeliveredRabbit(taskqueue, message, ack) {
|
||||||
if (message?.fields?.redelivered) {
|
if (message?.fields?.redelivered) {
|
||||||
try {
|
try {
|
||||||
logger.warn('checkRedelivered redelivered data=%j', message);
|
operationContext.global.logger.warn('checkRedelivered redelivered data=%j', message);
|
||||||
//remove current task and add new into tail of queue to remove redelivered flag
|
//remove current task and add new into tail of queue to remove redelivered flag
|
||||||
let data = message.content.toString();
|
let data = message.content.toString();
|
||||||
let redeliveredCount = message.properties.headers['x-redelivered-count'];
|
let redeliveredCount = message.properties.headers['x-redelivered-count'];
|
||||||
@ -264,7 +265,7 @@ function* pushBackRedeliveredRabbit(taskqueue, message, ack) {
|
|||||||
yield taskqueue.addResponse(taskqueue.simulateErrorResponse(data));
|
yield taskqueue.addResponse(taskqueue.simulateErrorResponse(data));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('checkRedelivered error: %s', err.stack);
|
operationContext.global.logger.error('checkRedelivered error: %s', err.stack);
|
||||||
} finally{
|
} finally{
|
||||||
ack();
|
ack();
|
||||||
}
|
}
|
||||||
@ -274,14 +275,14 @@ function* pushBackRedeliveredRabbit(taskqueue, message, ack) {
|
|||||||
}
|
}
|
||||||
function* pushBackRedeliveredActive(taskqueue, context, ack) {
|
function* pushBackRedeliveredActive(taskqueue, context, ack) {
|
||||||
if (undefined !== context.message.delivery_count) {
|
if (undefined !== context.message.delivery_count) {
|
||||||
logger.warn('checkRedelivered redelivered data=%j', context.message);
|
operationContext.global.logger.warn('checkRedelivered redelivered data=%j', context.message);
|
||||||
if (context.message.delivery_count > cfgMaxRedeliveredCount) {
|
if (context.message.delivery_count > cfgMaxRedeliveredCount) {
|
||||||
try {
|
try {
|
||||||
if (taskqueue.simulateErrorResponse) {
|
if (taskqueue.simulateErrorResponse) {
|
||||||
yield taskqueue.addResponse(taskqueue.simulateErrorResponse(context.message.body));
|
yield taskqueue.addResponse(taskqueue.simulateErrorResponse(context.message.body));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('checkRedelivered error: %s', err.stack);
|
operationContext.global.logger.error('checkRedelivered error: %s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
ack();
|
ack();
|
||||||
}
|
}
|
||||||
|
|||||||
138
Common/sources/tenantManager.js
Normal file
138
Common/sources/tenantManager.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright Ascensio System SIA 2010-2019
|
||||||
|
*
|
||||||
|
* This program is a free software product. You can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||||
|
* version 3 as published by the Free Software Foundation. In accordance with
|
||||||
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||||
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||||
|
* of any third-party rights.
|
||||||
|
*
|
||||||
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||||
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
*
|
||||||
|
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
|
||||||
|
* street, Riga, Latvia, EU, LV-1050.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of the Program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU AGPL version 3.
|
||||||
|
*
|
||||||
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||||
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||||
|
* grant you any rights under trademark law for use of our trademarks.
|
||||||
|
*
|
||||||
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||||
|
* well as technical writing content are licensed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||||
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const config = require('config');
|
||||||
|
const co = require('co');
|
||||||
|
const license = require('./../../Common/sources/license');
|
||||||
|
const constants = require('./../../Common/sources/constants');
|
||||||
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
|
const utils = require('./../../Common/sources/utils');
|
||||||
|
const { readFile } = require('fs/promises');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const oPackageType = config.get('license.packageType');
|
||||||
|
const cfgTenantsBaseDomain = config.get('tenants.baseDomain');
|
||||||
|
const cfgTenantsBaseDir = config.get('tenants.baseDir');
|
||||||
|
const cfgTenantsFilenameSecret = config.get('tenants.filenameSecret');
|
||||||
|
const cfgTenantsFilenameLicense = config.get('tenants.filenameLicense');
|
||||||
|
const cfgTenantsDefaultTetant = config.get('tenants.defaultTetant');
|
||||||
|
const cfgSecretInbox = config.get('services.CoAuthoring.secret.inbox');
|
||||||
|
const cfgSecretOutbox = config.get('services.CoAuthoring.secret.outbox');
|
||||||
|
const cfgSecretSession = config.get('services.CoAuthoring.secret.session');
|
||||||
|
|
||||||
|
let licenseInfo;
|
||||||
|
let licenseOriginal;
|
||||||
|
|
||||||
|
function getDefautTenant() {
|
||||||
|
return cfgTenantsDefaultTetant;
|
||||||
|
}
|
||||||
|
function getTenant(ctx, domain) {
|
||||||
|
let tenant = getDefautTenant();
|
||||||
|
if (domain) {
|
||||||
|
//remove port
|
||||||
|
domain = domain.substring(0, domain.indexOf(':'));
|
||||||
|
let index = domain.indexOf('.' + cfgTenantsBaseDomain);
|
||||||
|
if (-1 !== index) {
|
||||||
|
tenant = domain.substring(0, index);
|
||||||
|
} else {
|
||||||
|
ctx.logger.warn('getTenant invalid domain=%s', domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tenant;
|
||||||
|
}
|
||||||
|
function getTenantByConnection(ctx, conn) {
|
||||||
|
return isMultitenantMode() ? getTenant(ctx, utils.getDomainByConnection(ctx, conn)) : getDefautTenant();
|
||||||
|
}
|
||||||
|
function getTenantByRequest(ctx, req) {
|
||||||
|
return isMultitenantMode() ? getTenant(ctx, utils.getDomainByRequest(ctx, req)) : getDefautTenant();
|
||||||
|
}
|
||||||
|
function getTenantPathPrefix(ctx) {
|
||||||
|
return isMultitenantMode() ? utils.removeIllegalCharacters(ctx.tenant) + '/' : '';
|
||||||
|
}
|
||||||
|
function getTenantSecret(ctx, type) {
|
||||||
|
return co(function*() {
|
||||||
|
let res = undefined;
|
||||||
|
if (isMultitenantMode()) {
|
||||||
|
let tenantPath = utils.removeIllegalCharacters(ctx.tenant);
|
||||||
|
let secretPath = path.join(cfgTenantsBaseDir, tenantPath, cfgTenantsFilenameSecret);
|
||||||
|
ctx.logger.debug('getTenantSecret path=%s', secretPath);
|
||||||
|
res = yield readFile(secretPath, {encoding: 'utf8'});
|
||||||
|
} else {
|
||||||
|
switch (type) {
|
||||||
|
case commonDefines.c_oAscSecretType.Browser:
|
||||||
|
case commonDefines.c_oAscSecretType.Inbox:
|
||||||
|
res = utils.getSecretByElem(cfgSecretInbox);
|
||||||
|
break;
|
||||||
|
case commonDefines.c_oAscSecretType.Outbox:
|
||||||
|
res = utils.getSecretByElem(cfgSecretOutbox);
|
||||||
|
break;
|
||||||
|
case commonDefines.c_oAscSecretType.Session:
|
||||||
|
res = utils.getSecretByElem(cfgSecretSession);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDefLicense(data, original) {
|
||||||
|
licenseInfo = data;
|
||||||
|
licenseOriginal = original;
|
||||||
|
}
|
||||||
|
function getTenantLicense(ctx) {
|
||||||
|
return co(function*() {
|
||||||
|
let res = undefined;
|
||||||
|
if (isMultitenantMode()) {
|
||||||
|
let tenantPath = utils.removeIllegalCharacters(ctx.tenant);
|
||||||
|
let licensePath = path.join(cfgTenantsBaseDir, tenantPath, cfgTenantsFilenameLicense);
|
||||||
|
ctx.logger.debug('getTenantLicense path=%s', licensePath);
|
||||||
|
[res] = yield* license.readLicense(licensePath);
|
||||||
|
} else {
|
||||||
|
res = licenseInfo;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function isMultitenantMode() {
|
||||||
|
return !!cfgTenantsBaseDir && !!cfgTenantsBaseDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getDefautTenant = getDefautTenant;
|
||||||
|
exports.getTenantByConnection = getTenantByConnection;
|
||||||
|
exports.getTenantByRequest = getTenantByRequest;
|
||||||
|
exports.getTenantPathPrefix = getTenantPathPrefix;
|
||||||
|
exports.getTenantSecret = getTenantSecret;
|
||||||
|
exports.getTenantLicense = getTenantLicense;
|
||||||
|
exports.setDefLicense = setDefLicense;
|
||||||
|
exports.isMultitenantMode = isMultitenantMode;
|
||||||
@ -72,7 +72,6 @@ var cfgTokenOutboxHeader = config.get('services.CoAuthoring.token.outbox.header'
|
|||||||
var cfgTokenOutboxPrefix = config.get('services.CoAuthoring.token.outbox.prefix');
|
var cfgTokenOutboxPrefix = config.get('services.CoAuthoring.token.outbox.prefix');
|
||||||
var cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm');
|
var cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm');
|
||||||
var cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires');
|
var cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires');
|
||||||
var cfgSignatureSecretOutbox = config.get('services.CoAuthoring.secret.outbox');
|
|
||||||
var cfgVisibilityTimeout = config.get('queue.visibilityTimeout');
|
var cfgVisibilityTimeout = config.get('queue.visibilityTimeout');
|
||||||
var cfgQueueRetentionPeriod = config.get('queue.retentionPeriod');
|
var cfgQueueRetentionPeriod = config.get('queue.retentionPeriod');
|
||||||
var cfgRequestDefaults = config.get('services.CoAuthoring.requestDefaults');
|
var cfgRequestDefaults = config.get('services.CoAuthoring.requestDefaults');
|
||||||
@ -261,13 +260,13 @@ function raiseErrorObj(ro, error) {
|
|||||||
function isRedirectResponse(response) {
|
function isRedirectResponse(response) {
|
||||||
return response && response.statusCode >= 300 && response.statusCode < 400 && response.caseless.has('location');
|
return response && response.statusCode >= 300 && response.statusCode < 400 && response.caseless.has('location');
|
||||||
}
|
}
|
||||||
function downloadUrlPromise(uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) {
|
function downloadUrlPromise(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) {
|
||||||
//todo replace deprecated request module
|
//todo replace deprecated request module
|
||||||
const maxRedirects = (undefined !== cfgRequestDefaults.maxRedirects) ? cfgRequestDefaults.maxRedirects : 10;
|
const maxRedirects = (undefined !== cfgRequestDefaults.maxRedirects) ? cfgRequestDefaults.maxRedirects : 10;
|
||||||
const followRedirect = (undefined !== cfgRequestDefaults.followRedirect) ? cfgRequestDefaults.followRedirect : true;
|
const followRedirect = (undefined !== cfgRequestDefaults.followRedirect) ? cfgRequestDefaults.followRedirect : true;
|
||||||
var redirectsFollowed = 0;
|
var redirectsFollowed = 0;
|
||||||
let doRequest = function(curUrl) {
|
let doRequest = function(curUrl) {
|
||||||
return downloadUrlPromiseWithoutRedirect(curUrl, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter)
|
return downloadUrlPromiseWithoutRedirect(ctx, curUrl, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter)
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
let response = err.response;
|
let response = err.response;
|
||||||
if (isRedirectResponse(response)) {
|
if (isRedirectResponse(response)) {
|
||||||
@ -277,7 +276,7 @@ function downloadUrlPromise(uri, optTimeout, optLimit, opt_Authorization, opt_fi
|
|||||||
redirectTo = url.resolve(err.request.uri.href, redirectTo)
|
redirectTo = url.resolve(err.request.uri.href, redirectTo)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('downloadUrlPromise redirectsFollowed:%d redirectTo: %s', redirectsFollowed, redirectTo);
|
ctx.logger.debug('downloadUrlPromise redirectsFollowed:%d redirectTo: %s', redirectsFollowed, redirectTo);
|
||||||
redirectsFollowed++;
|
redirectsFollowed++;
|
||||||
return doRequest(redirectTo);
|
return doRequest(redirectTo);
|
||||||
}
|
}
|
||||||
@ -287,7 +286,7 @@ function downloadUrlPromise(uri, optTimeout, optLimit, opt_Authorization, opt_fi
|
|||||||
};
|
};
|
||||||
return doRequest(uri);
|
return doRequest(uri);
|
||||||
}
|
}
|
||||||
function downloadUrlPromiseWithoutRedirect(uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) {
|
function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_Authorization, opt_filterPrivate, opt_headers, opt_streamWriter) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
//IRI to URI
|
//IRI to URI
|
||||||
uri = URI.serialize(URI.parse(uri));
|
uri = URI.serialize(URI.parse(uri));
|
||||||
@ -323,7 +322,7 @@ function downloadUrlPromiseWithoutRedirect(uri, optTimeout, optLimit, opt_Author
|
|||||||
} else {
|
} else {
|
||||||
var contentLength = response.caseless.get('content-length');
|
var contentLength = response.caseless.get('content-length');
|
||||||
if (contentLength && body.length !== (contentLength - 0)) {
|
if (contentLength && body.length !== (contentLength - 0)) {
|
||||||
logger.warn('downloadUrlPromise body size mismatch: uri=%s; content-length=%s; body.length=%d', uri, contentLength, body.length);
|
ctx.logger.warn('downloadUrlPromise body size mismatch: uri=%s; content-length=%s; body.length=%d', uri, contentLength, body.length);
|
||||||
}
|
}
|
||||||
resolve({response: response, body: body});
|
resolve({response: response, body: body});
|
||||||
}
|
}
|
||||||
@ -654,6 +653,9 @@ function containsAllAsciiNP(str) {
|
|||||||
return /^[\040-\176]*$/.test(str);//non-printing characters
|
return /^[\040-\176]*$/.test(str);//non-printing characters
|
||||||
}
|
}
|
||||||
exports.containsAllAsciiNP = containsAllAsciiNP;
|
exports.containsAllAsciiNP = containsAllAsciiNP;
|
||||||
|
function getDomain(hostHeader, forwardedHostHeader) {
|
||||||
|
return forwardedHostHeader || hostHeader || 'localhost';
|
||||||
|
};
|
||||||
function getBaseUrl(protocol, hostHeader, forwardedProtoHeader, forwardedHostHeader, forwardedPrefixHeader) {
|
function getBaseUrl(protocol, hostHeader, forwardedProtoHeader, forwardedHostHeader, forwardedPrefixHeader) {
|
||||||
var url = '';
|
var url = '';
|
||||||
if (forwardedProtoHeader) {
|
if (forwardedProtoHeader) {
|
||||||
@ -664,13 +666,7 @@ function getBaseUrl(protocol, hostHeader, forwardedProtoHeader, forwardedHostHea
|
|||||||
url += 'http';
|
url += 'http';
|
||||||
}
|
}
|
||||||
url += '://';
|
url += '://';
|
||||||
if (forwardedHostHeader) {
|
url += getDomain(hostHeader, forwardedHostHeader);
|
||||||
url += forwardedHostHeader;
|
|
||||||
} else if (hostHeader) {
|
|
||||||
url += hostHeader;
|
|
||||||
} else {
|
|
||||||
url += 'localhost';
|
|
||||||
}
|
|
||||||
if (forwardedPrefixHeader) {
|
if (forwardedPrefixHeader) {
|
||||||
url += forwardedPrefixHeader;
|
url += forwardedPrefixHeader;
|
||||||
}
|
}
|
||||||
@ -684,6 +680,20 @@ function getBaseUrlByRequest(req) {
|
|||||||
}
|
}
|
||||||
exports.getBaseUrlByConnection = getBaseUrlByConnection;
|
exports.getBaseUrlByConnection = getBaseUrlByConnection;
|
||||||
exports.getBaseUrlByRequest = getBaseUrlByRequest;
|
exports.getBaseUrlByRequest = getBaseUrlByRequest;
|
||||||
|
function getDomainByConnection(ctx, conn) {
|
||||||
|
let host = conn.headers['host'];
|
||||||
|
let forwardedHost = conn.headers['x-forwarded-host'];
|
||||||
|
ctx.logger.debug("getDomainByConnection headers['host']=%s headers['x-forwarded-host']=%s", host, forwardedHost);
|
||||||
|
return getDomain(host, forwardedHost);
|
||||||
|
}
|
||||||
|
function getDomainByRequest(ctx, req) {
|
||||||
|
let host = req.get('host');
|
||||||
|
let forwardedHost = req.get('x-forwarded-host');
|
||||||
|
ctx.logger.debug("getDomainByRequest headers['host']=%s headers['x-forwarded-host']=%s", host, forwardedHost);
|
||||||
|
return getDomain(req.get('host'), req.get('x-forwarded-host'));
|
||||||
|
}
|
||||||
|
exports.getDomainByConnection = getDomainByConnection;
|
||||||
|
exports.getDomainByRequest = getDomainByRequest;
|
||||||
function stream2Buffer(stream) {
|
function stream2Buffer(stream) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (!stream.readable) {
|
if (!stream.readable) {
|
||||||
@ -761,14 +771,14 @@ function checkIpFilter(ipString, opt_hostname) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
exports.checkIpFilter = checkIpFilter;
|
exports.checkIpFilter = checkIpFilter;
|
||||||
function* checkHostFilter(hostname) {
|
function* checkHostFilter(ctx, hostname) {
|
||||||
let status = 0;
|
let status = 0;
|
||||||
let hostIp;
|
let hostIp;
|
||||||
try {
|
try {
|
||||||
hostIp = yield dnsLookup(hostname);
|
hostIp = yield dnsLookup(hostname);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
status = cfgIpFilterErrorCode;
|
status = cfgIpFilterErrorCode;
|
||||||
logger.error('dnsLookup error: hostname = %s\r\n%s', hostname, e.stack);
|
ctx.logger.error('dnsLookup error: hostname = %s %s', hostname, e.stack);
|
||||||
}
|
}
|
||||||
if (0 === status) {
|
if (0 === status) {
|
||||||
status = checkIpFilter(hostIp, hostname);
|
status = checkIpFilter(hostIp, hostname);
|
||||||
@ -832,29 +842,7 @@ function getSecretByElem(secretElem) {
|
|||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
exports.getSecretByElem = getSecretByElem;
|
exports.getSecretByElem = getSecretByElem;
|
||||||
function getSecret(docId, secretElem, opt_iss, opt_token) {
|
function fillJwtForRequest(payload, secret, opt_inBody) {
|
||||||
if (!isEmptyObject(secretElem.tenants)) {
|
|
||||||
var iss;
|
|
||||||
if (opt_token) {
|
|
||||||
//look for issuer
|
|
||||||
var decodedTemp = jwt.decode(opt_token);
|
|
||||||
if (decodedTemp && decodedTemp.iss) {
|
|
||||||
iss = decodedTemp.iss;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
iss = opt_iss;
|
|
||||||
}
|
|
||||||
if (iss) {
|
|
||||||
secretElem = secretElem.tenants[iss];
|
|
||||||
if (!secretElem) {
|
|
||||||
logger.error('getSecret unknown issuer: docId = %s iss = %s', docId, iss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getSecretByElem(secretElem);
|
|
||||||
}
|
|
||||||
exports.getSecret = getSecret;
|
|
||||||
function fillJwtForRequest(payload, opt_inBody) {
|
|
||||||
//todo refuse prototypes in payload(they are simple getter/setter).
|
//todo refuse prototypes in payload(they are simple getter/setter).
|
||||||
//JSON.parse/stringify is more universal but Object.assign is enough for our inputs
|
//JSON.parse/stringify is more universal but Object.assign is enough for our inputs
|
||||||
payload = Object.assign(Object.create(null), payload);
|
payload = Object.assign(Object.create(null), payload);
|
||||||
@ -866,7 +854,6 @@ function fillJwtForRequest(payload, opt_inBody) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let options = {algorithm: cfgTokenOutboxAlgorithm, expiresIn: cfgTokenOutboxExpires};
|
let options = {algorithm: cfgTokenOutboxAlgorithm, expiresIn: cfgTokenOutboxExpires};
|
||||||
let secret = getSecretByElem(cfgSignatureSecretOutbox);
|
|
||||||
return jwt.sign(data, secret, options);
|
return jwt.sign(data, secret, options);
|
||||||
}
|
}
|
||||||
exports.fillJwtForRequest = fillJwtForRequest;
|
exports.fillJwtForRequest = fillJwtForRequest;
|
||||||
@ -874,13 +861,13 @@ exports.forwarded = forwarded;
|
|||||||
exports.getIndexFromUserId = function(userId, userIdOriginal){
|
exports.getIndexFromUserId = function(userId, userIdOriginal){
|
||||||
return parseInt(userId.substring(userIdOriginal.length));
|
return parseInt(userId.substring(userIdOriginal.length));
|
||||||
};
|
};
|
||||||
exports.checkPathTraversal = function(docId, rootDirectory, filename) {
|
exports.checkPathTraversal = function(ctx, docId, rootDirectory, filename) {
|
||||||
if (filename.indexOf('\0') !== -1) {
|
if (filename.indexOf('\0') !== -1) {
|
||||||
logger.warn('checkPathTraversal Poison Null Bytes docId=%s filename=%s', docId, filename);
|
ctx.logger.warn('checkPathTraversal Poison Null Bytes filename=%s', filename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!filename.startsWith(rootDirectory)) {
|
if (!filename.startsWith(rootDirectory)) {
|
||||||
logger.warn('checkPathTraversal Path Traversal docId=%s filename=%s', docId, filename);
|
ctx.logger.warn('checkPathTraversal Path Traversal filename=%s', filename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -905,14 +892,14 @@ exports.getConnectionInfoStr = function(conn){
|
|||||||
exports.isLiveViewer = function(conn){
|
exports.isLiveViewer = function(conn){
|
||||||
return conn.user?.view && "fast" === conn.coEditingMode;
|
return conn.user?.view && "fast" === conn.coEditingMode;
|
||||||
};
|
};
|
||||||
exports.canIncludeOutboxAuthorization = function (url) {
|
exports.canIncludeOutboxAuthorization = function (ctx, url) {
|
||||||
if (cfgTokenEnableRequestOutbox) {
|
if (cfgTokenEnableRequestOutbox) {
|
||||||
if (!outboxUrlExclusionRegex) {
|
if (!outboxUrlExclusionRegex) {
|
||||||
return true;
|
return true;
|
||||||
} else if (!outboxUrlExclusionRegex.test(url)) {
|
} else if (!outboxUrlExclusionRegex.test(url)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
logger.debug('canIncludeOutboxAuthorization excluded by token.outbox.urlExclusionRegex url=%s', url);
|
ctx.logger.debug('canIncludeOutboxAuthorization excluded by token.outbox.urlExclusionRegex url=%s', url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -981,8 +968,7 @@ exports.checkBaseUrl = function(baseUrl) {
|
|||||||
};
|
};
|
||||||
exports.resolvePath = function(object, path, defaultValue) {
|
exports.resolvePath = function(object, path, defaultValue) {
|
||||||
return path.split('.').reduce((o, p) => o ? o[p] : defaultValue, object);
|
return path.split('.').reduce((o, p) => o ? o[p] : defaultValue, object);
|
||||||
}
|
};
|
||||||
|
|
||||||
Date.isLeapYear = function (year) {
|
Date.isLeapYear = function (year) {
|
||||||
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
|
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
|
||||||
};
|
};
|
||||||
@ -1023,3 +1009,15 @@ exports.getLicensePeriod = function(startDate, now) {
|
|||||||
startDate.setUTCHours(0,0,0,0);
|
startDate.setUTCHours(0,0,0,0);
|
||||||
return startDate.getTime();
|
return startDate.getTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.removeIllegalCharacters = function(filename) {
|
||||||
|
return filename?.replace(/[/\\?%*:|"<>]/g, '-') || filename;
|
||||||
|
}
|
||||||
|
exports.getFunctionArguments = function(func) {
|
||||||
|
return func.toString().
|
||||||
|
replace(/[\r\n\s]+/g, ' ').
|
||||||
|
match(/(?:function\s*\w*)?\s*(?:\((.*?)\)|([^\s]+))/).
|
||||||
|
slice(1, 3).
|
||||||
|
join('').
|
||||||
|
split(/\s*,\s*/);
|
||||||
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,6 @@ var sqlDataBaseType = {
|
|||||||
|
|
||||||
var config = require('config').get('services.CoAuthoring.sql');
|
var config = require('config').get('services.CoAuthoring.sql');
|
||||||
var baseConnector = (sqlDataBaseType.mySql === config.get('type') || sqlDataBaseType.mariaDB === config.get('type')) ? require('./mySqlBaseConnector') : require('./postgreSqlBaseConnector');
|
var baseConnector = (sqlDataBaseType.mySql === config.get('type') || sqlDataBaseType.mariaDB === config.get('type')) ? require('./mySqlBaseConnector') : require('./postgreSqlBaseConnector');
|
||||||
var logger = require('./../../Common/sources/logger');
|
|
||||||
let constants = require('./../../Common/sources/constants');
|
let constants = require('./../../Common/sources/constants');
|
||||||
|
|
||||||
const tableChanges = config.get('tableChanges'),
|
const tableChanges = config.get('tableChanges'),
|
||||||
@ -52,9 +51,9 @@ let addSqlParam = baseConnector.addSqlParameter;
|
|||||||
var maxPacketSize = config.get('max_allowed_packet'); // Размер по умолчанию для запроса в базу данных 1Mb - 1 (т.к. он не пишет 1048575, а пишет 1048574)
|
var maxPacketSize = config.get('max_allowed_packet'); // Размер по умолчанию для запроса в базу данных 1Mb - 1 (т.к. он не пишет 1048575, а пишет 1048574)
|
||||||
|
|
||||||
exports.baseConnector = baseConnector;
|
exports.baseConnector = baseConnector;
|
||||||
exports.insertChangesPromiseCompatibility = function (objChanges, docId, index, user) {
|
exports.insertChangesPromiseCompatibility = function (ctx, objChanges, docId, index, user) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
_insertChangesCallback(0, objChanges, docId, index, user, function(error, result) {
|
_insertChangesCallback(ctx, 0, objChanges, docId, index, user, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -63,13 +62,13 @@ exports.insertChangesPromiseCompatibility = function (objChanges, docId, index,
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.insertChangesPromiseFast = function (objChanges, docId, index, user) {
|
exports.insertChangesPromiseFast = function (ctx, objChanges, docId, index, user) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
baseConnector.insertChanges(tableChanges, 0, objChanges, docId, index, user, function(error, result, isSupported) {
|
baseConnector.insertChanges(ctx, tableChanges, 0, objChanges, docId, index, user, function(error, result, isSupported) {
|
||||||
isSupportFastInsert = isSupported;
|
isSupportFastInsert = isSupported;
|
||||||
if (error) {
|
if (error) {
|
||||||
if (!isSupportFastInsert) {
|
if (!isSupportFastInsert) {
|
||||||
resolve(exports.insertChangesPromiseCompatibility(objChanges, docId, index, user));
|
resolve(exports.insertChangesPromiseCompatibility(ctx, objChanges, docId, index, user));
|
||||||
} else {
|
} else {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
@ -79,11 +78,11 @@ exports.insertChangesPromiseFast = function (objChanges, docId, index, user) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.insertChangesPromise = function (objChanges, docId, index, user) {
|
exports.insertChangesPromise = function (ctx, objChanges, docId, index, user) {
|
||||||
if (isSupportFastInsert) {
|
if (isSupportFastInsert) {
|
||||||
return exports.insertChangesPromiseFast(objChanges, docId, index, user);
|
return exports.insertChangesPromiseFast(ctx, objChanges, docId, index, user);
|
||||||
} else {
|
} else {
|
||||||
return exports.insertChangesPromiseCompatibility(objChanges, docId, index, user);
|
return exports.insertChangesPromiseCompatibility(ctx, objChanges, docId, index, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -93,7 +92,7 @@ function _getDateTime2(oDate) {
|
|||||||
|
|
||||||
exports.getDateTime = _getDateTime2;
|
exports.getDateTime = _getDateTime2;
|
||||||
|
|
||||||
function _insertChangesCallback (startIndex, objChanges, docId, index, user, callback) {
|
function _insertChangesCallback (ctx, startIndex, objChanges, docId, index, user, callback) {
|
||||||
var sqlCommand = `INSERT INTO ${tableChanges} VALUES`;
|
var sqlCommand = `INSERT INTO ${tableChanges} VALUES`;
|
||||||
var i = startIndex, l = objChanges.length, lengthUtf8Current = sqlCommand.length, lengthUtf8Row = 0, values = [];
|
var i = startIndex, l = objChanges.length, lengthUtf8Current = sqlCommand.length, lengthUtf8Row = 0, values = [];
|
||||||
if (i === l)
|
if (i === l)
|
||||||
@ -106,13 +105,14 @@ function _insertChangesCallback (startIndex, objChanges, docId, index, user, cal
|
|||||||
if (lengthUtf8Row + lengthUtf8Current >= maxPacketSize && i > startIndex) {
|
if (lengthUtf8Row + lengthUtf8Current >= maxPacketSize && i > startIndex) {
|
||||||
sqlCommand += ';';
|
sqlCommand += ';';
|
||||||
(function(tmpStart, tmpIndex) {
|
(function(tmpStart, tmpIndex) {
|
||||||
baseConnector.sqlQuery(sqlCommand, function() {
|
baseConnector.sqlQuery(ctx, sqlCommand, function() {
|
||||||
// lock не снимаем, а продолжаем добавлять
|
// lock не снимаем, а продолжаем добавлять
|
||||||
_insertChangesCallback(tmpStart, objChanges, docId, tmpIndex, user, callback);
|
_insertChangesCallback(ctx, tmpStart, objChanges, docId, tmpIndex, user, callback);
|
||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
})(i, index);
|
})(i, index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let p0 = addSqlParam(ctx.tenant, values);
|
||||||
let p1 = addSqlParam(docId, values);
|
let p1 = addSqlParam(docId, values);
|
||||||
let p2 = addSqlParam(index, values);
|
let p2 = addSqlParam(index, values);
|
||||||
let p3 = addSqlParam(user.id, values);
|
let p3 = addSqlParam(user.id, values);
|
||||||
@ -123,27 +123,28 @@ function _insertChangesCallback (startIndex, objChanges, docId, index, user, cal
|
|||||||
if (i > startIndex) {
|
if (i > startIndex) {
|
||||||
sqlCommand += ',';
|
sqlCommand += ',';
|
||||||
}
|
}
|
||||||
sqlCommand += `(${p1},${p2},${p3},${p4},${p5},${p6},${p7})`;
|
sqlCommand += `(${p0},${p1},${p2},${p3},${p4},${p5},${p6},${p7})`;
|
||||||
lengthUtf8Current += lengthUtf8Row;
|
lengthUtf8Current += lengthUtf8Row;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlCommand += ';';
|
sqlCommand += ';';
|
||||||
baseConnector.sqlQuery(sqlCommand, callback, undefined, undefined, values);
|
baseConnector.sqlQuery(ctx, sqlCommand, callback, undefined, undefined, values);
|
||||||
}
|
}
|
||||||
exports.deleteChangesCallback = function(docId, deleteIndex, callback) {
|
exports.deleteChangesCallback = function(ctx, docId, deleteIndex, callback) {
|
||||||
let sqlCommand, values = [];
|
let sqlCommand, values = [];
|
||||||
let sqlParam1 = addSqlParam(docId, values);
|
let p1 = addSqlParam(ctx.tenant, values);
|
||||||
|
let p2 = addSqlParam(docId, values);
|
||||||
if (null !== deleteIndex) {
|
if (null !== deleteIndex) {
|
||||||
let sqlParam2 = addSqlParam(deleteIndex, values);
|
let sqlParam2 = addSqlParam(deleteIndex, values);
|
||||||
sqlCommand = `DELETE FROM ${tableChanges} WHERE id=${sqlParam1} AND change_id >= ${sqlParam2};`;
|
sqlCommand = `DELETE FROM ${tableChanges} WHERE tenant=${p1} AND id=${p2} AND change_id >= ${sqlParam2};`;
|
||||||
} else {
|
} else {
|
||||||
sqlCommand = `DELETE FROM ${tableChanges} WHERE id=${sqlParam1};`;
|
sqlCommand = `DELETE FROM ${tableChanges} WHERE tenant=${p1} AND id=${p2};`;
|
||||||
}
|
}
|
||||||
baseConnector.sqlQuery(sqlCommand, callback, undefined, undefined, values);
|
baseConnector.sqlQuery(ctx, sqlCommand, callback, undefined, undefined, values);
|
||||||
};
|
};
|
||||||
exports.deleteChangesPromise = function (docId, deleteIndex) {
|
exports.deleteChangesPromise = function (ctx, docId, deleteIndex) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
exports.deleteChangesCallback(docId, deleteIndex, function(error, result) {
|
exports.deleteChangesCallback(ctx, docId, deleteIndex, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -152,21 +153,22 @@ exports.deleteChangesPromise = function (docId, deleteIndex) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.deleteChanges = function (docId, deleteIndex) {
|
exports.deleteChanges = function (ctx, docId, deleteIndex) {
|
||||||
lockCriticalSection(docId, function () {_deleteChanges(docId, deleteIndex);});
|
lockCriticalSection(docId, function () {_deleteChanges(ctx, docId, deleteIndex);});
|
||||||
};
|
};
|
||||||
function _deleteChanges (docId, deleteIndex) {
|
function _deleteChanges (ctx, docId, deleteIndex) {
|
||||||
exports.deleteChangesCallback(docId, deleteIndex, function () {unLockCriticalSection(docId);});
|
exports.deleteChangesCallback(ctx, docId, deleteIndex, function () {unLockCriticalSection(docId);});
|
||||||
}
|
}
|
||||||
exports.getChangesIndex = function(docId, callback) {
|
exports.getChangesIndex = function(ctx, docId, callback) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let sqlParam = addSqlParam(docId, values);
|
let p1 = addSqlParam(ctx.tenant, values);
|
||||||
var sqlCommand = `SELECT MAX(change_id) as change_id FROM ${tableChanges} WHERE id=${sqlParam};`;
|
let p2 = addSqlParam(docId, values);
|
||||||
baseConnector.sqlQuery(sqlCommand, callback, undefined, undefined, values);
|
var sqlCommand = `SELECT MAX(change_id) as change_id FROM ${tableChanges} WHERE tenant=${p1} AND id=${p2};`;
|
||||||
|
baseConnector.sqlQuery(ctx, sqlCommand, callback, undefined, undefined, values);
|
||||||
};
|
};
|
||||||
exports.getChangesIndexPromise = function(docId) {
|
exports.getChangesIndexPromise = function(ctx, docId) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
exports.getChangesIndex(docId, function(error, result) {
|
exports.getChangesIndex(ctx, docId, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -175,11 +177,13 @@ exports.getChangesIndexPromise = function(docId) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.getChangesPromise = function (docId, optStartIndex, optEndIndex, opt_time) {
|
exports.getChangesPromise = function (ctx, docId, optStartIndex, optEndIndex, opt_time) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let sqlParam = addSqlParam(docId, values);
|
let sqlParam = addSqlParam(ctx.tenant, values);
|
||||||
let sqlWhere = `id=${sqlParam}`;
|
let sqlWhere = `tenant=${sqlParam}`;
|
||||||
|
sqlParam = addSqlParam(docId, values);
|
||||||
|
sqlWhere += ` AND id=${sqlParam}`;
|
||||||
if (null != optStartIndex) {
|
if (null != optStartIndex) {
|
||||||
sqlParam = addSqlParam(optStartIndex, values);
|
sqlParam = addSqlParam(optStartIndex, values);
|
||||||
sqlWhere += ` AND change_id>=${sqlParam}`;
|
sqlWhere += ` AND change_id>=${sqlParam}`;
|
||||||
@ -198,7 +202,7 @@ exports.getChangesPromise = function (docId, optStartIndex, optEndIndex, opt_tim
|
|||||||
sqlWhere += ' ORDER BY change_id ASC';
|
sqlWhere += ' ORDER BY change_id ASC';
|
||||||
var sqlCommand = `SELECT * FROM ${tableChanges} WHERE ${sqlWhere};`;
|
var sqlCommand = `SELECT * FROM ${tableChanges} WHERE ${sqlWhere};`;
|
||||||
|
|
||||||
baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -207,23 +211,6 @@ exports.getChangesPromise = function (docId, optStartIndex, optEndIndex, opt_tim
|
|||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.checkStatusFile = function (docId, callbackFunction) {
|
|
||||||
let values = [];
|
|
||||||
let sqlParam = addSqlParam(docId, values);
|
|
||||||
var sqlCommand = `SELECT status, status_info FROM ${tableResult} WHERE id=${sqlParam};`;
|
|
||||||
baseConnector.sqlQuery(sqlCommand, callbackFunction, undefined, undefined, values);
|
|
||||||
};
|
|
||||||
exports.checkStatusFilePromise = function (docId) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
exports.checkStatusFile(docId, function(error, result) {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.isLockCriticalSection = function (id) {
|
exports.isLockCriticalSection = function (id) {
|
||||||
return !!(g_oCriticalSection[id]);
|
return !!(g_oCriticalSection[id]);
|
||||||
@ -249,11 +236,11 @@ function unLockCriticalSection (id) {
|
|||||||
else
|
else
|
||||||
delete g_oCriticalSection[id];
|
delete g_oCriticalSection[id];
|
||||||
}
|
}
|
||||||
exports.healthCheck = function () {
|
exports.healthCheck = function (ctx) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
//SELECT 1; usefull for H2, MySQL, Microsoft SQL Server, PostgreSQL, SQLite
|
//SELECT 1; usefull for H2, MySQL, Microsoft SQL Server, PostgreSQL, SQLite
|
||||||
//http://stackoverflow.com/questions/3668506/efficient-sql-test-query-or-validation-query-that-will-work-across-all-or-most
|
//http://stackoverflow.com/questions/3668506/efficient-sql-test-query-or-validation-query-that-will-work-across-all-or-most
|
||||||
baseConnector.sqlQuery('SELECT 1;', function(error, result) {
|
baseConnector.sqlQuery(ctx, 'SELECT 1;', function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -263,10 +250,22 @@ exports.healthCheck = function () {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.getEmptyCallbacks = function() {
|
exports.getEmptyCallbacks = function(ctx) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
const sqlCommand = "SELECT DISTINCT t1.id FROM doc_changes t1 LEFT JOIN task_result t2 ON t2.id = t1.id WHERE t2.callback = '';";
|
const sqlCommand = "SELECT DISTINCT t1.tenant, t1.id FROM doc_changes t1 LEFT JOIN task_result t2 ON t2.tenant = t1.tenant AND t2.id = t1.id WHERE t2.callback = '';";
|
||||||
baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
exports.getTableColumns = function(ctx, tableName) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
const sqlCommand = `SELECT column_name FROM information_schema.COLUMNS WHERE TABLE_NAME = '${tableName}';`;
|
||||||
|
baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -291,8 +290,8 @@ UserCallback.prototype.delimiter = constants.CHAR_DELIMITER;
|
|||||||
UserCallback.prototype.toSQLInsert = function(){
|
UserCallback.prototype.toSQLInsert = function(){
|
||||||
return this.delimiter + JSON.stringify(this);
|
return this.delimiter + JSON.stringify(this);
|
||||||
};
|
};
|
||||||
UserCallback.prototype.getCallbackByUserIndex = function(docId, callbacksStr, opt_userIndex) {
|
UserCallback.prototype.getCallbackByUserIndex = function(ctx, callbacksStr, opt_userIndex) {
|
||||||
logger.debug("getCallbackByUserIndex: docId = %s userIndex = %s callbacks = %s", docId, opt_userIndex, callbacksStr);
|
ctx.logger.debug("getCallbackByUserIndex: userIndex = %s callbacks = %s", opt_userIndex, callbacksStr);
|
||||||
if (!callbacksStr || !callbacksStr.startsWith(UserCallback.prototype.delimiter)) {
|
if (!callbacksStr || !callbacksStr.startsWith(UserCallback.prototype.delimiter)) {
|
||||||
let index = callbacksStr.indexOf(UserCallback.prototype.delimiter);
|
let index = callbacksStr.indexOf(UserCallback.prototype.delimiter);
|
||||||
if (-1 === index) {
|
if (-1 === index) {
|
||||||
@ -314,8 +313,8 @@ UserCallback.prototype.getCallbackByUserIndex = function(docId, callbacksStr, op
|
|||||||
}
|
}
|
||||||
return callbackUrl;
|
return callbackUrl;
|
||||||
};
|
};
|
||||||
UserCallback.prototype.getCallbacks = function(docId, callbacksStr) {
|
UserCallback.prototype.getCallbacks = function(ctx, callbacksStr) {
|
||||||
logger.debug("getCallbacks: docId = %s callbacks = %s", docId, callbacksStr);
|
ctx.logger.debug("getCallbacks: callbacks = %s", callbacksStr);
|
||||||
if (!callbacksStr || !callbacksStr.startsWith(UserCallback.prototype.delimiter)) {
|
if (!callbacksStr || !callbacksStr.startsWith(UserCallback.prototype.delimiter)) {
|
||||||
let index = callbacksStr.indexOf(UserCallback.prototype.delimiter);
|
let index = callbacksStr.indexOf(UserCallback.prototype.delimiter);
|
||||||
if (-1 === index) {
|
if (-1 === index) {
|
||||||
@ -359,10 +358,10 @@ DocumentPassword.prototype.toSQLInsert = function(){
|
|||||||
DocumentPassword.prototype.isInitial = function(){
|
DocumentPassword.prototype.isInitial = function(){
|
||||||
return !this.change;
|
return !this.change;
|
||||||
};
|
};
|
||||||
DocumentPassword.prototype.getDocPassword = function(docId, docPasswordStr) {
|
DocumentPassword.prototype.getDocPassword = function(ctx, docPasswordStr) {
|
||||||
let res = {initial: undefined, current: undefined, change: undefined};
|
let res = {initial: undefined, current: undefined, change: undefined};
|
||||||
if (docPasswordStr) {
|
if (docPasswordStr) {
|
||||||
logger.debug("getDocPassword: docId = %s passwords = %s", docId, docPasswordStr);
|
ctx.logger.debug("getDocPassword: passwords = %s", docPasswordStr);
|
||||||
let passwords = docPasswordStr.split(UserCallback.prototype.delimiter);
|
let passwords = docPasswordStr.split(UserCallback.prototype.delimiter);
|
||||||
|
|
||||||
for (let i = 1; i < passwords.length; ++i) {
|
for (let i = 1; i < passwords.length; ++i) {
|
||||||
@ -378,12 +377,12 @@ DocumentPassword.prototype.getDocPassword = function(docId, docPasswordStr) {
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
DocumentPassword.prototype.getCurPassword = function(docId, docPasswordStr) {
|
DocumentPassword.prototype.getCurPassword = function(ctx, docPasswordStr) {
|
||||||
let docPassword = this.getDocPassword(docId, docPasswordStr);
|
let docPassword = this.getDocPassword(ctx, docPasswordStr);
|
||||||
return docPassword.current;
|
return docPassword.current;
|
||||||
};
|
};
|
||||||
DocumentPassword.prototype.hasPasswordChanges = function(docId, docPasswordStr) {
|
DocumentPassword.prototype.hasPasswordChanges = function(ctx, docPasswordStr) {
|
||||||
let docPassword = this.getDocPassword(docId, docPasswordStr);
|
let docPassword = this.getDocPassword(ctx, docPasswordStr);
|
||||||
return docPassword.initial !== docPassword.current;
|
return docPassword.initial !== docPassword.current;
|
||||||
};
|
};
|
||||||
exports.DocumentPassword = DocumentPassword;
|
exports.DocumentPassword = DocumentPassword;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,6 @@ var config = require('config');
|
|||||||
var co = require('co');
|
var co = require('co');
|
||||||
const locale = require('windows-locale');
|
const locale = require('windows-locale');
|
||||||
var taskResult = require('./taskresult');
|
var taskResult = require('./taskresult');
|
||||||
var logger = require('./../../Common/sources/logger');
|
|
||||||
var utils = require('./../../Common/sources/utils');
|
var utils = require('./../../Common/sources/utils');
|
||||||
var constants = require('./../../Common/sources/constants');
|
var constants = require('./../../Common/sources/constants');
|
||||||
var commonDefines = require('./../../Common/sources/commondefines');
|
var commonDefines = require('./../../Common/sources/commondefines');
|
||||||
@ -47,18 +46,19 @@ var storage = require('./../../Common/sources/storage-base');
|
|||||||
var formatChecker = require('./../../Common/sources/formatchecker');
|
var formatChecker = require('./../../Common/sources/formatchecker');
|
||||||
var statsDClient = require('./../../Common/sources/statsdclient');
|
var statsDClient = require('./../../Common/sources/statsdclient');
|
||||||
var storageBase = require('./../../Common/sources/storage-base');
|
var storageBase = require('./../../Common/sources/storage-base');
|
||||||
|
var operationContext = require('./../../Common/sources/operationContext');
|
||||||
const sqlBase = require('./baseConnector');
|
const sqlBase = require('./baseConnector');
|
||||||
|
|
||||||
var CONVERT_ASYNC_DELAY = 1000;
|
var CONVERT_ASYNC_DELAY = 1000;
|
||||||
|
|
||||||
var clientStatsD = statsDClient.getClient();
|
var clientStatsD = statsDClient.getClient();
|
||||||
|
|
||||||
function* getConvertStatus(cmd, selectRes, opt_checkPassword) {
|
function* getConvertStatus(ctx, cmd, selectRes, opt_checkPassword) {
|
||||||
var status = new commonDefines.ConvertStatus(constants.NO_ERROR);
|
var status = new commonDefines.ConvertStatus(constants.NO_ERROR);
|
||||||
if (selectRes.length > 0) {
|
if (selectRes.length > 0) {
|
||||||
var docId = cmd.getDocId();
|
var docId = cmd.getDocId();
|
||||||
var row = selectRes[0];
|
var row = selectRes[0];
|
||||||
let password = opt_checkPassword && sqlBase.DocumentPassword.prototype.getCurPassword(docId, row.password);
|
let password = opt_checkPassword && sqlBase.DocumentPassword.prototype.getCurPassword(ctx, row.password);
|
||||||
switch (row.status) {
|
switch (row.status) {
|
||||||
case taskResult.FileStatus.Ok:
|
case taskResult.FileStatus.Ok:
|
||||||
if (password) {
|
if (password) {
|
||||||
@ -70,10 +70,10 @@ function* getConvertStatus(cmd, selectRes, opt_checkPassword) {
|
|||||||
isCorrectPassword = decryptedPassword === userPassword;
|
isCorrectPassword = decryptedPassword === userPassword;
|
||||||
}
|
}
|
||||||
if (isCorrectPassword) {
|
if (isCorrectPassword) {
|
||||||
logger.debug("getConvertStatus password match: docId = %s", docId);
|
ctx.logger.debug("getConvertStatus password match");
|
||||||
status.end = true;
|
status.end = true;
|
||||||
} else {
|
} else {
|
||||||
logger.debug("getConvertStatus password mismatch: docId = %s", docId);
|
ctx.logger.debug("getConvertStatus password mismatch");
|
||||||
status.err = constants.CONVERT_PASSWORD;
|
status.err = constants.CONVERT_PASSWORD;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -85,7 +85,7 @@ function* getConvertStatus(cmd, selectRes, opt_checkPassword) {
|
|||||||
case taskResult.FileStatus.NeedPassword:
|
case taskResult.FileStatus.NeedPassword:
|
||||||
status.err = row.status_info;
|
status.err = row.status_info;
|
||||||
if (taskResult.FileStatus.ErrToReload == row.status || taskResult.FileStatus.NeedPassword == row.status) {
|
if (taskResult.FileStatus.ErrToReload == row.status || taskResult.FileStatus.NeedPassword == row.status) {
|
||||||
yield canvasService.cleanupCache(docId);
|
yield canvasService.cleanupCache(ctx);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case taskResult.FileStatus.NeedParams:
|
case taskResult.FileStatus.NeedParams:
|
||||||
@ -103,9 +103,9 @@ function* getConvertStatus(cmd, selectRes, opt_checkPassword) {
|
|||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
function* getConvertPath(docId, fileTo, formatTo) {
|
function* getConvertPath(ctx, docId, fileTo, formatTo) {
|
||||||
if (constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML === formatTo || constants.AVS_OFFICESTUDIO_FILE_OTHER_ODF === formatTo) {
|
if (constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML === formatTo || constants.AVS_OFFICESTUDIO_FILE_OTHER_ODF === formatTo) {
|
||||||
let list = yield storage.listObjects(docId);
|
let list = yield storage.listObjects(ctx, docId);
|
||||||
let baseName = path.basename(fileTo, path.extname(fileTo));
|
let baseName = path.basename(fileTo, path.extname(fileTo));
|
||||||
for (let i = 0; i < list.length; ++i) {
|
for (let i = 0; i < list.length; ++i) {
|
||||||
if (path.basename(list[i], path.extname(list[i])) === baseName) {
|
if (path.basename(list[i], path.extname(list[i])) === baseName) {
|
||||||
@ -115,28 +115,29 @@ function* getConvertPath(docId, fileTo, formatTo) {
|
|||||||
}
|
}
|
||||||
return docId + '/' + fileTo;
|
return docId + '/' + fileTo;
|
||||||
}
|
}
|
||||||
function* getConvertUrl(baseUrl, fileToPath, title) {
|
function* getConvertUrl(ctx, baseUrl, fileToPath, title) {
|
||||||
if (title) {
|
if (title) {
|
||||||
title = path.basename(title, path.extname(title)) + path.extname(fileToPath);
|
title = path.basename(title, path.extname(title)) + path.extname(fileToPath);
|
||||||
}
|
}
|
||||||
return yield storage.getSignedUrl(baseUrl, fileToPath, commonDefines.c_oAscUrlTypes.Temporary, title);
|
return yield storage.getSignedUrl(ctx, baseUrl, fileToPath, commonDefines.c_oAscUrlTypes.Temporary, title);
|
||||||
}
|
}
|
||||||
function* convertByCmd(cmd, async, opt_fileTo, opt_taskExist, opt_priority, opt_expiration, opt_queue, opt_checkPassword) {
|
function* convertByCmd(ctx, cmd, async, opt_fileTo, opt_taskExist, opt_priority, opt_expiration, opt_queue, opt_checkPassword) {
|
||||||
var docId = cmd.getDocId();
|
var docId = cmd.getDocId();
|
||||||
var startDate = null;
|
var startDate = null;
|
||||||
if (clientStatsD) {
|
if (clientStatsD) {
|
||||||
startDate = new Date();
|
startDate = new Date();
|
||||||
}
|
}
|
||||||
logger.debug('Start convert request docId = %s', docId);
|
ctx.logger.debug('Start convert request');
|
||||||
|
|
||||||
let bCreate = false;
|
let bCreate = false;
|
||||||
if (!opt_taskExist) {
|
if (!opt_taskExist) {
|
||||||
let task = new taskResult.TaskResultData();
|
let task = new taskResult.TaskResultData();
|
||||||
|
task.tenant = ctx.tenant;
|
||||||
task.key = docId;
|
task.key = docId;
|
||||||
task.status = taskResult.FileStatus.WaitQueue;
|
task.status = taskResult.FileStatus.WaitQueue;
|
||||||
task.statusInfo = constants.NO_ERROR;
|
task.statusInfo = constants.NO_ERROR;
|
||||||
|
|
||||||
let upsertRes = yield taskResult.upsert(task);
|
let upsertRes = yield taskResult.upsert(ctx, task);
|
||||||
//if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values
|
//if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values
|
||||||
//http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
|
//http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
|
||||||
bCreate = upsertRes.affectedRows == 1;
|
bCreate = upsertRes.affectedRows == 1;
|
||||||
@ -144,10 +145,11 @@ function* convertByCmd(cmd, async, opt_fileTo, opt_taskExist, opt_priority, opt_
|
|||||||
var selectRes;
|
var selectRes;
|
||||||
var status;
|
var status;
|
||||||
if (!bCreate) {
|
if (!bCreate) {
|
||||||
selectRes = yield taskResult.select(docId);
|
selectRes = yield taskResult.select(ctx, docId);
|
||||||
status = yield* getConvertStatus(cmd, selectRes, opt_checkPassword);
|
status = yield* getConvertStatus(ctx, cmd, selectRes, opt_checkPassword);
|
||||||
} else {
|
} else {
|
||||||
var queueData = new commonDefines.TaskQueueData();
|
var queueData = new commonDefines.TaskQueueData();
|
||||||
|
queueData.setCtx(ctx);
|
||||||
queueData.setCmd(cmd);
|
queueData.setCmd(cmd);
|
||||||
if (opt_fileTo) {
|
if (opt_fileTo) {
|
||||||
queueData.setToFile(opt_fileTo);
|
queueData.setToFile(opt_fileTo);
|
||||||
@ -165,22 +167,22 @@ function* convertByCmd(cmd, async, opt_fileTo, opt_taskExist, opt_priority, opt_
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yield utils.sleep(CONVERT_ASYNC_DELAY);
|
yield utils.sleep(CONVERT_ASYNC_DELAY);
|
||||||
selectRes = yield taskResult.select(docId);
|
selectRes = yield taskResult.select(ctx, docId);
|
||||||
status = yield* getConvertStatus(cmd, selectRes, opt_checkPassword);
|
status = yield* getConvertStatus(ctx, cmd, selectRes, opt_checkPassword);
|
||||||
waitTime += CONVERT_ASYNC_DELAY;
|
waitTime += CONVERT_ASYNC_DELAY;
|
||||||
if (waitTime > utils.CONVERTION_TIMEOUT) {
|
if (waitTime > utils.CONVERTION_TIMEOUT) {
|
||||||
status.err = constants.CONVERT_TIMEOUT;
|
status.err = constants.CONVERT_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug('End convert request end %s status %s docId = %s', status.end, status.err, docId);
|
ctx.logger.debug('End convert request end %s status %s', status.end, status.err);
|
||||||
if (clientStatsD) {
|
if (clientStatsD) {
|
||||||
clientStatsD.timing('coauth.convertservice', new Date() - startDate);
|
clientStatsD.timing('coauth.convertservice', new Date() - startDate);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* convertFromChanges(docId, baseUrl, forceSave, externalChangeInfo, opt_userdata, opt_userConnectionId,
|
let convertFromChanges = co.wrap(function*(ctx, docId, baseUrl, forceSave, externalChangeInfo, opt_userdata, opt_userConnectionId,
|
||||||
opt_responseKey, opt_priority, opt_expiration, opt_queue, opt_redisKey) {
|
opt_responseKey, opt_priority, opt_expiration, opt_queue, opt_redisKey) {
|
||||||
var cmd = new commonDefines.InputCommand();
|
var cmd = new commonDefines.InputCommand();
|
||||||
cmd.setCommand('sfcm');
|
cmd.setCommand('sfcm');
|
||||||
@ -204,50 +206,56 @@ function* convertFromChanges(docId, baseUrl, forceSave, externalChangeInfo, opt_
|
|||||||
cmd.setRedisKey(opt_redisKey);
|
cmd.setRedisKey(opt_redisKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
yield* canvasService.commandSfctByCmd(cmd, opt_priority, opt_expiration, opt_queue);
|
yield canvasService.commandSfctByCmd(ctx, cmd, opt_priority, opt_expiration, opt_queue);
|
||||||
var fileTo = constants.OUTPUT_NAME;
|
var fileTo = constants.OUTPUT_NAME;
|
||||||
let outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat());
|
let outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat());
|
||||||
if (outputExt) {
|
if (outputExt) {
|
||||||
fileTo += '.' + outputExt;
|
fileTo += '.' + outputExt;
|
||||||
}
|
}
|
||||||
let status = yield* convertByCmd(cmd, true, fileTo, undefined, opt_priority, opt_expiration, opt_queue);
|
let status = yield* convertByCmd(ctx, cmd, true, fileTo, undefined, opt_priority, opt_expiration, opt_queue);
|
||||||
if (status.end) {
|
if (status.end) {
|
||||||
let fileToPath = yield* getConvertPath(docId, fileTo, cmd.getOutputFormat());
|
let fileToPath = yield* getConvertPath(ctx, docId, fileTo, cmd.getOutputFormat());
|
||||||
status.setExtName(path.extname(fileToPath));
|
status.setExtName(path.extname(fileToPath));
|
||||||
status.setUrl(yield* getConvertUrl(baseUrl, fileToPath, cmd.getTitle()));
|
status.setUrl(yield* getConvertUrl(ctx, baseUrl, fileToPath, cmd.getTitle()));
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
});
|
||||||
function parseIntParam(val){
|
function parseIntParam(val){
|
||||||
return (typeof val === 'string') ? parseInt(val) : val;
|
return (typeof val === 'string') ? parseInt(val) : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertRequest(req, res, isJson) {
|
function convertRequest(req, res, isJson) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
var docId = 'convertRequest';
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
|
ctx.initFromRequest(req);
|
||||||
|
ctx.logger.info('convertRequest start');
|
||||||
let params;
|
let params;
|
||||||
let authRes = docsCoServer.getRequestParams(docId, req);
|
let authRes = yield docsCoServer.getRequestParams(ctx, req);
|
||||||
if(authRes.code === constants.NO_ERROR){
|
if(authRes.code === constants.NO_ERROR){
|
||||||
params = authRes.params;
|
params = authRes.params;
|
||||||
} else {
|
} else {
|
||||||
|
ctx.logger.warn('convertRequest auth failed %j', authRes);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(authRes.code), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(authRes.code), isJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let outputtype = params.outputtype || '';
|
||||||
|
let docId = 'conv_' + params.key + '_' + outputtype;
|
||||||
|
ctx.setDocId(docId);
|
||||||
|
|
||||||
if (params.key && !constants.DOC_ID_REGEX.test(params.key)) {
|
if (params.key && !constants.DOC_ID_REGEX.test(params.key)) {
|
||||||
logger.warn('convertRequest unexpected key = %s: docId = %s', params.key, docId);
|
ctx.logger.warn('convertRequest unexpected key = %s', params.key);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (params.filetype && !constants.EXTENTION_REGEX.test(params.filetype)) {
|
if (params.filetype && !constants.EXTENTION_REGEX.test(params.filetype)) {
|
||||||
logger.warn('convertRequest unexpected filetype = %s: docId = %s', params.filetype, docId);
|
ctx.logger.warn('convertRequest unexpected filetype = %s', params.filetype);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let outputtype = params.outputtype || '';
|
|
||||||
let outputFormat = formatChecker.getFormatFromString(outputtype);
|
let outputFormat = formatChecker.getFormatFromString(outputtype);
|
||||||
if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN === outputFormat) {
|
if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN === outputFormat) {
|
||||||
logger.warn('convertRequest unexpected outputtype = %s: docId = %s', outputtype, docId);
|
ctx.logger.warn('convertRequest unexpected outputtype = %s', outputtype);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -256,7 +264,6 @@ function convertRequest(req, res, isJson) {
|
|||||||
cmd.setUrl(params.url);
|
cmd.setUrl(params.url);
|
||||||
cmd.setEmbeddedFonts(false);//params.embeddedfonts'];
|
cmd.setEmbeddedFonts(false);//params.embeddedfonts'];
|
||||||
cmd.setFormat(params.filetype);
|
cmd.setFormat(params.filetype);
|
||||||
docId = 'conv_' + params.key + '_' + outputtype;
|
|
||||||
cmd.setDocId(docId);
|
cmd.setDocId(docId);
|
||||||
cmd.setOutputFormat(outputFormat);
|
cmd.setOutputFormat(outputFormat);
|
||||||
|
|
||||||
@ -275,7 +282,7 @@ function convertRequest(req, res, isJson) {
|
|||||||
}
|
}
|
||||||
if (params.password) {
|
if (params.password) {
|
||||||
if (params.password.length > constants.PASSWORD_MAX_LENGTH) {
|
if (params.password.length > constants.PASSWORD_MAX_LENGTH) {
|
||||||
logger.warn('convertRequest password too long actual = %s; max = %s;docId = %s', params.password.length, constants.PASSWORD_MAX_LENGTH, docId);
|
ctx.logger.warn('convertRequest password too long actual = %s; max = %s', params.password.length, constants.PASSWORD_MAX_LENGTH);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -340,23 +347,24 @@ function convertRequest(req, res, isJson) {
|
|||||||
|
|
||||||
if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN !== cmd.getOutputFormat()) {
|
if (constants.AVS_OFFICESTUDIO_FILE_UNKNOWN !== cmd.getOutputFormat()) {
|
||||||
let fileTo = constants.OUTPUT_NAME + '.' + outputExt;
|
let fileTo = constants.OUTPUT_NAME + '.' + outputExt;
|
||||||
var status = yield* convertByCmd(cmd, async, fileTo, undefined, undefined, undefined, undefined, true);
|
var status = yield* convertByCmd(ctx, cmd, async, fileTo, undefined, undefined, undefined, undefined, true);
|
||||||
if (status.end) {
|
if (status.end) {
|
||||||
let fileToPath = yield* getConvertPath(docId, fileTo, cmd.getOutputFormat());
|
let fileToPath = yield* getConvertPath(ctx, docId, fileTo, cmd.getOutputFormat());
|
||||||
status.setExtName(path.extname(fileToPath));
|
status.setExtName(path.extname(fileToPath));
|
||||||
status.setUrl(yield* getConvertUrl(utils.getBaseUrlByRequest(req), fileToPath, cmd.getTitle()));
|
status.setUrl(yield* getConvertUrl(ctx, utils.getBaseUrlByRequest(req), fileToPath, cmd.getTitle()));
|
||||||
logger.debug('convertRequest: url = %s docId = %s', status.url, docId);
|
ctx.logger.debug('convertRequest: url = %s', status.url);
|
||||||
}
|
}
|
||||||
utils.fillResponse(req, res, status, isJson);
|
utils.fillResponse(req, res, status, isJson);
|
||||||
} else {
|
} else {
|
||||||
var addresses = utils.forwarded(req);
|
var addresses = utils.forwarded(req);
|
||||||
logger.warn('Error convert unknown outputtype: query = %j from = %s docId = %s', params, addresses, docId);
|
ctx.logger.warn('Error convert unknown outputtype: query = %j from = %s', params, addresses);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), isJson);
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
ctx.logger.error('convertRequest error: %s', e.stack);
|
||||||
logger.error('Error convert: docId = %s\r\n%s', docId, e.stack);
|
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), isJson);
|
||||||
|
} finally {
|
||||||
|
ctx.logger.info('convertRequest end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -369,59 +377,65 @@ function convertRequestXml(req, res) {
|
|||||||
|
|
||||||
function builderRequest(req, res) {
|
function builderRequest(req, res) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
let docId = 'builderRequest';
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
|
ctx.initFromRequest(req);
|
||||||
|
ctx.logger.info('builderRequest start');
|
||||||
let authRes;
|
let authRes;
|
||||||
if (!utils.isEmptyObject(req.query)) {
|
if (!utils.isEmptyObject(req.query)) {
|
||||||
//todo this is a stub for compatibility. remove in future version
|
//todo this is a stub for compatibility. remove in future version
|
||||||
authRes = docsCoServer.getRequestParams(docId, req, true);
|
authRes = yield docsCoServer.getRequestParams(ctx, req, true);
|
||||||
} else {
|
} else {
|
||||||
authRes = docsCoServer.getRequestParams(docId, req);
|
authRes = yield docsCoServer.getRequestParams(ctx, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = authRes.params;
|
let params = authRes.params;
|
||||||
|
let docId = params.key;
|
||||||
|
ctx.setDocId(docId);
|
||||||
|
|
||||||
let error = authRes.code;
|
let error = authRes.code;
|
||||||
let urls;
|
let urls;
|
||||||
let end = false;
|
let end = false;
|
||||||
if (error === constants.NO_ERROR &&
|
if (error === constants.NO_ERROR &&
|
||||||
(params.key || params.url || (req.body && Buffer.isBuffer(req.body) && req.body.length > 0))) {
|
(params.key || params.url || (req.body && Buffer.isBuffer(req.body) && req.body.length > 0))) {
|
||||||
docId = params.key;
|
|
||||||
let cmd = new commonDefines.InputCommand();
|
let cmd = new commonDefines.InputCommand();
|
||||||
cmd.setCommand('builder');
|
cmd.setCommand('builder');
|
||||||
cmd.setIsBuilder(true);
|
cmd.setIsBuilder(true);
|
||||||
cmd.setWithAuthorization(true);
|
cmd.setWithAuthorization(true);
|
||||||
cmd.setDocId(docId);
|
cmd.setDocId(docId);
|
||||||
if (!docId) {
|
if (!docId) {
|
||||||
let task = yield* taskResult.addRandomKeyTask(undefined, 'bld_', 8);
|
let task = yield* taskResult.addRandomKeyTask(ctx, undefined, 'bld_', 8);
|
||||||
docId = task.key;
|
docId = task.key;
|
||||||
cmd.setDocId(docId);
|
cmd.setDocId(docId);
|
||||||
if (params.url) {
|
if (params.url) {
|
||||||
cmd.setUrl(params.url);
|
cmd.setUrl(params.url);
|
||||||
cmd.setFormat('docbuilder');
|
cmd.setFormat('docbuilder');
|
||||||
} else {
|
} else {
|
||||||
yield storageBase.putObject(docId + '/script.docbuilder', req.body, req.body.length);
|
yield storageBase.putObject(ctx, docId + '/script.docbuilder', req.body, req.body.length);
|
||||||
}
|
}
|
||||||
let queueData = new commonDefines.TaskQueueData();
|
let queueData = new commonDefines.TaskQueueData();
|
||||||
|
queueData.setCtx(ctx);
|
||||||
queueData.setCmd(cmd);
|
queueData.setCmd(cmd);
|
||||||
yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW);
|
yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_LOW);
|
||||||
}
|
}
|
||||||
let async = (typeof params.async === 'string') ? 'true' === params.async : params.async;
|
let async = (typeof params.async === 'string') ? 'true' === params.async : params.async;
|
||||||
let status = yield* convertByCmd(cmd, async, utils.getBaseUrlByRequest(req), undefined, true);
|
let status = yield* convertByCmd(ctx, cmd, async, utils.getBaseUrlByRequest(req), undefined, true);
|
||||||
end = status.end;
|
end = status.end;
|
||||||
error = status.err;
|
error = status.err;
|
||||||
if (end) {
|
if (end) {
|
||||||
urls = yield storageBase.getSignedUrls(utils.getBaseUrlByRequest(req), docId + '/output',
|
urls = yield storageBase.getSignedUrls(ctx, utils.getBaseUrlByRequest(req), docId + '/output',
|
||||||
commonDefines.c_oAscUrlTypes.Temporary);
|
commonDefines.c_oAscUrlTypes.Temporary);
|
||||||
}
|
}
|
||||||
} else if (error === constants.NO_ERROR) {
|
} else if (error === constants.NO_ERROR) {
|
||||||
error = constants.UNKNOWN;
|
error = constants.UNKNOWN;
|
||||||
}
|
}
|
||||||
logger.debug('End builderRequest request: docId = %s urls = %j end = %s error = %s', docId, urls, end, error);
|
ctx.logger.debug('End builderRequest request: urls = %j end = %s error = %s', urls, end, error);
|
||||||
utils.fillResponseBuilder(res, docId, urls, end, error);
|
utils.fillResponseBuilder(res, docId, urls, end, error);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
logger.error('Error builderRequest: docId = %s\r\n%s', docId, e.stack);
|
ctx.logger.error('Error builderRequest: %s', e.stack);
|
||||||
utils.fillResponseBuilder(res, undefined, undefined, undefined, constants.UNKNOWN);
|
utils.fillResponseBuilder(res, undefined, undefined, undefined, constants.UNKNOWN);
|
||||||
|
} finally {
|
||||||
|
ctx.logger.info('builderRequest end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@ const config = require('config');
|
|||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
const utils = require('./../../Common/sources/utils');
|
const utils = require('./../../Common/sources/utils');
|
||||||
const commonDefines = require('./../../Common/sources/commondefines');
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
|
const tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
|
|
||||||
const cfgExpMonthUniqueUsers = ms(config.get('services.CoAuthoring.expire.monthUniqueUsers'));
|
const cfgExpMonthUniqueUsers = ms(config.get('services.CoAuthoring.expire.monthUniqueUsers'));
|
||||||
|
|
||||||
@ -46,18 +47,22 @@ function EditorData() {
|
|||||||
this.uniqueViewUser = {};
|
this.uniqueViewUser = {};
|
||||||
this.uniqueViewUsersOfMonth = {};
|
this.uniqueViewUsersOfMonth = {};
|
||||||
this.shutdown = {};
|
this.shutdown = {};
|
||||||
this.stat = [];
|
this.stat = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
EditorData.prototype._getDocumentData = function(docId) {
|
EditorData.prototype._getDocumentData = function(ctx, docId) {
|
||||||
let options = this.data[docId];
|
let tenantData = this.data[ctx.tenant];
|
||||||
|
if (!tenantData) {
|
||||||
|
this.data[ctx.tenant] = tenantData = {};
|
||||||
|
}
|
||||||
|
let options = tenantData[docId];
|
||||||
if (!options) {
|
if (!options) {
|
||||||
this.data[docId] = options = {};
|
tenantData[docId] = options = {};
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
};
|
};
|
||||||
EditorData.prototype._checkAndLock = function(name, docId, fencingToken, ttl) {
|
EditorData.prototype._checkAndLock = function(ctx, name, docId, fencingToken, ttl) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
let res = true;
|
let res = true;
|
||||||
if (data[name] && now < data[name].expireAt && fencingToken !== data[name].fencingToken) {
|
if (data[name] && now < data[name].expireAt && fencingToken !== data[name].fencingToken) {
|
||||||
@ -68,8 +73,8 @@ EditorData.prototype._checkAndLock = function(name, docId, fencingToken, ttl) {
|
|||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
EditorData.prototype._checkAndUnlock = function(name, docId, fencingToken) {
|
EditorData.prototype._checkAndUnlock = function(ctx, name, docId, fencingToken) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
let res;
|
let res;
|
||||||
if (data[name] && now < data[name].expireAt) {
|
if (data[name] && now < data[name].expireAt) {
|
||||||
@ -86,100 +91,101 @@ EditorData.prototype._checkAndUnlock = function(name, docId, fencingToken) {
|
|||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addPresence = function(docId, userId, userInfo) {
|
EditorData.prototype.addPresence = function(ctx, docId, userId, userInfo) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.removePresence = function(docId, userId) {
|
EditorData.prototype.removePresence = function(ctx, docId, userId) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresence = function(docId, connections) {
|
EditorData.prototype.getPresence = function(ctx, docId, connections) {
|
||||||
let hvals = [];
|
let hvals = [];
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
if (connections[i].docId === docId) {
|
let conn = connections[i];
|
||||||
hvals.push(utils.getConnectionInfoStr(connections[i]));
|
if (conn.docId === docId && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
|
hvals.push(utils.getConnectionInfoStr(conn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(hvals);
|
return Promise.resolve(hvals);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.lockSave = function(docId, userId, ttl) {
|
EditorData.prototype.lockSave = function(ctx, docId, userId, ttl) {
|
||||||
return this._checkAndLock('lockSave', docId, userId, ttl);
|
return this._checkAndLock(ctx, 'lockSave', docId, userId, ttl);
|
||||||
};
|
};
|
||||||
EditorData.prototype.unlockSave = function(docId, userId) {
|
EditorData.prototype.unlockSave = function(ctx, docId, userId) {
|
||||||
return this._checkAndUnlock('lockSave', docId, userId);
|
return this._checkAndUnlock(ctx, 'lockSave', docId, userId);
|
||||||
};
|
};
|
||||||
EditorData.prototype.lockAuth = function(docId, userId, ttl) {
|
EditorData.prototype.lockAuth = function(ctx, docId, userId, ttl) {
|
||||||
return this._checkAndLock('lockAuth', docId, userId, ttl);
|
return this._checkAndLock(ctx, 'lockAuth', docId, userId, ttl);
|
||||||
};
|
};
|
||||||
EditorData.prototype.unlockAuth = function(docId, userId) {
|
EditorData.prototype.unlockAuth = function(ctx, docId, userId) {
|
||||||
return this._checkAndUnlock('lockAuth', docId, userId);
|
return this._checkAndUnlock(ctx, 'lockAuth', docId, userId);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.getDocumentPresenceExpired = function(now) {
|
EditorData.prototype.getDocumentPresenceExpired = function(now) {
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
};
|
};
|
||||||
EditorData.prototype.removePresenceDocument = function(docId) {
|
EditorData.prototype.removePresenceDocument = function(ctx, docId) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addLocks = function(docId, locks) {
|
EditorData.prototype.addLocks = function(ctx, docId, locks) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
if (!data.locks) {
|
if (!data.locks) {
|
||||||
data.locks = [];
|
data.locks = [];
|
||||||
}
|
}
|
||||||
data.locks = data.locks.concat(locks);
|
data.locks = data.locks.concat(locks);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.removeLocks = function(docId) {
|
EditorData.prototype.removeLocks = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.locks = undefined;
|
data.locks = undefined;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getLocks = function(docId) {
|
EditorData.prototype.getLocks = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
return Promise.resolve(data.locks || []);
|
return Promise.resolve(data.locks || []);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addMessage = function(docId, msg) {
|
EditorData.prototype.addMessage = function(ctx, docId, msg) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
if (!data.messages) {
|
if (!data.messages) {
|
||||||
data.messages = [];
|
data.messages = [];
|
||||||
}
|
}
|
||||||
data.messages.push(msg);
|
data.messages.push(msg);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.removeMessages = function(docId) {
|
EditorData.prototype.removeMessages = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.messages = undefined;
|
data.messages = undefined;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getMessages = function(docId) {
|
EditorData.prototype.getMessages = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
return Promise.resolve(data.messages || []);
|
return Promise.resolve(data.messages || []);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.setSaved = function(docId, status) {
|
EditorData.prototype.setSaved = function(ctx, docId, status) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.saved = status;
|
data.saved = status;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getdelSaved = function(docId) {
|
EditorData.prototype.getdelSaved = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
let res = data.saved;
|
let res = data.saved;
|
||||||
data.saved = undefined;
|
data.saved = undefined;
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
EditorData.prototype.setForceSave = function(docId, time, index, baseUrl, changeInfo) {
|
EditorData.prototype.setForceSave = function(ctx, docId, time, index, baseUrl, changeInfo) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.forceSave = {time: time, index: index, baseUrl: baseUrl, changeInfo: changeInfo, started: false, ended: false};
|
data.forceSave = {time: time, index: index, baseUrl: baseUrl, changeInfo: changeInfo, started: false, ended: false};
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getForceSave = function(docId) {
|
EditorData.prototype.getForceSave = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
return Promise.resolve(data.forceSave || null);
|
return Promise.resolve(data.forceSave || null);
|
||||||
};
|
};
|
||||||
EditorData.prototype.checkAndStartForceSave = function(docId) {
|
EditorData.prototype.checkAndStartForceSave = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
let res;
|
let res;
|
||||||
if (data.forceSave && !data.forceSave.started) {
|
if (data.forceSave && !data.forceSave.started) {
|
||||||
data.forceSave.started = true;
|
data.forceSave.started = true;
|
||||||
@ -188,8 +194,8 @@ EditorData.prototype.checkAndStartForceSave = function(docId) {
|
|||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
EditorData.prototype.checkAndSetForceSave = function(docId, time, index, started, ended) {
|
EditorData.prototype.checkAndSetForceSave = function(ctx, docId, time, index, started, ended) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
let res;
|
let res;
|
||||||
if (data.forceSave && time === data.forceSave.time && index === data.forceSave.index) {
|
if (data.forceSave && time === data.forceSave.time && index === data.forceSave.index) {
|
||||||
data.forceSave.started = started;
|
data.forceSave.started = started;
|
||||||
@ -198,180 +204,235 @@ EditorData.prototype.checkAndSetForceSave = function(docId, time, index, started
|
|||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
EditorData.prototype.removeForceSave = function(docId) {
|
EditorData.prototype.removeForceSave = function(ctx, docId) {
|
||||||
let data = this._getDocumentData(docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.forceSave = undefined;
|
data.forceSave = undefined;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.cleanDocumentOnExit = function(docId) {
|
EditorData.prototype.cleanDocumentOnExit = function(ctx, docId) {
|
||||||
delete this.data[docId];
|
let tenantData = this.data[ctx.tenant];
|
||||||
delete this.forceSaveTimer[docId];
|
if (tenantData) {
|
||||||
|
delete tenantData[docId];
|
||||||
|
}
|
||||||
|
let tenantTimer = this.forceSaveTimer[ctx.tenant];
|
||||||
|
if (tenantTimer) {
|
||||||
|
delete tenantTimer[docId];
|
||||||
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addForceSaveTimerNX = function(docId, expireAt) {
|
EditorData.prototype.addForceSaveTimerNX = function(ctx, docId, expireAt) {
|
||||||
if (!this.forceSaveTimer[docId]) {
|
let tenantTimer = this.forceSaveTimer[ctx.tenant];
|
||||||
this.forceSaveTimer[docId] = expireAt;
|
if (!tenantTimer) {
|
||||||
|
this.forceSaveTimer[ctx.tenant] = tenantTimer = {};
|
||||||
|
}
|
||||||
|
if (!tenantTimer[docId]) {
|
||||||
|
tenantTimer[docId] = expireAt;
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getForceSaveTimer = function(now) {
|
EditorData.prototype.getForceSaveTimer = function(now) {
|
||||||
let res = [];
|
let res = [];
|
||||||
for (let docId in this.forceSaveTimer) {
|
for (let tenant in this.forceSaveTimer) {
|
||||||
if (this.forceSaveTimer.hasOwnProperty(docId)) {
|
if (this.forceSaveTimer.hasOwnProperty(tenant)) {
|
||||||
if (this.forceSaveTimer[docId] < now) {
|
let tenantTimer = this.forceSaveTimer[tenant];
|
||||||
res.push(docId);
|
for (let docId in tenantTimer) {
|
||||||
delete this.forceSaveTimer[docId];
|
if (tenantTimer.hasOwnProperty(docId)) {
|
||||||
|
if (tenantTimer[docId] < now) {
|
||||||
|
res.push([tenant, docId]);
|
||||||
|
delete tenantTimer[docId];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addPresenceUniqueUser = function(userId, expireAt, userInfo) {
|
EditorData.prototype.addPresenceUniqueUser = function(ctx, userId, expireAt, userInfo) {
|
||||||
this.uniqueUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
let tenantUser = this.uniqueUser[ctx.tenant];
|
||||||
|
if (!tenantUser) {
|
||||||
|
this.uniqueUser[ctx.tenant] = tenantUser = {};
|
||||||
|
}
|
||||||
|
tenantUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueUser = function(nowUTC) {
|
EditorData.prototype.getPresenceUniqueUser = function(ctx, nowUTC) {
|
||||||
let res = [];
|
let res = [];
|
||||||
for (let userId in this.uniqueUser) {
|
let tenantUser = this.uniqueUser[ctx.tenant];
|
||||||
if (this.uniqueUser.hasOwnProperty(userId)) {
|
if (!tenantUser) {
|
||||||
if (this.uniqueUser[userId].expireAt > nowUTC) {
|
this.uniqueUser[ctx.tenant] = tenantUser = {};
|
||||||
let elem = this.uniqueUser[userId];
|
}
|
||||||
|
for (let userId in tenantUser) {
|
||||||
|
if (tenantUser.hasOwnProperty(userId)) {
|
||||||
|
if (tenantUser[userId].expireAt > nowUTC) {
|
||||||
|
let elem = tenantUser[userId];
|
||||||
let newElem = {userid: userId, expire: new Date(elem.expireAt * 1000)};
|
let newElem = {userid: userId, expire: new Date(elem.expireAt * 1000)};
|
||||||
Object.assign(newElem, elem.userInfo);
|
Object.assign(newElem, elem.userInfo);
|
||||||
res.push(newElem);
|
res.push(newElem);
|
||||||
} else {
|
} else {
|
||||||
delete this.uniqueUser[userId];
|
delete tenantUser[userId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
EditorData.prototype.addPresenceUniqueUsersOfMonth = function(userId, period, userInfo) {
|
EditorData.prototype.addPresenceUniqueUsersOfMonth = function(ctx, userId, period, userInfo) {
|
||||||
if(!this.uniqueUsersOfMonth[period]) {
|
let tenantUser = this.uniqueUsersOfMonth[ctx.tenant];
|
||||||
let expireAt = Date.now() + cfgExpMonthUniqueUsers;
|
if (!tenantUser) {
|
||||||
this.uniqueUsersOfMonth[period] = {expireAt: expireAt, data: {}};
|
this.uniqueUsersOfMonth[ctx.tenant] = tenantUser = {};
|
||||||
}
|
}
|
||||||
this.uniqueUsersOfMonth[period].data[userId] = userInfo;
|
if(!tenantUser[period]) {
|
||||||
|
let expireAt = Date.now() + cfgExpMonthUniqueUsers;
|
||||||
|
tenantUser[period] = {expireAt: expireAt, data: {}};
|
||||||
|
}
|
||||||
|
tenantUser[period].data[userId] = userInfo;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueUsersOfMonth = function() {
|
EditorData.prototype.getPresenceUniqueUsersOfMonth = function(ctx) {
|
||||||
let res = {};
|
let res = {};
|
||||||
let nowUTC = Date.now();
|
let nowUTC = Date.now();
|
||||||
for (let periodId in this.uniqueUsersOfMonth) {
|
let tenantUser = this.uniqueUsersOfMonth[ctx.tenant];
|
||||||
if (this.uniqueUsersOfMonth.hasOwnProperty(periodId)) {
|
if (!tenantUser) {
|
||||||
if (this.uniqueUsersOfMonth[periodId].expireAt <= nowUTC) {
|
this.uniqueUsersOfMonth[ctx.tenant] = tenantUser = {};
|
||||||
delete this.uniqueUsersOfMonth[periodId];
|
}
|
||||||
|
for (let periodId in tenantUser) {
|
||||||
|
if (tenantUser.hasOwnProperty(periodId)) {
|
||||||
|
if (tenantUser[periodId].expireAt <= nowUTC) {
|
||||||
|
delete tenantUser[periodId];
|
||||||
} else {
|
} else {
|
||||||
let date = new Date(parseInt(periodId)).toISOString();
|
let date = new Date(parseInt(periodId)).toISOString();
|
||||||
res[date] = this.uniqueUsersOfMonth[periodId].data;
|
res[date] = tenantUser[periodId].data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addPresenceUniqueViewUser = function(userId, expireAt, userInfo) {
|
EditorData.prototype.addPresenceUniqueViewUser = function(ctx, userId, expireAt, userInfo) {
|
||||||
this.uniqueViewUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
let tenantUser = this.uniqueViewUser[ctx.tenant];
|
||||||
|
if (!tenantUser) {
|
||||||
|
this.uniqueViewUser[ctx.tenant] = tenantUser = {};
|
||||||
|
}
|
||||||
|
tenantUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueViewUser = function(nowUTC) {
|
EditorData.prototype.getPresenceUniqueViewUser = function(ctx, nowUTC) {
|
||||||
let res = [];
|
let res = [];
|
||||||
for (let userId in this.uniqueViewUser) {
|
let tenantUser = this.uniqueViewUser[ctx.tenant];
|
||||||
if (this.uniqueViewUser.hasOwnProperty(userId)) {
|
if (!tenantUser) {
|
||||||
if (this.uniqueViewUser[userId].expireAt > nowUTC) {
|
this.uniqueViewUser[ctx.tenant] = tenantUser = {};
|
||||||
let elem = this.uniqueViewUser[userId];
|
}
|
||||||
|
for (let userId in tenantUser) {
|
||||||
|
if (tenantUser.hasOwnProperty(userId)) {
|
||||||
|
if (tenantUser[userId].expireAt > nowUTC) {
|
||||||
|
let elem = tenantUser[userId];
|
||||||
let newElem = {userid: userId, expire: new Date(elem.expireAt * 1000)};
|
let newElem = {userid: userId, expire: new Date(elem.expireAt * 1000)};
|
||||||
Object.assign(newElem, elem.userInfo);
|
Object.assign(newElem, elem.userInfo);
|
||||||
res.push(newElem);
|
res.push(newElem);
|
||||||
} else {
|
} else {
|
||||||
delete this.uniqueViewUser[userId];
|
delete tenantUser[userId];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
EditorData.prototype.addPresenceUniqueViewUsersOfMonth = function(userId, period, userInfo) {
|
EditorData.prototype.addPresenceUniqueViewUsersOfMonth = function(ctx, userId, period, userInfo) {
|
||||||
if(!this.uniqueViewUsersOfMonth[period]) {
|
let tenantUser = this.uniqueViewUsersOfMonth[ctx.tenant];
|
||||||
let expireAt = Date.now() + cfgExpMonthUniqueUsers;
|
if (!tenantUser) {
|
||||||
this.uniqueViewUsersOfMonth[period] = {expireAt: expireAt, data: {}};
|
this.uniqueViewUsersOfMonth[ctx.tenant] = tenantUser = {};
|
||||||
}
|
}
|
||||||
this.uniqueViewUsersOfMonth[period].data[userId] = userInfo;
|
if(!tenantUser[period]) {
|
||||||
|
let expireAt = Date.now() + cfgExpMonthUniqueUsers;
|
||||||
|
tenantUser[period] = {expireAt: expireAt, data: {}};
|
||||||
|
}
|
||||||
|
tenantUser[period].data[userId] = userInfo;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueViewUsersOfMonth = function() {
|
EditorData.prototype.getPresenceUniqueViewUsersOfMonth = function(ctx) {
|
||||||
let res = {};
|
let res = {};
|
||||||
let nowUTC = Date.now();
|
let nowUTC = Date.now();
|
||||||
for (let periodId in this.uniqueViewUsersOfMonth) {
|
let tenantUser = this.uniqueViewUsersOfMonth[ctx.tenant];
|
||||||
if (this.uniqueViewUsersOfMonth.hasOwnProperty(periodId)) {
|
if (!tenantUser) {
|
||||||
if (this.uniqueViewUsersOfMonth[periodId].expireAt <= nowUTC) {
|
this.uniqueViewUsersOfMonth[ctx.tenant] = tenantUser = {};
|
||||||
delete this.uniqueViewUsersOfMonth[periodId];
|
}
|
||||||
|
for (let periodId in tenantUser) {
|
||||||
|
if (tenantUser.hasOwnProperty(periodId)) {
|
||||||
|
if (tenantUser[periodId].expireAt <= nowUTC) {
|
||||||
|
delete tenantUser[periodId];
|
||||||
} else {
|
} else {
|
||||||
let date = new Date(parseInt(periodId)).toISOString();
|
let date = new Date(parseInt(periodId)).toISOString();
|
||||||
res[date] = this.uniqueViewUsersOfMonth[periodId].data;
|
res[date] = tenantUser[periodId].data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return Promise.resolve(res);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.setEditorConnections = function(countEdit, countLiveView, countView, now, precision) {
|
EditorData.prototype.setEditorConnections = function(ctx, countEdit, countLiveView, countView, now, precision) {
|
||||||
this.stat.push({time: now, edit: countEdit, liveview: countLiveView, view: countView});
|
let tenantStat = this.stat[ctx.tenant];
|
||||||
|
if (!tenantStat) {
|
||||||
|
this.stat[ctx.tenant] = tenantStat = [];
|
||||||
|
}
|
||||||
|
tenantStat.push({time: now, edit: countEdit, liveview: countLiveView, view: countView});
|
||||||
let i = 0;
|
let i = 0;
|
||||||
while (i < this.stat.length && this.stat[i] < now - precision[precision.length - 1].val) {
|
while (i < tenantStat.length && tenantStat[i] < now - precision[precision.length - 1].val) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
this.stat.splice(0, i);
|
tenantStat.splice(0, i);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getEditorConnections = function() {
|
EditorData.prototype.getEditorConnections = function(ctx) {
|
||||||
return Promise.resolve(this.stat);
|
let tenantStat = this.stat[ctx.tenant];
|
||||||
|
if (!tenantStat) {
|
||||||
|
this.stat[ctx.tenant] = tenantStat = [];
|
||||||
|
}
|
||||||
|
return Promise.resolve(tenantStat);
|
||||||
};
|
};
|
||||||
EditorData.prototype.setEditorConnectionsCountByShard = function(shardId, count) {
|
EditorData.prototype.setEditorConnectionsCountByShard = function(ctx, shardId, count) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.incrEditorConnectionsCountByShard = function(shardId, count) {
|
EditorData.prototype.incrEditorConnectionsCountByShard = function(ctx, shardId, count) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getEditorConnectionsCount = function(connections) {
|
EditorData.prototype.getEditorConnectionsCount = function(ctx, connections) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
let conn = connections[i];
|
let conn = connections[i];
|
||||||
if (!(conn.isCloseCoAuthoring || (conn.user && conn.user.view))) {
|
if (!(conn.isCloseCoAuthoring || (conn.user && conn.user.view)) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(count);
|
return Promise.resolve(count);
|
||||||
};
|
};
|
||||||
EditorData.prototype.setViewerConnectionsCountByShard = function(shardId, count) {
|
EditorData.prototype.setViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.incrViewerConnectionsCountByShard = function(shardId, count) {
|
EditorData.prototype.incrViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getViewerConnectionsCount = function(connections) {
|
EditorData.prototype.getViewerConnectionsCount = function(ctx, connections) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
let conn = connections[i];
|
let conn = connections[i];
|
||||||
if (conn.isCloseCoAuthoring || (conn.user && conn.user.view)) {
|
if (conn.isCloseCoAuthoring || (conn.user && conn.user.view) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(count);
|
return Promise.resolve(count);
|
||||||
};
|
};
|
||||||
EditorData.prototype.setLiveViewerConnectionsCountByShard = function(shardId, count) {
|
EditorData.prototype.setLiveViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.incrLiveViewerConnectionsCountByShard = function(shardId, count) {
|
EditorData.prototype.incrLiveViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
EditorData.prototype.getLiveViewerConnectionsCount = function(connections) {
|
EditorData.prototype.getLiveViewerConnectionsCount = function(ctx, connections) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
let conn = connections[i];
|
let conn = connections[i];
|
||||||
if (utils.isLiveViewer(conn)) {
|
if (utils.isLiveViewer(conn) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,8 +41,8 @@ var utils = require('./../../Common/sources/utils');
|
|||||||
var constants = require('./../../Common/sources/constants');
|
var constants = require('./../../Common/sources/constants');
|
||||||
var storageBase = require('./../../Common/sources/storage-base');
|
var storageBase = require('./../../Common/sources/storage-base');
|
||||||
var formatChecker = require('./../../Common/sources/formatchecker');
|
var formatChecker = require('./../../Common/sources/formatchecker');
|
||||||
var logger = require('./../../Common/sources/logger');
|
|
||||||
const commonDefines = require('./../../Common/sources/commondefines');
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
|
const operationContext = require('./../../Common/sources/operationContext');
|
||||||
|
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
var configServer = config.get('services.CoAuthoring.server');
|
var configServer = config.get('services.CoAuthoring.server');
|
||||||
@ -57,9 +57,12 @@ const PATTERN_ENCRYPTED = 'ENCRYPTED;';
|
|||||||
exports.uploadTempFile = function(req, res) {
|
exports.uploadTempFile = function(req, res) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
var docId = 'uploadTempFile';
|
var docId = 'uploadTempFile';
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
|
ctx.initFromRequest(req);
|
||||||
|
ctx.logger.info('uploadTempFile start');
|
||||||
let params;
|
let params;
|
||||||
let authRes = docsCoServer.getRequestParams(docId, req, true);
|
let authRes = yield docsCoServer.getRequestParams(ctx, req, true);
|
||||||
if(authRes.code === constants.NO_ERROR){
|
if(authRes.code === constants.NO_ERROR){
|
||||||
params = authRes.params;
|
params = authRes.params;
|
||||||
} else {
|
} else {
|
||||||
@ -67,33 +70,34 @@ exports.uploadTempFile = function(req, res) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
docId = params.key;
|
docId = params.key;
|
||||||
logger.debug('Start uploadTempFile: docId = %s', docId);
|
ctx.setDocId(docId);
|
||||||
|
ctx.logger.debug('Start uploadTempFile');
|
||||||
if (docId && constants.DOC_ID_REGEX.test(docId) && req.body && Buffer.isBuffer(req.body)) {
|
if (docId && constants.DOC_ID_REGEX.test(docId) && req.body && Buffer.isBuffer(req.body)) {
|
||||||
var task = yield* taskResult.addRandomKeyTask(docId);
|
var task = yield* taskResult.addRandomKeyTask(ctx, docId);
|
||||||
var strPath = task.key + '/' + docId + '.tmp';
|
var strPath = task.key + '/' + docId + '.tmp';
|
||||||
yield storageBase.putObject(strPath, req.body, req.body.length);
|
yield storageBase.putObject(ctx, strPath, req.body, req.body.length);
|
||||||
var url = yield storageBase.getSignedUrl(utils.getBaseUrlByRequest(req), strPath,
|
var url = yield storageBase.getSignedUrl(ctx, utils.getBaseUrlByRequest(req), strPath,
|
||||||
commonDefines.c_oAscUrlTypes.Temporary);
|
commonDefines.c_oAscUrlTypes.Temporary);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.NO_ERROR, url), false);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.NO_ERROR, url), false);
|
||||||
} else {
|
} else {
|
||||||
if (!constants.DOC_ID_REGEX.test(docId)) {
|
if (!constants.DOC_ID_REGEX.test(docId)) {
|
||||||
logger.warn('Error uploadTempFile unexpected key: docId = %s', docId);
|
ctx.logger.warn('Error uploadTempFile unexpected key');
|
||||||
}
|
}
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), false);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), false);
|
||||||
}
|
}
|
||||||
logger.debug('End uploadTempFile: docId = %s', docId);
|
} catch (e) {
|
||||||
}
|
ctx.logger.error('Error uploadTempFile: %s', e.stack);
|
||||||
catch (e) {
|
|
||||||
logger.error('Error uploadTempFile: docId = %s\r\n%s', docId, e.stack);
|
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), false);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.UNKNOWN), false);
|
||||||
|
} finally {
|
||||||
|
ctx.logger.info('uploadTempFile end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
function checkJwtUpload(docId, errorName, token){
|
function* checkJwtUpload(ctx, errorName, token){
|
||||||
let checkJwtRes = docsCoServer.checkJwt(docId, token, commonDefines.c_oAscSecretType.Session);
|
let checkJwtRes = yield docsCoServer.checkJwt(ctx, token, commonDefines.c_oAscSecretType.Session);
|
||||||
return checkJwtUploadTransformRes(docId, errorName, checkJwtRes);
|
return checkJwtUploadTransformRes(ctx, errorName, checkJwtRes);
|
||||||
}
|
}
|
||||||
function checkJwtUploadTransformRes(docId, errorName, checkJwtRes){
|
function checkJwtUploadTransformRes(ctx, errorName, checkJwtRes){
|
||||||
var res = {err: true, docId: null, userid: null, encrypted: null};
|
var res = {err: true, docId: null, userid: null, encrypted: null};
|
||||||
if (checkJwtRes.decoded) {
|
if (checkJwtRes.decoded) {
|
||||||
var doc = checkJwtRes.decoded.document;
|
var doc = checkJwtRes.decoded.document;
|
||||||
@ -106,19 +110,23 @@ function checkJwtUploadTransformRes(docId, errorName, checkJwtRes){
|
|||||||
res.userid = edit.user.id;
|
res.userid = edit.user.id;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn('Error %s jwt: docId = %s\r\n%s', errorName, docId, 'access deny');
|
ctx.logger.warn('Error %s jwt: %s', errorName, 'access deny');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn('Error %s jwt: docId = %s\r\n%s', errorName, docId, checkJwtRes.description);
|
ctx.logger.warn('Error %s jwt: %s', errorName, checkJwtRes.description);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
exports.uploadImageFileOld = function(req, res) {
|
exports.uploadImageFileOld = function(req, res) {
|
||||||
|
return co(function* () {
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
|
ctx.initFromRequest(req);
|
||||||
var docId = req.params.docid;
|
var docId = req.params.docid;
|
||||||
logger.debug('Start uploadImageFileOld: docId = %s', docId);
|
|
||||||
var userid = req.params.userid;
|
var userid = req.params.userid;
|
||||||
|
ctx.init(ctx.tenant, docId, userid);
|
||||||
|
ctx.logger.debug('Start uploadImageFileOld');
|
||||||
if (cfgTokenEnableBrowser) {
|
if (cfgTokenEnableBrowser) {
|
||||||
var checkJwtRes = checkJwtUpload(docId, 'uploadImageFileOld', req.query['token']);
|
var checkJwtRes = yield* checkJwtUpload(ctx, 'uploadImageFileOld', req.query['token']);
|
||||||
if(!checkJwtRes.err){
|
if(!checkJwtRes.err){
|
||||||
docId = checkJwtRes.docId || docId;
|
docId = checkJwtRes.docId || docId;
|
||||||
userid = checkJwtRes.userid || userid;
|
userid = checkJwtRes.userid || userid;
|
||||||
@ -127,13 +135,14 @@ exports.uploadImageFileOld = function(req, res) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctx.init(ctx.tenant, docId, userid);
|
||||||
var listImages = [];
|
var listImages = [];
|
||||||
//todo userid
|
//todo userid
|
||||||
if (docId) {
|
if (docId) {
|
||||||
var isError = false;
|
var isError = false;
|
||||||
var form = new multiparty.Form();
|
var form = new multiparty.Form();
|
||||||
form.on('error', function(err) {
|
form.on('error', function(err) {
|
||||||
logger.error('Error parsing form: docId = %s\r\n%s', docId, err.toString());
|
ctx.logger.error('Error parsing form:%s', err.toString());
|
||||||
res.sendStatus(400);
|
res.sendStatus(400);
|
||||||
});
|
});
|
||||||
form.on('part', function(part) {
|
form.on('part', function(part) {
|
||||||
@ -153,25 +162,25 @@ exports.uploadImageFileOld = function(req, res) {
|
|||||||
var strPath = docId + '/media/' + strImageName + '.jpg';
|
var strPath = docId + '/media/' + strImageName + '.jpg';
|
||||||
listImages.push(strPath);
|
listImages.push(strPath);
|
||||||
utils.stream2Buffer(part).then(function(buffer) {
|
utils.stream2Buffer(part).then(function(buffer) {
|
||||||
return storageBase.putObject(strPath, buffer, buffer.length);
|
return storageBase.putObject(ctx, strPath, buffer, buffer.length);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
part.resume();
|
part.resume();
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
logger.error('Upload putObject: docId = %s\r\n%s', docId, err.stack);
|
ctx.logger.error('Upload putObject:%s', err.stack);
|
||||||
isError = true;
|
isError = true;
|
||||||
part.resume();
|
part.resume();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
part.on('error', function(err) {
|
part.on('error', function(err) {
|
||||||
logger.error('Error parsing form part: docId = %s\r\n%s', docId, err.toString());
|
ctx.logger.error('Error parsing form part:%s', err.toString());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
form.on('close', function() {
|
form.on('close', function() {
|
||||||
if (isError) {
|
if (isError) {
|
||||||
res.sendStatus(400);
|
res.sendStatus(400);
|
||||||
} else {
|
} else {
|
||||||
storageBase.getSignedUrlsByArray(utils.getBaseUrlByRequest(req), listImages, docId,
|
storageBase.getSignedUrlsByArray(ctx, utils.getBaseUrlByRequest(req), listImages, docId,
|
||||||
commonDefines.c_oAscUrlTypes.Session).then(function(urls) {
|
commonDefines.c_oAscUrlTypes.Session).then(function(urls) {
|
||||||
var outputData = {'type': 0, 'error': constants.NO_ERROR, 'urls': urls, 'input': req.query};
|
var outputData = {'type': 0, 'error': constants.NO_ERROR, 'urls': urls, 'input': req.query};
|
||||||
var output = '<html><head><script type="text/javascript">function load(){ parent.postMessage("';
|
var output = '<html><head><script type="text/javascript">function load(){ parent.postMessage("';
|
||||||
@ -181,19 +190,20 @@ exports.uploadImageFileOld = function(req, res) {
|
|||||||
//res.setHeader('Access-Control-Allow-Origin', '*');
|
//res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
res.setHeader('Content-Type', 'text/html');
|
res.setHeader('Content-Type', 'text/html');
|
||||||
res.send(output);
|
res.send(output);
|
||||||
logger.debug('End uploadImageFileOld: docId = %s %s', docId, output);
|
ctx.logger.debug('End uploadImageFileOld:%s', output);
|
||||||
}
|
}
|
||||||
).catch(function(err) {
|
).catch(function(err) {
|
||||||
res.sendStatus(400);
|
res.sendStatus(400);
|
||||||
logger.error('upload getSignedUrlsByArray: docId = %s\r\n%s', docId, err.stack);
|
ctx.logger.error('upload getSignedUrlsByArray:%s', err.stack);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
form.parse(req);
|
form.parse(req);
|
||||||
} else {
|
} else {
|
||||||
logger.debug('Error params uploadImageFileOld: docId = %s', docId);
|
ctx.logger.debug('Error params uploadImageFileOld');
|
||||||
res.sendStatus(400);
|
res.sendStatus(400);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
exports.uploadImageFile = function(req, res) {
|
exports.uploadImageFile = function(req, res) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
@ -201,18 +211,21 @@ exports.uploadImageFile = function(req, res) {
|
|||||||
var docId = 'null';
|
var docId = 'null';
|
||||||
let output = {};
|
let output = {};
|
||||||
let isValidJwt = true;
|
let isValidJwt = true;
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
|
ctx.initFromRequest(req);
|
||||||
docId = req.params.docid;
|
docId = req.params.docid;
|
||||||
|
ctx.setDocId(docId);
|
||||||
let encrypted = false;
|
let encrypted = false;
|
||||||
logger.debug('Start uploadImageFile: docId = %s', docId);
|
ctx.logger.debug('Start uploadImageFile');
|
||||||
|
|
||||||
if (cfgTokenEnableBrowser) {
|
if (cfgTokenEnableBrowser) {
|
||||||
let checkJwtRes = docsCoServer.checkJwtHeader(docId, req, 'Authorization', 'Bearer ', commonDefines.c_oAscSecretType.Session);
|
let checkJwtRes = yield docsCoServer.checkJwtHeader(ctx, req, 'Authorization', 'Bearer ', commonDefines.c_oAscSecretType.Session);
|
||||||
if (!checkJwtRes) {
|
if (!checkJwtRes) {
|
||||||
//todo remove compatibility with previous versions
|
//todo remove compatibility with previous versions
|
||||||
checkJwtRes = docsCoServer.checkJwt(docId, req.query['token'], commonDefines.c_oAscSecretType.Session);
|
checkJwtRes = yield docsCoServer.checkJwt(ctx, req.query['token'], commonDefines.c_oAscSecretType.Session);
|
||||||
}
|
}
|
||||||
let transformedRes = checkJwtUploadTransformRes(docId, 'uploadImageFile', checkJwtRes);
|
let transformedRes = checkJwtUploadTransformRes(ctx, 'uploadImageFile', checkJwtRes);
|
||||||
if (!transformedRes.err) {
|
if (!transformedRes.err) {
|
||||||
docId = transformedRes.docId || docId;
|
docId = transformedRes.docId || docId;
|
||||||
encrypted = transformedRes.encrypted;
|
encrypted = transformedRes.encrypted;
|
||||||
@ -220,11 +233,12 @@ exports.uploadImageFile = function(req, res) {
|
|||||||
isValidJwt = false;
|
isValidJwt = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctx.setDocId(docId);
|
||||||
|
|
||||||
if (isValidJwt && docId && req.body && Buffer.isBuffer(req.body)) {
|
if (isValidJwt && docId && req.body && Buffer.isBuffer(req.body)) {
|
||||||
let buffer = req.body;
|
let buffer = req.body;
|
||||||
if (buffer.length <= cfgImageSize) {
|
if (buffer.length <= cfgImageSize) {
|
||||||
var format = formatChecker.getImageFormat(buffer, undefined);
|
var format = formatChecker.getImageFormat(ctx, buffer);
|
||||||
var formatStr = formatChecker.getStringFromFormat(format);
|
var formatStr = formatChecker.getStringFromFormat(format);
|
||||||
if (encrypted && PATTERN_ENCRYPTED === buffer.toString('utf8', 0, PATTERN_ENCRYPTED.length)) {
|
if (encrypted && PATTERN_ENCRYPTED === buffer.toString('utf8', 0, PATTERN_ENCRYPTED.length)) {
|
||||||
formatStr = buffer.toString('utf8', PATTERN_ENCRYPTED.length, buffer.indexOf(';', PATTERN_ENCRYPTED.length));
|
formatStr = buffer.toString('utf8', PATTERN_ENCRYPTED.length, buffer.indexOf(';', PATTERN_ENCRYPTED.length));
|
||||||
@ -236,20 +250,20 @@ exports.uploadImageFile = function(req, res) {
|
|||||||
var strImageName = crypto.randomBytes(16).toString("hex");
|
var strImageName = crypto.randomBytes(16).toString("hex");
|
||||||
var strPathRel = 'media/' + strImageName + '.' + formatStr;
|
var strPathRel = 'media/' + strImageName + '.' + formatStr;
|
||||||
var strPath = docId + '/' + strPathRel;
|
var strPath = docId + '/' + strPathRel;
|
||||||
yield storageBase.putObject(strPath, buffer, buffer.length);
|
yield storageBase.putObject(ctx, strPath, buffer, buffer.length);
|
||||||
output[strPathRel] = yield storageBase.getSignedUrl(utils.getBaseUrlByRequest(req), strPath,
|
output[strPathRel] = yield storageBase.getSignedUrl(ctx, utils.getBaseUrlByRequest(req), strPath,
|
||||||
commonDefines.c_oAscUrlTypes.Session);
|
commonDefines.c_oAscUrlTypes.Session);
|
||||||
isError = false;
|
isError = false;
|
||||||
} else {
|
} else {
|
||||||
logger.debug('uploadImageFile format is not supported: docId = %s', docId);
|
ctx.logger.debug('uploadImageFile format is not supported');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.debug('uploadImageFile size limit exceeded: buffer.length = %d docId = %s', buffer.length, docId);
|
ctx.logger.debug('uploadImageFile size limit exceeded: buffer.length = %d', buffer.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
isError = true;
|
isError = true;
|
||||||
logger.error('Error uploadImageFile: docId = %s\r\n%s', docId, e.stack);
|
ctx.logger.error('Error uploadImageFile:%s', e.stack);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (!isError) {
|
if (!isError) {
|
||||||
@ -258,9 +272,9 @@ exports.uploadImageFile = function(req, res) {
|
|||||||
} else {
|
} else {
|
||||||
res.sendStatus(isValidJwt ? 400 : 403);
|
res.sendStatus(isValidJwt ? 400 : 403);
|
||||||
}
|
}
|
||||||
logger.debug('End uploadImageFile: isError = %s docId = %s', isError, docId);
|
ctx.logger.debug('End uploadImageFile: isError = %s', isError);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('Error uploadImageFile: docId = %s\r\n%s', docId, e.stack);
|
ctx.logger.error('Error uploadImageFile:%s', e.stack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -46,6 +46,7 @@ var logger = require('./../../Common/sources/logger');
|
|||||||
var constants = require('./../../Common/sources/constants');
|
var constants = require('./../../Common/sources/constants');
|
||||||
var commondefines = require('./../../Common/sources/commondefines');
|
var commondefines = require('./../../Common/sources/commondefines');
|
||||||
var queueService = require('./../../Common/sources/taskqueueRabbitMQ');
|
var queueService = require('./../../Common/sources/taskqueueRabbitMQ');
|
||||||
|
var operationContext = require('./../../Common/sources/operationContext');
|
||||||
var pubsubService = require('./pubsubRabbitMQ');
|
var pubsubService = require('./pubsubRabbitMQ');
|
||||||
|
|
||||||
var cfgExpFilesCron = config.get('expire.filesCron');
|
var cfgExpFilesCron = config.get('expire.filesCron');
|
||||||
@ -65,31 +66,36 @@ let expDocumentsStep = getCronStep(cfgExpDocumentsCron);
|
|||||||
|
|
||||||
var checkFileExpire = function() {
|
var checkFileExpire = function() {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
logger.debug('checkFileExpire start');
|
ctx.logger.info('checkFileExpire start');
|
||||||
|
let removedCount = 0;
|
||||||
var expired;
|
var expired;
|
||||||
var removedCount = 0;
|
|
||||||
var currentRemovedCount;
|
var currentRemovedCount;
|
||||||
do {
|
do {
|
||||||
currentRemovedCount = 0;
|
currentRemovedCount = 0;
|
||||||
expired = yield taskResult.getExpired(cfgExpFilesRemovedAtOnce, cfgExpFiles);
|
expired = yield taskResult.getExpired(ctx, cfgExpFilesRemovedAtOnce, cfgExpFiles);
|
||||||
for (var i = 0; i < expired.length; ++i) {
|
for (var i = 0; i < expired.length; ++i) {
|
||||||
var docId = expired[i].id;
|
let tenant = expired[i].tenant;
|
||||||
|
let docId = expired[i].id;
|
||||||
|
ctx.init(tenant, docId, ctx.userId);
|
||||||
|
//todo tenant
|
||||||
//проверяем что никто не сидит в документе
|
//проверяем что никто не сидит в документе
|
||||||
let editorsCount = yield docsCoServer.getEditorsCountPromise(docId);
|
let editorsCount = yield docsCoServer.getEditorsCountPromise(ctx, docId);
|
||||||
if(0 === editorsCount){
|
if(0 === editorsCount){
|
||||||
if (yield canvasService.cleanupCache(docId)) {
|
if (yield canvasService.cleanupCache(ctx)) {
|
||||||
currentRemovedCount++;
|
currentRemovedCount++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.debug('checkFileExpire expire but presence: editorsCount = %d; docId = %s', editorsCount, docId);
|
ctx.logger.debug('checkFileExpire expire but presence: editorsCount = %d', editorsCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removedCount += currentRemovedCount;
|
removedCount += currentRemovedCount;
|
||||||
} while (currentRemovedCount > 0);
|
} while (currentRemovedCount > 0);
|
||||||
logger.debug('checkFileExpire end: removedCount = %d', removedCount);
|
ctx.initDefault();
|
||||||
|
ctx.logger.info('checkFileExpire end: removedCount = %d', removedCount);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('checkFileExpire error:\r\n%s', e.stack);
|
ctx.logger.error('checkFileExpire error: %s', e.stack);
|
||||||
} finally {
|
} finally {
|
||||||
setTimeout(checkFileExpire, expFilesStep);
|
setTimeout(checkFileExpire, expFilesStep);
|
||||||
}
|
}
|
||||||
@ -100,8 +106,9 @@ var checkDocumentExpire = function() {
|
|||||||
var queue = null;
|
var queue = null;
|
||||||
var removedCount = 0;
|
var removedCount = 0;
|
||||||
var startSaveCount = 0;
|
var startSaveCount = 0;
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
logger.debug('checkDocumentExpire start');
|
ctx.logger.info('checkDocumentExpire start');
|
||||||
var now = (new Date()).getTime();
|
var now = (new Date()).getTime();
|
||||||
let expiredKeys = yield docsCoServer.editorData.getDocumentPresenceExpired(now);
|
let expiredKeys = yield docsCoServer.editorData.getDocumentPresenceExpired(now);
|
||||||
if (expiredKeys.length > 0) {
|
if (expiredKeys.length > 0) {
|
||||||
@ -109,30 +116,33 @@ var checkDocumentExpire = function() {
|
|||||||
yield queue.initPromise(true, false, false, false, false, false);
|
yield queue.initPromise(true, false, false, false, false, false);
|
||||||
|
|
||||||
for (var i = 0; i < expiredKeys.length; ++i) {
|
for (var i = 0; i < expiredKeys.length; ++i) {
|
||||||
var docId = expiredKeys[i];
|
let tenant = expiredKeys[i][0];
|
||||||
|
let docId = expiredKeys[i][1];
|
||||||
if (docId) {
|
if (docId) {
|
||||||
var hasChanges = yield docsCoServer.hasChanges(docId);
|
ctx.init(tenant, docId, ctx.userId);
|
||||||
|
var hasChanges = yield docsCoServer.hasChanges(ctx, docId);
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
yield docsCoServer.createSaveTimerPromise(docId, null, null, queue, true);
|
yield docsCoServer.createSaveTimer(ctx, docId, null, null, queue, true);
|
||||||
startSaveCount++;
|
startSaveCount++;
|
||||||
} else {
|
} else {
|
||||||
yield docsCoServer.cleanDocumentOnExitNoChangesPromise(docId);
|
yield docsCoServer.cleanDocumentOnExitNoChangesPromise(ctx, docId);
|
||||||
removedCount++;
|
removedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctx.initDefault();
|
||||||
|
ctx.logger.info('checkDocumentExpire end: startSaveCount = %d, removedCount = %d', startSaveCount, removedCount);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('checkDocumentExpire error:\r\n%s', e.stack);
|
ctx.logger.error('checkDocumentExpire error: %s', e.stack);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (queue) {
|
if (queue) {
|
||||||
yield queue.close();
|
yield queue.close();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('checkDocumentExpire error:\r\n%s', e.stack);
|
ctx.logger.error('checkDocumentExpire error: %s', e.stack);
|
||||||
}
|
}
|
||||||
logger.debug('checkDocumentExpire end: startSaveCount = %d, removedCount = %d', startSaveCount, removedCount);
|
|
||||||
setTimeout(checkDocumentExpire, expDocumentsStep);
|
setTimeout(checkDocumentExpire, expDocumentsStep);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -141,8 +151,9 @@ let forceSaveTimeout = function() {
|
|||||||
return co(function* () {
|
return co(function* () {
|
||||||
let queue = null;
|
let queue = null;
|
||||||
let pubsub = null;
|
let pubsub = null;
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
logger.debug('forceSaveTimeout start');
|
ctx.logger.info('forceSaveTimeout start');
|
||||||
let now = (new Date()).getTime();
|
let now = (new Date()).getTime();
|
||||||
let expiredKeys = yield docsCoServer.editorData.getForceSaveTimer(now);
|
let expiredKeys = yield docsCoServer.editorData.getForceSaveTimer(now);
|
||||||
if (expiredKeys.length > 0) {
|
if (expiredKeys.length > 0) {
|
||||||
@ -154,18 +165,21 @@ let forceSaveTimeout = function() {
|
|||||||
|
|
||||||
let actions = [];
|
let actions = [];
|
||||||
for (let i = 0; i < expiredKeys.length; ++i) {
|
for (let i = 0; i < expiredKeys.length; ++i) {
|
||||||
let docId = expiredKeys[i];
|
let tenant = expiredKeys[i][0];
|
||||||
|
let docId = expiredKeys[i][1];
|
||||||
if (docId) {
|
if (docId) {
|
||||||
actions.push(docsCoServer.startForceSave(docId, commondefines.c_oAscForceSaveTypes.Timeout,
|
ctx.init(tenant, docId, ctx.userId);
|
||||||
|
actions.push(docsCoServer.startForceSave(ctx, docId, commondefines.c_oAscForceSaveTypes.Timeout,
|
||||||
undefined, undefined, undefined, undefined, undefined, undefined, queue, pubsub));
|
undefined, undefined, undefined, undefined, undefined, undefined, queue, pubsub));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield Promise.all(actions);
|
yield Promise.all(actions);
|
||||||
logger.debug('forceSaveTimeout actions.length %d', actions.length);
|
ctx.logger.debug('forceSaveTimeout actions.length %d', actions.length);
|
||||||
}
|
}
|
||||||
logger.debug('forceSaveTimeout end');
|
ctx.initDefault();
|
||||||
|
ctx.logger.info('forceSaveTimeout end');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('forceSaveTimeout error:\r\n%s', e.stack);
|
ctx.logger.error('forceSaveTimeout error: %s', e.stack);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (queue) {
|
if (queue) {
|
||||||
@ -175,7 +189,7 @@ let forceSaveTimeout = function() {
|
|||||||
yield pubsub.close();
|
yield pubsub.close();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('checkDocumentExpire error:\r\n%s', e.stack);
|
ctx.logger.error('checkDocumentExpire error: %s', e.stack);
|
||||||
}
|
}
|
||||||
setTimeout(forceSaveTimeout, cfgForceSaveStep);
|
setTimeout(forceSaveTimeout, cfgForceSaveStep);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,22 +46,21 @@ var pool = mysql.createPool({
|
|||||||
timezone : 'Z',
|
timezone : 'Z',
|
||||||
flags : '-FOUND_ROWS'
|
flags : '-FOUND_ROWS'
|
||||||
});
|
});
|
||||||
var logger = require('./../../Common/sources/logger');
|
|
||||||
|
|
||||||
exports.sqlQuery = function (sqlCommand, callbackFunction, opt_noModifyRes, opt_noLog, opt_values) {
|
exports.sqlQuery = function (ctx, sqlCommand, callbackFunction, opt_noModifyRes, opt_noLog, opt_values) {
|
||||||
pool.getConnection(function(err, connection) {
|
pool.getConnection(function(err, connection) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error('pool.getConnection error: %s', err);
|
ctx.logger.error('pool.getConnection error: %s', err);
|
||||||
if (callbackFunction) callbackFunction(err, null);
|
if (callbackFunction) callbackFunction(err, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let queryCallback = function (error, result) {
|
let queryCallback = function (error, result) {
|
||||||
connection.release();
|
connection.release();
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error('________________________error_____________________');
|
ctx.logger.error('________________________error_____________________');
|
||||||
logger.error('sqlQuery: %s sqlCommand: %s', error.code, sqlCommand);
|
ctx.logger.error('sqlQuery: %s sqlCommand: %s', error.code, sqlCommand);
|
||||||
logger.error(error);
|
ctx.logger.error(error);
|
||||||
logger.error('_____________________end_error_____________________');
|
ctx.logger.error('_____________________end_error_____________________');
|
||||||
}
|
}
|
||||||
if (callbackFunction) callbackFunction(error, result);
|
if (callbackFunction) callbackFunction(error, result);
|
||||||
};
|
};
|
||||||
@ -82,7 +81,7 @@ let concatParams = function (val1, val2) {
|
|||||||
};
|
};
|
||||||
exports.concatParams = concatParams;
|
exports.concatParams = concatParams;
|
||||||
|
|
||||||
exports.upsert = function(task, opt_updateUserIndex) {
|
exports.upsert = function(ctx, task, opt_updateUserIndex) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
task.completeDefaults();
|
task.completeDefaults();
|
||||||
let dateNow = new Date();
|
let dateNow = new Date();
|
||||||
@ -93,6 +92,7 @@ exports.upsert = function(task, opt_updateUserIndex) {
|
|||||||
userCallback.fromValues(task.userIndex, task.callback);
|
userCallback.fromValues(task.userIndex, task.callback);
|
||||||
cbInsert = userCallback.toSQLInsert();
|
cbInsert = userCallback.toSQLInsert();
|
||||||
}
|
}
|
||||||
|
let p0 = addSqlParam(task.tenant, values);
|
||||||
let p1 = addSqlParam(task.key, values);
|
let p1 = addSqlParam(task.key, values);
|
||||||
let p2 = addSqlParam(task.status, values);
|
let p2 = addSqlParam(task.status, values);
|
||||||
let p3 = addSqlParam(task.statusInfo, values);
|
let p3 = addSqlParam(task.statusInfo, values);
|
||||||
@ -102,8 +102,8 @@ exports.upsert = function(task, opt_updateUserIndex) {
|
|||||||
let p7 = addSqlParam(cbInsert, values);
|
let p7 = addSqlParam(cbInsert, values);
|
||||||
let p8 = addSqlParam(task.baseurl, values);
|
let p8 = addSqlParam(task.baseurl, values);
|
||||||
let p9 = addSqlParam(dateNow, values);
|
let p9 = addSqlParam(dateNow, values);
|
||||||
var sqlCommand = 'INSERT INTO task_result (id, status, status_info, last_open_date, user_index, change_id, callback, baseurl)'+
|
var sqlCommand = 'INSERT INTO task_result (tenant, id, status, status_info, last_open_date, user_index, change_id, callback, baseurl)'+
|
||||||
` VALUES (${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8}) ON DUPLICATE KEY UPDATE` +
|
` VALUES (${p0}, ${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8}) ON DUPLICATE KEY UPDATE` +
|
||||||
` last_open_date = ${p9}`;
|
` last_open_date = ${p9}`;
|
||||||
if (task.callback) {
|
if (task.callback) {
|
||||||
let p10 = addSqlParam(JSON.stringify(task.callback), values);
|
let p10 = addSqlParam(JSON.stringify(task.callback), values);
|
||||||
@ -118,7 +118,7 @@ exports.upsert = function(task, opt_updateUserIndex) {
|
|||||||
}
|
}
|
||||||
sqlCommand += ';';
|
sqlCommand += ';';
|
||||||
|
|
||||||
exports.sqlQuery(sqlCommand, function(error, result) {
|
exports.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -62,11 +62,9 @@ types.setTypeParser(1184, function(stringValue) {
|
|||||||
return new Date(stringValue + '+0000');
|
return new Date(stringValue + '+0000');
|
||||||
});
|
});
|
||||||
|
|
||||||
var logger = require('./../../Common/sources/logger');
|
|
||||||
|
|
||||||
var maxPacketSize = configSql.get('max_allowed_packet');
|
var maxPacketSize = configSql.get('max_allowed_packet');
|
||||||
|
|
||||||
exports.sqlQuery = function(sqlCommand, callbackFunction, opt_noModifyRes, opt_noLog, opt_values) {
|
exports.sqlQuery = function(ctx, sqlCommand, callbackFunction, opt_noModifyRes, opt_noLog, opt_values) {
|
||||||
co(function *() {
|
co(function *() {
|
||||||
var result = null;
|
var result = null;
|
||||||
var error = null;
|
var error = null;
|
||||||
@ -75,7 +73,7 @@ exports.sqlQuery = function(sqlCommand, callbackFunction, opt_noModifyRes, opt_n
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
error = err;
|
error = err;
|
||||||
if (!opt_noLog) {
|
if (!opt_noLog) {
|
||||||
logger.warn('sqlQuery error sqlCommand: %s:\r\n%s', sqlCommand.slice(0, 50), err.stack);
|
ctx.logger.warn('sqlQuery error sqlCommand: %s: %s', sqlCommand.slice(0, 50), err.stack);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (callbackFunction) {
|
if (callbackFunction) {
|
||||||
@ -112,6 +110,7 @@ function getUpsertString(task, values) {
|
|||||||
userCallback.fromValues(task.userIndex, task.callback);
|
userCallback.fromValues(task.userIndex, task.callback);
|
||||||
cbInsert = userCallback.toSQLInsert();
|
cbInsert = userCallback.toSQLInsert();
|
||||||
}
|
}
|
||||||
|
let p0 = addSqlParam(task.tenant, values);
|
||||||
let p1 = addSqlParam(task.key, values);
|
let p1 = addSqlParam(task.key, values);
|
||||||
let p2 = addSqlParam(task.status, values);
|
let p2 = addSqlParam(task.status, values);
|
||||||
let p3 = addSqlParam(task.statusInfo, values);
|
let p3 = addSqlParam(task.statusInfo, values);
|
||||||
@ -123,9 +122,9 @@ function getUpsertString(task, values) {
|
|||||||
if (isSupportOnConflict) {
|
if (isSupportOnConflict) {
|
||||||
let p9 = addSqlParam(dateNow, values);
|
let p9 = addSqlParam(dateNow, values);
|
||||||
//http://stackoverflow.com/questions/34762732/how-to-find-out-if-an-upsert-was-an-update-with-postgresql-9-5-upsert
|
//http://stackoverflow.com/questions/34762732/how-to-find-out-if-an-upsert-was-an-update-with-postgresql-9-5-upsert
|
||||||
let sqlCommand = "INSERT INTO task_result (id, status, status_info, last_open_date, user_index, change_id, callback, baseurl)";
|
let sqlCommand = "INSERT INTO task_result (tenant, id, status, status_info, last_open_date, user_index, change_id, callback, baseurl)";
|
||||||
sqlCommand += ` VALUES (${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8})`;
|
sqlCommand += ` VALUES (${p0}, ${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8})`;
|
||||||
sqlCommand += ` ON CONFLICT (id) DO UPDATE SET last_open_date = ${p9}`;
|
sqlCommand += ` ON CONFLICT (tenant, id) DO UPDATE SET last_open_date = ${p9}`;
|
||||||
if (task.callback) {
|
if (task.callback) {
|
||||||
let p10 = addSqlParam(JSON.stringify(task.callback), values);
|
let p10 = addSqlParam(JSON.stringify(task.callback), values);
|
||||||
sqlCommand += `, callback = task_result.callback || '${sqlBase.UserCallback.prototype.delimiter}{"userIndex":' `;
|
sqlCommand += `, callback = task_result.callback || '${sqlBase.UserCallback.prototype.delimiter}{"userIndex":' `;
|
||||||
@ -138,20 +137,20 @@ function getUpsertString(task, values) {
|
|||||||
sqlCommand += ", user_index = task_result.user_index + 1 RETURNING user_index as userindex;";
|
sqlCommand += ", user_index = task_result.user_index + 1 RETURNING user_index as userindex;";
|
||||||
return sqlCommand;
|
return sqlCommand;
|
||||||
} else {
|
} else {
|
||||||
return `SELECT * FROM merge_db(${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8});`;
|
return `SELECT * FROM merge_db(${p0}, ${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8});`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.upsert = function(task) {
|
exports.upsert = function(ctx, task) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
var sqlCommand = getUpsertString(task, values);
|
var sqlCommand = getUpsertString(task, values);
|
||||||
exports.sqlQuery(sqlCommand, function(error, result) {
|
exports.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
if (isSupportOnConflict && '42601' === error.code) {
|
if (isSupportOnConflict && '42601' === error.code) {
|
||||||
//SYNTAX ERROR
|
//SYNTAX ERROR
|
||||||
isSupportOnConflict = false;
|
isSupportOnConflict = false;
|
||||||
logger.warn('checkIsSupportOnConflict false');
|
ctx.logger.warn('checkIsSupportOnConflict false');
|
||||||
resolve(exports.upsert(task));
|
resolve(exports.upsert(ctx, task));
|
||||||
} else {
|
} else {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
@ -167,12 +166,13 @@ exports.upsert = function(task) {
|
|||||||
}, true, undefined, values);
|
}, true, undefined, values);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.insertChanges = function(tableChanges, startIndex, objChanges, docId, index, user, callback) {
|
exports.insertChanges = function(ctx, tableChanges, startIndex, objChanges, docId, index, user, callback) {
|
||||||
let i = startIndex;
|
let i = startIndex;
|
||||||
if (i >= objChanges.length) {
|
if (i >= objChanges.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let isSupported = true;
|
let isSupported = true;
|
||||||
|
let tenant = [];
|
||||||
let id = [];
|
let id = [];
|
||||||
let changeId = [];
|
let changeId = [];
|
||||||
let userId = [];
|
let userId = [];
|
||||||
@ -181,27 +181,28 @@ exports.insertChanges = function(tableChanges, startIndex, objChanges, docId, in
|
|||||||
let change = [];
|
let change = [];
|
||||||
let time = [];
|
let time = [];
|
||||||
//Postgres 9.4 multi-argument unnest
|
//Postgres 9.4 multi-argument unnest
|
||||||
let sqlCommand = `INSERT INTO ${tableChanges} (id, change_id, user_id, user_id_original, user_name, change_data, change_date) `;
|
let sqlCommand = `INSERT INTO ${tableChanges} (tenant, id, change_id, user_id, user_id_original, user_name, change_data, change_date) `;
|
||||||
sqlCommand += "SELECT * FROM UNNEST ($1::text[], $2::int[], $3::text[], $4::text[], $5::text[], $6::text[], $7::timestamp[]);";
|
sqlCommand += "SELECT * FROM UNNEST ($1::text[], $2::text[], $3::int[], $4::text[], $5::text[], $6::text[], $7::text[], $8::timestamp[]);";
|
||||||
let values = [id, changeId, userId, userIdOriginal, username, change, time];
|
let values = [tenant, id, changeId, userId, userIdOriginal, username, change, time];
|
||||||
let curLength = sqlCommand.length;
|
let curLength = sqlCommand.length;
|
||||||
for (; i < objChanges.length; ++i) {
|
for (; i < objChanges.length; ++i) {
|
||||||
//4 is max utf8 bytes per symbol
|
//4 is max utf8 bytes per symbol
|
||||||
curLength += 4 * (docId.length + user.id.length + user.idOriginal.length + user.username.length + objChanges[i].change.length) + 4 + 8;
|
curLength += 4 * (docId.length + user.id.length + user.idOriginal.length + user.username.length + objChanges[i].change.length) + 4 + 8;
|
||||||
if (curLength >= maxPacketSize && i > startIndex) {
|
if (curLength >= maxPacketSize && i > startIndex) {
|
||||||
exports.sqlQuery(sqlCommand, function(error, output) {
|
exports.sqlQuery(ctx, sqlCommand, function(error, output) {
|
||||||
if (error && '42883' == error.code) {
|
if (error && '42883' == error.code) {
|
||||||
isSupported = false;
|
isSupported = false;
|
||||||
logger.warn('postgresql does not support UNNEST');
|
ctx.logger.warn('postgresql does not support UNNEST');
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(error, output, isSupported);
|
callback(error, output, isSupported);
|
||||||
} else {
|
} else {
|
||||||
exports.insertChanges(tableChanges, i, objChanges, docId, index, user, callback);
|
exports.insertChanges(ctx, tableChanges, i, objChanges, docId, index, user, callback);
|
||||||
}
|
}
|
||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
tenant.push(ctx.tenant);
|
||||||
id.push(docId);
|
id.push(docId);
|
||||||
changeId.push(index++);
|
changeId.push(index++);
|
||||||
userId.push(user.id);
|
userId.push(user.id);
|
||||||
@ -210,10 +211,10 @@ exports.insertChanges = function(tableChanges, startIndex, objChanges, docId, in
|
|||||||
change.push(objChanges[i].change);
|
change.push(objChanges[i].change);
|
||||||
time.push(objChanges[i].time);
|
time.push(objChanges[i].time);
|
||||||
}
|
}
|
||||||
exports.sqlQuery(sqlCommand, function(error, output) {
|
exports.sqlQuery(ctx, sqlCommand, function(error, output) {
|
||||||
if (error && '42883' == error.code) {
|
if (error && '42883' == error.code) {
|
||||||
isSupported = false;
|
isSupported = false;
|
||||||
logger.warn('postgresql does not support UNNEST');
|
ctx.logger.warn('postgresql does not support UNNEST');
|
||||||
}
|
}
|
||||||
callback(error, output, isSupported);
|
callback(error, output, isSupported);
|
||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
|
|||||||
@ -40,7 +40,6 @@ const commonDefines = require('./../../Common/sources/commondefines');
|
|||||||
var utils = require('./../../Common/sources/utils');
|
var utils = require('./../../Common/sources/utils');
|
||||||
var rabbitMQCore = require('./../../Common/sources/rabbitMQCore');
|
var rabbitMQCore = require('./../../Common/sources/rabbitMQCore');
|
||||||
var activeMQCore = require('./../../Common/sources/activeMQCore');
|
var activeMQCore = require('./../../Common/sources/activeMQCore');
|
||||||
const logger = require('./../../Common/sources/logger');
|
|
||||||
|
|
||||||
const cfgQueueType = config.get('queue.type');
|
const cfgQueueType = config.get('queue.type');
|
||||||
var cfgRabbitExchangePubSub = config.get('rabbitmq.exchangepubsub');
|
var cfgRabbitExchangePubSub = config.get('rabbitmq.exchangepubsub');
|
||||||
|
|||||||
@ -56,6 +56,8 @@ const wopiClient = require('./wopiClient');
|
|||||||
const constants = require('./../../Common/sources/constants');
|
const constants = require('./../../Common/sources/constants');
|
||||||
const utils = require('./../../Common/sources/utils');
|
const utils = require('./../../Common/sources/utils');
|
||||||
const commonDefines = require('./../../Common/sources/commondefines');
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
|
const operationContext = require('./../../Common/sources/operationContext');
|
||||||
|
const tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
const configStorage = configCommon.get('storage');
|
const configStorage = configCommon.get('storage');
|
||||||
|
|
||||||
const cfgWopiEnable = configCommon.get('wopi.enable');
|
const cfgWopiEnable = configCommon.get('wopi.enable');
|
||||||
@ -63,6 +65,7 @@ const cfgHtmlTemplate = configCommon.get('wopi.htmlTemplate');
|
|||||||
const cfgTokenEnableBrowser = configCommon.get('services.CoAuthoring.token.enable.browser');
|
const cfgTokenEnableBrowser = configCommon.get('services.CoAuthoring.token.enable.browser');
|
||||||
const cfgTokenEnableRequestInbox = configCommon.get('services.CoAuthoring.token.enable.request.inbox');
|
const cfgTokenEnableRequestInbox = configCommon.get('services.CoAuthoring.token.enable.request.inbox');
|
||||||
const cfgTokenEnableRequestOutbox = configCommon.get('services.CoAuthoring.token.enable.request.outbox');
|
const cfgTokenEnableRequestOutbox = configCommon.get('services.CoAuthoring.token.enable.request.outbox');
|
||||||
|
const cfgLicenseFile = configCommon.get('license.license_file');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.disable('x-powered-by');
|
app.disable('x-powered-by');
|
||||||
@ -74,45 +77,51 @@ const server = http.createServer(app);
|
|||||||
let licenseInfo, licenseOriginal, updatePluginsTime, userPlugins, pluginsLoaded;
|
let licenseInfo, licenseOriginal, updatePluginsTime, userPlugins, pluginsLoaded;
|
||||||
|
|
||||||
const updatePlugins = (eventType, filename) => {
|
const updatePlugins = (eventType, filename) => {
|
||||||
console.log('update Folder: %s ; %s', eventType, filename);
|
operationContext.global.logger.info('update Folder: %s ; %s', eventType, filename);
|
||||||
if (updatePluginsTime && 1000 >= (new Date() - updatePluginsTime)) {
|
if (updatePluginsTime && 1000 >= (new Date() - updatePluginsTime)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('update Folder true: %s ; %s', eventType, filename);
|
operationContext.global.logger.info('update Folder true: %s ; %s', eventType, filename);
|
||||||
updatePluginsTime = new Date();
|
updatePluginsTime = new Date();
|
||||||
pluginsLoaded = false;
|
pluginsLoaded = false;
|
||||||
};
|
};
|
||||||
const readLicense = function*() {
|
const readLicense = function*() {
|
||||||
[licenseInfo, licenseOriginal] = yield* license.readLicense();
|
[licenseInfo, licenseOriginal] = yield* license.readLicense(cfgLicenseFile);
|
||||||
};
|
};
|
||||||
const updateLicense = () => {
|
const updateLicense = () => {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
try {
|
try {
|
||||||
yield* readLicense();
|
yield* readLicense();
|
||||||
docsCoServer.setLicenseInfo(licenseInfo, licenseOriginal);
|
docsCoServer.setLicenseInfo(licenseInfo, licenseOriginal);
|
||||||
console.log('End updateLicense');
|
operationContext.global.logger.info('End updateLicense');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('updateLicense error:\r\n%s', err.stack);
|
operationContext.global.logger.error('updateLicense error: %s', err.stack);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.warn('Express server starting...');
|
operationContext.global.logger.warn('Express server starting...');
|
||||||
|
|
||||||
if (!(cfgTokenEnableBrowser && cfgTokenEnableRequestInbox && cfgTokenEnableRequestOutbox)) {
|
if (!(cfgTokenEnableBrowser && cfgTokenEnableRequestInbox && cfgTokenEnableRequestOutbox)) {
|
||||||
logger.warn('Set services.CoAuthoring.token.enable.browser, services.CoAuthoring.token.enable.request.inbox, ' +
|
operationContext.global.logger.warn('Set services.CoAuthoring.token.enable.browser, services.CoAuthoring.token.enable.request.inbox, ' +
|
||||||
'services.CoAuthoring.token.enable.request.outbox in the Document Server config ' +
|
'services.CoAuthoring.token.enable.request.outbox in the Document Server config ' +
|
||||||
'to prevent an unauthorized access to your documents and the substitution of important parameters in ONLYOFFICE Document Server requests.');
|
'to prevent an unauthorized access to your documents and the substitution of important parameters in ONLYOFFICE Document Server requests.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tenantManager.isMultitenantMode()) {
|
||||||
updateLicense();
|
updateLicense();
|
||||||
|
fs.watchFile(cfgLicenseFile, updateLicense);
|
||||||
|
setInterval(updateLicense, 86400000);
|
||||||
|
}
|
||||||
|
|
||||||
if (config.has('server.static_content')) {
|
if (config.has('server.static_content')) {
|
||||||
const staticContent = config.get('server.static_content');
|
const staticContent = config.get('server.static_content');
|
||||||
for (let i in staticContent) {
|
for (let i in staticContent) {
|
||||||
|
if (staticContent.hasOwnProperty(i)) {
|
||||||
app.use(i, express.static(staticContent[i]['path'], staticContent[i]['options']));
|
app.use(i, express.static(staticContent[i]['path'], staticContent[i]['options']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (configStorage.has('fs.folderPath')) {
|
if (configStorage.has('fs.folderPath')) {
|
||||||
const cfgBucketName = configStorage.get('bucketName');
|
const cfgBucketName = configStorage.get('bucketName');
|
||||||
@ -133,7 +142,7 @@ if (configStorage.has('fs.folderPath')) {
|
|||||||
const realUrl = req.url.substring(0, index);
|
const realUrl = req.url.substring(0, index);
|
||||||
res.sendFile(realUrl, sendFileOptions, (err) => {
|
res.sendFile(realUrl, sendFileOptions, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error(err);
|
operationContext.global.logger.error(err);
|
||||||
res.status(400).end();
|
res.status(400).end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -146,22 +155,24 @@ if (configStorage.has('fs.folderPath')) {
|
|||||||
try {
|
try {
|
||||||
fs.watch(config.get('plugins.path'), updatePlugins);
|
fs.watch(config.get('plugins.path'), updatePlugins);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn('Failed to subscribe to plugin folder updates. When changing the list of plugins, you must restart the server. https://nodejs.org/docs/latest/api/fs.html#fs_availability');
|
operationContext.global.logger.warn('Failed to subscribe to plugin folder updates. When changing the list of plugins, you must restart the server. https://nodejs.org/docs/latest/api/fs.html#fs_availability');
|
||||||
}
|
}
|
||||||
fs.watchFile(configCommon.get('license').get('license_file'), updateLicense);
|
|
||||||
setInterval(updateLicense, 86400000);
|
|
||||||
|
|
||||||
// Если захочется использовать 'development' и 'production',
|
// Если захочется использовать 'development' и 'production',
|
||||||
// то с помощью app.settings.env (https://github.com/strongloop/express/issues/936)
|
// то с помощью app.settings.env (https://github.com/strongloop/express/issues/936)
|
||||||
// Если нужна обработка ошибок, то теперь она такая https://github.com/expressjs/errorhandler
|
// Если нужна обработка ошибок, то теперь она такая https://github.com/expressjs/errorhandler
|
||||||
docsCoServer.install(server, () => {
|
docsCoServer.install(server, () => {
|
||||||
console.log('Start callbackFunction');
|
operationContext.global.logger.info('Start callbackFunction');
|
||||||
|
|
||||||
server.listen(config.get('server.port'), () => {
|
server.listen(config.get('server.port'), () => {
|
||||||
logger.warn("Express server listening on port %d in %s mode. Version: %s. Build: %s", config.get('server.port'), app.settings.env, commonDefines.buildVersion, commonDefines.buildNumber);
|
operationContext.global.logger.warn("Express server listening on port %d in %s mode. Version: %s. Build: %s", config.get('server.port'), app.settings.env, commonDefines.buildVersion, commonDefines.buildNumber);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/index.html', (req, res) => {
|
app.get('/index.html', (req, res) => {
|
||||||
|
return co(function*() {
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
|
ctx.initFromRequest(req);
|
||||||
|
let licenseInfo = yield tenantManager.getTenantLicense(ctx);
|
||||||
let buildVersion = commonDefines.buildVersion;
|
let buildVersion = commonDefines.buildVersion;
|
||||||
let buildNumber = commonDefines.buildNumber;
|
let buildNumber = commonDefines.buildNumber;
|
||||||
let buildDate, packageType, customerId = "";
|
let buildDate, packageType, customerId = "";
|
||||||
@ -174,6 +185,7 @@ docsCoServer.install(server, () => {
|
|||||||
output += `. Release date: ${buildDate}. Package type: ${packageType}. Customer Id: ${customerId}`;
|
output += `. Release date: ${buildDate}. Package type: ${packageType}. Customer Id: ${customerId}`;
|
||||||
res.send(output);
|
res.send(output);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
const rawFileParser = bodyParser.raw(
|
const rawFileParser = bodyParser.raw(
|
||||||
{inflate: true, limit: config.get('server.limits_tempfile_upload'), type: function() {return true;}});
|
{inflate: true, limit: config.get('server.limits_tempfile_upload'), type: function() {return true;}});
|
||||||
const urleEcodedParser = bodyParser.urlencoded({ extended: false });
|
const urleEcodedParser = bodyParser.urlencoded({ extended: false });
|
||||||
@ -237,7 +249,9 @@ docsCoServer.install(server, () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.post('/dummyCallback', utils.checkClientIp, rawFileParser, function(req, res){
|
app.post('/dummyCallback', utils.checkClientIp, rawFileParser, function(req, res){
|
||||||
logger.debug(`dummyCallback req.body:%s`, req.body);
|
let ctx = new operationContext.Context();
|
||||||
|
ctx.initFromRequest(req);
|
||||||
|
ctx.logger.debug(`dummyCallback req.body:%s`, req.body);
|
||||||
utils.fillResponseSimple(res, JSON.stringify({error: 0}, "application/json"));
|
utils.fillResponseSimple(res, JSON.stringify({error: 0}, "application/json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -292,8 +306,10 @@ docsCoServer.install(server, () => {
|
|||||||
app.get('/themes.json', apicache.middleware("5 minutes"), (req, res) => {
|
app.get('/themes.json', apicache.middleware("5 minutes"), (req, res) => {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
let themes = [];
|
let themes = [];
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
logger.info('themes.json start');
|
ctx.initFromRequest(req);
|
||||||
|
ctx.logger.info('themes.json start');
|
||||||
if (!config.has('server.static_content') || !config.has('themes.uri')) {
|
if (!config.has('server.static_content') || !config.has('themes.uri')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -305,8 +321,8 @@ docsCoServer.install(server, () => {
|
|||||||
if (staticContent.hasOwnProperty(i) && themesUri.startsWith(i)) {
|
if (staticContent.hasOwnProperty(i) && themesUri.startsWith(i)) {
|
||||||
let dir = staticContent[i].path + themesUri.substring(i.length);
|
let dir = staticContent[i].path + themesUri.substring(i.length);
|
||||||
themesList = yield utils.listObjects(dir, true);
|
themesList = yield utils.listObjects(dir, true);
|
||||||
logger.debug('themes.json dir:%s', dir);
|
ctx.logger.debug('themes.json dir:%s', dir);
|
||||||
logger.debug('themes.json themesList:%j', themesList);
|
ctx.logger.debug('themes.json themesList:%j', themesList);
|
||||||
for (let j = 0; j < themesList.length; ++j) {
|
for (let j = 0; j < themesList.length; ++j) {
|
||||||
if (themesList[j].endsWith('.json')) {
|
if (themesList[j].endsWith('.json')) {
|
||||||
let data = yield utils.readFile(themesList[j], true);
|
let data = yield utils.readFile(themesList[j], true);
|
||||||
@ -317,7 +333,7 @@ docsCoServer.install(server, () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('themes.json error:%s', err.stack);
|
ctx.logger.error('themes.json error:%s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
if (themes.length > 0) {
|
if (themes.length > 0) {
|
||||||
res.setHeader('Content-Type', 'application/json');
|
res.setHeader('Content-Type', 'application/json');
|
||||||
@ -325,15 +341,15 @@ docsCoServer.install(server, () => {
|
|||||||
} else {
|
} else {
|
||||||
res.sendStatus(404);
|
res.sendStatus(404);
|
||||||
}
|
}
|
||||||
logger.info('themes.json end');
|
ctx.logger.info('themes.json end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('uncaughtException', (err) => {
|
process.on('uncaughtException', (err) => {
|
||||||
logger.error((new Date).toUTCString() + ' uncaughtException:', err.message);
|
operationContext.global.logger.error((new Date).toUTCString() + ' uncaughtException:', err.message);
|
||||||
logger.error(err.stack);
|
operationContext.global.logger.error(err.stack);
|
||||||
logger.shutdown(() => {
|
logger.shutdown(() => {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -47,11 +47,11 @@ var WAIT_TIMEOUT = 30000;
|
|||||||
var LOOP_TIMEOUT = 1000;
|
var LOOP_TIMEOUT = 1000;
|
||||||
var EXEC_TIMEOUT = WAIT_TIMEOUT + utils.CONVERTION_TIMEOUT;
|
var EXEC_TIMEOUT = WAIT_TIMEOUT + utils.CONVERTION_TIMEOUT;
|
||||||
|
|
||||||
exports.shutdown = function(editorData, status) {
|
exports.shutdown = function(ctx, editorData, status) {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
var res = true;
|
var res = true;
|
||||||
try {
|
try {
|
||||||
logger.debug('shutdown start:' + EXEC_TIMEOUT);
|
ctx.logger.debug('shutdown start:' + EXEC_TIMEOUT);
|
||||||
|
|
||||||
//redisKeyShutdown не простой счетчик, чтобы его не уменьшала сборка, которая началась перед запуском Shutdown
|
//redisKeyShutdown не простой счетчик, чтобы его не уменьшала сборка, которая началась перед запуском Shutdown
|
||||||
//сбрасываем redisKeyShutdown на всякий случай, если предыдущий запуск не дошел до конца
|
//сбрасываем redisKeyShutdown на всякий случай, если предыдущий запуск не дошел до конца
|
||||||
@ -60,24 +60,24 @@ exports.shutdown = function(editorData, status) {
|
|||||||
var pubsub = new pubsubService();
|
var pubsub = new pubsubService();
|
||||||
yield pubsub.initPromise();
|
yield pubsub.initPromise();
|
||||||
//inner ping to update presence
|
//inner ping to update presence
|
||||||
logger.debug('shutdown pubsub shutdown message');
|
ctx.logger.debug('shutdown pubsub shutdown message');
|
||||||
pubsub.publish(JSON.stringify({type: commonDefines.c_oPublishType.shutdown, status: status}));
|
pubsub.publish(JSON.stringify({type: commonDefines.c_oPublishType.shutdown, ctx: ctx, status: status}));
|
||||||
//wait while pubsub deliver and start conversion
|
//wait while pubsub deliver and start conversion
|
||||||
logger.debug('shutdown start wait pubsub deliver');
|
ctx.logger.debug('shutdown start wait pubsub deliver');
|
||||||
var startTime = new Date().getTime();
|
var startTime = new Date().getTime();
|
||||||
var isStartWait = true;
|
var isStartWait = true;
|
||||||
while (true) {
|
while (true) {
|
||||||
var curTime = new Date().getTime() - startTime;
|
var curTime = new Date().getTime() - startTime;
|
||||||
if (isStartWait && curTime >= WAIT_TIMEOUT) {
|
if (isStartWait && curTime >= WAIT_TIMEOUT) {
|
||||||
isStartWait = false;
|
isStartWait = false;
|
||||||
logger.debug('shutdown stop wait pubsub deliver');
|
ctx.logger.debug('shutdown stop wait pubsub deliver');
|
||||||
} else if (curTime >= EXEC_TIMEOUT) {
|
} else if (curTime >= EXEC_TIMEOUT) {
|
||||||
res = false;
|
res = false;
|
||||||
logger.debug('shutdown timeout');
|
ctx.logger.debug('shutdown timeout');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var remainingFiles = yield editorData.getShutdownCount(redisKeyShutdown);
|
var remainingFiles = yield editorData.getShutdownCount(redisKeyShutdown);
|
||||||
logger.debug('shutdown remaining files:%d', remainingFiles);
|
ctx.logger.debug('shutdown remaining files:%d', remainingFiles);
|
||||||
if (!isStartWait && remainingFiles <= 0) {
|
if (!isStartWait && remainingFiles <= 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -88,10 +88,10 @@ exports.shutdown = function(editorData, status) {
|
|||||||
yield editorData.cleanupShutdown(redisKeyShutdown);
|
yield editorData.cleanupShutdown(redisKeyShutdown);
|
||||||
yield pubsub.close();
|
yield pubsub.close();
|
||||||
|
|
||||||
logger.debug('shutdown end');
|
ctx.logger.debug('shutdown end');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
res = false;
|
res = false;
|
||||||
logger.error('shutdown error:\r\n%s', e.stack);
|
ctx.logger.error('shutdown error: %s', e.stack);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -34,9 +34,9 @@
|
|||||||
|
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
var sqlBase = require('./baseConnector');
|
var sqlBase = require('./baseConnector');
|
||||||
var logger = require('./../../Common/sources/logger');
|
|
||||||
var utils = require('./../../Common/sources/utils');
|
var utils = require('./../../Common/sources/utils');
|
||||||
var constants = require('./../../Common/sources/constants');
|
var constants = require('./../../Common/sources/constants');
|
||||||
|
var tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
|
|
||||||
let addSqlParam = sqlBase.baseConnector.addSqlParameter;
|
let addSqlParam = sqlBase.baseConnector.addSqlParameter;
|
||||||
let concatParams = sqlBase.baseConnector.concatParams;
|
let concatParams = sqlBase.baseConnector.concatParams;
|
||||||
@ -56,6 +56,7 @@ var FileStatus = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function TaskResultData() {
|
function TaskResultData() {
|
||||||
|
this.tenant = null;
|
||||||
this.key = null;
|
this.key = null;
|
||||||
this.status = null;
|
this.status = null;
|
||||||
this.statusInfo = null;
|
this.statusInfo = null;
|
||||||
@ -71,6 +72,9 @@ function TaskResultData() {
|
|||||||
this.innerPasswordChange = null;//not a DB field
|
this.innerPasswordChange = null;//not a DB field
|
||||||
}
|
}
|
||||||
TaskResultData.prototype.completeDefaults = function() {
|
TaskResultData.prototype.completeDefaults = function() {
|
||||||
|
if (!this.tenant) {
|
||||||
|
this.tenant = tenantManager.getDefautTenant();
|
||||||
|
}
|
||||||
if (!this.key) {
|
if (!this.key) {
|
||||||
this.key = '';
|
this.key = '';
|
||||||
}
|
}
|
||||||
@ -100,16 +104,17 @@ TaskResultData.prototype.completeDefaults = function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function upsert(task, opt_updateUserIndex) {
|
function upsert(ctx, task, opt_updateUserIndex) {
|
||||||
return sqlBase.baseConnector.upsert(task, opt_updateUserIndex);
|
return sqlBase.baseConnector.upsert(ctx, task, opt_updateUserIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
function select(docId) {
|
function select(ctx, docId) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let sqlParam = addSqlParam(docId, values);
|
let p1 = addSqlParam(ctx.tenant, values);
|
||||||
let sqlCommand = `SELECT * FROM task_result WHERE id=${sqlParam};`;
|
let p2 = addSqlParam(docId, values);
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
let sqlCommand = `SELECT * FROM task_result WHERE tenant=${p1} AND id=${p2};`;
|
||||||
|
sqlBase.baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -170,14 +175,15 @@ function toUpdateArray(task, updateTime, isMask, values, setPassword) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(task, setPassword) {
|
function update(ctx, task, setPassword) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let updateElems = toUpdateArray(task, true, false, values, setPassword);
|
let updateElems = toUpdateArray(task, true, false, values, setPassword);
|
||||||
let sqlSet = updateElems.join(', ');
|
let sqlSet = updateElems.join(', ');
|
||||||
let sqlParam = addSqlParam(task.key, values);
|
let p1 = addSqlParam(task.tenant, values);
|
||||||
let sqlCommand = `UPDATE task_result SET ${sqlSet} WHERE id=${sqlParam};`;
|
let p2 = addSqlParam(task.key, values);
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
let sqlCommand = `UPDATE task_result SET ${sqlSet} WHERE tenant=${p1} AND id=${p2};`;
|
||||||
|
sqlBase.baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -187,16 +193,17 @@ function update(task, setPassword) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateIf(task, mask) {
|
function updateIf(ctx, task, mask) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let commandArg = toUpdateArray(task, true, false, values, false);
|
let commandArg = toUpdateArray(task, true, false, values, false);
|
||||||
let commandArgMask = toUpdateArray(mask, false, true, values, false);
|
let commandArgMask = toUpdateArray(mask, false, true, values, false);
|
||||||
|
commandArgMask.push('tenant=' + addSqlParam(mask.tenant, values));
|
||||||
commandArgMask.push('id=' + addSqlParam(mask.key, values));
|
commandArgMask.push('id=' + addSqlParam(mask.key, values));
|
||||||
let sqlSet = commandArg.join(', ');
|
let sqlSet = commandArg.join(', ');
|
||||||
let sqlWhere = commandArgMask.join(' AND ');
|
let sqlWhere = commandArgMask.join(' AND ');
|
||||||
let sqlCommand = `UPDATE task_result SET ${sqlSet} WHERE ${sqlWhere};`;
|
let sqlCommand = `UPDATE task_result SET ${sqlSet} WHERE ${sqlWhere};`;
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
sqlBase.baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -205,28 +212,30 @@ function updateIf(task, mask) {
|
|||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function restoreInitialPassword(docId) {
|
function restoreInitialPassword(ctx, docId) {
|
||||||
return select(docId).then(function(selectRes) {
|
return select(ctx, docId).then(function(selectRes) {
|
||||||
if (selectRes.length > 0) {
|
if (selectRes.length > 0) {
|
||||||
var row = selectRes[0];
|
var row = selectRes[0];
|
||||||
let docPassword = sqlBase.DocumentPassword.prototype.getDocPassword(docId, row.password);
|
let docPassword = sqlBase.DocumentPassword.prototype.getDocPassword(ctx, row.password);
|
||||||
var updateTask = new TaskResultData();
|
var updateTask = new TaskResultData();
|
||||||
|
updateTask.tenant = ctx.tenant;
|
||||||
updateTask.key = docId;
|
updateTask.key = docId;
|
||||||
if (docPassword.initial) {
|
if (docPassword.initial) {
|
||||||
var documentPassword = new sqlBase.DocumentPassword();
|
var documentPassword = new sqlBase.DocumentPassword();
|
||||||
documentPassword.fromValues(docPassword.initial);
|
documentPassword.fromValues(docPassword.initial);
|
||||||
updateTask.password = documentPassword.toSQLInsert();
|
updateTask.password = documentPassword.toSQLInsert();
|
||||||
return update(updateTask, true);
|
return update(ctx, updateTask, true);
|
||||||
} else if (docPassword.current) {
|
} else if (docPassword.current) {
|
||||||
updateTask.password = null;
|
updateTask.password = null;
|
||||||
return update(updateTask, true);
|
return update(ctx, updateTask, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRandomKey(task, opt_prefix, opt_size) {
|
function addRandomKey(ctx, task, opt_prefix, opt_size) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
|
task.tenant = ctx.tenant;
|
||||||
if (undefined !== opt_prefix && undefined !== opt_size) {
|
if (undefined !== opt_prefix && undefined !== opt_size) {
|
||||||
task.key = opt_prefix + crypto.randomBytes(opt_size).toString("hex");
|
task.key = opt_prefix + crypto.randomBytes(opt_size).toString("hex");
|
||||||
} else {
|
} else {
|
||||||
@ -234,6 +243,7 @@ function addRandomKey(task, opt_prefix, opt_size) {
|
|||||||
}
|
}
|
||||||
task.completeDefaults();
|
task.completeDefaults();
|
||||||
let values = [];
|
let values = [];
|
||||||
|
let p0 = addSqlParam(task.tenant, values);
|
||||||
let p1 = addSqlParam(task.key, values);
|
let p1 = addSqlParam(task.key, values);
|
||||||
let p2 = addSqlParam(task.status, values);
|
let p2 = addSqlParam(task.status, values);
|
||||||
let p3 = addSqlParam(task.statusInfo, values);
|
let p3 = addSqlParam(task.statusInfo, values);
|
||||||
@ -242,9 +252,9 @@ function addRandomKey(task, opt_prefix, opt_size) {
|
|||||||
let p6 = addSqlParam(task.changeId, values);
|
let p6 = addSqlParam(task.changeId, values);
|
||||||
let p7 = addSqlParam(task.callback, values);
|
let p7 = addSqlParam(task.callback, values);
|
||||||
let p8 = addSqlParam(task.baseurl, values);
|
let p8 = addSqlParam(task.baseurl, values);
|
||||||
let sqlCommand = 'INSERT INTO task_result (id, status, status_info, last_open_date, user_index, change_id, callback, baseurl)' +
|
let sqlCommand = 'INSERT INTO task_result (tenant, id, status, status_info, last_open_date, user_index, change_id, callback, baseurl)' +
|
||||||
` VALUES (${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8});`;
|
` VALUES (${p0}, ${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8});`;
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
sqlBase.baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -253,8 +263,9 @@ function addRandomKey(task, opt_prefix, opt_size) {
|
|||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function* addRandomKeyTask(key, opt_prefix, opt_size) {
|
function* addRandomKeyTask(ctx, key, opt_prefix, opt_size) {
|
||||||
var task = new TaskResultData();
|
var task = new TaskResultData();
|
||||||
|
task.tenant = ctx.tenant;
|
||||||
task.key = key;
|
task.key = key;
|
||||||
task.status = FileStatus.WaitQueue;
|
task.status = FileStatus.WaitQueue;
|
||||||
//nTryCount чтобы не зависнуть если реально будут проблемы с DB
|
//nTryCount чтобы не зависнуть если реально будут проблемы с DB
|
||||||
@ -262,7 +273,7 @@ function* addRandomKeyTask(key, opt_prefix, opt_size) {
|
|||||||
var addRes = null;
|
var addRes = null;
|
||||||
while (nTryCount-- > 0) {
|
while (nTryCount-- > 0) {
|
||||||
try {
|
try {
|
||||||
addRes = yield addRandomKey(task, opt_prefix, opt_size);
|
addRes = yield addRandomKey(ctx, task, opt_prefix, opt_size);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
addRes = null;
|
addRes = null;
|
||||||
//key exist, try again
|
//key exist, try again
|
||||||
@ -278,12 +289,13 @@ function* addRandomKeyTask(key, opt_prefix, opt_size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove(docId) {
|
function remove(ctx, docId) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let sqlParam = addSqlParam(docId, values);
|
let p1 = addSqlParam(ctx.tenant, values);
|
||||||
const sqlCommand = `DELETE FROM task_result WHERE id=${sqlParam};`;
|
let p2 = addSqlParam(docId, values);
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
const sqlCommand = `DELETE FROM task_result WHERE tenant=${p1} AND id=${p2};`;
|
||||||
|
sqlBase.baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -292,14 +304,15 @@ function remove(docId) {
|
|||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function removeIf(mask) {
|
function removeIf(ctx, mask) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let commandArgMask = toUpdateArray(mask, false, true, values, false);
|
let commandArgMask = toUpdateArray(mask, false, true, values, false);
|
||||||
|
commandArgMask.push('tenant=' + addSqlParam(mask.tenant, values));
|
||||||
commandArgMask.push('id=' + addSqlParam(mask.key, values));
|
commandArgMask.push('id=' + addSqlParam(mask.key, values));
|
||||||
let sqlWhere = commandArgMask.join(' AND ');
|
let sqlWhere = commandArgMask.join(' AND ');
|
||||||
const sqlCommand = `DELETE FROM task_result WHERE ${sqlWhere};`;
|
const sqlCommand = `DELETE FROM task_result WHERE ${sqlWhere};`;
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
sqlBase.baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
@ -308,7 +321,7 @@ function removeIf(mask) {
|
|||||||
}, undefined, undefined, values);
|
}, undefined, undefined, values);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function getExpired(maxCount, expireSeconds) {
|
function getExpired(ctx, maxCount, expireSeconds) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
let values = [];
|
let values = [];
|
||||||
let expireDate = new Date();
|
let expireDate = new Date();
|
||||||
@ -316,8 +329,8 @@ function getExpired(maxCount, expireSeconds) {
|
|||||||
let sqlParam1 = addSqlParam(expireDate, values);
|
let sqlParam1 = addSqlParam(expireDate, values);
|
||||||
let sqlParam2 = addSqlParam(maxCount, values);
|
let sqlParam2 = addSqlParam(maxCount, values);
|
||||||
let sqlCommand = `SELECT * FROM task_result WHERE last_open_date <= ${sqlParam1}` +
|
let sqlCommand = `SELECT * FROM task_result WHERE last_open_date <= ${sqlParam1}` +
|
||||||
` AND NOT EXISTS(SELECT id FROM doc_changes WHERE doc_changes.id = task_result.id LIMIT 1) LIMIT ${sqlParam2};`;
|
` AND NOT EXISTS(SELECT tenant, id FROM doc_changes WHERE doc_changes.tenant = task_result.tenant AND doc_changes.id = task_result.id LIMIT 1) LIMIT ${sqlParam2};`;
|
||||||
sqlBase.baseConnector.sqlQuery(sqlCommand, function(error, result) {
|
sqlBase.baseConnector.sqlQuery(ctx, sqlCommand, function(error, result) {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -44,13 +44,14 @@ const logger = require('./../../Common/sources/logger');
|
|||||||
const utils = require('./../../Common/sources/utils');
|
const utils = require('./../../Common/sources/utils');
|
||||||
const constants = require('./../../Common/sources/constants');
|
const constants = require('./../../Common/sources/constants');
|
||||||
const commonDefines = require('./../../Common/sources/commondefines');
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
|
const operationContext = require('./../../Common/sources/operationContext');
|
||||||
|
const tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
const sqlBase = require('./baseConnector');
|
const sqlBase = require('./baseConnector');
|
||||||
const taskResult = require('./taskresult');
|
const taskResult = require('./taskresult');
|
||||||
const canvasService = require('./canvasservice');
|
const canvasService = require('./canvasservice');
|
||||||
|
|
||||||
const cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm');
|
const cfgTokenOutboxAlgorithm = config.get('services.CoAuthoring.token.outbox.algorithm');
|
||||||
const cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires');
|
const cfgTokenOutboxExpires = config.get('services.CoAuthoring.token.outbox.expires');
|
||||||
const cfgSignatureSecretOutbox = config.get('services.CoAuthoring.secret.outbox');
|
|
||||||
const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser');
|
const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser');
|
||||||
const cfgCallbackRequestTimeout = config.get('services.CoAuthoring.server.callbackRequestTimeout');
|
const cfgCallbackRequestTimeout = config.get('services.CoAuthoring.server.callbackRequestTimeout');
|
||||||
const cfgDownloadTimeout = config.get('FileConverter.converter.downloadTimeout');
|
const cfgDownloadTimeout = config.get('FileConverter.converter.downloadTimeout');
|
||||||
@ -97,8 +98,10 @@ let mimeTypesByExt = (function() {
|
|||||||
function discovery(req, res) {
|
function discovery(req, res) {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
let output = '';
|
let output = '';
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
logger.info('wopiDiscovery start');
|
ctx.initFromRequest(req);
|
||||||
|
ctx.logger.info('wopiDiscovery start');
|
||||||
let baseUrl = cfgWopiHost || utils.getBaseUrlByRequest(req);
|
let baseUrl = cfgWopiHost || utils.getBaseUrlByRequest(req);
|
||||||
let names = ['Word','Excel','PowerPoint'];
|
let names = ['Word','Excel','PowerPoint'];
|
||||||
let favIconUrls = [cfgWopiFavIconUrlWord, cfgWopiFavIconUrlCell, cfgWopiFavIconUrlSlide];
|
let favIconUrls = [cfgWopiFavIconUrlWord, cfgWopiFavIconUrlCell, cfgWopiFavIconUrlSlide];
|
||||||
@ -179,11 +182,11 @@ function discovery(req, res) {
|
|||||||
}
|
}
|
||||||
output += `</net-zone>${proofKey}</wopi-discovery>`;
|
output += `</net-zone>${proofKey}</wopi-discovery>`;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('wopiDiscovery error:%s', err.stack);
|
ctx.logger.error('wopiDiscovery error:%s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
res.setHeader('Content-Type', 'text/xml');
|
res.setHeader('Content-Type', 'text/xml');
|
||||||
res.send(output);
|
res.send(output);
|
||||||
logger.info('wopiDiscovery end');
|
ctx.logger.info('wopiDiscovery end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -193,13 +196,15 @@ function collaboraCapabilities(req, res) {
|
|||||||
"convert-to": {"available": false}, "hasMobileSupport": true, "hasProxyPrefix": false, "hasTemplateSaveAs": false,
|
"convert-to": {"available": false}, "hasMobileSupport": true, "hasProxyPrefix": false, "hasTemplateSaveAs": false,
|
||||||
"hasTemplateSource": true, "productVersion": commonDefines.buildVersion
|
"hasTemplateSource": true, "productVersion": commonDefines.buildVersion
|
||||||
};
|
};
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
logger.info('collaboraCapabilities start');
|
ctx.initFromRequest(req);
|
||||||
|
ctx.logger.info('collaboraCapabilities start');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('collaboraCapabilities error:%s', err.stack);
|
ctx.logger.error('collaboraCapabilities error:%s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
utils.fillResponseSimple(res, JSON.stringify(output), "application/json");
|
utils.fillResponseSimple(res, JSON.stringify(output), "application/json");
|
||||||
logger.info('collaboraCapabilities end');
|
ctx.logger.info('collaboraCapabilities end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -233,7 +238,7 @@ function getLastModifiedTimeFromCallbacks(callbacks) {
|
|||||||
function isCorrectUserAuth(userAuth) {
|
function isCorrectUserAuth(userAuth) {
|
||||||
return undefined !== userAuth.wopiSrc;
|
return undefined !== userAuth.wopiSrc;
|
||||||
}
|
}
|
||||||
function parseWopiCallback(docId, userAuthStr, opt_url) {
|
function parseWopiCallback(ctx, userAuthStr, opt_url) {
|
||||||
let wopiParams = null;
|
let wopiParams = null;
|
||||||
if (isWopiCallback(userAuthStr)) {
|
if (isWopiCallback(userAuthStr)) {
|
||||||
let userAuth = JSON.parse(userAuthStr);
|
let userAuth = JSON.parse(userAuthStr);
|
||||||
@ -243,58 +248,59 @@ function parseWopiCallback(docId, userAuthStr, opt_url) {
|
|||||||
let commonInfo = null;
|
let commonInfo = null;
|
||||||
let lastModifiedTime = null;
|
let lastModifiedTime = null;
|
||||||
if (opt_url) {
|
if (opt_url) {
|
||||||
let commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(docId, opt_url, 1);
|
let commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, opt_url, 1);
|
||||||
if (isWopiCallback(commonInfoStr)) {
|
if (isWopiCallback(commonInfoStr)) {
|
||||||
commonInfo = JSON.parse(commonInfoStr);
|
commonInfo = JSON.parse(commonInfoStr);
|
||||||
lastModifiedTime = commonInfo.fileInfo.LastModifiedTime;
|
lastModifiedTime = commonInfo.fileInfo.LastModifiedTime;
|
||||||
if (lastModifiedTime) {
|
if (lastModifiedTime) {
|
||||||
let callbacks = sqlBase.UserCallback.prototype.getCallbacks(docId, opt_url);
|
let callbacks = sqlBase.UserCallback.prototype.getCallbacks(ctx, opt_url);
|
||||||
lastModifiedTime = getLastModifiedTimeFromCallbacks(callbacks);
|
lastModifiedTime = getLastModifiedTimeFromCallbacks(callbacks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wopiParams = {commonInfo: commonInfo, userAuth: userAuth, LastModifiedTime: lastModifiedTime};
|
wopiParams = {commonInfo: commonInfo, userAuth: userAuth, LastModifiedTime: lastModifiedTime};
|
||||||
logger.debug('parseWopiCallback wopiParams:%j', wopiParams);
|
ctx.logger.debug('parseWopiCallback wopiParams:%j', wopiParams);
|
||||||
}
|
}
|
||||||
return wopiParams;
|
return wopiParams;
|
||||||
}
|
}
|
||||||
function checkAndInvalidateCache(docId, fileInfo) {
|
function checkAndInvalidateCache(ctx, docId, fileInfo) {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
let res = {success: true, lockId: undefined};
|
let res = {success: true, lockId: undefined};
|
||||||
let selectRes = yield taskResult.select(docId);
|
let selectRes = yield taskResult.select(ctx, docId);
|
||||||
if (selectRes.length > 0) {
|
if (selectRes.length > 0) {
|
||||||
let row = selectRes[0];
|
let row = selectRes[0];
|
||||||
if (row.callback) {
|
if (row.callback) {
|
||||||
let commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(docId, row.callback, 1);
|
let commonInfoStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback, 1);
|
||||||
if (isWopiCallback(commonInfoStr)) {
|
if (isWopiCallback(commonInfoStr)) {
|
||||||
let commonInfo = JSON.parse(commonInfoStr);
|
let commonInfo = JSON.parse(commonInfoStr);
|
||||||
res.lockId = commonInfo.lockId;
|
res.lockId = commonInfo.lockId;
|
||||||
logger.debug('wopiEditor lockId from DB lockId=%s', res.lockId);
|
ctx.logger.debug('wopiEditor lockId from DB lockId=%s', res.lockId);
|
||||||
let unlockMarkStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(docId, row.callback);
|
let unlockMarkStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
||||||
logger.debug('wopiEditor commonInfoStr=%s', commonInfoStr);
|
ctx.logger.debug('wopiEditor commonInfoStr=%s', commonInfoStr);
|
||||||
logger.debug('wopiEditor unlockMarkStr=%s', unlockMarkStr);
|
ctx.logger.debug('wopiEditor unlockMarkStr=%s', unlockMarkStr);
|
||||||
let hasUnlockMarker = isWopiUnlockMarker(unlockMarkStr);
|
let hasUnlockMarker = isWopiUnlockMarker(unlockMarkStr);
|
||||||
logger.debug('wopiEditor hasUnlockMarker=%s', hasUnlockMarker);
|
ctx.logger.debug('wopiEditor hasUnlockMarker=%s', hasUnlockMarker);
|
||||||
if (hasUnlockMarker) {
|
if (hasUnlockMarker) {
|
||||||
let fileInfoVersion = fileInfo.Version;
|
let fileInfoVersion = fileInfo.Version;
|
||||||
let cacheVersion = commonInfo.fileInfo.Version;
|
let cacheVersion = commonInfo.fileInfo.Version;
|
||||||
let fileInfoModified = fileInfo.LastModifiedTime;
|
let fileInfoModified = fileInfo.LastModifiedTime;
|
||||||
let cacheModified = commonInfo.fileInfo.LastModifiedTime;
|
let cacheModified = commonInfo.fileInfo.LastModifiedTime;
|
||||||
logger.debug('wopiEditor version fileInfo=%s; cache=%s', fileInfoVersion, cacheVersion);
|
ctx.logger.debug('wopiEditor version fileInfo=%s; cache=%s', fileInfoVersion, cacheVersion);
|
||||||
logger.debug('wopiEditor LastModifiedTime fileInfo=%s; cache=%s', fileInfoModified, cacheModified);
|
ctx.logger.debug('wopiEditor LastModifiedTime fileInfo=%s; cache=%s', fileInfoModified, cacheModified);
|
||||||
if (fileInfoVersion !== cacheVersion || (fileInfoModified !== cacheModified)) {
|
if (fileInfoVersion !== cacheVersion || (fileInfoModified !== cacheModified)) {
|
||||||
var mask = new taskResult.TaskResultData();
|
var mask = new taskResult.TaskResultData();
|
||||||
|
mask.tenant = ctx.tenant;
|
||||||
mask.key = docId;
|
mask.key = docId;
|
||||||
mask.last_open_date = row.last_open_date;
|
mask.last_open_date = row.last_open_date;
|
||||||
//cleanupRes can be false in case of simultaneous opening. it is OK
|
//cleanupRes can be false in case of simultaneous opening. it is OK
|
||||||
let cleanupRes = yield canvasService.cleanupCacheIf(mask);
|
let cleanupRes = yield canvasService.cleanupCacheIf(ctx, mask);
|
||||||
logger.debug('wopiEditor cleanupRes=%s', cleanupRes);
|
ctx.logger.debug('wopiEditor cleanupRes=%s', cleanupRes);
|
||||||
res.lockId = undefined;
|
res.lockId = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
res.success = false;
|
res.success = false;
|
||||||
logger.warn('wopiEditor attempt to open not wopi record');
|
ctx.logger.warn('wopiEditor attempt to open not wopi record');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -304,14 +310,19 @@ function checkAndInvalidateCache(docId, fileInfo) {
|
|||||||
function getEditorHtml(req, res) {
|
function getEditorHtml(req, res) {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
let params = {key: undefined, fileInfo: {}, userAuth: {}, queryParams: req.query, token: undefined, documentType: undefined};
|
let params = {key: undefined, fileInfo: {}, userAuth: {}, queryParams: req.query, token: undefined, documentType: undefined};
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
logger.info('wopiEditor start');
|
ctx.initFromRequest(req);
|
||||||
logger.debug(`wopiEditor req.url:%s`, req.url);
|
let wopiSrc = req.query['wopisrc'];
|
||||||
logger.debug(`wopiEditor req.query:%j`, req.query);
|
let fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||||
logger.debug(`wopiEditor req.body:%j`, req.body);
|
ctx.setDocId(fileId);
|
||||||
|
|
||||||
|
ctx.logger.info('wopiEditor start');
|
||||||
|
ctx.logger.debug(`wopiEditor req.url:%s`, req.url);
|
||||||
|
ctx.logger.debug(`wopiEditor req.query:%j`, req.query);
|
||||||
|
ctx.logger.debug(`wopiEditor req.body:%j`, req.body);
|
||||||
params.documentType = req.params.documentType;
|
params.documentType = req.params.documentType;
|
||||||
let mode = req.params.mode;
|
let mode = req.params.mode;
|
||||||
let wopiSrc = req.query['wopisrc'];
|
|
||||||
let sc = req.query['sc'];
|
let sc = req.query['sc'];
|
||||||
let hostSessionId = req.query['hid'];
|
let hostSessionId = req.query['hid'];
|
||||||
let access_token = req.body['access_token'] || "";
|
let access_token = req.body['access_token'] || "";
|
||||||
@ -319,7 +330,7 @@ function getEditorHtml(req, res) {
|
|||||||
|
|
||||||
let uri = `${encodeURI(wopiSrc)}?access_token=${encodeURIComponent(access_token)}`;
|
let uri = `${encodeURI(wopiSrc)}?access_token=${encodeURIComponent(access_token)}`;
|
||||||
|
|
||||||
let fileInfo = params.fileInfo = yield checkFileInfo(uri, access_token, sc);
|
let fileInfo = params.fileInfo = yield checkFileInfo(ctx, uri, access_token, sc);
|
||||||
if (!fileInfo) {
|
if (!fileInfo) {
|
||||||
params.fileInfo = {};
|
params.fileInfo = {};
|
||||||
return;
|
return;
|
||||||
@ -330,7 +341,6 @@ function getEditorHtml(req, res) {
|
|||||||
}
|
}
|
||||||
//docId
|
//docId
|
||||||
let docId = undefined;
|
let docId = undefined;
|
||||||
let fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
|
||||||
if ('view' !== mode) {
|
if ('view' !== mode) {
|
||||||
docId = `${fileId}`;
|
docId = `${fileId}`;
|
||||||
} else {
|
} else {
|
||||||
@ -344,7 +354,7 @@ function getEditorHtml(req, res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
docId = docId.replace(constants.DOC_ID_REPLACE_REGEX, '_').substring(0, constants.DOC_ID_MAX_LENGTH);
|
docId = docId.replace(constants.DOC_ID_REPLACE_REGEX, '_').substring(0, constants.DOC_ID_MAX_LENGTH);
|
||||||
logger.debug(`wopiEditor docId=%s`, docId);
|
ctx.logger.debug(`wopiEditor`);
|
||||||
params.key = docId;
|
params.key = docId;
|
||||||
let userAuth = params.userAuth = {
|
let userAuth = params.userAuth = {
|
||||||
wopiSrc: wopiSrc, access_token: access_token, access_token_ttl: access_token_ttl,
|
wopiSrc: wopiSrc, access_token: access_token, access_token_ttl: access_token_ttl,
|
||||||
@ -352,7 +362,7 @@ function getEditorHtml(req, res) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//check and invalidate cache
|
//check and invalidate cache
|
||||||
let checkRes = yield checkAndInvalidateCache(docId, fileInfo);
|
let checkRes = yield checkAndInvalidateCache(ctx, docId, fileInfo);
|
||||||
let lockId = checkRes.lockId;
|
let lockId = checkRes.lockId;
|
||||||
if (!checkRes.success) {
|
if (!checkRes.success) {
|
||||||
params.fileInfo = {};
|
params.fileInfo = {};
|
||||||
@ -364,12 +374,12 @@ function getEditorHtml(req, res) {
|
|||||||
fileType = fileInfo.FileExtension ? fileInfo.FileExtension.substr(1) : fileType;
|
fileType = fileInfo.FileExtension ? fileInfo.FileExtension.substr(1) : fileType;
|
||||||
lockId = crypto.randomBytes(16).toString('base64');
|
lockId = crypto.randomBytes(16).toString('base64');
|
||||||
let commonInfo = JSON.stringify({lockId: lockId, fileInfo: fileInfo});
|
let commonInfo = JSON.stringify({lockId: lockId, fileInfo: fileInfo});
|
||||||
yield canvasService.commandOpenStartPromise(docId, utils.getBaseUrlByRequest(req), 1, commonInfo, fileType);
|
yield canvasService.commandOpenStartPromise(ctx, docId, utils.getBaseUrlByRequest(req), 1, commonInfo, fileType);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Lock
|
//Lock
|
||||||
if ('view' !== mode) {
|
if ('view' !== mode) {
|
||||||
let lockRes = yield lock('LOCK', lockId, fileInfo, userAuth);
|
let lockRes = yield lock(ctx, 'LOCK', lockId, fileInfo, userAuth);
|
||||||
if (!lockRes) {
|
if (!lockRes) {
|
||||||
params.fileInfo = {};
|
params.fileInfo = {};
|
||||||
return;
|
return;
|
||||||
@ -384,36 +394,36 @@ function getEditorHtml(req, res) {
|
|||||||
|
|
||||||
if (cfgTokenEnableBrowser) {
|
if (cfgTokenEnableBrowser) {
|
||||||
let options = {algorithm: cfgTokenOutboxAlgorithm, expiresIn: cfgTokenOutboxExpires};
|
let options = {algorithm: cfgTokenOutboxAlgorithm, expiresIn: cfgTokenOutboxExpires};
|
||||||
let secret = utils.getSecretByElem(cfgSignatureSecretOutbox);
|
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Inbox);
|
||||||
params.token = jwt.sign(params, secret, options);
|
params.token = jwt.sign(params, secret, options);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('wopiEditor error:%s', err.stack);
|
ctx.logger.error('wopiEditor error:%s', err.stack);
|
||||||
params.fileInfo = {};
|
params.fileInfo = {};
|
||||||
} finally {
|
} finally {
|
||||||
logger.debug('wopiEditor render params=%j', params);
|
ctx.logger.debug('wopiEditor render params=%j', params);
|
||||||
try {
|
try {
|
||||||
res.render("editor-wopi", params);
|
res.render("editor-wopi", params);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('wopiEditor error:%s', err.stack);
|
ctx.logger.error('wopiEditor error:%s', err.stack);
|
||||||
res.sendStatus(400);
|
res.sendStatus(400);
|
||||||
}
|
}
|
||||||
logger.info('wopiEditor end');
|
ctx.logger.info('wopiEditor end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function putFile(wopiParams, data, dataStream, dataSize, userLastChangeId, isModifiedByUser, isAutosave, isExitSave) {
|
function putFile(ctx, wopiParams, data, dataStream, dataSize, userLastChangeId, isModifiedByUser, isAutosave, isExitSave) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
let postRes = null;
|
let postRes = null;
|
||||||
try {
|
try {
|
||||||
logger.info('wopi PutFile start');
|
ctx.logger.info('wopi PutFile start');
|
||||||
if (!wopiParams.userAuth) {
|
if (!wopiParams.userAuth) {
|
||||||
return postRes;
|
return postRes;
|
||||||
}
|
}
|
||||||
let fileInfo = wopiParams.commonInfo.fileInfo;
|
let fileInfo = wopiParams.commonInfo.fileInfo;
|
||||||
let userAuth = wopiParams.userAuth;
|
let userAuth = wopiParams.userAuth;
|
||||||
let uri = `${userAuth.wopiSrc}/contents?access_token=${userAuth.access_token}`;
|
let uri = `${userAuth.wopiSrc}/contents?access_token=${userAuth.access_token}`;
|
||||||
let filterStatus = yield checkIpFilter(uri);
|
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||||
if (0 !== filterStatus) {
|
if (0 !== filterStatus) {
|
||||||
return postRes;
|
return postRes;
|
||||||
}
|
}
|
||||||
@ -432,33 +442,33 @@ function putFile(wopiParams, data, dataStream, dataSize, userLastChangeId, isMod
|
|||||||
headers['X-LOOL-WOPI-Timestamp'] = wopiParams.LastModifiedTime;
|
headers['X-LOOL-WOPI-Timestamp'] = wopiParams.LastModifiedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('wopi PutFile request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi PutFile request uri=%s headers=%j', uri, headers);
|
||||||
postRes = yield utils.postRequestPromise(uri, data, dataStream, dataSize, cfgCallbackRequestTimeout, undefined, headers);
|
postRes = yield utils.postRequestPromise(uri, data, dataStream, dataSize, cfgCallbackRequestTimeout, undefined, headers);
|
||||||
logger.debug('wopi PutFile response headers=%j', postRes.response.headers);
|
ctx.logger.debug('wopi PutFile response headers=%j', postRes.response.headers);
|
||||||
logger.debug('wopi PutFile response body:%s', postRes.body);
|
ctx.logger.debug('wopi PutFile response body:%s', postRes.body);
|
||||||
} else {
|
} else {
|
||||||
logger.warn('wopi SupportsUpdate = false or UserCanWrite = false');
|
ctx.logger.warn('wopi SupportsUpdate = false or UserCanWrite = false');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('wopi error PutFile:%s', err.stack);
|
ctx.logger.error('wopi error PutFile:%s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
logger.info('wopi PutFile end');
|
ctx.logger.info('wopi PutFile end');
|
||||||
}
|
}
|
||||||
return postRes;
|
return postRes;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function renameFile(wopiParams, name) {
|
function renameFile(ctx, wopiParams, name) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
let res;
|
let res = undefined;
|
||||||
try {
|
try {
|
||||||
logger.info('wopi RenameFile start');
|
ctx.logger.info('wopi RenameFile start');
|
||||||
if (!wopiParams.userAuth) {
|
if (!wopiParams.userAuth) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
let fileInfo = wopiParams.commonInfo.fileInfo;
|
let fileInfo = wopiParams.commonInfo.fileInfo;
|
||||||
let userAuth = wopiParams.userAuth;
|
let userAuth = wopiParams.userAuth;
|
||||||
let uri = `${userAuth.wopiSrc}?access_token=${userAuth.access_token}`;
|
let uri = `${userAuth.wopiSrc}?access_token=${userAuth.access_token}`;
|
||||||
let filterStatus = yield checkIpFilter(uri);
|
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||||
if (0 !== filterStatus) {
|
if (0 !== filterStatus) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -471,9 +481,9 @@ function renameFile(wopiParams, name) {
|
|||||||
let headers = {'X-WOPI-Override': 'RENAME_FILE', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-RequestedName': utf7.encode(name)};
|
let headers = {'X-WOPI-Override': 'RENAME_FILE', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-RequestedName': utf7.encode(name)};
|
||||||
fillStandardHeaders(headers, uri, userAuth.access_token);
|
fillStandardHeaders(headers, uri, userAuth.access_token);
|
||||||
|
|
||||||
logger.debug('wopi RenameFile request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi RenameFile request uri=%s headers=%j', uri, headers);
|
||||||
let postRes = yield utils.postRequestPromise(uri, undefined, undefined, undefined, cfgCallbackRequestTimeout, undefined, headers);
|
let postRes = yield utils.postRequestPromise(uri, undefined, undefined, undefined, cfgCallbackRequestTimeout, undefined, headers);
|
||||||
logger.debug('wopi RenameFile response headers=%j body=%s', postRes.response.headers, postRes.body);
|
ctx.logger.debug('wopi RenameFile response headers=%j body=%s', postRes.response.headers, postRes.body);
|
||||||
if (postRes.body) {
|
if (postRes.body) {
|
||||||
res = JSON.parse(postRes.body);
|
res = JSON.parse(postRes.body);
|
||||||
} else {
|
} else {
|
||||||
@ -481,22 +491,22 @@ function renameFile(wopiParams, name) {
|
|||||||
res = {"Name": name};
|
res = {"Name": name};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.info('wopi SupportsRename = false');
|
ctx.logger.info('wopi SupportsRename = false');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('wopi error RenameFile:%s', err.stack);
|
ctx.logger.error('wopi error RenameFile:%s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
logger.info('wopi RenameFile end');
|
ctx.logger.info('wopi RenameFile end');
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function checkFileInfo(uri, access_token, sc) {
|
function checkFileInfo(ctx, uri, access_token, sc) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
let fileInfo;
|
let fileInfo = undefined;
|
||||||
try {
|
try {
|
||||||
logger.info('wopi checkFileInfo start');
|
ctx.logger.info('wopi checkFileInfo start');
|
||||||
let filterStatus = yield checkIpFilter(uri);
|
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||||
if (0 !== filterStatus) {
|
if (0 !== filterStatus) {
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
@ -505,23 +515,23 @@ function checkFileInfo(uri, access_token, sc) {
|
|||||||
headers['X-WOPI-SessionContext'] = sc;
|
headers['X-WOPI-SessionContext'] = sc;
|
||||||
}
|
}
|
||||||
fillStandardHeaders(headers, uri, access_token);
|
fillStandardHeaders(headers, uri, access_token);
|
||||||
logger.debug('wopi checkFileInfo request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi checkFileInfo request uri=%s headers=%j', uri, headers);
|
||||||
let getRes = yield utils.downloadUrlPromise(uri, cfgDownloadTimeout, undefined, undefined, false, headers);
|
let getRes = yield utils.downloadUrlPromise(ctx, uri, cfgDownloadTimeout, undefined, undefined, false, headers);
|
||||||
logger.debug(`wopi checkFileInfo headers=%j body=%s`, getRes.response.headers, getRes.body);
|
ctx.logger.debug(`wopi checkFileInfo headers=%j body=%s`, getRes.response.headers, getRes.body);
|
||||||
fileInfo = JSON.parse(getRes.body);
|
fileInfo = JSON.parse(getRes.body);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('wopi error checkFileInfo:%s', err.stack);
|
ctx.logger.error('wopi error checkFileInfo:%s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
logger.info('wopi checkFileInfo end');
|
ctx.logger.info('wopi checkFileInfo end');
|
||||||
}
|
}
|
||||||
return fileInfo;
|
return fileInfo;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function lock(command, lockId, fileInfo, userAuth) {
|
function lock(ctx, command, lockId, fileInfo, userAuth) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
let res = true;
|
let res = true;
|
||||||
try {
|
try {
|
||||||
logger.info('wopi %s start', command);
|
ctx.logger.info('wopi %s start', command);
|
||||||
if (fileInfo && fileInfo.SupportsLocks) {
|
if (fileInfo && fileInfo.SupportsLocks) {
|
||||||
if (!userAuth) {
|
if (!userAuth) {
|
||||||
return false;
|
return false;
|
||||||
@ -529,32 +539,32 @@ function lock(command, lockId, fileInfo, userAuth) {
|
|||||||
let wopiSrc = userAuth.wopiSrc;
|
let wopiSrc = userAuth.wopiSrc;
|
||||||
let access_token = userAuth.access_token;
|
let access_token = userAuth.access_token;
|
||||||
let uri = `${wopiSrc}?access_token=${access_token}`;
|
let uri = `${wopiSrc}?access_token=${access_token}`;
|
||||||
let filterStatus = yield checkIpFilter(uri);
|
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||||
if (0 !== filterStatus) {
|
if (0 !== filterStatus) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers = {"X-WOPI-Override": command, "X-WOPI-Lock": lockId};
|
let headers = {"X-WOPI-Override": command, "X-WOPI-Lock": lockId};
|
||||||
fillStandardHeaders(headers, uri, access_token);
|
fillStandardHeaders(headers, uri, access_token);
|
||||||
logger.debug('wopi %s request uri=%s headers=%j', command, uri, headers);
|
ctx.logger.debug('wopi %s request uri=%s headers=%j', command, uri, headers);
|
||||||
let postRes = yield utils.postRequestPromise(uri, undefined, undefined, undefined, cfgCallbackRequestTimeout, undefined, headers);
|
let postRes = yield utils.postRequestPromise(uri, undefined, undefined, undefined, cfgCallbackRequestTimeout, undefined, headers);
|
||||||
logger.debug('wopi %s response headers=%j', command, postRes.response.headers);
|
ctx.logger.debug('wopi %s response headers=%j', command, postRes.response.headers);
|
||||||
} else {
|
} else {
|
||||||
logger.info('wopi %s SupportsLocks = false', command);
|
ctx.logger.info('wopi %s SupportsLocks = false', command);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res = false;
|
res = false;
|
||||||
logger.error('wopi error %s:%s', command, err.stack);
|
ctx.logger.error('wopi error %s:%s', command, err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
logger.info('wopi %s end', command);
|
ctx.logger.info('wopi %s end', command);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function unlock(wopiParams) {
|
function unlock(ctx, wopiParams) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
try {
|
try {
|
||||||
logger.info('wopi Unlock start');
|
ctx.logger.info('wopi Unlock start');
|
||||||
let fileInfo = wopiParams.commonInfo.fileInfo;
|
let fileInfo = wopiParams.commonInfo.fileInfo;
|
||||||
if (fileInfo && fileInfo.SupportsLocks) {
|
if (fileInfo && fileInfo.SupportsLocks) {
|
||||||
if (!wopiParams.userAuth) {
|
if (!wopiParams.userAuth) {
|
||||||
@ -564,23 +574,23 @@ function unlock(wopiParams) {
|
|||||||
let lockId = wopiParams.commonInfo.lockId;
|
let lockId = wopiParams.commonInfo.lockId;
|
||||||
let access_token = wopiParams.userAuth.access_token;
|
let access_token = wopiParams.userAuth.access_token;
|
||||||
let uri = `${wopiSrc}?access_token=${access_token}`;
|
let uri = `${wopiSrc}?access_token=${access_token}`;
|
||||||
let filterStatus = yield checkIpFilter(uri);
|
let filterStatus = yield checkIpFilter(ctx, uri);
|
||||||
if (0 !== filterStatus) {
|
if (0 !== filterStatus) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers = {"X-WOPI-Override": "UNLOCK", "X-WOPI-Lock": lockId};
|
let headers = {"X-WOPI-Override": "UNLOCK", "X-WOPI-Lock": lockId};
|
||||||
fillStandardHeaders(headers, uri, access_token);
|
fillStandardHeaders(headers, uri, access_token);
|
||||||
logger.debug('wopi Unlock request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi Unlock request uri=%s headers=%j', uri, headers);
|
||||||
let postRes = yield utils.postRequestPromise(uri, undefined, undefined, undefined, cfgCallbackRequestTimeout, undefined, headers);
|
let postRes = yield utils.postRequestPromise(uri, undefined, undefined, undefined, cfgCallbackRequestTimeout, undefined, headers);
|
||||||
logger.debug('wopi Unlock response headers=%j', postRes.response.headers);
|
ctx.logger.debug('wopi Unlock response headers=%j', postRes.response.headers);
|
||||||
} else {
|
} else {
|
||||||
logger.info('wopi SupportsLocks = false');
|
ctx.logger.info('wopi SupportsLocks = false');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('wopi error Unlock:%s', err.stack);
|
ctx.logger.error('wopi error Unlock:%s', err.stack);
|
||||||
} finally {
|
} finally {
|
||||||
logger.info('wopi Unlock end');
|
ctx.logger.info('wopi Unlock end');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -630,12 +640,12 @@ function fillStandardHeaders(headers, url, access_token) {
|
|||||||
headers['Authorization'] = `Bearer ${access_token}`;
|
headers['Authorization'] = `Bearer ${access_token}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIpFilter(uri){
|
function checkIpFilter(ctx, uri){
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
let urlParsed = new URL(uri);
|
let urlParsed = new URL(uri);
|
||||||
let filterStatus = yield* utils.checkHostFilter(urlParsed.hostname);
|
let filterStatus = yield* utils.checkHostFilter(ctx, urlParsed.hostname);
|
||||||
if (0 !== filterStatus) {
|
if (0 !== filterStatus) {
|
||||||
logger.warn('wopi checkIpFilter error: url = %s', uri);
|
ctx.logger.warn('wopi checkIpFilter error: url = %s', uri);
|
||||||
}
|
}
|
||||||
return filterStatus;
|
return filterStatus;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -53,6 +53,8 @@ const wopiClient = require('./../../DocService/sources/wopiClient');
|
|||||||
var statsDClient = require('./../../Common/sources/statsdclient');
|
var statsDClient = require('./../../Common/sources/statsdclient');
|
||||||
var queueService = require('./../../Common/sources/taskqueueRabbitMQ');
|
var queueService = require('./../../Common/sources/taskqueueRabbitMQ');
|
||||||
const formatChecker = require('./../../Common/sources/formatchecker');
|
const formatChecker = require('./../../Common/sources/formatchecker');
|
||||||
|
const operationContext = require('./../../Common/sources/operationContext');
|
||||||
|
const tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
|
|
||||||
var cfgDownloadMaxBytes = configConverter.has('maxDownloadBytes') ? configConverter.get('maxDownloadBytes') : 100000000;
|
var cfgDownloadMaxBytes = configConverter.has('maxDownloadBytes') ? configConverter.get('maxDownloadBytes') : 100000000;
|
||||||
var cfgDownloadTimeout = configConverter.has('downloadTimeout') ? configConverter.get('downloadTimeout') : 60;
|
var cfgDownloadTimeout = configConverter.has('downloadTimeout') ? configConverter.get('downloadTimeout') : 60;
|
||||||
@ -278,7 +280,7 @@ function getTempDir() {
|
|||||||
fs.mkdirSync(resultDir);
|
fs.mkdirSync(resultDir);
|
||||||
return {temp: newTemp, source: sourceDir, result: resultDir};
|
return {temp: newTemp, source: sourceDir, result: resultDir};
|
||||||
}
|
}
|
||||||
function* replaceEmptyFile(docId, fileFrom, ext, _lcid) {
|
function* replaceEmptyFile(ctx, fileFrom, ext, _lcid) {
|
||||||
if (!fs.existsSync(fileFrom) || 0 === fs.lstatSync(fileFrom).size) {
|
if (!fs.existsSync(fileFrom) || 0 === fs.lstatSync(fileFrom).size) {
|
||||||
let locale = 'en-US';
|
let locale = 'en-US';
|
||||||
if (_lcid) {
|
if (_lcid) {
|
||||||
@ -288,11 +290,11 @@ function* replaceEmptyFile(docId, fileFrom, ext, _lcid) {
|
|||||||
if (fs.existsSync(path.join(cfgNewFileTemplate, localeNew))) {
|
if (fs.existsSync(path.join(cfgNewFileTemplate, localeNew))) {
|
||||||
locale = localeNew;
|
locale = localeNew;
|
||||||
} else {
|
} else {
|
||||||
logger.debug('replaceEmptyFile empty locale dir locale=%s (id=%s)', localeNew, docId);
|
ctx.logger.debug('replaceEmptyFile empty locale dir locale=%s', localeNew);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug('replaceEmptyFile format=%s locale=%s (id=%s)', ext, locale, docId);
|
ctx.logger.debug('replaceEmptyFile format=%s locale=%s', ext, locale);
|
||||||
let format = formatChecker.getFormatFromString(ext);
|
let format = formatChecker.getFormatFromString(ext);
|
||||||
if (formatChecker.isDocumentFormat(format)) {
|
if (formatChecker.isDocumentFormat(format)) {
|
||||||
fs.copyFileSync(path.join(cfgNewFileTemplate, locale, 'new.docx'), fileFrom);
|
fs.copyFileSync(path.join(cfgNewFileTemplate, locale, 'new.docx'), fileFrom);
|
||||||
@ -303,25 +305,26 @@ function* replaceEmptyFile(docId, fileFrom, ext, _lcid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function* downloadFile(docId, uri, fileFrom, withAuthorization, filterPrivate, opt_headers) {
|
function* downloadFile(ctx, uri, fileFrom, withAuthorization, filterPrivate, opt_headers) {
|
||||||
var res = constants.CONVERT_DOWNLOAD;
|
var res = constants.CONVERT_DOWNLOAD;
|
||||||
var data = null;
|
var data = null;
|
||||||
var downloadAttemptCount = 0;
|
var downloadAttemptCount = 0;
|
||||||
var urlParsed = url.parse(uri);
|
var urlParsed = url.parse(uri);
|
||||||
var filterStatus = yield* utils.checkHostFilter(urlParsed.hostname);
|
var filterStatus = yield* utils.checkHostFilter(ctx, urlParsed.hostname);
|
||||||
if (0 == filterStatus) {
|
if (0 == filterStatus) {
|
||||||
while (constants.NO_ERROR !== res && downloadAttemptCount++ < cfgDownloadAttemptMaxCount) {
|
while (constants.NO_ERROR !== res && downloadAttemptCount++ < cfgDownloadAttemptMaxCount) {
|
||||||
try {
|
try {
|
||||||
let authorization;
|
let authorization;
|
||||||
if (utils.canIncludeOutboxAuthorization(uri) && withAuthorization) {
|
if (utils.canIncludeOutboxAuthorization(ctx, uri) && withAuthorization) {
|
||||||
authorization = utils.fillJwtForRequest({url: uri}, false);
|
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Outbox);
|
||||||
|
authorization = utils.fillJwtForRequest({url: uri}, secret, false);
|
||||||
}
|
}
|
||||||
let getRes = yield utils.downloadUrlPromise(uri, cfgDownloadTimeout, cfgDownloadMaxBytes, authorization, filterPrivate, opt_headers);
|
let getRes = yield utils.downloadUrlPromise(ctx, uri, cfgDownloadTimeout, cfgDownloadMaxBytes, authorization, filterPrivate, opt_headers);
|
||||||
data = getRes.body;
|
data = getRes.body;
|
||||||
res = constants.NO_ERROR;
|
res = constants.NO_ERROR;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res = constants.CONVERT_DOWNLOAD;
|
res = constants.CONVERT_DOWNLOAD;
|
||||||
logger.error('error downloadFile:url=%s;attempt=%d;code:%s;connect:%s;(id=%s)\r\n%s', uri, downloadAttemptCount, err.code, err.connect, docId, err.stack);
|
ctx.logger.error('error downloadFile:url=%s;attempt=%d;code:%s;connect:%s %s', uri, downloadAttemptCount, err.code, err.connect, err.stack);
|
||||||
//not continue attempts if timeout
|
//not continue attempts if timeout
|
||||||
if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
|
if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
|
||||||
break;
|
break;
|
||||||
@ -334,18 +337,18 @@ function* downloadFile(docId, uri, fileFrom, withAuthorization, filterPrivate, o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (constants.NO_ERROR === res) {
|
if (constants.NO_ERROR === res) {
|
||||||
logger.debug('downloadFile complete filesize=%d (id=%s)', data.length, docId);
|
ctx.logger.debug('downloadFile complete filesize=%d', data.length);
|
||||||
fs.writeFileSync(fileFrom, data);
|
fs.writeFileSync(fileFrom, data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error('checkIpFilter error:url=%s;code:%s;(id=%s)', uri, filterStatus, docId);
|
ctx.logger.error('checkIpFilter error:url=%s;code:%s;', uri, filterStatus);
|
||||||
res = constants.CONVERT_DOWNLOAD;
|
res = constants.CONVERT_DOWNLOAD;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
function* downloadFileFromStorage(id, strPath, dir) {
|
function* downloadFileFromStorage(ctx, strPath, dir) {
|
||||||
var list = yield storage.listObjects(strPath);
|
var list = yield storage.listObjects(ctx, strPath);
|
||||||
logger.debug('downloadFileFromStorage list %s (id=%s)', list.toString(), id);
|
ctx.logger.debug('downloadFileFromStorage list %s', list.toString());
|
||||||
//create dirs
|
//create dirs
|
||||||
var dirsToCreate = [];
|
var dirsToCreate = [];
|
||||||
var dirStruct = {};
|
var dirStruct = {};
|
||||||
@ -371,36 +374,36 @@ function* downloadFileFromStorage(id, strPath, dir) {
|
|||||||
for (var i = 0; i < list.length; ++i) {
|
for (var i = 0; i < list.length; ++i) {
|
||||||
var file = list[i];
|
var file = list[i];
|
||||||
var fileRel = storage.getRelativePath(strPath, file);
|
var fileRel = storage.getRelativePath(strPath, file);
|
||||||
var data = yield storage.getObject(file);
|
var data = yield storage.getObject(ctx, file);
|
||||||
fs.writeFileSync(path.join(dir, fileRel), data);
|
fs.writeFileSync(path.join(dir, fileRel), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function* processDownloadFromStorage(dataConvert, cmd, task, tempDirs, authorProps) {
|
function* processDownloadFromStorage(ctx, dataConvert, cmd, task, tempDirs, authorProps) {
|
||||||
let res = constants.NO_ERROR;
|
let res = constants.NO_ERROR;
|
||||||
let needConcatFiles = false;
|
let needConcatFiles = false;
|
||||||
if (task.getFromOrigin() || task.getFromSettings()) {
|
if (task.getFromOrigin() || task.getFromSettings()) {
|
||||||
dataConvert.fileFrom = path.join(tempDirs.source, 'origin.' + cmd.getFormat());
|
dataConvert.fileFrom = path.join(tempDirs.source, 'origin.' + cmd.getFormat());
|
||||||
} else {
|
} else {
|
||||||
//перезаписываем некоторые файлы из m_sKey(например Editor.bin или changes)
|
//перезаписываем некоторые файлы из m_sKey(например Editor.bin или changes)
|
||||||
yield* downloadFileFromStorage(cmd.getSaveKey(), cmd.getSaveKey(), tempDirs.source);
|
yield* downloadFileFromStorage(ctx, cmd.getSaveKey(), tempDirs.source);
|
||||||
let format = cmd.getFormat() || 'bin';
|
let format = cmd.getFormat() || 'bin';
|
||||||
dataConvert.fileFrom = path.join(tempDirs.source, 'Editor.' + format);
|
dataConvert.fileFrom = path.join(tempDirs.source, 'Editor.' + format);
|
||||||
needConcatFiles = true;
|
needConcatFiles = true;
|
||||||
}
|
}
|
||||||
if (!utils.checkPathTraversal(dataConvert.key, tempDirs.source, dataConvert.fileFrom)) {
|
if (!utils.checkPathTraversal(ctx, dataConvert.key, tempDirs.source, dataConvert.fileFrom)) {
|
||||||
return constants.CONVERT_PARAMS;
|
return constants.CONVERT_PARAMS;
|
||||||
}
|
}
|
||||||
//mail merge
|
//mail merge
|
||||||
let mailMergeSend = cmd.getMailMergeSend();
|
let mailMergeSend = cmd.getMailMergeSend();
|
||||||
if (mailMergeSend) {
|
if (mailMergeSend) {
|
||||||
yield* downloadFileFromStorage(mailMergeSend.getJsonKey(), mailMergeSend.getJsonKey(), tempDirs.source);
|
yield* downloadFileFromStorage(ctx, mailMergeSend.getJsonKey(), tempDirs.source);
|
||||||
needConcatFiles = true;
|
needConcatFiles = true;
|
||||||
}
|
}
|
||||||
if (needConcatFiles) {
|
if (needConcatFiles) {
|
||||||
yield* concatFiles(tempDirs.source);
|
yield* concatFiles(tempDirs.source);
|
||||||
}
|
}
|
||||||
if (task.getFromChanges()) {
|
if (task.getFromChanges()) {
|
||||||
res = yield* processChanges(tempDirs, cmd, authorProps);
|
res = yield* processChanges(ctx, tempDirs, cmd, authorProps);
|
||||||
}
|
}
|
||||||
//todo rework
|
//todo rework
|
||||||
if (!fs.existsSync(dataConvert.fileFrom)) {
|
if (!fs.existsSync(dataConvert.fileFrom)) {
|
||||||
@ -443,7 +446,7 @@ function* concatFiles(source) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function* processChanges(tempDirs, cmd, authorProps) {
|
function* processChanges(ctx, tempDirs, cmd, authorProps) {
|
||||||
let res = constants.NO_ERROR;
|
let res = constants.NO_ERROR;
|
||||||
let changesDir = path.join(tempDirs.source, constants.CHANGES_NAME);
|
let changesDir = path.join(tempDirs.source, constants.CHANGES_NAME);
|
||||||
fs.mkdirSync(changesDir);
|
fs.mkdirSync(changesDir);
|
||||||
@ -472,13 +475,13 @@ function* processChanges(tempDirs, cmd, authorProps) {
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
let streamObj = yield* streamCreate(cmd.getDocId(), changesDir, indexFile++, {highWaterMark: cfgStreamWriterBufferSize});
|
let streamObj = yield* streamCreate(ctx, changesDir, indexFile++, {highWaterMark: cfgStreamWriterBufferSize});
|
||||||
let curIndexStart = 0;
|
let curIndexStart = 0;
|
||||||
let curIndexEnd = Math.min(curIndexStart + cfgMaxRequestChanges, forceSaveIndex);
|
let curIndexEnd = Math.min(curIndexStart + cfgMaxRequestChanges, forceSaveIndex);
|
||||||
while (curIndexStart < curIndexEnd || extChanges) {
|
while (curIndexStart < curIndexEnd || extChanges) {
|
||||||
let changes = [];
|
let changes = [];
|
||||||
if (curIndexStart < curIndexEnd) {
|
if (curIndexStart < curIndexEnd) {
|
||||||
changes = yield baseConnector.getChangesPromise(cmd.getDocId(), curIndexStart, curIndexEnd, forceSaveTime);
|
changes = yield baseConnector.getChangesPromise(ctx, cmd.getDocId(), curIndexStart, curIndexEnd, forceSaveTime);
|
||||||
}
|
}
|
||||||
if (0 === changes.length && extChanges) {
|
if (0 === changes.length && extChanges) {
|
||||||
changes = extChanges;
|
changes = extChanges;
|
||||||
@ -487,7 +490,7 @@ function* processChanges(tempDirs, cmd, authorProps) {
|
|||||||
for (let i = 0; i < changes.length; ++i) {
|
for (let i = 0; i < changes.length; ++i) {
|
||||||
let change = changes[i];
|
let change = changes[i];
|
||||||
if (change.change_data.startsWith('ENCRYPTED;')) {
|
if (change.change_data.startsWith('ENCRYPTED;')) {
|
||||||
logger.warn('processChanges encrypted changes (id=%s)', cmd.getDocId());
|
ctx.logger.warn('processChanges encrypted changes');
|
||||||
//todo sql request instead?
|
//todo sql request instead?
|
||||||
res = constants.EDITOR_CHANGES;
|
res = constants.EDITOR_CHANGES;
|
||||||
break;
|
break;
|
||||||
@ -495,7 +498,7 @@ function* processChanges(tempDirs, cmd, authorProps) {
|
|||||||
if (null === changesAuthor || changesAuthor !== change.user_id_original) {
|
if (null === changesAuthor || changesAuthor !== change.user_id_original) {
|
||||||
if (null !== changesAuthor) {
|
if (null !== changesAuthor) {
|
||||||
yield* streamEnd(streamObj, ']');
|
yield* streamEnd(streamObj, ']');
|
||||||
streamObj = yield* streamCreate(cmd.getDocId(), changesDir, indexFile++);
|
streamObj = yield* streamCreate(ctx, changesDir, indexFile++);
|
||||||
}
|
}
|
||||||
let strDate = baseConnector.getDateTime(change.change_date);
|
let strDate = baseConnector.getDateTime(change.change_date);
|
||||||
changesHistory.changes.push({'created': strDate, 'user': {'id': change.user_id_original, 'name': change.user_name}});
|
changesHistory.changes.push({'created': strDate, 'user': {'id': change.user_id_original, 'name': change.user_name}});
|
||||||
@ -537,13 +540,13 @@ function* processChanges(tempDirs, cmd, authorProps) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* streamCreate(docId, changesDir, indexFile, opt_options) {
|
function* streamCreate(ctx, changesDir, indexFile, opt_options) {
|
||||||
let fileName = constants.CHANGES_NAME + indexFile + '.json';
|
let fileName = constants.CHANGES_NAME + indexFile + '.json';
|
||||||
let filePath = path.join(changesDir, fileName);
|
let filePath = path.join(changesDir, fileName);
|
||||||
let writeStream = yield utils.promiseCreateWriteStream(filePath, opt_options);
|
let writeStream = yield utils.promiseCreateWriteStream(filePath, opt_options);
|
||||||
writeStream.on('error', function(err) {
|
writeStream.on('error', function(err) {
|
||||||
//todo integrate error handle in main thread (probable: set flag here and check it in main thread)
|
//todo integrate error handle in main thread (probable: set flag here and check it in main thread)
|
||||||
logger.error('WriteStreamError (id=%s)\r\n%s', docId, err.stack);
|
ctx.logger.error('WriteStreamError %s', err.stack);
|
||||||
});
|
});
|
||||||
return {writeStream: writeStream, filePath: filePath, isNoChangesInFile: true};
|
return {writeStream: writeStream, filePath: filePath, isNoChangesInFile: true};
|
||||||
}
|
}
|
||||||
@ -558,41 +561,41 @@ function* streamEnd(streamObj, text) {
|
|||||||
streamObj.writeStream.end(text, 'utf8');
|
streamObj.writeStream.end(text, 'utf8');
|
||||||
yield utils.promiseWaitClose(streamObj.writeStream);
|
yield utils.promiseWaitClose(streamObj.writeStream);
|
||||||
}
|
}
|
||||||
function* processUploadToStorage(dir, storagePath) {
|
function* processUploadToStorage(ctx, dir, storagePath) {
|
||||||
var list = yield utils.listObjects(dir);
|
var list = yield utils.listObjects(dir);
|
||||||
if (list.length < MAX_OPEN_FILES) {
|
if (list.length < MAX_OPEN_FILES) {
|
||||||
yield* processUploadToStorageChunk(list, dir, storagePath);
|
yield* processUploadToStorageChunk(ctx, list, dir, storagePath);
|
||||||
} else {
|
} else {
|
||||||
for (var i = 0, j = list.length; i < j; i += MAX_OPEN_FILES) {
|
for (var i = 0, j = list.length; i < j; i += MAX_OPEN_FILES) {
|
||||||
yield* processUploadToStorageChunk(list.slice(i, i + MAX_OPEN_FILES), dir, storagePath);
|
yield* processUploadToStorageChunk(ctx, list.slice(i, i + MAX_OPEN_FILES), dir, storagePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function* processUploadToStorageChunk(list, dir, storagePath) {
|
function* processUploadToStorageChunk(ctx, list, dir, storagePath) {
|
||||||
yield Promise.all(list.map(function (curValue) {
|
yield Promise.all(list.map(function (curValue) {
|
||||||
let localValue = storagePath + '/' + curValue.substring(dir.length + 1);
|
let localValue = storagePath + '/' + curValue.substring(dir.length + 1);
|
||||||
return storage.uploadObject(localValue, curValue);
|
return storage.uploadObject(ctx, localValue, curValue);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
function writeProcessOutputToLog(docId, childRes, isDebug) {
|
function writeProcessOutputToLog(ctx, childRes, isDebug) {
|
||||||
if (childRes) {
|
if (childRes) {
|
||||||
if (undefined !== childRes.stdout) {
|
if (undefined !== childRes.stdout) {
|
||||||
if (isDebug) {
|
if (isDebug) {
|
||||||
logger.debug('stdout (id=%s):%s', docId, childRes.stdout);
|
ctx.logger.debug('stdout:%s', childRes.stdout);
|
||||||
} else {
|
} else {
|
||||||
logger.error('stdout (id=%s):%s', docId, childRes.stdout);
|
ctx.logger.error('stdout:%s', childRes.stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (undefined !== childRes.stderr) {
|
if (undefined !== childRes.stderr) {
|
||||||
if (isDebug) {
|
if (isDebug) {
|
||||||
logger.debug('stderr (id=%s):%s', docId, childRes.stderr);
|
ctx.logger.debug('stderr:%s', childRes.stderr);
|
||||||
} else {
|
} else {
|
||||||
logger.error('stderr (id=%s):%s', docId, childRes.stderr);
|
ctx.logger.error('stderr:%s', childRes.stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function* postProcess(cmd, dataConvert, tempDirs, childRes, error, isTimeout) {
|
function* postProcess(ctx, cmd, dataConvert, tempDirs, childRes, error, isTimeout) {
|
||||||
var exitCode = 0;
|
var exitCode = 0;
|
||||||
var exitSignal = null;
|
var exitSignal = null;
|
||||||
if(childRes) {
|
if(childRes) {
|
||||||
@ -608,23 +611,23 @@ function* postProcess(cmd, dataConvert, tempDirs, childRes, error, isTimeout) {
|
|||||||
error = constants.CONVERT;
|
error = constants.CONVERT;
|
||||||
}
|
}
|
||||||
if (-1 !== exitCodesMinorError.indexOf(error)) {
|
if (-1 !== exitCodesMinorError.indexOf(error)) {
|
||||||
writeProcessOutputToLog(dataConvert.key, childRes, true);
|
writeProcessOutputToLog(ctx, childRes, true);
|
||||||
logger.debug('ExitCode (code=%d;signal=%s;error:%d;id=%s)', exitCode, exitSignal, error, dataConvert.key);
|
ctx.logger.debug('ExitCode (code=%d;signal=%s;error:%d)', exitCode, exitSignal, error);
|
||||||
} else {
|
} else {
|
||||||
writeProcessOutputToLog(dataConvert.key, childRes, false);
|
writeProcessOutputToLog(ctx, childRes, false);
|
||||||
logger.error('ExitCode (code=%d;signal=%s;error:%d;id=%s)', exitCode, exitSignal, error, dataConvert.key);
|
ctx.logger.error('ExitCode (code=%d;signal=%s;error:%d)', exitCode, exitSignal, error);
|
||||||
if (cfgErrorFiles) {
|
if (cfgErrorFiles) {
|
||||||
yield* processUploadToStorage(tempDirs.temp, cfgErrorFiles + '/' + dataConvert.key);
|
yield* processUploadToStorage(ctx, tempDirs.temp, cfgErrorFiles + '/' + dataConvert.key);
|
||||||
logger.debug('processUploadToStorage error complete(id=%s)', dataConvert.key);
|
ctx.logger.debug('processUploadToStorage error complete(id=%s)', dataConvert.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writeProcessOutputToLog(dataConvert.key, childRes, true);
|
writeProcessOutputToLog(ctx, childRes, true);
|
||||||
logger.debug('ExitCode (code=%d;signal=%s;error:%d;id=%s)', exitCode, exitSignal, error, dataConvert.key);
|
ctx.logger.debug('ExitCode (code=%d;signal=%s;error:%d)', exitCode, exitSignal, error);
|
||||||
}
|
}
|
||||||
if (-1 !== exitCodesUpload.indexOf(error)) {
|
if (-1 !== exitCodesUpload.indexOf(error)) {
|
||||||
yield* processUploadToStorage(tempDirs.result, dataConvert.key);
|
yield* processUploadToStorage(ctx, tempDirs.result, dataConvert.key);
|
||||||
logger.debug('processUploadToStorage complete(id=%s)', dataConvert.key);
|
ctx.logger.debug('processUploadToStorage complete');
|
||||||
}
|
}
|
||||||
cmd.setStatusInfo(error);
|
cmd.setStatusInfo(error);
|
||||||
var existFile = false;
|
var existFile = false;
|
||||||
@ -651,13 +654,14 @@ function* postProcess(cmd, dataConvert, tempDirs, childRes, error, isTimeout) {
|
|||||||
cmd.setTitle(cmd.getOutputPath());
|
cmd.setTitle(cmd.getOutputPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = new commonDefines.TaskQueueData();
|
var queueData = new commonDefines.TaskQueueData();
|
||||||
res.setCmd(cmd);
|
queueData.setCtx(ctx);
|
||||||
logger.debug('output (data=%s;id=%s)', JSON.stringify(res), dataConvert.key);
|
queueData.setCmd(cmd);
|
||||||
return res;
|
ctx.logger.debug('output (data=%j)', queueData);
|
||||||
|
return queueData;
|
||||||
}
|
}
|
||||||
|
|
||||||
function* spawnProcess(isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task, cmd) {
|
function* spawnProcess(ctx, isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task) {
|
||||||
let childRes, isTimeout = false;
|
let childRes, isTimeout = false;
|
||||||
let childArgs;
|
let childArgs;
|
||||||
if (cfgArgs.length > 0) {
|
if (cfgArgs.length > 0) {
|
||||||
@ -707,8 +711,11 @@ function* spawnProcess(isBuilder, tempDirs, dataConvert, authorProps, getTaskTim
|
|||||||
}, waitMS);
|
}, waitMS);
|
||||||
childRes = yield spawnAsyncPromise;
|
childRes = yield spawnAsyncPromise;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
let fLog = null === err.status ? logger.error : logger.debug;
|
if (null === err.status) {
|
||||||
fLog.call(logger, 'error spawnAsync(id=%s)\r\n%s', cmd.getDocId(), err.stack);
|
ctx.logger.error('error spawnAsync %s', err.stack);
|
||||||
|
} else {
|
||||||
|
ctx.logger.debug('error spawnAsync %s', err.stack);
|
||||||
|
}
|
||||||
childRes = err;
|
childRes = err;
|
||||||
}
|
}
|
||||||
if (undefined !== timeoutId) {
|
if (undefined !== timeoutId) {
|
||||||
@ -717,7 +724,7 @@ function* spawnProcess(isBuilder, tempDirs, dataConvert, authorProps, getTaskTim
|
|||||||
return {childRes: childRes, isTimeout: isTimeout};
|
return {childRes: childRes, isTimeout: isTimeout};
|
||||||
}
|
}
|
||||||
|
|
||||||
function* ExecuteTask(task) {
|
function* ExecuteTask(ctx, task) {
|
||||||
var startDate = null;
|
var startDate = null;
|
||||||
var curDate = null;
|
var curDate = null;
|
||||||
if(clientStatsD) {
|
if(clientStatsD) {
|
||||||
@ -728,7 +735,7 @@ function* ExecuteTask(task) {
|
|||||||
var getTaskTime = new Date();
|
var getTaskTime = new Date();
|
||||||
var cmd = task.getCmd();
|
var cmd = task.getCmd();
|
||||||
var dataConvert = new TaskQueueDataConvert(task);
|
var dataConvert = new TaskQueueDataConvert(task);
|
||||||
logger.debug('Start Task(id=%s)', dataConvert.key);
|
ctx.logger.info('Start Task');
|
||||||
var error = constants.NO_ERROR;
|
var error = constants.NO_ERROR;
|
||||||
tempDirs = getTempDir();
|
tempDirs = getTempDir();
|
||||||
let fileTo = task.getToFile();
|
let fileTo = task.getToFile();
|
||||||
@ -738,7 +745,7 @@ function* ExecuteTask(task) {
|
|||||||
if (cmd.getUrl()) {
|
if (cmd.getUrl()) {
|
||||||
let format = cmd.getFormat();
|
let format = cmd.getFormat();
|
||||||
dataConvert.fileFrom = path.join(tempDirs.source, dataConvert.key + '.' + format);
|
dataConvert.fileFrom = path.join(tempDirs.source, dataConvert.key + '.' + format);
|
||||||
if (utils.checkPathTraversal(dataConvert.key, tempDirs.source, dataConvert.fileFrom)) {
|
if (utils.checkPathTraversal(ctx, dataConvert.key, tempDirs.source, dataConvert.fileFrom)) {
|
||||||
let url = cmd.getUrl();
|
let url = cmd.getUrl();
|
||||||
let withAuthorization = cmd.getWithAuthorization();
|
let withAuthorization = cmd.getWithAuthorization();
|
||||||
let filterPrivate = !withAuthorization;
|
let filterPrivate = !withAuthorization;
|
||||||
@ -760,13 +767,13 @@ function* ExecuteTask(task) {
|
|||||||
headers = {'X-WOPI-MaxExpectedSize': cfgDownloadMaxBytes, 'X-WOPI-ItemVersion': fileInfo.Version};
|
headers = {'X-WOPI-MaxExpectedSize': cfgDownloadMaxBytes, 'X-WOPI-ItemVersion': fileInfo.Version};
|
||||||
wopiClient.fillStandardHeaders(headers, url, userAuth.access_token);
|
wopiClient.fillStandardHeaders(headers, url, userAuth.access_token);
|
||||||
}
|
}
|
||||||
logger.debug('wopi url=%s; headers=%j(id=%s)', url, headers, dataConvert.key);
|
ctx.logger.debug('wopi url=%s; headers=%j', url, headers);
|
||||||
}
|
}
|
||||||
if (undefined === fileSize || fileSize > 0) {
|
if (undefined === fileSize || fileSize > 0) {
|
||||||
error = yield* downloadFile(dataConvert.key, url, dataConvert.fileFrom, withAuthorization, filterPrivate, headers);
|
error = yield* downloadFile(ctx, url, dataConvert.fileFrom, withAuthorization, filterPrivate, headers);
|
||||||
}
|
}
|
||||||
if (constants.NO_ERROR === error) {
|
if (constants.NO_ERROR === error) {
|
||||||
yield* replaceEmptyFile(dataConvert.key, dataConvert.fileFrom, format, cmd.getLCID());
|
yield* replaceEmptyFile(ctx, dataConvert.fileFrom, format, cmd.getLCID());
|
||||||
}
|
}
|
||||||
if(clientStatsD) {
|
if(clientStatsD) {
|
||||||
clientStatsD.timing('conv.downloadFile', new Date() - curDate);
|
clientStatsD.timing('conv.downloadFile', new Date() - curDate);
|
||||||
@ -776,16 +783,16 @@ function* ExecuteTask(task) {
|
|||||||
error = constants.CONVERT_PARAMS;
|
error = constants.CONVERT_PARAMS;
|
||||||
}
|
}
|
||||||
} else if (cmd.getSaveKey()) {
|
} else if (cmd.getSaveKey()) {
|
||||||
yield* downloadFileFromStorage(cmd.getDocId(), cmd.getDocId(), tempDirs.source);
|
yield* downloadFileFromStorage(ctx, cmd.getDocId(), tempDirs.source);
|
||||||
logger.debug('downloadFileFromStorage complete(id=%s)', dataConvert.key);
|
ctx.logger.debug('downloadFileFromStorage complete');
|
||||||
if(clientStatsD) {
|
if(clientStatsD) {
|
||||||
clientStatsD.timing('conv.downloadFileFromStorage', new Date() - curDate);
|
clientStatsD.timing('conv.downloadFileFromStorage', new Date() - curDate);
|
||||||
curDate = new Date();
|
curDate = new Date();
|
||||||
}
|
}
|
||||||
error = yield* processDownloadFromStorage(dataConvert, cmd, task, tempDirs, authorProps);
|
error = yield* processDownloadFromStorage(ctx, dataConvert, cmd, task, tempDirs, authorProps);
|
||||||
} else if (cmd.getForgotten()) {
|
} else if (cmd.getForgotten()) {
|
||||||
yield* downloadFileFromStorage(cmd.getDocId(), cmd.getForgotten(), tempDirs.source);
|
yield* downloadFileFromStorage(ctx, cmd.getForgotten(), tempDirs.source);
|
||||||
logger.debug('downloadFileFromStorage complete(id=%s)', dataConvert.key);
|
ctx.logger.debug('downloadFileFromStorage complete');
|
||||||
let list = yield utils.listObjects(tempDirs.source, false);
|
let list = yield utils.listObjects(tempDirs.source, false);
|
||||||
if (list.length > 0) {
|
if (list.length > 0) {
|
||||||
dataConvert.fileFrom = list[0];
|
dataConvert.fileFrom = list[0];
|
||||||
@ -797,8 +804,8 @@ function* ExecuteTask(task) {
|
|||||||
}
|
}
|
||||||
} else if (isBuilder) {
|
} else if (isBuilder) {
|
||||||
//in cause script in POST body
|
//in cause script in POST body
|
||||||
yield* downloadFileFromStorage(cmd.getDocId(), cmd.getDocId(), tempDirs.source);
|
yield* downloadFileFromStorage(ctx, cmd.getDocId(), tempDirs.source);
|
||||||
logger.debug('downloadFileFromStorage complete(id=%s)', dataConvert.key);
|
ctx.logger.debug('downloadFileFromStorage complete');
|
||||||
let list = yield utils.listObjects(tempDirs.source, false);
|
let list = yield utils.listObjects(tempDirs.source, false);
|
||||||
if (list.length > 0) {
|
if (list.length > 0) {
|
||||||
dataConvert.fileFrom = list[0];
|
dataConvert.fileFrom = list[0];
|
||||||
@ -813,16 +820,16 @@ function* ExecuteTask(task) {
|
|||||||
//todo заглушка.вся конвертация на клиенте, но нет простого механизма сохранения на клиенте
|
//todo заглушка.вся конвертация на клиенте, но нет простого механизма сохранения на клиенте
|
||||||
yield utils.pipeFiles(dataConvert.fileFrom, dataConvert.fileTo);
|
yield utils.pipeFiles(dataConvert.fileFrom, dataConvert.fileTo);
|
||||||
} else {
|
} else {
|
||||||
({childRes, isTimeout} = yield* spawnProcess(isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task, cmd));
|
({childRes, isTimeout} = yield* spawnProcess(ctx, isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task));
|
||||||
if (childRes && 0 !== childRes.status && !isTimeout && task.getFromChanges()
|
if (childRes && 0 !== childRes.status && !isTimeout && task.getFromChanges()
|
||||||
&& constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML !== dataConvert.formatTo
|
&& constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML !== dataConvert.formatTo
|
||||||
&& !formatChecker.isOOXFormat(dataConvert.formatTo) && !cmd.getWopiParams()) {
|
&& !formatChecker.isOOXFormat(dataConvert.formatTo) && !cmd.getWopiParams()) {
|
||||||
logger.warn('rollback to save changes to ooxml. See assemblyFormatAsOrigin param. formatTo=%s (id=%s)', formatChecker.getStringFromFormat(dataConvert.formatTo), dataConvert.key);
|
ctx.logger.warn('rollback to save changes to ooxml. See assemblyFormatAsOrigin param. formatTo=%s', formatChecker.getStringFromFormat(dataConvert.formatTo));
|
||||||
let extOld = path.extname(dataConvert.fileTo);
|
let extOld = path.extname(dataConvert.fileTo);
|
||||||
let extNew = '.' + formatChecker.getStringFromFormat(constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML);
|
let extNew = '.' + formatChecker.getStringFromFormat(constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML);
|
||||||
dataConvert.formatTo = constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML;
|
dataConvert.formatTo = constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML;
|
||||||
dataConvert.fileTo = dataConvert.fileTo.slice(0, -extOld.length) + extNew;
|
dataConvert.fileTo = dataConvert.fileTo.slice(0, -extOld.length) + extNew;
|
||||||
({childRes, isTimeout} = yield* spawnProcess(isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task, cmd));
|
({childRes, isTimeout} = yield* spawnProcess(ctx, isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(clientStatsD) {
|
if(clientStatsD) {
|
||||||
@ -830,15 +837,15 @@ function* ExecuteTask(task) {
|
|||||||
curDate = new Date();
|
curDate = new Date();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resData = yield* postProcess(cmd, dataConvert, tempDirs, childRes, error, isTimeout);
|
resData = yield* postProcess(ctx, cmd, dataConvert, tempDirs, childRes, error, isTimeout);
|
||||||
logger.debug('postProcess (id=%s)', dataConvert.key);
|
ctx.logger.debug('postProcess');
|
||||||
if(clientStatsD) {
|
if(clientStatsD) {
|
||||||
clientStatsD.timing('conv.postProcess', new Date() - curDate);
|
clientStatsD.timing('conv.postProcess', new Date() - curDate);
|
||||||
curDate = new Date();
|
curDate = new Date();
|
||||||
}
|
}
|
||||||
if (tempDirs) {
|
if (tempDirs) {
|
||||||
fs.rmSync(tempDirs.temp, { recursive: true, force: true });
|
fs.rmSync(tempDirs.temp, { recursive: true, force: true });
|
||||||
logger.debug('deleteFolderRecursive (id=%s)', dataConvert.key);
|
ctx.logger.debug('deleteFolderRecursive');
|
||||||
if(clientStatsD) {
|
if(clientStatsD) {
|
||||||
clientStatsD.timing('conv.deleteFolderRecursive', new Date() - curDate);
|
clientStatsD.timing('conv.deleteFolderRecursive', new Date() - curDate);
|
||||||
curDate = new Date();
|
curDate = new Date();
|
||||||
@ -847,6 +854,7 @@ function* ExecuteTask(task) {
|
|||||||
if(clientStatsD) {
|
if(clientStatsD) {
|
||||||
clientStatsD.timing('conv.allconvert', new Date() - startDate);
|
clientStatsD.timing('conv.allconvert', new Date() - startDate);
|
||||||
}
|
}
|
||||||
|
ctx.logger.info('End Task');
|
||||||
return resData;
|
return resData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -854,13 +862,15 @@ function receiveTask(data, ack) {
|
|||||||
return co(function* () {
|
return co(function* () {
|
||||||
var res = null;
|
var res = null;
|
||||||
var task = null;
|
var task = null;
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
task = new commonDefines.TaskQueueData(JSON.parse(data));
|
task = new commonDefines.TaskQueueData(JSON.parse(data));
|
||||||
if (task) {
|
if (task) {
|
||||||
res = yield* ExecuteTask(task);
|
ctx.initFromTaskQueueData(task);
|
||||||
|
res = yield* ExecuteTask(ctx, task);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err);
|
ctx.logger.error(err);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
if (!res && task) {
|
if (!res && task) {
|
||||||
@ -868,13 +878,14 @@ function receiveTask(data, ack) {
|
|||||||
var cmd = task.getCmd();
|
var cmd = task.getCmd();
|
||||||
cmd.setStatusInfo(constants.CONVERT);
|
cmd.setStatusInfo(constants.CONVERT);
|
||||||
res = new commonDefines.TaskQueueData();
|
res = new commonDefines.TaskQueueData();
|
||||||
|
res.setCtx(ctx);
|
||||||
res.setCmd(cmd);
|
res.setCmd(cmd);
|
||||||
}
|
}
|
||||||
if (res) {
|
if (res) {
|
||||||
yield queue.addResponse(res);
|
yield queue.addResponse(res);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err);
|
ctx.logger.error(err);
|
||||||
} finally {
|
} finally {
|
||||||
ack();
|
ack();
|
||||||
}
|
}
|
||||||
@ -883,10 +894,13 @@ function receiveTask(data, ack) {
|
|||||||
}
|
}
|
||||||
function simulateErrorResponse(data){
|
function simulateErrorResponse(data){
|
||||||
let task = new commonDefines.TaskQueueData(JSON.parse(data));
|
let task = new commonDefines.TaskQueueData(JSON.parse(data));
|
||||||
|
let ctx = new operationContext.Context();
|
||||||
|
ctx.initFromTaskQueueData(task);
|
||||||
//simulate error response
|
//simulate error response
|
||||||
let cmd = task.getCmd();
|
let cmd = task.getCmd();
|
||||||
cmd.setStatusInfo(constants.CONVERT);
|
cmd.setStatusInfo(constants.CONVERT);
|
||||||
let res = new commonDefines.TaskQueueData();
|
let res = new commonDefines.TaskQueueData();
|
||||||
|
task.setCtx(ctx);
|
||||||
res.setCmd(cmd);
|
res.setCmd(cmd);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -895,7 +909,7 @@ function run() {
|
|||||||
queue.on('task', receiveTask);
|
queue.on('task', receiveTask);
|
||||||
queue.init(true, true, true, false, false, false, function(err) {
|
queue.init(true, true, true, false, false, false, function(err) {
|
||||||
if (null != err) {
|
if (null != err) {
|
||||||
logger.error('createTaskQueue error :\r\n%s', err.stack);
|
operationContext.global.logger.error('createTaskQueue error: %s', err.stack);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
const cluster = require('cluster');
|
const cluster = require('cluster');
|
||||||
const logger = require('./../../Common/sources/logger');
|
const logger = require('./../../Common/sources/logger');
|
||||||
|
const operationContext = require('./../../Common/sources/operationContext');
|
||||||
|
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@ -42,12 +43,18 @@ if (cluster.isMaster) {
|
|||||||
const configCommon = require('config');
|
const configCommon = require('config');
|
||||||
const config = configCommon.get('FileConverter.converter');
|
const config = configCommon.get('FileConverter.converter');
|
||||||
const license = require('./../../Common/sources/license');
|
const license = require('./../../Common/sources/license');
|
||||||
|
const tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
|
|
||||||
|
const cfgLicenseFile = configCommon.get('license.license_file');
|
||||||
|
|
||||||
const cfgMaxProcessCount = config.get('maxprocesscount');
|
const cfgMaxProcessCount = config.get('maxprocesscount');
|
||||||
var licenseInfo, workersCount = 0;
|
var workersCount = 0;
|
||||||
const readLicense = function* () {
|
const readLicense = function* () {
|
||||||
[licenseInfo] = yield* license.readLicense();
|
workersCount = Math.ceil(numCPUs * cfgMaxProcessCount);
|
||||||
workersCount = Math.min(licenseInfo.count, Math.ceil(numCPUs * cfgMaxProcessCount));
|
if (!tenantManager.isMultitenantMode()) {
|
||||||
|
let [licenseInfo] = yield* license.readLicense(cfgLicenseFile);
|
||||||
|
workersCount = Math.min(licenseInfo.count, workersCount);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const updateWorkers = () => {
|
const updateWorkers = () => {
|
||||||
var i;
|
var i;
|
||||||
@ -55,7 +62,7 @@ if (cluster.isMaster) {
|
|||||||
if (arrKeyWorkers.length < workersCount) {
|
if (arrKeyWorkers.length < workersCount) {
|
||||||
for (i = arrKeyWorkers.length; i < workersCount; ++i) {
|
for (i = arrKeyWorkers.length; i < workersCount; ++i) {
|
||||||
const newWorker = cluster.fork();
|
const newWorker = cluster.fork();
|
||||||
logger.warn('worker %s started.', newWorker.process.pid);
|
operationContext.global.logger.warn('worker %s started.', newWorker.process.pid);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = workersCount; i < arrKeyWorkers.length; ++i) {
|
for (i = workersCount; i < arrKeyWorkers.length; ++i) {
|
||||||
@ -70,31 +77,33 @@ if (cluster.isMaster) {
|
|||||||
return co(function*() {
|
return co(function*() {
|
||||||
try {
|
try {
|
||||||
yield* readLicense();
|
yield* readLicense();
|
||||||
logger.warn('update cluster with %s workers', workersCount);
|
operationContext.global.logger.warn('update cluster with %s workers', workersCount);
|
||||||
updateWorkers();
|
updateWorkers();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('updateLicense error:\r\n%s', err.stack);
|
operationContext.global.logger.error('updateLicense error: %s', err.stack);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cluster.on('exit', (worker, code, signal) => {
|
cluster.on('exit', (worker, code, signal) => {
|
||||||
logger.warn('worker %s died (code = %s; signal = %s).', worker.process.pid, code, signal);
|
operationContext.global.logger.warn('worker %s died (code = %s; signal = %s).', worker.process.pid, code, signal);
|
||||||
updateWorkers();
|
updateWorkers();
|
||||||
});
|
});
|
||||||
|
|
||||||
updateLicense();
|
updateLicense();
|
||||||
|
|
||||||
fs.watchFile(configCommon.get('license').get('license_file'), updateLicense);
|
if (!tenantManager.isMultitenantMode()) {
|
||||||
|
fs.watchFile(cfgLicenseFile, updateLicense);
|
||||||
setInterval(updateLicense, 86400000);
|
setInterval(updateLicense, 86400000);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const converter = require('./converter');
|
const converter = require('./converter');
|
||||||
converter.run();
|
converter.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on('uncaughtException', (err) => {
|
process.on('uncaughtException', (err) => {
|
||||||
logger.error((new Date).toUTCString() + ' uncaughtException:', err.message);
|
operationContext.global.logger.error((new Date).toUTCString() + ' uncaughtException:', err.message);
|
||||||
logger.error(err.stack);
|
operationContext.global.logger.error(err.stack);
|
||||||
logger.shutdown(() => {
|
logger.shutdown(() => {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -26,6 +26,7 @@ USE onlyoffice;
|
|||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `doc_changes` (
|
CREATE TABLE IF NOT EXISTS `doc_changes` (
|
||||||
|
`tenant` varchar(255) NOT NULL,
|
||||||
`id` varchar(255) NOT NULL,
|
`id` varchar(255) NOT NULL,
|
||||||
`change_id` int(10) unsigned NOT NULL,
|
`change_id` int(10) unsigned NOT NULL,
|
||||||
`user_id` varchar(255) NOT NULL,
|
`user_id` varchar(255) NOT NULL,
|
||||||
@ -33,7 +34,7 @@ CREATE TABLE IF NOT EXISTS `doc_changes` (
|
|||||||
`user_name` varchar(255) NOT NULL,
|
`user_name` varchar(255) NOT NULL,
|
||||||
`change_data` longtext NOT NULL,
|
`change_data` longtext NOT NULL,
|
||||||
`change_date` datetime NOT NULL,
|
`change_date` datetime NOT NULL,
|
||||||
PRIMARY KEY (`id`,`change_id`)
|
PRIMARY KEY (`tenant`, `id`,`change_id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -48,6 +49,7 @@ CREATE TABLE IF NOT EXISTS `doc_changes` (
|
|||||||
--
|
--
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `task_result` (
|
CREATE TABLE IF NOT EXISTS `task_result` (
|
||||||
|
`tenant` varchar(255) NOT NULL,
|
||||||
`id` varchar(255) NOT NULL,
|
`id` varchar(255) NOT NULL,
|
||||||
`status` tinyint(3) NOT NULL,
|
`status` tinyint(3) NOT NULL,
|
||||||
`status_info` int(10) NOT NULL,
|
`status_info` int(10) NOT NULL,
|
||||||
@ -59,7 +61,7 @@ CREATE TABLE IF NOT EXISTS `task_result` (
|
|||||||
`baseurl` text NOT NULL,
|
`baseurl` text NOT NULL,
|
||||||
`password` longtext NULL,
|
`password` longtext NULL,
|
||||||
`additional` longtext NULL,
|
`additional` longtext NULL,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`tenant`, `id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
-- Table structure for doc_changes
|
-- Table structure for doc_changes
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
CREATE TABLE IF NOT EXISTS "public"."doc_changes" (
|
CREATE TABLE IF NOT EXISTS "public"."doc_changes" (
|
||||||
|
"tenant" varchar(255) COLLATE "default" NOT NULL,
|
||||||
"id" varchar(255) COLLATE "default" NOT NULL,
|
"id" varchar(255) COLLATE "default" NOT NULL,
|
||||||
"change_id" int4 NOT NULL,
|
"change_id" int4 NOT NULL,
|
||||||
"user_id" varchar(255) COLLATE "default" NOT NULL,
|
"user_id" varchar(255) COLLATE "default" NOT NULL,
|
||||||
@ -15,7 +16,7 @@ CREATE TABLE IF NOT EXISTS "public"."doc_changes" (
|
|||||||
"user_name" varchar(255) COLLATE "default" NOT NULL,
|
"user_name" varchar(255) COLLATE "default" NOT NULL,
|
||||||
"change_data" text COLLATE "default" NOT NULL,
|
"change_data" text COLLATE "default" NOT NULL,
|
||||||
"change_date" timestamp without time zone NOT NULL,
|
"change_date" timestamp without time zone NOT NULL,
|
||||||
PRIMARY KEY ("id", "change_id")
|
PRIMARY KEY ("tenant", "id", "change_id")
|
||||||
)
|
)
|
||||||
WITH (OIDS=FALSE);
|
WITH (OIDS=FALSE);
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ WITH (OIDS=FALSE);
|
|||||||
-- Table structure for task_result
|
-- Table structure for task_result
|
||||||
-- ----------------------------
|
-- ----------------------------
|
||||||
CREATE TABLE IF NOT EXISTS "public"."task_result" (
|
CREATE TABLE IF NOT EXISTS "public"."task_result" (
|
||||||
|
"tenant" varchar(255) COLLATE "default" NOT NULL,
|
||||||
"id" varchar(255) COLLATE "default" NOT NULL,
|
"id" varchar(255) COLLATE "default" NOT NULL,
|
||||||
"status" int2 NOT NULL,
|
"status" int2 NOT NULL,
|
||||||
"status_info" int4 NOT NULL,
|
"status_info" int4 NOT NULL,
|
||||||
@ -34,11 +36,11 @@ CREATE TABLE IF NOT EXISTS "public"."task_result" (
|
|||||||
"baseurl" text COLLATE "default" NOT NULL,
|
"baseurl" text COLLATE "default" NOT NULL,
|
||||||
"password" text COLLATE "default" NULL,
|
"password" text COLLATE "default" NULL,
|
||||||
"additional" text COLLATE "default" NULL,
|
"additional" text COLLATE "default" NULL,
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("tenant", "id")
|
||||||
)
|
)
|
||||||
WITH (OIDS=FALSE);
|
WITH (OIDS=FALSE);
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION merge_db(_id varchar(255), _status int2, _status_info int4, _last_open_date timestamp without time zone, _user_index int4, _change_id int4, _callback text, _baseurl text, OUT isupdate char(5), OUT userindex int4) AS
|
CREATE OR REPLACE FUNCTION merge_db(_tetant varchar(255), _id varchar(255), _status int2, _status_info int4, _last_open_date timestamp without time zone, _user_index int4, _change_id int4, _callback text, _baseurl text, OUT isupdate char(5), OUT userindex int4) AS
|
||||||
$$
|
$$
|
||||||
DECLARE
|
DECLARE
|
||||||
t_var "public"."task_result"."user_index"%TYPE;
|
t_var "public"."task_result"."user_index"%TYPE;
|
||||||
@ -47,9 +49,9 @@ BEGIN
|
|||||||
-- first try to update the key
|
-- first try to update the key
|
||||||
-- note that "a" must be unique
|
-- note that "a" must be unique
|
||||||
IF ((_callback <> '') IS TRUE) AND ((_baseurl <> '') IS TRUE) THEN
|
IF ((_callback <> '') IS TRUE) AND ((_baseurl <> '') IS TRUE) THEN
|
||||||
UPDATE "public"."task_result" SET last_open_date=_last_open_date, user_index=user_index+1,callback=_callback,baseurl=_baseurl WHERE id = _id RETURNING user_index into userindex;
|
UPDATE "public"."task_result" SET last_open_date=_last_open_date, user_index=user_index+1,callback=_callback,baseurl=_baseurl WHERE tenant = _tetant AND id = _id RETURNING user_index into userindex;
|
||||||
ELSE
|
ELSE
|
||||||
UPDATE "public"."task_result" SET last_open_date=_last_open_date, user_index=user_index+1 WHERE id = _id RETURNING user_index into userindex;
|
UPDATE "public"."task_result" SET last_open_date=_last_open_date, user_index=user_index+1 WHERE tenant = _tetant AND id = _id RETURNING user_index into userindex;
|
||||||
END IF;
|
END IF;
|
||||||
IF found THEN
|
IF found THEN
|
||||||
isupdate := 'true';
|
isupdate := 'true';
|
||||||
@ -59,7 +61,7 @@ BEGIN
|
|||||||
-- if someone else inserts the same key concurrently,
|
-- if someone else inserts the same key concurrently,
|
||||||
-- we could get a unique-key failure
|
-- we could get a unique-key failure
|
||||||
BEGIN
|
BEGIN
|
||||||
INSERT INTO "public"."task_result"(id, status, status_info, last_open_date, user_index, change_id, callback, baseurl) VALUES(_id, _status, _status_info, _last_open_date, _user_index, _change_id, _callback, _baseurl) RETURNING user_index into userindex;
|
INSERT INTO "public"."task_result"(id, status, status_info, last_open_date, user_index, change_id, callback, baseurl) VALUES(_tetant, _id, _status, _status_info, _last_open_date, _user_index, _change_id, _callback, _baseurl) RETURNING user_index into userindex;
|
||||||
isupdate := 'false';
|
isupdate := 'false';
|
||||||
RETURN;
|
RETURN;
|
||||||
EXCEPTION WHEN unique_violation THEN
|
EXCEPTION WHEN unique_violation THEN
|
||||||
|
|||||||
Reference in New Issue
Block a user