mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
v5.1.5
This commit is contained in:
@ -182,7 +182,8 @@
|
||||
}
|
||||
},
|
||||
"license" : {
|
||||
"license_file": ""
|
||||
"license_file": "",
|
||||
"warning_limit_percents": "70"
|
||||
},
|
||||
"FileConverter": {
|
||||
"converter": {
|
||||
|
||||
@ -47,7 +47,8 @@
|
||||
}
|
||||
},
|
||||
"license": {
|
||||
"license_file": "./../../license.lic"
|
||||
"license_file": "./../../license.lic",
|
||||
"warning_limit_percents": "70"
|
||||
},
|
||||
"FileConverter": {
|
||||
"converter": {
|
||||
|
||||
@ -47,7 +47,8 @@
|
||||
}
|
||||
},
|
||||
"license": {
|
||||
"license_file": "./../../license.lic"
|
||||
"license_file": "./../../license.lic",
|
||||
"warning_limit_percents": "70"
|
||||
},
|
||||
"FileConverter": {
|
||||
"converter": {
|
||||
|
||||
@ -42,7 +42,8 @@
|
||||
}
|
||||
},
|
||||
"license": {
|
||||
"license_file": "/var/www/onlyoffice/Data/license.lic"
|
||||
"license_file": "/var/www/onlyoffice/Data/license.lic",
|
||||
"warning_limit_percents": "70"
|
||||
},
|
||||
"FileConverter": {
|
||||
"converter": {
|
||||
|
||||
@ -42,7 +42,8 @@
|
||||
}
|
||||
},
|
||||
"license": {
|
||||
"license_file": "./../../license.lic"
|
||||
"license_file": "./../../license.lic",
|
||||
"warning_limit_percents": "70"
|
||||
},
|
||||
"FileConverter": {
|
||||
"converter": {
|
||||
|
||||
@ -53,14 +53,16 @@ exports.LICENSE_MODE = {
|
||||
};
|
||||
|
||||
exports.LICENSE_RESULT = {
|
||||
Error : 1,
|
||||
Expired : 2,
|
||||
Success : 3,
|
||||
UnknownUser : 4,
|
||||
Connections : 5,
|
||||
ExpiredTrial: 6,
|
||||
SuccessLimit: 7,
|
||||
UsersCount : 8
|
||||
Error : 1,
|
||||
Expired : 2,
|
||||
Success : 3,
|
||||
UnknownUser : 4,
|
||||
Connections : 5,
|
||||
ExpiredTrial : 6,
|
||||
SuccessLimit : 7,
|
||||
UsersCount : 8,
|
||||
ConnectionsOS : 9,
|
||||
UsersCountOS : 10
|
||||
};
|
||||
|
||||
exports.LICENSE_CONNECTIONS = 20;
|
||||
@ -223,3 +225,5 @@ exports.CONTENT_DISPOSITION_INLINE = 'inline';
|
||||
exports.CONTENT_DISPOSITION_ATTACHMENT = 'attachment';
|
||||
|
||||
exports.CONN_CLOSED = 3;
|
||||
|
||||
exports.FILE_STATUS_UPDATE_VERSION = 'updateversion';
|
||||
|
||||
@ -63,12 +63,13 @@ exports.readLicense = function*() {
|
||||
branding: false,
|
||||
connections: constants.LICENSE_CONNECTIONS,
|
||||
usersCount: 0,
|
||||
usersExpire: constants.LICENSE_EXPIRE_USERS_ONE_DAY
|
||||
usersExpire: constants.LICENSE_EXPIRE_USERS_ONE_DAY,
|
||||
hasLicense: false
|
||||
};
|
||||
let checkFile = false;
|
||||
try {
|
||||
const oFile = fs.readFileSync(configL.get('license_file')).toString();
|
||||
checkFile = true;
|
||||
res.hasLicense = checkFile = true;
|
||||
const oLicense = JSON.parse(oFile);
|
||||
const sign = oLicense['signature'];
|
||||
delete oLicense['signature'];
|
||||
@ -127,7 +128,7 @@ exports.readLicense = function*() {
|
||||
}
|
||||
if (res.type === c_LR.Expired || res.type === c_LR.ExpiredTrial) {
|
||||
res.count = 1;
|
||||
logger.error('License Expired!!!');
|
||||
logger.error('License: License Expired!!!');
|
||||
}
|
||||
|
||||
if (checkFile) {
|
||||
|
||||
@ -143,6 +143,7 @@ const cfgForceSaveStep = ms(config.get('autoAssembly.step'));
|
||||
const cfgQueueRetentionPeriod = configCommon.get('queue.retentionPeriod');
|
||||
const cfgForgottenFiles = config.get('server.forgottenfiles');
|
||||
const cfgMaxRequestChanges = config.get('server.maxRequestChanges');
|
||||
const cfgWarningLimitPercents = configCommon.get('license.warning_limit_percents') / 100;
|
||||
|
||||
const redisKeySaveLock = cfgRedisPrefix + constants.REDIS_KEY_SAVE_LOCK;
|
||||
const redisKeyPresenceHash = cfgRedisPrefix + constants.REDIS_KEY_PRESENCE_HASH;
|
||||
@ -829,7 +830,7 @@ function handleDeadLetter(data) {
|
||||
* @param callback
|
||||
* @param baseUrl
|
||||
*/
|
||||
function* sendStatusDocument(docId, bChangeBase, userAction, callback, baseUrl, opt_userData) {
|
||||
function* sendStatusDocument(docId, bChangeBase, userAction, callback, baseUrl, opt_userData, opt_forceClose) {
|
||||
if (!callback) {
|
||||
var getRes = yield* getCallback(docId);
|
||||
if (getRes) {
|
||||
@ -847,7 +848,7 @@ function* sendStatusDocument(docId, bChangeBase, userAction, callback, baseUrl,
|
||||
var participants = yield* getOriginalParticipantsId(docId);
|
||||
if (0 === participants.length) {
|
||||
var puckerIndex = yield* getChangesIndex(docId);
|
||||
if (!(puckerIndex > 0)) {
|
||||
if (!(puckerIndex > 0) || opt_forceClose) {
|
||||
status = c_oAscServerStatus.Closed;
|
||||
}
|
||||
}
|
||||
@ -999,10 +1000,10 @@ function* cleanDocumentOnExit(docId, deleteChanges) {
|
||||
yield storage.deletePath(cfgForgottenFiles + '/' + docId);
|
||||
}
|
||||
}
|
||||
function* cleanDocumentOnExitNoChanges(docId, opt_userId) {
|
||||
function* cleanDocumentOnExitNoChanges(docId, opt_userId, opt_forceClose) {
|
||||
var userAction = opt_userId ? new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, opt_userId) : null;
|
||||
// Отправляем, что все ушли и нет изменений (чтобы выставить статус на сервере об окончании редактирования)
|
||||
yield* sendStatusDocument(docId, c_oAscChangeBase.No, userAction);
|
||||
yield* sendStatusDocument(docId, c_oAscChangeBase.No, userAction, undefined, undefined, undefined, opt_forceClose);
|
||||
//если пользователь зашел в документ, соединение порвалось, на сервере удалилась вся информация,
|
||||
//при восстановлении соединения userIndex сохранится и он совпадет с userIndex следующего пользователя
|
||||
yield* cleanDocumentOnExit(docId, false);
|
||||
@ -2052,6 +2053,8 @@ exports.install = function(server, callbackFunction) {
|
||||
// error version
|
||||
yield* sendFileErrorAuth(conn, data.sessionId, 'Update Version error');
|
||||
return;
|
||||
} else if (taskResult.FileStatus.None === status && conn.encrypted) {
|
||||
//ok
|
||||
} else {
|
||||
// Other error
|
||||
yield* sendFileErrorAuth(conn, data.sessionId, 'Other error');
|
||||
@ -2695,6 +2698,7 @@ exports.install = function(server, callbackFunction) {
|
||||
}
|
||||
|
||||
function* _checkLicenseAuth(userId) {
|
||||
let licenseWarningLimit = false;
|
||||
const c_LR = constants.LICENSE_RESULT;
|
||||
let licenseType = licenseInfo.type;
|
||||
if (licenseInfo.usersCount) {
|
||||
@ -2712,6 +2716,7 @@ exports.install = function(server, callbackFunction) {
|
||||
} else {
|
||||
licenseType = -1 === execRes[0].indexOf(userId) ? c_LR.UsersCount : c_LR.Success;
|
||||
}
|
||||
licenseWarningLimit = licenseInfo.usersCount * cfgWarningLimitPercents <= execRes[0].length;
|
||||
}
|
||||
} else {
|
||||
// Warning. Cluster version or if workers > 1 will work with increasing numbers.
|
||||
@ -2727,6 +2732,7 @@ exports.install = function(server, callbackFunction) {
|
||||
return true !== el.isCloseCoAuthoring && el.user.view !== true;
|
||||
})).length;
|
||||
licenseType = (connectionsCount > editConnectionsCount) ? licenseType : c_LR.Connections;
|
||||
licenseWarningLimit = connectionsCount * cfgWarningLimitPercents <= editConnectionsCount;
|
||||
}
|
||||
/*if (constants.PACKAGE_TYPE_OS === licenseInfo.packageType && c_LR.Error === licenseType) {
|
||||
licenseType = c_LR.SuccessLimit;
|
||||
@ -2760,6 +2766,20 @@ exports.install = function(server, callbackFunction) {
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if (c_LR.UsersCount === licenseType) {
|
||||
if (!licenseInfo.hasLicense) {
|
||||
licenseType = c_LR.UsersCountOS;
|
||||
}
|
||||
logger.error('License: User limit exceeded!!!');
|
||||
} else if (c_LR.Connections === licenseType) {
|
||||
if (!licenseInfo.hasLicense) {
|
||||
licenseType = c_LR.ConnectionsOS;
|
||||
}
|
||||
logger.error('License: Connection limit exceeded!!!');
|
||||
} else if (licenseWarningLimit) {
|
||||
logger.warn('License: Warning limit exceeded!!!');
|
||||
}
|
||||
return licenseType;
|
||||
}
|
||||
|
||||
|
||||
@ -139,7 +139,7 @@ function* getOutputData(cmd, outputData, key, status, statusInfo, optConn, optAd
|
||||
(!opt_bIsRestore && taskResult.FileStatus.UpdateVersion === status &&
|
||||
Date.now() - statusInfo * 60000 > cfgExpUpdateVersionStatus)) {
|
||||
if ((optConn && optConn.user.view) || optConn.isCloseCoAuthoring) {
|
||||
outputData.setStatus('updateversion');
|
||||
outputData.setStatus(constants.FILE_STATUS_UPDATE_VERSION);
|
||||
} else {
|
||||
if (taskResult.FileStatus.UpdateVersion === status) {
|
||||
logger.warn("UpdateVersion expired: docId = %s", docId);
|
||||
@ -155,11 +155,11 @@ function* getOutputData(cmd, outputData, key, status, statusInfo, optConn, optAd
|
||||
if (updateIfRes.affectedRows > 0) {
|
||||
outputData.setStatus('ok');
|
||||
} else {
|
||||
outputData.setStatus('updateversion');
|
||||
outputData.setStatus(constants.FILE_STATUS_UPDATE_VERSION);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
outputData.setStatus('updateversion');
|
||||
outputData.setStatus(constants.FILE_STATUS_UPDATE_VERSION);
|
||||
}
|
||||
var command = cmd.getCommand();
|
||||
if ('open' != command && 'reopen' != command && !cmd.getOutputUrls()) {
|
||||
@ -317,7 +317,13 @@ function* commandOpen(conn, cmd, outputData, opt_upsertRes, opt_bIsRestore) {
|
||||
if (!bCreate) {
|
||||
needAddTask = yield* commandOpenFillOutput(conn, cmd, outputData, opt_bIsRestore);
|
||||
}
|
||||
if (needAddTask) {
|
||||
if (conn.encrypted) {
|
||||
logger.debug("commandOpen encrypted %j: docId = %s", outputData, cmd.getDocId());
|
||||
if (constants.FILE_STATUS_UPDATE_VERSION !== outputData.getStatus()) {
|
||||
//don't send output data
|
||||
outputData.setStatus(undefined);
|
||||
}
|
||||
} else if (needAddTask) {
|
||||
let updateMask = new taskResult.TaskResultData();
|
||||
updateMask.key = cmd.getDocId();
|
||||
updateMask.status = taskResult.FileStatus.None;
|
||||
@ -328,35 +334,35 @@ function* commandOpen(conn, cmd, outputData, opt_upsertRes, opt_bIsRestore) {
|
||||
task.statusInfo = constants.NO_ERROR;
|
||||
|
||||
let updateIfRes = yield taskResult.updateIf(task, updateMask);
|
||||
if (updateIfRes.affectedRows > 0) {
|
||||
let forgottenId = cfgForgottenFiles + '/' + cmd.getDocId();
|
||||
let forgotten = yield storage.listObjects(forgottenId);
|
||||
//replace url with forgotten file because it absorbed all lost changes
|
||||
if (forgotten.length > 0) {
|
||||
logger.debug("commandOpen from forgotten: docId = %s", cmd.getDocId());
|
||||
cmd.setUrl(undefined);
|
||||
cmd.setForgotten(forgottenId);
|
||||
if (updateIfRes.affectedRows > 0) {
|
||||
let forgottenId = cfgForgottenFiles + '/' + cmd.getDocId();
|
||||
let forgotten = yield storage.listObjects(forgottenId);
|
||||
//replace url with forgotten file because it absorbed all lost changes
|
||||
if (forgotten.length > 0) {
|
||||
logger.debug("commandOpen from forgotten: docId = %s", cmd.getDocId());
|
||||
cmd.setUrl(undefined);
|
||||
cmd.setForgotten(forgottenId);
|
||||
}
|
||||
//add task
|
||||
cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS);
|
||||
cmd.setEmbeddedFonts(false);
|
||||
var dataQueue = new commonDefines.TaskQueueData();
|
||||
dataQueue.setCmd(cmd);
|
||||
dataQueue.setToFile('Editor.bin');
|
||||
var priority = constants.QUEUE_PRIORITY_HIGH;
|
||||
var formatIn = formatChecker.getFormatFromString(cmd.getFormat());
|
||||
//decrease pdf, djvu, xps convert priority becase long open time
|
||||
if (constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === formatIn ||
|
||||
constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU === formatIn ||
|
||||
constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS === formatIn) {
|
||||
priority = constants.QUEUE_PRIORITY_LOW;
|
||||
}
|
||||
yield* docsCoServer.addTask(dataQueue, priority);
|
||||
} else {
|
||||
yield* commandOpenFillOutput(conn, cmd, outputData, opt_bIsRestore);
|
||||
}
|
||||
//add task
|
||||
cmd.setOutputFormat(constants.AVS_OFFICESTUDIO_FILE_CANVAS);
|
||||
cmd.setEmbeddedFonts(false);
|
||||
var dataQueue = new commonDefines.TaskQueueData();
|
||||
dataQueue.setCmd(cmd);
|
||||
dataQueue.setToFile('Editor.bin');
|
||||
var priority = constants.QUEUE_PRIORITY_HIGH;
|
||||
var formatIn = formatChecker.getFormatFromString(cmd.getFormat());
|
||||
//decrease pdf, djvu, xps convert priority becase long open time
|
||||
if (constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === formatIn ||
|
||||
constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU === formatIn ||
|
||||
constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS === formatIn) {
|
||||
priority = constants.QUEUE_PRIORITY_LOW;
|
||||
}
|
||||
yield* docsCoServer.addTask(dataQueue, priority);
|
||||
} else {
|
||||
yield* commandOpenFillOutput(conn, cmd, outputData, opt_bIsRestore);
|
||||
}
|
||||
}
|
||||
}
|
||||
function* commandOpenFillOutput(conn, cmd, outputData, opt_bIsRestore) {
|
||||
let needAddTask = false;
|
||||
let selectRes = yield taskResult.select(cmd.getDocId());
|
||||
@ -401,15 +407,6 @@ function* commandReopen(cmd) {
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function* commandOpenEncrypted(cmd) {
|
||||
//todo if None, NeedPassword
|
||||
let updateTask = new taskResult.TaskResultData();
|
||||
updateTask.key = cmd.getDocId();
|
||||
updateTask.status = taskResult.FileStatus.Ok;
|
||||
updateTask.statusInfo = constants.NO_ERROR;
|
||||
|
||||
yield taskResult.update(updateTask);
|
||||
}
|
||||
function* commandSave(cmd, outputData) {
|
||||
var completeParts = yield* saveParts(cmd, "Editor.bin");
|
||||
if (completeParts) {
|
||||
@ -640,191 +637,207 @@ function checkAuthorizationLength(authorization, data){
|
||||
function* commandSfcCallback(cmd, isSfcm, isEncrypted) {
|
||||
var docId = cmd.getDocId();
|
||||
logger.debug('Start commandSfcCallback: docId = %s', docId);
|
||||
var saveKey = cmd.getSaveKey();
|
||||
var statusInfo = cmd.getStatusInfo();
|
||||
var isError = constants.NO_ERROR != statusInfo;
|
||||
var isErrorCorrupted = constants.CONVERT_CORRUPTED == statusInfo;
|
||||
var savePathDoc = saveKey + '/' + cmd.getOutputPath();
|
||||
var savePathChanges = saveKey + '/changes.zip';
|
||||
var savePathHistory = saveKey + '/changesHistory.json';
|
||||
var getRes = yield* docsCoServer.getCallback(docId);
|
||||
var forceSave = cmd.getForceSave();
|
||||
var forceSaveType = forceSave ? forceSave.getType() : commonDefines.c_oAscForceSaveTypes.Command;
|
||||
var isSfcmSuccess = false;
|
||||
let storeForgotten = false;
|
||||
let replyStr;
|
||||
var statusOk;
|
||||
var statusErr;
|
||||
if (isSfcm) {
|
||||
statusOk = docsCoServer.c_oAscServerStatus.MustSaveForce;
|
||||
statusErr = docsCoServer.c_oAscServerStatus.CorruptedForce;
|
||||
} else {
|
||||
statusOk = docsCoServer.c_oAscServerStatus.MustSave;
|
||||
statusErr = docsCoServer.c_oAscServerStatus.Corrupted;
|
||||
}
|
||||
let updateMask = new taskResult.TaskResultData();
|
||||
updateMask.key = docId;
|
||||
if (!isEncrypted) {
|
||||
updateMask.status = taskResult.FileStatus.SaveVersion;
|
||||
updateMask.statusInfo = cmd.getData();
|
||||
} else {
|
||||
updateMask.status = taskResult.FileStatus.Ok;
|
||||
}
|
||||
let updateIfTask = new taskResult.TaskResultData();
|
||||
updateIfTask.status = taskResult.FileStatus.UpdateVersion;
|
||||
updateIfTask.statusInfo = Math.floor(Date.now() / 60000);//minutes
|
||||
let updateIfRes;
|
||||
if (getRes) {
|
||||
logger.debug('Callback commandSfcCallback: docId = %s callback = %s', docId, getRes.server.href);
|
||||
var outputSfc = new commonDefines.OutputSfcData();
|
||||
outputSfc.setKey(docId);
|
||||
outputSfc.setEncrypted(isEncrypted);
|
||||
var users = [];
|
||||
let isOpenFromForgotten = false;
|
||||
//setUserId - set from changes in convert
|
||||
//setUserActionId - used in case of save without changes(forgotten files)
|
||||
let userLastChangeId = cmd.getUserId() || cmd.getUserActionId();
|
||||
if (userLastChangeId) {
|
||||
users.push(userLastChangeId);
|
||||
if (constants.EDITOR_CHANGES !== statusInfo || isSfcm) {
|
||||
var saveKey = cmd.getSaveKey();
|
||||
var isError = constants.NO_ERROR != statusInfo;
|
||||
var isErrorCorrupted = constants.CONVERT_CORRUPTED == statusInfo;
|
||||
var savePathDoc = saveKey + '/' + cmd.getOutputPath();
|
||||
var savePathChanges = saveKey + '/changes.zip';
|
||||
var savePathHistory = saveKey + '/changesHistory.json';
|
||||
var getRes = yield* docsCoServer.getCallback(docId);
|
||||
var forceSave = cmd.getForceSave();
|
||||
var forceSaveType = forceSave ? forceSave.getType() : commonDefines.c_oAscForceSaveTypes.Command;
|
||||
var isSfcmSuccess = false;
|
||||
let storeForgotten = false;
|
||||
var statusOk;
|
||||
var statusErr;
|
||||
if (isSfcm) {
|
||||
statusOk = docsCoServer.c_oAscServerStatus.MustSaveForce;
|
||||
statusErr = docsCoServer.c_oAscServerStatus.CorruptedForce;
|
||||
} else {
|
||||
statusOk = docsCoServer.c_oAscServerStatus.MustSave;
|
||||
statusErr = docsCoServer.c_oAscServerStatus.Corrupted;
|
||||
}
|
||||
outputSfc.setUsers(users);
|
||||
if (!isSfcm) {
|
||||
var actions = [];
|
||||
//use UserId case UserActionId miss in gc convertion
|
||||
var userActionId = cmd.getUserActionId() || cmd.getUserId();
|
||||
if (userActionId) {
|
||||
actions.push(new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, userActionId));
|
||||
}
|
||||
outputSfc.setActions(actions);
|
||||
}
|
||||
outputSfc.setUserData(cmd.getUserData());
|
||||
if (!isError || isErrorCorrupted) {
|
||||
try {
|
||||
let forgottenId = cfgForgottenFiles + '/' + docId;
|
||||
let forgotten = yield storage.listObjects(forgottenId);
|
||||
let isSendHistory = 0 === forgotten.length;
|
||||
if (!isSendHistory) {
|
||||
//check indicator file to determine if opening was from the forgotten file
|
||||
var forgottenMarkPath = docId + '/' + cfgForgottenFilesName + '.txt';
|
||||
var forgottenMark = yield storage.listObjects(forgottenMarkPath);
|
||||
isOpenFromForgotten = 0 !== forgottenMark.length;
|
||||
isSendHistory = !isOpenFromForgotten;
|
||||
logger.debug('commandSfcCallback forgotten no empty: docId = %s isSendHistory = %s', docId, isSendHistory);
|
||||
}
|
||||
if (isSendHistory && !isEncrypted) {
|
||||
//don't send history info because changes isn't from file in storage
|
||||
var data = yield storage.getObject(savePathHistory);
|
||||
outputSfc.setChangeHistory(JSON.parse(data.toString('utf-8')));
|
||||
let changeUrl = yield storage.getSignedUrl(getRes.baseUrl, savePathChanges,
|
||||
commonDefines.c_oAscUrlTypes.Temporary);
|
||||
outputSfc.setChangeUrl(changeUrl);
|
||||
} else {
|
||||
//for backward compatibility. remove this when Community is ready
|
||||
outputSfc.setChangeHistory({});
|
||||
}
|
||||
let url = yield storage.getSignedUrl(getRes.baseUrl, savePathDoc, commonDefines.c_oAscUrlTypes.Temporary);
|
||||
outputSfc.setUrl(url);
|
||||
} catch (e) {
|
||||
logger.error('Error commandSfcCallback: docId = %s\r\n%s', docId, e.stack);
|
||||
}
|
||||
if (outputSfc.getUrl() && outputSfc.getUsers().length > 0) {
|
||||
outputSfc.setStatus(statusOk);
|
||||
let recoverTask = new taskResult.TaskResultData();
|
||||
recoverTask.status = taskResult.FileStatus.Ok;
|
||||
recoverTask.statusInfo = constants.NO_ERROR;
|
||||
let updateMask = new taskResult.TaskResultData();
|
||||
updateMask.key = docId;
|
||||
if (!isEncrypted) {
|
||||
updateMask.status = taskResult.FileStatus.SaveVersion;
|
||||
updateMask.statusInfo = cmd.getData();
|
||||
} else {
|
||||
let selectRes = yield taskResult.select(docId);
|
||||
let row = selectRes.length > 0 ? selectRes[0] : null;
|
||||
if (row) {
|
||||
recoverTask.status = updateMask.status = row.status;
|
||||
recoverTask.statusInfo = updateMask.statusInfo = row.status_info;
|
||||
} else {
|
||||
isError = true;
|
||||
}
|
||||
}
|
||||
if (isError) {
|
||||
outputSfc.setStatus(statusErr);
|
||||
}
|
||||
var uri = getRes.server.href;
|
||||
if (isSfcm) {
|
||||
var selectRes = yield taskResult.select(docId);
|
||||
var row = selectRes.length > 0 ? selectRes[0] : null;
|
||||
//send only if FileStatus.Ok to prevent forcesave after final save
|
||||
if (row && row.status == taskResult.FileStatus.Ok) {
|
||||
if (forceSave) {
|
||||
outputSfc.setForceSaveType(forceSaveType);
|
||||
outputSfc.setLastSave(new Date(forceSave.getTime()).toISOString());
|
||||
let updateIfTask = new taskResult.TaskResultData();
|
||||
updateIfTask.status = taskResult.FileStatus.UpdateVersion;
|
||||
updateIfTask.statusInfo = Math.floor(Date.now() / 60000);//minutes
|
||||
let updateIfRes;
|
||||
if (getRes) {
|
||||
logger.debug('Callback commandSfcCallback: docId = %s callback = %s', docId, getRes.server.href);
|
||||
var outputSfc = new commonDefines.OutputSfcData();
|
||||
outputSfc.setKey(docId);
|
||||
outputSfc.setEncrypted(isEncrypted);
|
||||
var users = [];
|
||||
let isOpenFromForgotten = false;
|
||||
//setUserId - set from changes in convert
|
||||
//setUserActionId - used in case of save without changes(forgotten files)
|
||||
let userLastChangeId = cmd.getUserId() || cmd.getUserActionId();
|
||||
if (userLastChangeId) {
|
||||
users.push(userLastChangeId);
|
||||
}
|
||||
outputSfc.setUsers(users);
|
||||
if (!isSfcm) {
|
||||
var actions = [];
|
||||
//use UserId case UserActionId miss in gc convertion
|
||||
var userActionId = cmd.getUserActionId() || cmd.getUserId();
|
||||
if (userActionId) {
|
||||
actions.push(new commonDefines.OutputAction(commonDefines.c_oAscUserAction.Out, userActionId));
|
||||
}
|
||||
outputSfc.setActions(actions);
|
||||
}
|
||||
outputSfc.setUserData(cmd.getUserData());
|
||||
if (!isError || isErrorCorrupted) {
|
||||
try {
|
||||
replyStr = yield* docsCoServer.sendServerRequest(docId, uri, outputSfc, checkAuthorizationLength);
|
||||
let replyData = docsCoServer.parseReplyData(docId, replyStr);
|
||||
isSfcmSuccess = replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error;
|
||||
} catch (err) {
|
||||
logger.error('sendServerRequest error: docId = %s;url = %s;data = %j\r\n%s', docId, uri, outputSfc, err.stack);
|
||||
let forgottenId = cfgForgottenFiles + '/' + docId;
|
||||
let forgotten = yield storage.listObjects(forgottenId);
|
||||
let isSendHistory = 0 === forgotten.length;
|
||||
if (!isSendHistory) {
|
||||
//check indicator file to determine if opening was from the forgotten file
|
||||
var forgottenMarkPath = docId + '/' + cfgForgottenFilesName + '.txt';
|
||||
var forgottenMark = yield storage.listObjects(forgottenMarkPath);
|
||||
isOpenFromForgotten = 0 !== forgottenMark.length;
|
||||
isSendHistory = !isOpenFromForgotten;
|
||||
logger.debug('commandSfcCallback forgotten no empty: docId = %s isSendHistory = %s', docId, isSendHistory);
|
||||
}
|
||||
if (isSendHistory && !isEncrypted) {
|
||||
//don't send history info because changes isn't from file in storage
|
||||
var data = yield storage.getObject(savePathHistory);
|
||||
outputSfc.setChangeHistory(JSON.parse(data.toString('utf-8')));
|
||||
let changeUrl = yield storage.getSignedUrl(getRes.baseUrl, savePathChanges,
|
||||
commonDefines.c_oAscUrlTypes.Temporary);
|
||||
outputSfc.setChangeUrl(changeUrl);
|
||||
} else {
|
||||
//for backward compatibility. remove this when Community is ready
|
||||
outputSfc.setChangeHistory({});
|
||||
}
|
||||
let url = yield storage.getSignedUrl(getRes.baseUrl, savePathDoc, commonDefines.c_oAscUrlTypes.Temporary);
|
||||
outputSfc.setUrl(url);
|
||||
} catch (e) {
|
||||
logger.error('Error commandSfcCallback: docId = %s\r\n%s', docId, e.stack);
|
||||
}
|
||||
if (outputSfc.getUrl() && outputSfc.getUsers().length > 0) {
|
||||
outputSfc.setStatus(statusOk);
|
||||
} else {
|
||||
isError = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//if anybody in document stop save
|
||||
let editorsCount = yield docsCoServer.getEditorsCountPromise(docId);
|
||||
logger.debug('commandSfcCallback presence: docId = %s count = %d', docId, editorsCount);
|
||||
if (0 === editorsCount || (isEncrypted && 1 === editorsCount)) {
|
||||
let lastSave = yield* docsCoServer.getLastSave(docId);
|
||||
let notModified = yield* docsCoServer.getLastForceSave(docId, lastSave);
|
||||
var lastSaveDate = lastSave ? new Date(lastSave.time) : new Date();
|
||||
outputSfc.setLastSave(lastSaveDate.toISOString());
|
||||
outputSfc.setNotModified(notModified);
|
||||
updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask);
|
||||
if (updateIfRes.affectedRows > 0) {
|
||||
updateMask.status = updateIfTask.status;
|
||||
updateMask.statusInfo = updateIfTask.statusInfo;
|
||||
if (isError) {
|
||||
outputSfc.setStatus(statusErr);
|
||||
}
|
||||
var uri = getRes.server.href;
|
||||
if (isSfcm) {
|
||||
var selectRes = yield taskResult.select(docId);
|
||||
var row = selectRes.length > 0 ? selectRes[0] : null;
|
||||
//send only if FileStatus.Ok to prevent forcesave after final save
|
||||
if (row && row.status == taskResult.FileStatus.Ok) {
|
||||
if (forceSave) {
|
||||
outputSfc.setForceSaveType(forceSaveType);
|
||||
outputSfc.setLastSave(new Date(forceSave.getTime()).toISOString());
|
||||
}
|
||||
try {
|
||||
replyStr = yield* docsCoServer.sendServerRequest(docId, uri, outputSfc, checkAuthorizationLength);
|
||||
let replyData = docsCoServer.parseReplyData(docId, replyStr);
|
||||
isSfcmSuccess = replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error;
|
||||
} catch (err) {
|
||||
logger.error('sendServerRequest error: docId = %s;url = %s;data = %j\r\n%s', docId, uri, outputSfc, err.stack);
|
||||
}
|
||||
var requestRes = false;
|
||||
var replyData = docsCoServer.parseReplyData(docId, replyStr);
|
||||
if (replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error) {
|
||||
//в случае comunity server придет запрос в CommandService проверяем результат
|
||||
var multi = redisClient.multi([
|
||||
['get', redisKeySaved + docId],
|
||||
['del', redisKeySaved + docId]
|
||||
]);
|
||||
var execRes = yield utils.promiseRedis(multi, multi.exec);
|
||||
var savedVal = execRes[0];
|
||||
requestRes = (null == savedVal || '1' === savedVal);
|
||||
}
|
||||
if (requestRes) {
|
||||
updateIfTask = undefined;
|
||||
yield docsCoServer.cleanDocumentOnExitPromise(docId, true);
|
||||
if (isOpenFromForgotten) {
|
||||
//remove forgotten file in cache
|
||||
yield cleanupCache(docId);
|
||||
}
|
||||
} else {
|
||||
//if anybody in document stop save
|
||||
let editorsCount = yield docsCoServer.getEditorsCountPromise(docId);
|
||||
logger.debug('commandSfcCallback presence: docId = %s count = %d', docId, editorsCount);
|
||||
if (0 === editorsCount || (isEncrypted && 1 === editorsCount)) {
|
||||
let lastSave = yield* docsCoServer.getLastSave(docId);
|
||||
let notModified = yield* docsCoServer.getLastForceSave(docId, lastSave);
|
||||
var lastSaveDate = lastSave ? new Date(lastSave.time) : new Date();
|
||||
outputSfc.setLastSave(lastSaveDate.toISOString());
|
||||
outputSfc.setNotModified(notModified);
|
||||
updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask);
|
||||
if (updateIfRes.affectedRows > 0) {
|
||||
updateMask.status = updateIfTask.status;
|
||||
updateMask.statusInfo = updateIfTask.statusInfo;
|
||||
try {
|
||||
replyStr = yield* docsCoServer.sendServerRequest(docId, uri, outputSfc, checkAuthorizationLength);
|
||||
} catch (err) {
|
||||
logger.error('sendServerRequest error: docId = %s;url = %s;data = %j\r\n%s', docId, uri, outputSfc, err.stack);
|
||||
}
|
||||
var requestRes = false;
|
||||
var replyData = docsCoServer.parseReplyData(docId, replyStr);
|
||||
if (replyData && commonDefines.c_oAscServerCommandErrors.NoError == replyData.error) {
|
||||
//в случае comunity server придет запрос в CommandService проверяем результат
|
||||
var multi = redisClient.multi([
|
||||
['get', redisKeySaved + docId],
|
||||
['del', redisKeySaved + docId]
|
||||
]);
|
||||
var execRes = yield utils.promiseRedis(multi, multi.exec);
|
||||
var savedVal = execRes[0];
|
||||
requestRes = (null == savedVal || '1' === savedVal);
|
||||
}
|
||||
if (requestRes) {
|
||||
updateIfTask = undefined;
|
||||
yield docsCoServer.cleanDocumentOnExitPromise(docId, true);
|
||||
if (isOpenFromForgotten) {
|
||||
//remove forgotten file in cache
|
||||
yield cleanupCache(docId);
|
||||
}
|
||||
} else {
|
||||
storeForgotten = true;
|
||||
}
|
||||
} else {
|
||||
storeForgotten = true;
|
||||
updateIfTask = undefined;
|
||||
}
|
||||
} else {
|
||||
updateIfTask = undefined;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn('Empty Callback commandSfcCallback: docId = %s', docId);
|
||||
storeForgotten = true;
|
||||
}
|
||||
if (undefined !== updateIfTask && !isSfcm) {
|
||||
logger.debug('commandSfcCallback restore %d status: docId = %s', recoverTask.status, docId);
|
||||
updateIfTask.status = recoverTask.status;
|
||||
updateIfTask.statusInfo = recoverTask.statusInfo;
|
||||
updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask);
|
||||
if (!(updateIfRes.affectedRows > 0)) {
|
||||
logger.debug('commandSfcCallback restore %d status failed: docId = %s', recoverTask.status, docId);
|
||||
}
|
||||
}
|
||||
if (storeForgotten && (!isError || isErrorCorrupted)) {
|
||||
try {
|
||||
logger.debug("storeForgotten: docId = %s", docId);
|
||||
let forgottenName = cfgForgottenFilesName + pathModule.extname(cmd.getOutputPath());
|
||||
yield storage.copyObject(savePathDoc, cfgForgottenFiles + '/' + docId + '/' + forgottenName);
|
||||
} catch (err) {
|
||||
logger.error('Error storeForgotten: docId = %s\r\n%s', docId, err.stack);
|
||||
}
|
||||
}
|
||||
if (forceSave) {
|
||||
yield* docsCoServer.setForceSave(docId, forceSave, cmd, isSfcmSuccess && !isError);
|
||||
}
|
||||
} else {
|
||||
logger.warn('Empty Callback commandSfcCallback: docId = %s', docId);
|
||||
storeForgotten = true;
|
||||
}
|
||||
if (undefined !== updateIfTask && !isSfcm) {
|
||||
logger.debug('commandSfcCallback restore FileStatus.Ok status: docId = %s', docId);
|
||||
updateIfTask.status = taskResult.FileStatus.Ok;
|
||||
updateIfTask.statusInfo = constants.NO_ERROR;
|
||||
updateIfRes = yield taskResult.updateIf(updateIfTask, updateMask);
|
||||
if (!(updateIfRes.affectedRows > 0)) {
|
||||
logger.debug('commandSfcCallback restore FileStatus.Ok status failed: docId = %s', docId);
|
||||
}
|
||||
}
|
||||
if (storeForgotten && (!isError || isErrorCorrupted)) {
|
||||
try {
|
||||
logger.debug("storeForgotten: docId = %s", docId);
|
||||
let forgottenName = cfgForgottenFilesName + pathModule.extname(cmd.getOutputPath());
|
||||
yield storage.copyObject(savePathDoc, cfgForgottenFiles + '/' + docId + '/' + forgottenName);
|
||||
} catch (err) {
|
||||
logger.error('Error storeForgotten: docId = %s\r\n%s', docId, err.stack);
|
||||
}
|
||||
}
|
||||
if (forceSave) {
|
||||
yield* docsCoServer.setForceSave(docId, forceSave, cmd, isSfcmSuccess && !isError);
|
||||
logger.debug('commandSfcCallback cleanDocumentOnExitNoChangesPromise: docId = %s', docId);
|
||||
yield docsCoServer.cleanDocumentOnExitNoChangesPromise(docId, undefined, true);
|
||||
}
|
||||
|
||||
if ((docsCoServer.getIsShutdown() && !isSfcm) || cmd.getRedisKey()) {
|
||||
let keyRedis = cmd.getRedisKey() ? cmd.getRedisKey() : redisKeyShutdown;
|
||||
yield utils.promiseRedis(redisClient, redisClient.srem, keyRedis, docId);
|
||||
@ -904,11 +917,7 @@ exports.openDocument = function(conn, cmd, opt_upsertRes, opt_bIsRestore) {
|
||||
let res = true;
|
||||
switch (cmd.getCommand()) {
|
||||
case 'open':
|
||||
if (!conn.encrypted) {
|
||||
yield* commandOpen(conn, cmd, outputData, opt_upsertRes, opt_bIsRestore);
|
||||
} else {
|
||||
yield* commandOpenEncrypted(cmd);
|
||||
}
|
||||
yield* commandOpen(conn, cmd, outputData, opt_upsertRes, opt_bIsRestore);
|
||||
break;
|
||||
case 'reopen':
|
||||
res = yield* commandReopen(cmd);
|
||||
@ -1031,7 +1040,7 @@ exports.saveFile = function(req, res) {
|
||||
let strCmd = req.query['cmd'];
|
||||
let cmd = new commonDefines.InputCommand(JSON.parse(strCmd));
|
||||
docId = cmd.getDocId();
|
||||
logger.debug('Start saveFile: docId = %s %s', docId);
|
||||
logger.debug('Start saveFile: docId = %s', docId);
|
||||
|
||||
if (cfgTokenEnableBrowser) {
|
||||
let isValidJwt = false;
|
||||
|
||||
@ -52,6 +52,8 @@ var cfgImageSize = configServer.get('limits_image_size');
|
||||
var cfgTypesUpload = configUtils.get('limits_image_types_upload');
|
||||
var cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser');
|
||||
|
||||
const PATTERN_ENCRYPTED = 'ENCRYPTED;';
|
||||
|
||||
exports.uploadTempFile = function(req, res) {
|
||||
return co(function* () {
|
||||
var docId = 'uploadTempFile';
|
||||
@ -85,7 +87,7 @@ exports.uploadTempFile = function(req, res) {
|
||||
});
|
||||
};
|
||||
function checkJwtUpload(docId, errorName, token){
|
||||
var res = {err: true, docId: null, userid: null};
|
||||
var res = {err: true, docId: null, userid: null, encrypted: null};
|
||||
var checkJwtRes = docsCoServer.checkJwt(docId, token, commonDefines.c_oAscSecretType.Session);
|
||||
if (checkJwtRes.decoded) {
|
||||
var doc = checkJwtRes.decoded.document;
|
||||
@ -93,6 +95,7 @@ function checkJwtUpload(docId, errorName, token){
|
||||
if (!edit.ds_view && !edit.ds_isCloseCoAuthoring) {
|
||||
res.err = false;
|
||||
res.docId = doc.key;
|
||||
res.encrypted = doc.ds_encrypted;
|
||||
if (edit.user) {
|
||||
res.userid = edit.user.id;
|
||||
}
|
||||
@ -190,9 +193,11 @@ exports.uploadImageFile = function(req, res) {
|
||||
return co(function* () {
|
||||
var isError = true;
|
||||
var docId = 'null';
|
||||
let output = {};
|
||||
try {
|
||||
docId = req.params.docid;
|
||||
var userid = req.params.userid;
|
||||
let encrypted = false;
|
||||
logger.debug('Start uploadImageFile: docId = %s', docId);
|
||||
|
||||
var isValidJwt = true;
|
||||
@ -201,6 +206,7 @@ exports.uploadImageFile = function(req, res) {
|
||||
if (!checkJwtRes.err) {
|
||||
docId = checkJwtRes.docId || docId;
|
||||
userid = checkJwtRes.userid || userid;
|
||||
encrypted = checkJwtRes.encrypted;
|
||||
} else {
|
||||
isValidJwt = false;
|
||||
}
|
||||
@ -208,29 +214,45 @@ exports.uploadImageFile = function(req, res) {
|
||||
|
||||
var index = parseInt(req.params.index);
|
||||
if (isValidJwt && docId && req.body && Buffer.isBuffer(req.body)) {
|
||||
var buffer = req.body;
|
||||
var format = formatChecker.getImageFormat(buffer);
|
||||
var formatStr = formatChecker.getStringFromFormat(format);
|
||||
var supportedFormats = cfgTypesUpload || 'jpg';
|
||||
if (formatStr && -1 !== supportedFormats.indexOf(formatStr) && buffer.length <= cfgImageSize) {
|
||||
//в начале пишется хеш, чтобы избежать ошибок при параллельном upload в совместном редактировании
|
||||
var strImageName = utils.crc32(userid).toString(16) + '_image' + index;
|
||||
var strPathRel = 'media/' + strImageName + '.' + formatStr;
|
||||
var strPath = docId + '/' + strPathRel;
|
||||
yield storageBase.putObject(strPath, buffer, buffer.length);
|
||||
var output = {};
|
||||
output[strPathRel] = yield storageBase.getSignedUrl(utils.getBaseUrlByRequest(req), strPath,
|
||||
commonDefines.c_oAscUrlTypes.Session);
|
||||
res.send(JSON.stringify(output));
|
||||
isError = false;
|
||||
let buffer = req.body;
|
||||
if (buffer.length <= cfgImageSize) {
|
||||
var format = formatChecker.getImageFormat(buffer, undefined);
|
||||
var formatStr = formatChecker.getStringFromFormat(format);
|
||||
var supportedFormats = cfgTypesUpload || 'jpg';
|
||||
let formatLimit = formatStr && -1 !== supportedFormats.indexOf(formatStr);
|
||||
if (!formatLimit && encrypted && PATTERN_ENCRYPTED == buffer.toString('utf8', 0, PATTERN_ENCRYPTED.length)) {
|
||||
formatLimit = true;
|
||||
formatStr = buffer.toString('utf8', PATTERN_ENCRYPTED.length, buffer.indexOf(';', PATTERN_ENCRYPTED.length));
|
||||
}
|
||||
if (formatLimit) {
|
||||
//в начале пишется хеш, чтобы избежать ошибок при параллельном upload в совместном редактировании
|
||||
var strImageName = utils.crc32(userid).toString(16) + '_image' + index;
|
||||
var strPathRel = 'media/' + strImageName + '.' + formatStr;
|
||||
var strPath = docId + '/' + strPathRel;
|
||||
yield storageBase.putObject(strPath, buffer, buffer.length);
|
||||
output[strPathRel] = yield storageBase.getSignedUrl(utils.getBaseUrlByRequest(req), strPath,
|
||||
commonDefines.c_oAscUrlTypes.Session);
|
||||
isError = false;
|
||||
} else {
|
||||
logger.debug('uploadImageFile format is not supported: docId = %s', docId);
|
||||
}
|
||||
} else {
|
||||
logger.debug('uploadImageFile size limit exceeded: buffer.length = %d docId = %s', buffer.length, docId);
|
||||
}
|
||||
}
|
||||
logger.debug('End uploadImageFile: isError = %d docId = %s', isError, docId);
|
||||
} catch (e) {
|
||||
isError = true;
|
||||
logger.error('Error uploadImageFile: docId = %s\r\n%s', docId, e.stack);
|
||||
} finally {
|
||||
if (isError) {
|
||||
res.sendStatus(400);
|
||||
try {
|
||||
if (!isError) {
|
||||
res.send(JSON.stringify(output));
|
||||
} else {
|
||||
res.sendStatus(400);
|
||||
}
|
||||
logger.debug('End uploadImageFile: isError = %s docId = %s', isError, docId);
|
||||
} catch (e) {
|
||||
logger.error('Error uploadImageFile: docId = %s\r\n%s', docId, e.stack);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -307,6 +307,7 @@ function* downloadFileFromStorage(id, strPath, dir) {
|
||||
}
|
||||
}
|
||||
function* processDownloadFromStorage(dataConvert, cmd, task, tempDirs) {
|
||||
let res = constants.NO_ERROR;
|
||||
let needConcatFiles = false;
|
||||
if (task.getFromOrigin() || task.getFromSettings()) {
|
||||
dataConvert.fileFrom = path.join(tempDirs.source, 'origin.' + cmd.getFormat());
|
||||
@ -326,8 +327,9 @@ function* processDownloadFromStorage(dataConvert, cmd, task, tempDirs) {
|
||||
yield* concatFiles(tempDirs.source);
|
||||
}
|
||||
if (task.getFromChanges()) {
|
||||
yield* processChanges(tempDirs, cmd);
|
||||
res = yield* processChanges(tempDirs, cmd);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function* concatFiles(source) {
|
||||
@ -356,6 +358,7 @@ function* concatFiles(source) {
|
||||
}
|
||||
|
||||
function* processChanges(tempDirs, cmd) {
|
||||
let res = constants.NO_ERROR;
|
||||
let changesDir = path.join(tempDirs.source, 'changes');
|
||||
fs.mkdirSync(changesDir);
|
||||
let indexFile = 0;
|
||||
@ -378,6 +381,12 @@ function* processChanges(tempDirs, cmd) {
|
||||
let changes = yield baseConnector.getChangesPromise(cmd.getDocId(), curIndexStart, curIndexEnd, forceSaveTime);
|
||||
for (let i = 0; i < changes.length; ++i) {
|
||||
let change = changes[i];
|
||||
if (change.change_data.startsWith('ENCRYPTED;')) {
|
||||
logger.warn('processChanges encrypted changes (id=%s)', cmd.getDocId());
|
||||
//todo sql request instead?
|
||||
res = constants.EDITOR_CHANGES;
|
||||
break;
|
||||
}
|
||||
if (null === changesAuthor || changesAuthor !== change.user_id_original) {
|
||||
if (null !== changesAuthor) {
|
||||
yield* streamEnd(streamObj, ']');
|
||||
@ -406,6 +415,7 @@ function* processChanges(tempDirs, cmd) {
|
||||
}
|
||||
cmd.setUserId(changesAuthor);
|
||||
fs.writeFileSync(path.join(tempDirs.result, 'changesHistory.json'), JSON.stringify(changesHistory), 'utf8');
|
||||
return res;
|
||||
}
|
||||
|
||||
function* streamCreate(docId, changesDir, indexFile, opt_options) {
|
||||
@ -576,7 +586,7 @@ function* ExecuteTask(task) {
|
||||
clientStatsD.timing('conv.downloadFileFromStorage', new Date() - curDate);
|
||||
curDate = new Date();
|
||||
}
|
||||
yield* processDownloadFromStorage(dataConvert, cmd, task, tempDirs);
|
||||
error = yield* processDownloadFromStorage(dataConvert, cmd, task, tempDirs);
|
||||
} else if (cmd.getForgotten()) {
|
||||
yield* downloadFileFromStorage(cmd.getDocId(), cmd.getForgotten(), tempDirs.source);
|
||||
logger.debug('downloadFileFromStorage complete(id=%s)', dataConvert.key);
|
||||
|
||||
Reference in New Issue
Block a user