mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
Merge remote-tracking branch 'remotes/origin/release/v7.2.0' into develop
This commit is contained in:
@ -27,6 +27,7 @@
|
||||
"endpoint": "http://localhost/s3",
|
||||
"bucketName": "cache",
|
||||
"storageFolderName": "files",
|
||||
"cacheFolderName": "data",
|
||||
"urlExpires": 604800,
|
||||
"accessKeyId": "AKID",
|
||||
"secretAccessKey": "SECRET",
|
||||
@ -103,7 +104,12 @@
|
||||
"baseDomain": "",
|
||||
"filenameSecret": "secret.key",
|
||||
"filenameLicense": "license.lic",
|
||||
"defaultTetant": "tetant"
|
||||
"defaultTenant": "localhost",
|
||||
"cache" : {
|
||||
"stdTTL": 300,
|
||||
"checkperiod": 60,
|
||||
"useClones": false
|
||||
}
|
||||
},
|
||||
"services": {
|
||||
"CoAuthoring": {
|
||||
@ -258,6 +264,7 @@
|
||||
},
|
||||
"sockjs": {
|
||||
"sockjs_url": "",
|
||||
"disable_cors": true,
|
||||
"websocket": true
|
||||
},
|
||||
"callbackBackoffOptions": {
|
||||
|
||||
@ -904,7 +904,7 @@ function OutputMailMerge(mailMergeSendData) {
|
||||
this['title'] = mailMergeSendData.getFileName();
|
||||
const mailFormat = mailMergeSendData.getMailFormat();
|
||||
switch (mailFormat) {
|
||||
case constants.AVS_OFFICESTUDIO_FILE_OTHER_HTMLZIP :
|
||||
case constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_HTML :
|
||||
this['type'] = 0;
|
||||
break;
|
||||
case constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCX :
|
||||
|
||||
@ -37,42 +37,45 @@ var utils = require('./utils');
|
||||
var storage = require('./' + config.get('storage.name'));
|
||||
var tenantManager = require('./tenantManager');
|
||||
|
||||
function getStoragePath(ctx, strPath) {
|
||||
return tenantManager.getTenantPathPrefix(ctx) + strPath.replace(/\\/g, '/')
|
||||
const cfgCacheFolderName = config.get('storage.cacheFolderName');
|
||||
|
||||
function getStoragePath(ctx, strPath, opt_specialDir) {
|
||||
opt_specialDir = opt_specialDir || cfgCacheFolderName;
|
||||
return opt_specialDir + '/' + tenantManager.getTenantPathPrefix(ctx) + strPath.replace(/\\/g, '/')
|
||||
}
|
||||
|
||||
exports.headObject = function(ctx, strPath) {
|
||||
return storage.headObject(getStoragePath(ctx, strPath));
|
||||
exports.headObject = function(ctx, strPath, opt_specialDir) {
|
||||
return storage.headObject(getStoragePath(ctx, strPath, opt_specialDir));
|
||||
};
|
||||
exports.getObject = function(ctx, strPath) {
|
||||
return storage.getObject(getStoragePath(ctx, strPath));
|
||||
exports.getObject = function(ctx, strPath, opt_specialDir) {
|
||||
return storage.getObject(getStoragePath(ctx, strPath, opt_specialDir));
|
||||
};
|
||||
exports.createReadStream = function(ctx, strPath) {
|
||||
return storage.createReadStream(getStoragePath(ctx, strPath));
|
||||
exports.createReadStream = function(ctx, strPath, opt_specialDir) {
|
||||
return storage.createReadStream(getStoragePath(ctx, strPath, opt_specialDir));
|
||||
};
|
||||
exports.putObject = function(ctx, strPath, buffer, contentLength) {
|
||||
return storage.putObject(getStoragePath(ctx, strPath), buffer, contentLength);
|
||||
exports.putObject = function(ctx, strPath, buffer, contentLength, opt_specialDir) {
|
||||
return storage.putObject(getStoragePath(ctx, strPath, opt_specialDir), buffer, contentLength);
|
||||
};
|
||||
exports.uploadObject = function(ctx, strPath, filePath) {
|
||||
return storage.uploadObject(getStoragePath(ctx, strPath), filePath);
|
||||
exports.uploadObject = function(ctx, strPath, filePath, opt_specialDir) {
|
||||
return storage.uploadObject(getStoragePath(ctx, strPath, opt_specialDir), filePath);
|
||||
};
|
||||
exports.copyObject = function(ctx, sourceKey, destinationKey) {
|
||||
let storageSrc = getStoragePath(ctx, sourceKey);
|
||||
let storageDst = getStoragePath(ctx, destinationKey);
|
||||
exports.copyObject = function(ctx, sourceKey, destinationKey, opt_specialDirSrc, opt_specialDirDst) {
|
||||
let storageSrc = getStoragePath(ctx, sourceKey, opt_specialDirSrc);
|
||||
let storageDst = getStoragePath(ctx, destinationKey, opt_specialDirDst);
|
||||
return storage.copyObject(storageSrc, storageDst);
|
||||
};
|
||||
exports.copyPath = function(ctx, sourcePath, destinationPath) {
|
||||
let storageSrc = getStoragePath(ctx, sourcePath);
|
||||
let storageDst = getStoragePath(ctx, destinationPath);
|
||||
exports.copyPath = function(ctx, sourcePath, destinationPath, opt_specialDirSrc, opt_specialDirDst) {
|
||||
let storageSrc = getStoragePath(ctx, sourcePath, opt_specialDirSrc);
|
||||
let storageDst = getStoragePath(ctx, destinationPath, opt_specialDirDst);
|
||||
return storage.listObjects(storageSrc).then(function(list) {
|
||||
return Promise.all(list.map(function(curValue) {
|
||||
return storage.copyObject(curValue, storageDst + '/' + exports.getRelativePath(storageSrc, curValue));
|
||||
}));
|
||||
});
|
||||
};
|
||||
exports.listObjects = function(ctx, strPath) {
|
||||
let prefix = getStoragePath(ctx, "");
|
||||
return storage.listObjects(getStoragePath(ctx, strPath)).then(function(list) {
|
||||
exports.listObjects = function(ctx, strPath, opt_specialDir) {
|
||||
let prefix = getStoragePath(ctx, "", opt_specialDir);
|
||||
return storage.listObjects(getStoragePath(ctx, strPath, opt_specialDir)).then(function(list) {
|
||||
return list.map((currentValue) => {
|
||||
return currentValue.substring(prefix.length);
|
||||
});
|
||||
@ -81,26 +84,26 @@ exports.listObjects = function(ctx, strPath) {
|
||||
return [];
|
||||
});
|
||||
};
|
||||
exports.deleteObject = function(ctx, strPath) {
|
||||
return storage.deleteObject(getStoragePath(ctx, strPath));
|
||||
exports.deleteObject = function(ctx, strPath, opt_specialDir) {
|
||||
return storage.deleteObject(getStoragePath(ctx, strPath, opt_specialDir));
|
||||
};
|
||||
exports.deleteObjects = function(ctx, strPaths) {
|
||||
exports.deleteObjects = function(ctx, strPaths, opt_specialDir) {
|
||||
var StoragePaths = strPaths.map(function(curValue) {
|
||||
return getStoragePath(ctx, curValue);
|
||||
return getStoragePath(ctx, curValue, opt_specialDir);
|
||||
});
|
||||
return storage.deleteObjects(StoragePaths);
|
||||
};
|
||||
exports.deletePath = function(ctx, strPath) {
|
||||
let storageSrc = getStoragePath(ctx, strPath);
|
||||
exports.deletePath = function(ctx, strPath, opt_specialDir) {
|
||||
let storageSrc = getStoragePath(ctx, strPath, opt_specialDir);
|
||||
return storage.listObjects(storageSrc).then(function(list) {
|
||||
return storage.deleteObjects(list);
|
||||
});
|
||||
};
|
||||
exports.getSignedUrl = function(ctx, baseUrl, strPath, urlType, optFilename, opt_creationDate) {
|
||||
return storage.getSignedUrl(baseUrl, getStoragePath(ctx, strPath), urlType, optFilename, opt_creationDate);
|
||||
exports.getSignedUrl = function(ctx, baseUrl, strPath, urlType, optFilename, opt_creationDate, opt_specialDir) {
|
||||
return storage.getSignedUrl(baseUrl, getStoragePath(ctx, strPath, opt_specialDir), urlType, optFilename, opt_creationDate);
|
||||
};
|
||||
exports.getSignedUrls = function(ctx, baseUrl, strPath, urlType, opt_creationDate) {
|
||||
let storageSrc = getStoragePath(ctx, strPath);
|
||||
exports.getSignedUrls = function(ctx, baseUrl, strPath, urlType, opt_creationDate, opt_specialDir) {
|
||||
let storageSrc = getStoragePath(ctx, strPath, opt_specialDir);
|
||||
return storage.listObjects(storageSrc).then(function(list) {
|
||||
return Promise.all(list.map(function(curValue) {
|
||||
return storage.getSignedUrl(baseUrl, curValue, urlType, undefined, opt_creationDate);
|
||||
@ -113,18 +116,18 @@ exports.getSignedUrls = function(ctx, baseUrl, strPath, urlType, opt_creationDat
|
||||
});
|
||||
});
|
||||
};
|
||||
exports.getSignedUrlsArrayByArray = function(ctx, baseUrl, list, urlType) {
|
||||
exports.getSignedUrlsArrayByArray = function(ctx, baseUrl, list, urlType, opt_specialDir) {
|
||||
return Promise.all(list.map(function(curValue) {
|
||||
let storageSrc = getStoragePath(ctx, curValue);
|
||||
let storageSrc = getStoragePath(ctx, curValue, opt_specialDir);
|
||||
return storage.getSignedUrl(baseUrl, storageSrc, urlType, undefined);
|
||||
}));
|
||||
};
|
||||
exports.getSignedUrlsByArray = function(ctx, baseUrl, list, optPath, urlType) {
|
||||
return exports.getSignedUrlsArrayByArray(ctx, baseUrl, list, urlType).then(function(urls) {
|
||||
exports.getSignedUrlsByArray = function(ctx, baseUrl, list, optPath, urlType, opt_specialDir) {
|
||||
return exports.getSignedUrlsArrayByArray(ctx, baseUrl, list, urlType, opt_specialDir).then(function(urls) {
|
||||
var outputMap = {};
|
||||
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
||||
if (optPath) {
|
||||
let storageSrc = getStoragePath(ctx, optPath);
|
||||
let storageSrc = getStoragePath(ctx, optPath, opt_specialDir);
|
||||
outputMap[exports.getRelativePath(storageSrc, list[i])] = urls[i];
|
||||
} else {
|
||||
outputMap[list[i]] = urls[i];
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
|
||||
const config = require('config');
|
||||
const co = require('co');
|
||||
const NodeCache = require( "node-cache" );
|
||||
const license = require('./../../Common/sources/license');
|
||||
const constants = require('./../../Common/sources/constants');
|
||||
const commonDefines = require('./../../Common/sources/commondefines');
|
||||
@ -46,7 +47,8 @@ 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 cfgTenantsDefaultTenant = config.get('tenants.defaultTenant');
|
||||
const cfgTenantsCache = config.get('tenants.cache');
|
||||
const cfgSecretInbox = config.get('services.CoAuthoring.secret.inbox');
|
||||
const cfgSecretOutbox = config.get('services.CoAuthoring.secret.outbox');
|
||||
const cfgSecretSession = config.get('services.CoAuthoring.secret.session');
|
||||
@ -54,19 +56,22 @@ const cfgSecretSession = config.get('services.CoAuthoring.secret.session');
|
||||
let licenseInfo;
|
||||
let licenseOriginal;
|
||||
|
||||
const nodeCache = new NodeCache(cfgTenantsCache);
|
||||
|
||||
function getDefautTenant() {
|
||||
return cfgTenantsDefaultTetant;
|
||||
return cfgTenantsDefaultTenant;
|
||||
}
|
||||
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);
|
||||
domain = domain.replace(/\:.*$/, '');
|
||||
tenant = domain;
|
||||
if (cfgTenantsBaseDomain) {
|
||||
let index = domain.indexOf('.' + cfgTenantsBaseDomain);
|
||||
if (-1 !== index) {
|
||||
tenant = domain.substring(0, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tenant;
|
||||
@ -86,8 +91,14 @@ function getTenantSecret(ctx, type) {
|
||||
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'});
|
||||
res = nodeCache.get(secretPath);
|
||||
if (res) {
|
||||
ctx.logger.debug('getTenantSecret from cache');
|
||||
} else {
|
||||
res = yield readFile(secretPath, {encoding: 'utf8'});
|
||||
nodeCache.set(secretPath, res);
|
||||
ctx.logger.debug('getTenantSecret from %s', secretPath);
|
||||
}
|
||||
} else {
|
||||
switch (type) {
|
||||
case commonDefines.c_oAscSecretType.Browser:
|
||||
@ -116,8 +127,14 @@ function getTenantLicense(ctx) {
|
||||
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);
|
||||
res = nodeCache.get(licensePath);
|
||||
if (res) {
|
||||
ctx.logger.debug('getTenantLicense from cache');
|
||||
} else {
|
||||
[res] = yield* license.readLicense(licensePath);
|
||||
nodeCache.set(licensePath, res);
|
||||
ctx.logger.debug('getTenantLicense from %s', licensePath);
|
||||
}
|
||||
} else {
|
||||
res = licenseInfo;
|
||||
}
|
||||
@ -125,7 +142,7 @@ function getTenantLicense(ctx) {
|
||||
});
|
||||
}
|
||||
function isMultitenantMode() {
|
||||
return !!cfgTenantsBaseDir && !!cfgTenantsBaseDomain;
|
||||
return !!cfgTenantsBaseDir;
|
||||
}
|
||||
|
||||
exports.getDefautTenant = getDefautTenant;
|
||||
|
||||
@ -945,6 +945,7 @@ exports.convertLicenseInfoToFileParams = function(licenseInfo) {
|
||||
license.light = licenseInfo.light;
|
||||
license.branding = licenseInfo.branding;
|
||||
license.customization = licenseInfo.customization;
|
||||
license.advanced_api = licenseInfo.advancedApi;
|
||||
license.plugins = licenseInfo.plugins;
|
||||
license.connections = licenseInfo.connections;
|
||||
license.connections_view = licenseInfo.connectionsView;
|
||||
|
||||
@ -137,7 +137,6 @@ const cfgTokenSessionExpires = ms(config.get('token.session.expires'));
|
||||
const cfgTokenInboxHeader = config.get('token.inbox.header');
|
||||
const cfgTokenInboxPrefix = config.get('token.inbox.prefix');
|
||||
const cfgTokenVerifyOptions = config.get('token.verifyOptions');
|
||||
const cfgSecretSession = config.get('secret.session');
|
||||
const cfgForceSaveEnable = config.get('autoAssembly.enable');
|
||||
const cfgForceSaveInterval = ms(config.get('autoAssembly.interval'));
|
||||
const cfgForceSaveStep = ms(config.get('autoAssembly.step'));
|
||||
@ -465,41 +464,45 @@ let changeConnectionInfo = co.wrap(function*(ctx, conn, cmd) {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
function signToken(payload, algorithm, expiresIn, secretElem) {
|
||||
var options = {algorithm: algorithm, expiresIn: expiresIn};
|
||||
var secret = utils.getSecretByElem(secretElem);
|
||||
return jwt.sign(payload, secret, options);
|
||||
function signToken(ctx, payload, algorithm, expiresIn, secretElem) {
|
||||
return co(function*() {
|
||||
var options = {algorithm: algorithm, expiresIn: expiresIn};
|
||||
let secret = yield tenantManager.getTenantSecret(ctx, secretElem);
|
||||
return jwt.sign(payload, secret, options);
|
||||
});
|
||||
}
|
||||
function needSendChanges (conn){
|
||||
return !conn.user?.view || utils.isLiveViewer(conn);
|
||||
}
|
||||
function fillJwtByConnection(conn) {
|
||||
var payload = {document: {}, editorConfig: {user: {}}};
|
||||
var doc = payload.document;
|
||||
doc.key = conn.docId;
|
||||
doc.permissions = conn.permissions;
|
||||
doc.ds_encrypted = conn.encrypted;
|
||||
var edit = payload.editorConfig;
|
||||
//todo
|
||||
//edit.callbackUrl = callbackUrl;
|
||||
//edit.lang = conn.lang;
|
||||
//edit.mode = conn.mode;
|
||||
var user = edit.user;
|
||||
user.id = conn.user.idOriginal;
|
||||
user.name = conn.user.username;
|
||||
user.index = conn.user.indexUser;
|
||||
if (conn.coEditingMode) {
|
||||
edit.coEditing = {mode: conn.coEditingMode};
|
||||
}
|
||||
//no standart
|
||||
edit.ds_view = conn.user.view;
|
||||
edit.ds_isCloseCoAuthoring = conn.isCloseCoAuthoring;
|
||||
edit.ds_isEnterCorrectPassword = conn.isEnterCorrectPassword;
|
||||
// presenter viewer opens with same session jwt. do not put sessionId to jwt
|
||||
// edit.ds_sessionId = conn.sessionId;
|
||||
edit.ds_sessionTimeConnect = conn.sessionTimeConnect;
|
||||
function fillJwtByConnection(ctx, conn) {
|
||||
return co(function*() {
|
||||
var payload = {document: {}, editorConfig: {user: {}}};
|
||||
var doc = payload.document;
|
||||
doc.key = conn.docId;
|
||||
doc.permissions = conn.permissions;
|
||||
doc.ds_encrypted = conn.encrypted;
|
||||
var edit = payload.editorConfig;
|
||||
//todo
|
||||
//edit.callbackUrl = callbackUrl;
|
||||
//edit.lang = conn.lang;
|
||||
//edit.mode = conn.mode;
|
||||
var user = edit.user;
|
||||
user.id = conn.user.idOriginal;
|
||||
user.name = conn.user.username;
|
||||
user.index = conn.user.indexUser;
|
||||
if (conn.coEditingMode) {
|
||||
edit.coEditing = {mode: conn.coEditingMode};
|
||||
}
|
||||
//no standart
|
||||
edit.ds_view = conn.user.view;
|
||||
edit.ds_isCloseCoAuthoring = conn.isCloseCoAuthoring;
|
||||
edit.ds_isEnterCorrectPassword = conn.isEnterCorrectPassword;
|
||||
// presenter viewer opens with same session jwt. do not put sessionId to jwt
|
||||
// edit.ds_sessionId = conn.sessionId;
|
||||
edit.ds_sessionTimeConnect = conn.sessionTimeConnect;
|
||||
|
||||
return signToken(payload, cfgTokenSessionAlgorithm, cfgTokenSessionExpires / 1000, cfgSecretSession);
|
||||
return yield signToken(ctx, payload, cfgTokenSessionAlgorithm, cfgTokenSessionExpires / 1000, commonDefines.c_oAscSecretType.Session);
|
||||
});
|
||||
}
|
||||
|
||||
function sendData(ctx, conn, data) {
|
||||
@ -526,8 +529,8 @@ function sendDataMeta(ctx, conn, msg) {
|
||||
function sendDataSession(ctx, conn, msg) {
|
||||
sendData(ctx, conn, {type: "session", messages: msg});
|
||||
}
|
||||
function sendDataRefreshToken(ctx, conn) {
|
||||
sendData(ctx, conn, {type: "refreshToken", messages: fillJwtByConnection(conn)});
|
||||
function sendDataRefreshToken(ctx, conn, msg) {
|
||||
sendData(ctx, conn, {type: "refreshToken", messages: msg});
|
||||
}
|
||||
function sendDataRpc(ctx, conn, responseKey, data) {
|
||||
sendData(ctx, conn, {type: "rpc", responseKey: responseKey, data: data});
|
||||
@ -543,12 +546,15 @@ function sendReleaseLock(ctx, conn, userLocks) {
|
||||
})});
|
||||
}
|
||||
function modifyConnectionForPassword(ctx, conn, isEnterCorrectPassword) {
|
||||
if (isEnterCorrectPassword) {
|
||||
conn.isEnterCorrectPassword = true;
|
||||
if (cfgTokenEnableBrowser) {
|
||||
sendDataRefreshToken(ctx, conn);
|
||||
return co(function*() {
|
||||
if (isEnterCorrectPassword) {
|
||||
conn.isEnterCorrectPassword = true;
|
||||
if (cfgTokenEnableBrowser) {
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function getParticipants(docId, excludeClosed, excludeUserId, excludeViewer) {
|
||||
return _.filter(connections, function(el) {
|
||||
@ -1098,7 +1104,7 @@ function* cleanDocumentOnExit(ctx, docId, deleteChanges, opt_userIndex) {
|
||||
yield taskResult.restoreInitialPassword(ctx.tenant, docId);
|
||||
sqlBase.deleteChanges(ctx, docId, null);
|
||||
//delete forgotten after successful send on callbackUrl
|
||||
yield storage.deletePath(ctx, cfgForgottenFiles + '/' + docId);
|
||||
yield storage.deletePath(ctx, docId, cfgForgottenFiles);
|
||||
}
|
||||
yield unlockWopiDoc(ctx, docId, opt_userIndex);
|
||||
}
|
||||
@ -1300,12 +1306,12 @@ exports.install = function(server, callbackFunction) {
|
||||
var sockjs_echo = sockjs.createServer(cfgSockjs);
|
||||
|
||||
sockjs_echo.on('connection', function(conn) {
|
||||
let ctx = new operationContext.Context();
|
||||
ctx.initFromConnection(conn);
|
||||
if (!conn) {
|
||||
operationContext.global.logger.error("null == conn");
|
||||
return;
|
||||
}
|
||||
let ctx = new operationContext.Context();
|
||||
ctx.initFromConnection(conn);
|
||||
if (getIsShutdown()) {
|
||||
sendFileError(ctx, conn, 'Server shutdow');
|
||||
return;
|
||||
@ -1391,8 +1397,8 @@ exports.install = function(server, callbackFunction) {
|
||||
case 'changesError':
|
||||
ctx.logger.error("changesError: %s", data.stack);
|
||||
if (cfgErrorFiles && docId) {
|
||||
let destDir = cfgErrorFiles + '/browser/' + docId;
|
||||
yield storage.copyPath(ctx, docId, destDir);
|
||||
let destDir = 'browser/' + docId;
|
||||
yield storage.copyPath(ctx, docId, destDir, undefined, cfgErrorFiles);
|
||||
yield* saveErrorChanges(ctx, docId, destDir);
|
||||
}
|
||||
break;
|
||||
@ -1485,7 +1491,8 @@ exports.install = function(server, callbackFunction) {
|
||||
conn.isCloseCoAuthoring = true;
|
||||
yield addPresence(ctx, conn, true);
|
||||
if (cfgTokenEnableBrowser) {
|
||||
sendDataRefreshToken(ctx, conn);
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1546,7 +1553,7 @@ exports.install = function(server, callbackFunction) {
|
||||
if (!needSaveChanges) {
|
||||
//start save changes if forgotten file exists.
|
||||
//more effective to send file without sfc, but this method is simpler by code
|
||||
let forgotten = yield storage.listObjects(ctx, cfgForgottenFiles + '/' + docId);
|
||||
let forgotten = yield storage.listObjects(ctx, docId, cfgForgottenFiles);
|
||||
needSaveChanges = forgotten.length > 0;
|
||||
ctx.logger.debug('closeDocument hasForgotten %s', needSaveChanges);
|
||||
}
|
||||
@ -1592,7 +1599,8 @@ exports.install = function(server, callbackFunction) {
|
||||
conn.docId = docIdNew;
|
||||
yield addPresence(ctx, conn, true);
|
||||
if (cfgTokenEnableBrowser) {
|
||||
sendDataRefreshToken(ctx, conn);
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
}
|
||||
}
|
||||
//open
|
||||
@ -2124,6 +2132,7 @@ exports.install = function(server, callbackFunction) {
|
||||
function* auth(ctx, conn, data) {
|
||||
//TODO: Do authorization etc. check md5 or query db
|
||||
if (data.token && data.user) {
|
||||
ctx.setUserId(data.user.id);
|
||||
let licenseInfo = yield tenantManager.getTenantLicense(ctx);
|
||||
//check jwt
|
||||
if (cfgTokenEnableBrowser) {
|
||||
@ -2162,6 +2171,7 @@ exports.install = function(server, callbackFunction) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
ctx.setUserId(data.user.id);
|
||||
|
||||
let docId = data.docid;
|
||||
const user = data.user;
|
||||
@ -2433,7 +2443,7 @@ exports.install = function(server, callbackFunction) {
|
||||
let callback = yield* sendStatusDocument(ctx, docId, c_oAscChangeBase.No, userAction, userIndex, documentCallback, conn.baseUrl);
|
||||
if (!callback && !bIsRestore) {
|
||||
//check forgotten file
|
||||
let forgotten = yield storage.listObjects(ctx, cfgForgottenFiles + '/' + docId);
|
||||
let forgotten = yield storage.listObjects(ctx, docId, cfgForgottenFiles);
|
||||
hasForgotten = forgotten.length > 0;
|
||||
ctx.logger.debug('endAuth hasForgotten %s', hasForgotten);
|
||||
}
|
||||
@ -2507,7 +2517,7 @@ exports.install = function(server, callbackFunction) {
|
||||
}
|
||||
changesJSON += ']\r\n';
|
||||
let buffer = Buffer.from(changesJSON, 'utf8');
|
||||
yield storage.putObject(ctx, changesPrefix + (indexChunk++).toString().padStart(3, '0'), buffer, buffer.length);
|
||||
yield storage.putObject(ctx, changesPrefix + (indexChunk++).toString().padStart(3, '0'), buffer, buffer.length, cfgErrorFiles);
|
||||
}
|
||||
index += cfgMaxRequestChanges;
|
||||
} while (changes && cfgMaxRequestChanges === changes.length);
|
||||
@ -2560,6 +2570,10 @@ exports.install = function(server, callbackFunction) {
|
||||
}
|
||||
let allMessages = yield editorData.getMessages(ctx, docId);
|
||||
allMessages = allMessages.length > 0 ? allMessages : undefined;//todo client side
|
||||
let sessionToken;
|
||||
if (cfgTokenEnableBrowser && !bIsRestore) {
|
||||
sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
}
|
||||
const sendObject = {
|
||||
type: 'auth',
|
||||
result: 1,
|
||||
@ -2570,7 +2584,7 @@ exports.install = function(server, callbackFunction) {
|
||||
locks: docLock,
|
||||
indexUser: conn.user.indexUser,
|
||||
hasForgotten: opt_hasForgotten,
|
||||
jwt: (!bIsRestore && cfgTokenEnableBrowser) ? fillJwtByConnection(conn) : undefined,
|
||||
jwt: sessionToken,
|
||||
g_cAscSpellCheckUrl: cfgEditor["spellcheckerUrl"],
|
||||
buildVersion: commonDefines.buildVersion,
|
||||
buildNumber: commonDefines.buildNumber,
|
||||
@ -2975,6 +2989,7 @@ exports.install = function(server, callbackFunction) {
|
||||
function _checkLicense(ctx, conn) {
|
||||
return co(function* () {
|
||||
try {
|
||||
ctx.logger.info('_checkLicense start');
|
||||
let rights = constants.RIGHTS.Edit;
|
||||
if (config.get('server.edit_singleton')) {
|
||||
// ToDo docId from url ?
|
||||
@ -3005,9 +3020,11 @@ exports.install = function(server, callbackFunction) {
|
||||
liveViewerSupport: (licenseInfo.connectionsView > 0 || licenseInfo.usersViewCount > 0 ),
|
||||
branding: licenseInfo.branding,
|
||||
customization: licenseInfo.customization,
|
||||
advancedApi: licenseInfo.advancedApi,
|
||||
plugins: licenseInfo.plugins
|
||||
}
|
||||
});
|
||||
ctx.logger.info('_checkLicense end');
|
||||
} catch (err) {
|
||||
ctx.logger.error('_checkLicense error: %s', err.stack);
|
||||
}
|
||||
@ -3213,7 +3230,7 @@ exports.install = function(server, callbackFunction) {
|
||||
} else {
|
||||
let url;
|
||||
if (cmd.getInline()) {
|
||||
url = canvasService.getPrintFileUrl(data.needUrlKey, participant.baseUrl, cmd.getTitle());
|
||||
url = yield canvasService.getPrintFileUrl(ctx, data.needUrlKey, participant.baseUrl, cmd.getTitle());
|
||||
outputData.setExtName('.pdf');
|
||||
} else {
|
||||
url = yield storage.getSignedUrl(ctx, participant.baseUrl, data.needUrlKey, data.needUrlType, cmd.getTitle(), data.creationDate);
|
||||
@ -3224,7 +3241,7 @@ exports.install = function(server, callbackFunction) {
|
||||
if (undefined !== data.openedAt) {
|
||||
outputData.setOpenedAt(data.openedAt);
|
||||
}
|
||||
modifyConnectionForPassword(ctx, participant, data.needUrlIsCorrectPassword);
|
||||
yield modifyConnectionForPassword(ctx, participant, data.needUrlIsCorrectPassword);
|
||||
}
|
||||
sendData(ctx, participant, output);
|
||||
}
|
||||
@ -3283,7 +3300,8 @@ exports.install = function(server, callbackFunction) {
|
||||
participant.user.username = cmd.getUserName();
|
||||
yield addPresence(ctx, participant, false);
|
||||
if (cfgTokenEnableBrowser) {
|
||||
sendDataRefreshToken(ctx, participant);
|
||||
let sessionToken = yield fillJwtByConnection(ctx, participant);
|
||||
sendDataRefreshToken(ctx, participant, sessionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3316,6 +3334,7 @@ exports.install = function(server, callbackFunction) {
|
||||
return co(function* () {
|
||||
let ctx = new operationContext.Context();
|
||||
try {
|
||||
let tenants = {};
|
||||
let countEditByShard = 0;
|
||||
let countLiveViewByShard = 0;
|
||||
let countViewByShard = 0;
|
||||
@ -3325,6 +3344,10 @@ exports.install = function(server, callbackFunction) {
|
||||
for (var i = 0; i < connections.length; ++i) {
|
||||
var conn = connections[i];
|
||||
ctx.initFromConnection(conn);
|
||||
let tenant = tenants[ctx.tenant];
|
||||
if (!tenant) {
|
||||
tenant = tenants[ctx.tenant] = {countEditByShard: 0, countLiveViewByShard: 0, countViewByShard: 0};
|
||||
}
|
||||
//wopi access_token_ttl;
|
||||
if (cfgExpSessionAbsolute > 0 || conn.access_token_ttl) {
|
||||
if ((cfgExpSessionAbsolute > 0 && maxMs - conn.sessionTimeConnect > cfgExpSessionAbsolute ||
|
||||
@ -3339,7 +3362,7 @@ exports.install = function(server, callbackFunction) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (cfgExpSessionIdle > 0) {
|
||||
if (cfgExpSessionIdle > 0 && !conn.user?.view) {
|
||||
if (maxMs - conn.sessionTimeLastAction > cfgExpSessionIdle && !conn.sessionIsSendWarning) {
|
||||
conn.sessionIsSendWarning = true;
|
||||
sendDataSession(ctx, conn, {
|
||||
@ -3357,26 +3380,33 @@ exports.install = function(server, callbackFunction) {
|
||||
}
|
||||
yield addPresence(ctx, conn, false);
|
||||
if (utils.isLiveViewer(conn)) {
|
||||
countLiveViewByShard++;
|
||||
tenant.countLiveViewByShard++;
|
||||
} else if(conn.isCloseCoAuthoring || (conn.user && conn.user.view)) {
|
||||
countViewByShard++;
|
||||
tenant.countViewByShard++;
|
||||
} else {
|
||||
countEditByShard++;
|
||||
tenant.countEditByShard++;
|
||||
}
|
||||
}
|
||||
for (let tenantId in tenants) {
|
||||
if(tenants.hasOwnProperty(tenantId)) {
|
||||
ctx.setTenant(tenantId);
|
||||
let tenant = tenants[tenantId];
|
||||
yield* collectStats(ctx, tenant.countEditByShard, tenant.countLiveViewByShard, tenant.countViewByShard);
|
||||
yield editorData.setEditorConnectionsCountByShard(ctx, SHARD_ID, tenant.countEditByShard);
|
||||
yield editorData.setLiveViewerConnectionsCountByShard(ctx, SHARD_ID, tenant.countLiveViewByShard);
|
||||
yield editorData.setViewerConnectionsCountByShard(ctx, SHARD_ID, tenant.countViewByShard);
|
||||
if (clientStatsD) {
|
||||
//todo with multitenant
|
||||
let countEdit = yield editorData.getEditorConnectionsCount(ctx, connections);
|
||||
clientStatsD.gauge('expireDoc.connections.edit', countEdit);
|
||||
let countLiveView = yield editorData.getLiveViewerConnectionsCount(ctx, connections);
|
||||
clientStatsD.gauge('expireDoc.connections.liveview', countLiveView);
|
||||
let countView = yield editorData.getViewerConnectionsCount(ctx, connections);
|
||||
clientStatsD.gauge('expireDoc.connections.view', countView);
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.initDefault();
|
||||
yield* collectStats(ctx, countEditByShard, countLiveViewByShard, countViewByShard);
|
||||
yield editorData.setEditorConnectionsCountByShard(ctx, SHARD_ID, countEditByShard);
|
||||
yield editorData.setLiveViewerConnectionsCountByShard(ctx, SHARD_ID, countLiveViewByShard);
|
||||
yield editorData.setViewerConnectionsCountByShard(ctx, SHARD_ID, countViewByShard);
|
||||
if (clientStatsD) {
|
||||
let countEdit = yield editorData.getEditorConnectionsCount(ctx, connections);
|
||||
clientStatsD.gauge('expireDoc.connections.edit', countEdit);
|
||||
let countLiveView = yield editorData.getLiveViewerConnectionsCount(ctx, connections);
|
||||
clientStatsD.gauge('expireDoc.connections.liveview', countLiveView);
|
||||
let countView = yield editorData.getViewerConnectionsCount(ctx, connections);
|
||||
clientStatsD.gauge('expireDoc.connections.view', countView);
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.logger.error('expireDoc error: %s', err.stack);
|
||||
} finally {
|
||||
|
||||
@ -63,7 +63,6 @@ var cfgRedisPrefix = config.get('services.CoAuthoring.redis.prefix');
|
||||
var cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser');
|
||||
const cfgTokenSessionAlgorithm = config.get('services.CoAuthoring.token.session.algorithm');
|
||||
const cfgTokenSessionExpires = ms(config.get('services.CoAuthoring.token.session.expires'));
|
||||
const cfgSecretSession = config.get('services.CoAuthoring.secret.session');
|
||||
const cfgForgottenFiles = config_server.get('forgottenfiles');
|
||||
const cfgForgottenFilesName = config_server.get('forgottenfilesname');
|
||||
const cfgOpenProtectedFile = config_server.get('openProtectedFile');
|
||||
@ -221,7 +220,7 @@ var getOutputData = co.wrap(function* (ctx, cmd, outputData, key, optConn, optAd
|
||||
if (optConn) {
|
||||
let url;
|
||||
if(cmd.getInline()) {
|
||||
url = getPrintFileUrl(key, optConn.baseUrl, cmd.getTitle());
|
||||
url = yield getPrintFileUrl(ctx, key, optConn.baseUrl, cmd.getTitle());
|
||||
} else {
|
||||
url = yield storage.getSignedUrl(ctx, optConn.baseUrl, strPath, commonDefines.c_oAscUrlTypes.Temporary,
|
||||
cmd.getTitle());
|
||||
@ -487,13 +486,12 @@ function* commandOpen(ctx, conn, cmd, outputData, opt_upsertRes, opt_bIsRestore)
|
||||
|
||||
let updateIfRes = yield taskResult.updateIf(ctx, task, updateMask);
|
||||
if (updateIfRes.affectedRows > 0) {
|
||||
let forgottenId = cfgForgottenFiles + '/' + cmd.getDocId();
|
||||
let forgotten = yield storage.listObjects(ctx, forgottenId);
|
||||
let forgotten = yield storage.listObjects(ctx, cmd.getDocId(), cfgForgottenFiles);
|
||||
//replace url with forgotten file because it absorbed all lost changes
|
||||
if (forgotten.length > 0) {
|
||||
ctx.logger.debug("commandOpen from forgotten");
|
||||
cmd.setUrl(undefined);
|
||||
cmd.setForgotten(forgottenId);
|
||||
cmd.setForgotten(cmd.getDocId());
|
||||
}
|
||||
//add task
|
||||
cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS);
|
||||
@ -530,7 +528,7 @@ function* commandReopen(ctx, conn, cmd, outputData) {
|
||||
if (sqlBase.DocumentPassword.prototype.getCurPassword(ctx, row.password)) {
|
||||
ctx.logger.debug('commandReopen has password');
|
||||
yield* commandOpenFillOutput(ctx, conn, cmd, outputData, false);
|
||||
docsCoServer.modifyConnectionForPassword(ctx, conn, constants.FILE_STATUS_OK === outputData.getStatus());
|
||||
yield docsCoServer.modifyConnectionForPassword(ctx, conn, constants.FILE_STATUS_OK === outputData.getStatus());
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -848,7 +846,7 @@ function* commandSetPassword(ctx, conn, cmd, outputData) {
|
||||
if (upsertRes.affectedRows > 0) {
|
||||
outputData.setStatus('ok');
|
||||
if (!conn.isEnterCorrectPassword) {
|
||||
docsCoServer.modifyConnectionForPassword(ctx, conn, true);
|
||||
yield docsCoServer.modifyConnectionForPassword(ctx, conn, true);
|
||||
}
|
||||
yield docsCoServer.resetForceSaveAfterChanges(ctx, cmd.getDocId(), newChangesLastDate.getTime(), 0, utils.getBaseUrlByConnection(conn), changeInfo);
|
||||
} else {
|
||||
@ -979,8 +977,7 @@ function* commandSfcCallback(ctx, cmd, isSfcm, isEncrypted) {
|
||||
outputSfc.setUserData(cmd.getUserData());
|
||||
if (!isError || isErrorCorrupted) {
|
||||
try {
|
||||
let forgottenId = cfgForgottenFiles + '/' + docId;
|
||||
let forgotten = yield storage.listObjects(ctx, forgottenId);
|
||||
let forgotten = yield storage.listObjects(ctx, docId, cfgForgottenFiles);
|
||||
let isSendHistory = 0 === forgotten.length;
|
||||
if (!isSendHistory) {
|
||||
//check indicator file to determine if opening was from the forgotten file
|
||||
@ -1120,7 +1117,7 @@ function* commandSfcCallback(ctx, cmd, isSfcm, isEncrypted) {
|
||||
try {
|
||||
ctx.logger.warn("storeForgotten");
|
||||
let forgottenName = cfgForgottenFilesName + pathModule.extname(cmd.getOutputPath());
|
||||
yield storage.copyObject(ctx, savePathDoc, cfgForgottenFiles + '/' + docId + '/' + forgottenName);
|
||||
yield storage.copyObject(ctx, savePathDoc, docId + '/' + forgottenName, undefined, cfgForgottenFiles);
|
||||
} catch (err) {
|
||||
ctx.logger.error('Error storeForgotten: %s', err.stack);
|
||||
}
|
||||
@ -1453,17 +1450,19 @@ exports.saveFile = function(req, res) {
|
||||
}
|
||||
});
|
||||
};
|
||||
function getPrintFileUrl(docId, baseUrl, filename) {
|
||||
baseUrl = utils.checkBaseUrl(baseUrl);
|
||||
let token = '';
|
||||
if (cfgTokenEnableBrowser) {
|
||||
let payload = {document: {key: docId}};
|
||||
token = docsCoServer.signToken(payload, cfgTokenSessionAlgorithm, cfgTokenSessionExpires / 1000, cfgSecretSession);
|
||||
}
|
||||
//while save printed file Chrome's extension seems to rely on the resource name set in the URI https://stackoverflow.com/a/53593453
|
||||
//replace '/' with %2f before encodeURIComponent becase nginx determine %2f as '/' and get wrong system path
|
||||
var userFriendlyName = encodeURIComponent(filename.replace(/\//g, "%2f"));
|
||||
return `${baseUrl}/printfile/${encodeURIComponent(docId)}/${userFriendlyName}?token=${encodeURIComponent(token)}&filename=${userFriendlyName}`;
|
||||
function getPrintFileUrl(ctx, docId, baseUrl, filename) {
|
||||
return co(function*() {
|
||||
baseUrl = utils.checkBaseUrl(baseUrl);
|
||||
let token = '';
|
||||
if (cfgTokenEnableBrowser) {
|
||||
let payload = {document: {key: docId}};
|
||||
token = yield docsCoServer.signToken(ctx, payload, cfgTokenSessionAlgorithm, cfgTokenSessionExpires / 1000, commonDefines.c_oAscSecretType.Session);
|
||||
}
|
||||
//while save printed file Chrome's extension seems to rely on the resource name set in the URI https://stackoverflow.com/a/53593453
|
||||
//replace '/' with %2f before encodeURIComponent becase nginx determine %2f as '/' and get wrong system path
|
||||
var userFriendlyName = encodeURIComponent(filename.replace(/\//g, "%2f"));
|
||||
return `${baseUrl}/printfile/${encodeURIComponent(docId)}/${userFriendlyName}?token=${encodeURIComponent(token)}&filename=${userFriendlyName}`;
|
||||
});
|
||||
}
|
||||
exports.getPrintFileUrl = getPrintFileUrl;
|
||||
exports.printFile = function(req, res) {
|
||||
|
||||
@ -122,22 +122,20 @@ exports.uploadImageFileOld = function(req, res) {
|
||||
let ctx = new operationContext.Context();
|
||||
ctx.initFromRequest(req);
|
||||
var docId = req.params.docid;
|
||||
var userid = req.params.userid;
|
||||
ctx.init(ctx.tenant, docId, userid);
|
||||
ctx.setDocId(docId);
|
||||
ctx.logger.debug('Start uploadImageFileOld');
|
||||
if (cfgTokenEnableBrowser) {
|
||||
var checkJwtRes = yield* checkJwtUpload(ctx, 'uploadImageFileOld', req.query['token']);
|
||||
if(!checkJwtRes.err){
|
||||
docId = checkJwtRes.docId || docId;
|
||||
userid = checkJwtRes.userid || userid;
|
||||
ctx.setDocId(docId);
|
||||
ctx.setUserId(checkJwtRes.userid);
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ctx.init(ctx.tenant, docId, userid);
|
||||
var listImages = [];
|
||||
//todo userid
|
||||
if (docId) {
|
||||
var isError = false;
|
||||
var form = new multiparty.Form();
|
||||
@ -176,7 +174,7 @@ exports.uploadImageFileOld = function(req, res) {
|
||||
ctx.logger.error('Error parsing form part:%s', err.toString());
|
||||
});
|
||||
});
|
||||
form.on('close', function() {
|
||||
form.once('close', function() {
|
||||
if (isError) {
|
||||
res.sendStatus(400);
|
||||
} else {
|
||||
@ -193,8 +191,8 @@ exports.uploadImageFileOld = function(req, res) {
|
||||
ctx.logger.debug('End uploadImageFileOld:%s', output);
|
||||
}
|
||||
).catch(function(err) {
|
||||
ctx.logger.error('error getSignedUrlsByArray:%s', err.stack);
|
||||
res.sendStatus(400);
|
||||
ctx.logger.error('upload getSignedUrlsByArray:%s', err.stack);
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -229,11 +227,12 @@ exports.uploadImageFile = function(req, res) {
|
||||
if (!transformedRes.err) {
|
||||
docId = transformedRes.docId || docId;
|
||||
encrypted = transformedRes.encrypted;
|
||||
ctx.setDocId(docId);
|
||||
ctx.setUserId(transformedRes.userid);
|
||||
} else {
|
||||
isValidJwt = false;
|
||||
}
|
||||
}
|
||||
ctx.setDocId(docId);
|
||||
|
||||
if (isValidJwt && docId && req.body && Buffer.isBuffer(req.body)) {
|
||||
let buffer = req.body;
|
||||
|
||||
@ -218,8 +218,9 @@ docsCoServer.install(server, () => {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
});
|
||||
app.post('/uploadold/:docid/:userid/:index', fileUploaderService.uploadImageFileOld);
|
||||
app.post('/upload/:docid/:userid/:index', rawFileParser, fileUploaderService.uploadImageFile);
|
||||
//'*' for backward compatible
|
||||
app.post('/uploadold/:docid*', fileUploaderService.uploadImageFileOld);
|
||||
app.post('/upload/:docid*', rawFileParser, fileUploaderService.uploadImageFile);
|
||||
|
||||
app.post('/downloadas/:docid', rawFileParser, canvasService.downloadAs);
|
||||
app.post('/savefile/:docid', rawFileParser, canvasService.saveFile);
|
||||
|
||||
@ -74,6 +74,7 @@ var cfgInputLimits = configConverter.get('inputLimits');
|
||||
const cfgStreamWriterBufferSize = configConverter.get('streamWriterBufferSize');
|
||||
//cfgMaxRequestChanges was obtained as a result of the test: 84408 changes - 5,16 MB
|
||||
const cfgMaxRequestChanges = config.get('services.CoAuthoring.server.maxRequestChanges');
|
||||
const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles');
|
||||
const cfgForgottenFilesName = config.get('services.CoAuthoring.server.forgottenfilesname');
|
||||
const cfgNewFileTemplate = config.get('services.CoAuthoring.server.newFileTemplate');
|
||||
|
||||
@ -346,8 +347,8 @@ function* downloadFile(ctx, uri, fileFrom, withAuthorization, filterPrivate, opt
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function* downloadFileFromStorage(ctx, strPath, dir) {
|
||||
var list = yield storage.listObjects(ctx, strPath);
|
||||
function* downloadFileFromStorage(ctx, strPath, dir, opt_specialDir) {
|
||||
var list = yield storage.listObjects(ctx, strPath, opt_specialDir);
|
||||
ctx.logger.debug('downloadFileFromStorage list %s', list.toString());
|
||||
//create dirs
|
||||
var dirsToCreate = [];
|
||||
@ -374,7 +375,7 @@ function* downloadFileFromStorage(ctx, strPath, dir) {
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
var file = list[i];
|
||||
var fileRel = storage.getRelativePath(strPath, file);
|
||||
var data = yield storage.getObject(ctx, file);
|
||||
var data = yield storage.getObject(ctx, file, opt_specialDir);
|
||||
fs.writeFileSync(path.join(dir, fileRel), data);
|
||||
}
|
||||
}
|
||||
@ -617,7 +618,7 @@ function* postProcess(ctx, cmd, dataConvert, tempDirs, childRes, error, isTimeou
|
||||
writeProcessOutputToLog(ctx, childRes, false);
|
||||
ctx.logger.error('ExitCode (code=%d;signal=%s;error:%d)', exitCode, exitSignal, error);
|
||||
if (cfgErrorFiles) {
|
||||
yield* processUploadToStorage(ctx, tempDirs.temp, cfgErrorFiles + '/' + dataConvert.key);
|
||||
yield* processUploadToStorage(ctx, tempDirs.temp, dataConvert.key, cfgErrorFiles);
|
||||
ctx.logger.debug('processUploadToStorage error complete(id=%s)', dataConvert.key);
|
||||
}
|
||||
}
|
||||
@ -791,7 +792,7 @@ function* ExecuteTask(ctx, task) {
|
||||
}
|
||||
error = yield* processDownloadFromStorage(ctx, dataConvert, cmd, task, tempDirs, authorProps);
|
||||
} else if (cmd.getForgotten()) {
|
||||
yield* downloadFileFromStorage(ctx, cmd.getForgotten(), tempDirs.source);
|
||||
yield* downloadFileFromStorage(ctx, cmd.getForgotten(), tempDirs.source, cfgForgottenFiles);
|
||||
ctx.logger.debug('downloadFileFromStorage complete');
|
||||
let list = yield utils.listObjects(tempDirs.source, false);
|
||||
if (list.length > 0) {
|
||||
@ -816,21 +817,16 @@ function* ExecuteTask(ctx, task) {
|
||||
let childRes = null;
|
||||
let isTimeout = false;
|
||||
if (constants.NO_ERROR === error) {
|
||||
if(constants.AVS_OFFICESTUDIO_FILE_OTHER_HTMLZIP === dataConvert.formatTo && cmd.getSaveKey() && !dataConvert.mailMergeSend) {
|
||||
//todo заглушка.вся конвертация на клиенте, но нет простого механизма сохранения на клиенте
|
||||
yield utils.pipeFiles(dataConvert.fileFrom, dataConvert.fileTo);
|
||||
} else {
|
||||
({childRes, isTimeout} = yield* spawnProcess(ctx, isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task));
|
||||
if (childRes && 0 !== childRes.status && !isTimeout && task.getFromChanges()
|
||||
&& constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML !== dataConvert.formatTo
|
||||
&& !formatChecker.isOOXFormat(dataConvert.formatTo) && !cmd.getWopiParams()) {
|
||||
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 extNew = '.' + formatChecker.getStringFromFormat(constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML);
|
||||
dataConvert.formatTo = constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML;
|
||||
dataConvert.fileTo = dataConvert.fileTo.slice(0, -extOld.length) + extNew;
|
||||
({childRes, isTimeout} = yield* spawnProcess(ctx, isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task));
|
||||
if (childRes && 0 !== childRes.status && !isTimeout && task.getFromChanges()
|
||||
&& constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML !== dataConvert.formatTo
|
||||
&& !formatChecker.isOOXFormat(dataConvert.formatTo) && !cmd.getWopiParams()) {
|
||||
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 extNew = '.' + formatChecker.getStringFromFormat(constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML);
|
||||
dataConvert.formatTo = constants.AVS_OFFICESTUDIO_FILE_OTHER_OOXML;
|
||||
dataConvert.fileTo = dataConvert.fileTo.slice(0, -extOld.length) + extNew;
|
||||
({childRes, isTimeout} = yield* spawnProcess(ctx, isBuilder, tempDirs, dataConvert, authorProps, getTaskTime, task));
|
||||
}
|
||||
}
|
||||
if(clientStatsD) {
|
||||
clientStatsD.timing('conv.spawnSync', new Date() - curDate);
|
||||
|
||||
@ -40,7 +40,7 @@ PRIMARY KEY ("tenant", "id")
|
||||
)
|
||||
WITH (OIDS=FALSE);
|
||||
|
||||
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
|
||||
CREATE OR REPLACE FUNCTION merge_db(_tenant 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
|
||||
t_var "public"."task_result"."user_index"%TYPE;
|
||||
@ -49,9 +49,9 @@ BEGIN
|
||||
-- first try to update the key
|
||||
-- note that "a" must be unique
|
||||
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 tenant = _tetant AND 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 = _tenant AND id = _id RETURNING user_index into userindex;
|
||||
ELSE
|
||||
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;
|
||||
UPDATE "public"."task_result" SET last_open_date=_last_open_date, user_index=user_index+1 WHERE tenant = _tenant AND id = _id RETURNING user_index into userindex;
|
||||
END IF;
|
||||
IF found THEN
|
||||
isupdate := 'true';
|
||||
@ -61,7 +61,7 @@ BEGIN
|
||||
-- if someone else inserts the same key concurrently,
|
||||
-- we could get a unique-key failure
|
||||
BEGIN
|
||||
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;
|
||||
INSERT INTO "public"."task_result"(id, status, status_info, last_open_date, user_index, change_id, callback, baseurl) VALUES(_tenant, _id, _status, _status_info, _last_open_date, _user_index, _change_id, _callback, _baseurl) RETURNING user_index into userindex;
|
||||
isupdate := 'false';
|
||||
RETURN;
|
||||
EXCEPTION WHEN unique_violation THEN
|
||||
|
||||
Reference in New Issue
Block a user