mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-04-07 14:04:35 +08:00
Merge pull request 'feature/refresh-file' (#10) from feature/refresh-file into develop
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/server/pulls/10
This commit is contained in:
@ -50,7 +50,6 @@ function InputCommand(data, copyExplicit) {
|
||||
this['username'] = data['username'];
|
||||
this['tokenSession'] = data['tokenSession'];
|
||||
this['tokenDownload'] = data['tokenDownload'];
|
||||
this['tokenHistory'] = data['tokenHistory'];
|
||||
this['data'] = data['data'];
|
||||
this['editorid'] = data['editorid'];
|
||||
this['format'] = data['format'];
|
||||
@ -84,7 +83,6 @@ function InputCommand(data, copyExplicit) {
|
||||
this['savekey'] = data['savekey'];
|
||||
this['userconnectionid'] = data['userconnectionid'];
|
||||
this['responsekey'] = data['responsekey'];
|
||||
this['docconnectionid'] = data['docconnectionid'];
|
||||
this['jsonparams'] = data['jsonparams'];
|
||||
this['lcid'] = data['lcid'];
|
||||
this['useractionid'] = data['useractionid'];
|
||||
@ -101,7 +99,6 @@ function InputCommand(data, copyExplicit) {
|
||||
this['savepassword'] = data['savepassword'];
|
||||
this['withoutPassword'] = data['withoutPassword'];
|
||||
this['outputurls'] = data['outputurls'];
|
||||
this['closeonerror'] = data['closeonerror'];
|
||||
this['serverVersion'] = data['serverVersion'];
|
||||
this['rediskey'] = data['rediskey'];
|
||||
this['nobase64'] = data['nobase64'];
|
||||
@ -127,7 +124,6 @@ function InputCommand(data, copyExplicit) {
|
||||
this['username'] = undefined;
|
||||
this['tokenSession'] = undefined;//string validate
|
||||
this['tokenDownload'] = undefined;//string validate
|
||||
this['tokenHistory'] = undefined;//string validate
|
||||
this['data'] = undefined;//string
|
||||
//to open
|
||||
this['editorid'] = undefined;//int
|
||||
@ -152,7 +148,6 @@ function InputCommand(data, copyExplicit) {
|
||||
this['savekey'] = undefined;//int document id to save
|
||||
this['userconnectionid'] = undefined;//string internal
|
||||
this['responsekey'] = undefined;
|
||||
this['docconnectionid'] = undefined;//string internal
|
||||
this['jsonparams'] = undefined;//string
|
||||
this['lcid'] = undefined;
|
||||
this['useractionid'] = undefined;
|
||||
@ -165,7 +160,6 @@ function InputCommand(data, copyExplicit) {
|
||||
this['savepassword'] = undefined;
|
||||
this['withoutPassword'] = undefined;
|
||||
this['outputurls'] = undefined;
|
||||
this['closeonerror'] = undefined;
|
||||
this['serverVersion'] = undefined;
|
||||
this['rediskey'] = undefined;
|
||||
this['nobase64'] = true;
|
||||
@ -218,9 +212,6 @@ InputCommand.prototype = {
|
||||
getTokenDownload: function() {
|
||||
return this['tokenDownload'];
|
||||
},
|
||||
getTokenHistory: function() {
|
||||
return this['tokenHistory'];
|
||||
},
|
||||
getData: function() {
|
||||
return this['data'];
|
||||
},
|
||||
@ -359,12 +350,6 @@ InputCommand.prototype = {
|
||||
setResponseKey: function(data) {
|
||||
this['responsekey'] = data;
|
||||
},
|
||||
getDocConnectionId: function() {
|
||||
return this['docconnectionid'];
|
||||
},
|
||||
setDocConnectionId: function(data) {
|
||||
this['docconnectionid'] = data;
|
||||
},
|
||||
getJsonParams: function() {
|
||||
return this['jsonparams'];
|
||||
},
|
||||
@ -447,12 +432,6 @@ InputCommand.prototype = {
|
||||
getOutputUrls: function() {
|
||||
return this['outputurls'];
|
||||
},
|
||||
getCloseOnError: function() {
|
||||
return this['closeonerror'];
|
||||
},
|
||||
setCloseOnError: function(data) {
|
||||
this['closeonerror'] = data;
|
||||
},
|
||||
getServerVersion: function() {
|
||||
return this['serverVersion'];
|
||||
},
|
||||
|
||||
@ -1054,6 +1054,30 @@ let saveRelativeFromChanges = co.wrap(function*(ctx, conn, responseKey, data) {
|
||||
sendDataRpc(ctx, conn, responseKey, forceSaveRes);
|
||||
}
|
||||
})
|
||||
|
||||
async function startWopiRPC(ctx, docId, userId, userIdOriginal, data) {
|
||||
let res;
|
||||
let selectRes = await taskResult.select(ctx, docId);
|
||||
let row = selectRes.length > 0 ? selectRes[0] : null;
|
||||
if (row) {
|
||||
if (row.callback) {
|
||||
let userIndex = utils.getIndexFromUserId(userId, userIdOriginal);
|
||||
let uri = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback, userIndex);
|
||||
let wopiParams = wopiClient.parseWopiCallback(ctx, uri, row.callback);
|
||||
if (wopiParams) {
|
||||
switch (data.type) {
|
||||
case 'wopi_RenameFile':
|
||||
res = await wopiClient.renameFile(ctx, wopiParams, data.name);
|
||||
break;
|
||||
case 'wopi_RefreshFile':
|
||||
res = await wopiClient.refreshFile(ctx, wopiParams, row.baseurl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function* startRPC(ctx, conn, responseKey, data) {
|
||||
let docId = conn.docId;
|
||||
ctx.logger.debug('startRPC start responseKey:%s , %j', responseKey, data);
|
||||
@ -1077,21 +1101,11 @@ function* startRPC(ctx, conn, responseKey, data) {
|
||||
break;
|
||||
}
|
||||
case 'wopi_RenameFile':
|
||||
let renameRes;
|
||||
let selectRes = yield taskResult.select(ctx, docId);
|
||||
let row = selectRes.length > 0 ? selectRes[0] : null;
|
||||
if (row) {
|
||||
if (row.callback) {
|
||||
let userIndex = utils.getIndexFromUserId(conn.user.id, conn.user.idOriginal);
|
||||
let uri = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback, userIndex);
|
||||
let wopiParams = wopiClient.parseWopiCallback(ctx, uri, row.callback);
|
||||
if (wopiParams) {
|
||||
renameRes = yield wopiClient.renameFile(ctx, wopiParams, data.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
sendDataRpc(ctx, conn, responseKey, renameRes);
|
||||
case 'wopi_RefreshFile': {
|
||||
let res = yield startWopiRPC(ctx, conn.docId, conn.user.id, conn.user.idOriginal, data);
|
||||
sendDataRpc(ctx, conn, responseKey, res);
|
||||
break;
|
||||
}
|
||||
case 'pathurls':
|
||||
let outputData = new canvasService.OutputData(data.type);
|
||||
yield* canvasService.commandPathUrls(ctx, conn, data.data, outputData);
|
||||
@ -1720,11 +1734,6 @@ exports.install = function(server, callbackFunction) {
|
||||
case 'close':
|
||||
yield* closeDocument(ctx, conn);
|
||||
break;
|
||||
case 'versionHistory' : {
|
||||
let cmd = new commonDefines.InputCommand(data.cmd);
|
||||
yield* versionHistory(ctx, conn, cmd);
|
||||
break;
|
||||
}
|
||||
case 'openDocument' : {
|
||||
var cmd = new commonDefines.InputCommand(data.message);
|
||||
cmd.fillFromConnection(conn);
|
||||
@ -1935,42 +1944,6 @@ exports.install = function(server, callbackFunction) {
|
||||
}
|
||||
}
|
||||
|
||||
function* versionHistory(ctx, conn, cmd) {
|
||||
const tenTokenEnableBrowser = ctx.getCfg('services.CoAuthoring.token.enable.browser', cfgTokenEnableBrowser);
|
||||
|
||||
var docIdOld = conn.docId;
|
||||
var docIdNew = cmd.getDocId();
|
||||
//check jwt
|
||||
if (tenTokenEnableBrowser) {
|
||||
var checkJwtRes = yield checkJwt(ctx, cmd.getTokenHistory(), commonDefines.c_oAscSecretType.Browser);
|
||||
if (checkJwtRes.decoded) {
|
||||
fillVersionHistoryFromJwt(ctx, checkJwtRes.decoded, cmd);
|
||||
docIdNew = cmd.getDocId();
|
||||
cmd.setWithAuthorization(true);
|
||||
} else {
|
||||
sendData(ctx, conn, {type: "expiredToken", code: checkJwtRes.code, description: checkJwtRes.description});
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (docIdOld !== docIdNew) {
|
||||
//remove presence(other data was removed before in closeDocument)
|
||||
yield removePresence(ctx, conn);
|
||||
var hvals = yield editorData.getPresence(ctx, docIdOld, connections);
|
||||
if (hvals.length <= 0) {
|
||||
yield editorData.removePresenceDocument(ctx, docIdOld);
|
||||
}
|
||||
|
||||
//apply new
|
||||
conn.docId = docIdNew;
|
||||
yield addPresence(ctx, conn, true);
|
||||
if (tenTokenEnableBrowser) {
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
}
|
||||
}
|
||||
//open
|
||||
yield canvasService.openDocument(ctx, conn, cmd, null);
|
||||
}
|
||||
// Getting changes for the document (either from the cache or accessing the database, but only if there were saves)
|
||||
function* getDocumentChanges(ctx, docId, optStartIndex, optEndIndex) {
|
||||
// If during that moment, while we were waiting for a response from the database, everyone left, then nothing needs to be sent
|
||||
@ -2090,13 +2063,17 @@ exports.install = function(server, callbackFunction) {
|
||||
});
|
||||
}
|
||||
|
||||
function sendFileError(ctx, conn, errorId, code) {
|
||||
ctx.logger.warn('error description: errorId = %s', errorId);
|
||||
function sendFileError(ctx, conn, errorId, code, opt_notWarn) {
|
||||
if (opt_notWarn) {
|
||||
ctx.logger.debug('error description: errorId = %s', errorId);
|
||||
} else {
|
||||
ctx.logger.warn('error description: errorId = %s', errorId);
|
||||
}
|
||||
conn.isCiriticalError = true;
|
||||
sendData(ctx, conn, {type: 'error', description: errorId, code: code});
|
||||
}
|
||||
|
||||
function* sendFileErrorAuth(ctx, conn, sessionId, errorId, code) {
|
||||
function* sendFileErrorAuth(ctx, conn, sessionId, errorId, code, opt_notWarn) {
|
||||
const tenTokenEnableBrowser = ctx.getCfg('services.CoAuthoring.token.enable.browser', cfgTokenEnableBrowser);
|
||||
|
||||
conn.sessionId = sessionId;//restore old
|
||||
@ -2113,7 +2090,7 @@ exports.install = function(server, callbackFunction) {
|
||||
let sessionToken = yield fillJwtByConnection(ctx, conn);
|
||||
sendDataRefreshToken(ctx, conn, sessionToken);
|
||||
}
|
||||
sendFileError(ctx, conn, errorId, code);
|
||||
sendFileError(ctx, conn, errorId, code, opt_notWarn);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2333,14 +2310,14 @@ exports.install = function(server, callbackFunction) {
|
||||
openCmd.userid = fileInfo.UserId;
|
||||
}
|
||||
}
|
||||
let permissionsEdit = !fileInfo.ReadOnly && fileInfo.UserCanWrite && queryParams.formsubmit !== "1";
|
||||
let permissionsFillForm = permissionsEdit || queryParams.formsubmit === "1";
|
||||
let permissionsEdit = !fileInfo.ReadOnly && fileInfo.UserCanWrite && queryParams?.formsubmit !== "1";
|
||||
let permissionsFillForm = permissionsEdit || queryParams?.formsubmit === "1";
|
||||
let permissions = {
|
||||
edit: permissionsEdit,
|
||||
review: (fileInfo.SupportsReviewing === false) ? false : (fileInfo.UserCanReview === false ? false : fileInfo.UserCanReview),
|
||||
copy: fileInfo.CopyPasteRestrictions !== "CurrentDocumentOnly" && fileInfo.CopyPasteRestrictions !== "BlockAll",
|
||||
print: !fileInfo.DisablePrint && !fileInfo.HidePrintOption,
|
||||
chat: queryParams.dchat!=="1",
|
||||
chat: queryParams?.dchat!=="1",
|
||||
fillForms: permissionsFillForm
|
||||
};
|
||||
//todo (review: undefiend)
|
||||
@ -2351,11 +2328,6 @@ exports.install = function(server, callbackFunction) {
|
||||
//not '=' because if it jwt from previous version, we must use values from data
|
||||
Object.assign(data.permissions, permissions);
|
||||
}
|
||||
|
||||
//issuer for secret
|
||||
if (decoded.iss) {
|
||||
data.iss = decoded.iss;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function validateAuthToken(data, decoded) {
|
||||
@ -2477,29 +2449,25 @@ exports.install = function(server, callbackFunction) {
|
||||
ctx.logger.warn('fillDataFromJwt token has invalid format');
|
||||
res = false;
|
||||
}
|
||||
|
||||
//issuer for secret
|
||||
if (decoded.iss) {
|
||||
data.iss = decoded.iss;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function fillVersionHistoryFromJwt(ctx, decoded, cmd) {
|
||||
function fillVersionHistoryFromJwt(ctx, decoded, data) {
|
||||
let openCmd = data.openCmd;
|
||||
data.mode = 'view';
|
||||
data.coEditingMode = 'strict';
|
||||
data.docid = decoded.key;
|
||||
openCmd.url = decoded.url;
|
||||
if (decoded.changesUrl && decoded.previous) {
|
||||
let versionMatch = cmd.getServerVersion() === commonDefines.buildVersion;
|
||||
let openPreviousVersion = cmd.getDocId() === decoded.previous.key;
|
||||
let versionMatch = openCmd.serverVersion === commonDefines.buildVersion;
|
||||
let openPreviousVersion = openCmd.id === decoded.previous.key;
|
||||
if (versionMatch && openPreviousVersion) {
|
||||
cmd.setUrl(decoded.previous.url);
|
||||
cmd.setDocId(decoded.previous.key);
|
||||
data.docid = decoded.previous.key;
|
||||
openCmd.url = decoded.previous.url;
|
||||
} else {
|
||||
ctx.logger.warn('fillVersionHistoryFromJwt serverVersion mismatch or mismatch between previous url and changes. serverVersion=%s docId=%s', cmd.getServerVersion(), cmd.getDocId());
|
||||
cmd.setUrl(decoded.url);
|
||||
cmd.setDocId(decoded.key);
|
||||
ctx.logger.warn('fillVersionHistoryFromJwt serverVersion mismatch or mismatch between previous url and changes. serverVersion=%s docId=%s', openCmd.serverVersion, openCmd.id);
|
||||
}
|
||||
} else {
|
||||
cmd.setUrl(decoded.url);
|
||||
cmd.setDocId(decoded.key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function* auth(ctx, conn, data) {
|
||||
@ -2528,19 +2496,23 @@ exports.install = function(server, callbackFunction) {
|
||||
} else if (decoded.editorConfig && undefined !== decoded.editorConfig.ds_sessionTimeConnect) {
|
||||
//reconnection
|
||||
fillDataFromJwtRes = fillDataFromJwt(ctx, decoded, data);
|
||||
} else if (decoded.version) {//version required, but maybe add new type like jwtSession?
|
||||
//version history
|
||||
fillDataFromJwtRes = fillVersionHistoryFromJwt(ctx, decoded, data);
|
||||
} else {
|
||||
//opening
|
||||
let validationErr = validateAuthToken(data, decoded);
|
||||
if (!validationErr) {
|
||||
fillDataFromJwtRes = fillDataFromJwt(ctx, decoded, data);
|
||||
} else if (tenTokenRequiredParams) {
|
||||
ctx.logger.error("auth missing required parameter %s (since 7.1 version)", validationErr);
|
||||
sendDataDisconnectReason(ctx, conn, constants.JWT_ERROR_CODE, constants.JWT_ERROR_REASON);
|
||||
conn.disconnect(true);
|
||||
return;
|
||||
} else {
|
||||
ctx.logger.warn("auth missing required parameter %s (since 7.1 version)", validationErr);
|
||||
fillDataFromJwtRes = fillDataFromJwt(ctx, decoded, data);
|
||||
ctx.logger.error("auth missing required parameter %s (since 7.1 version)", validationErr);
|
||||
if (tenTokenRequiredParams) {
|
||||
sendDataDisconnectReason(ctx, conn, constants.JWT_ERROR_CODE, constants.JWT_ERROR_REASON);
|
||||
conn.disconnect(true);
|
||||
return;
|
||||
} else {
|
||||
fillDataFromJwtRes = fillDataFromJwt(ctx, decoded, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!fillDataFromJwtRes) {
|
||||
@ -2756,13 +2728,14 @@ exports.install = function(server, callbackFunction) {
|
||||
var updateIfRes = yield taskResult.updateIf(ctx, updateTask, updateMask);
|
||||
if (!(updateIfRes.affectedRows > 0)) {
|
||||
// error version
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Update Version error', constants.UPDATE_VERSION_CODE);
|
||||
//log level is debug because error handled via refreshFile
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Update Version error', constants.UPDATE_VERSION_CODE, true);
|
||||
return;
|
||||
}
|
||||
} else if (commonDefines.FileStatus.UpdateVersion === status) {
|
||||
if (bIsRestore) {
|
||||
// error version
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Update Version error', constants.UPDATE_VERSION_CODE);
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Update Version error', constants.UPDATE_VERSION_CODE, true);
|
||||
return;
|
||||
} else {
|
||||
modifyConnectionEditorToView(ctx, conn);
|
||||
@ -2772,8 +2745,11 @@ exports.install = function(server, callbackFunction) {
|
||||
//ok
|
||||
} else if (bIsRestore) {
|
||||
// Other error
|
||||
let code = null === status ? constants.NO_CACHE_CODE : undefined;
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Other error', code);
|
||||
if(null === status) {
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Other error', constants.NO_CACHE_CODE, true);
|
||||
} else {
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Other error');
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2814,17 +2790,17 @@ exports.install = function(server, callbackFunction) {
|
||||
if (wopiLockRes) {
|
||||
yield* authRestore(ctx, conn, data.sessionId);
|
||||
} else {
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Restore error. Wopi lock error.', constants.RESTORE_CODE);
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Restore error. Wopi lock error.', constants.RESTORE_CODE, true);
|
||||
}
|
||||
} else {
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Restore error. Locks not checked.', constants.RESTORE_CODE);
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Restore error. Locks not checked.', constants.RESTORE_CODE, true);
|
||||
}
|
||||
} else {
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Restore error. Document modified.', constants.RESTORE_CODE);
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'Restore error. Document modified.', constants.RESTORE_CODE, true);
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.logger.error("DataBase error: %s", err.stack);
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'DataBase error', constants.RESTORE_CODE);
|
||||
yield* sendFileErrorAuth(ctx, conn, data.sessionId, 'DataBase error', constants.RESTORE_CODE, true);
|
||||
}
|
||||
} else {
|
||||
yield* authRestore(ctx, conn, data.sessionId);
|
||||
@ -2897,7 +2873,7 @@ exports.install = function(server, callbackFunction) {
|
||||
}
|
||||
let lockDocument = null;
|
||||
let waitAuthUserId;
|
||||
if (!bIsRestore && 2 === countNoView && !tmpUser.view) {
|
||||
if (!bIsRestore && 2 === countNoView && !tmpUser.view && firstParticipantNoView) {
|
||||
// lock a document
|
||||
const lockRes = yield editorData.lockAuth(ctx, docId, firstParticipantNoView.id, 2 * tenExpLockDoc);
|
||||
if (constants.CONN_CLOSED === conn.conn.readyState) {
|
||||
@ -3655,13 +3631,7 @@ exports.install = function(server, callbackFunction) {
|
||||
output.fromObject(data.output);
|
||||
var outputData = output.getData();
|
||||
|
||||
var docConnectionId = cmd.getDocConnectionId();
|
||||
var docId;
|
||||
if(docConnectionId){
|
||||
docId = docConnectionId;
|
||||
} else {
|
||||
docId = cmd.getDocId();
|
||||
}
|
||||
var docId = cmd.getDocId();
|
||||
if (cmd.getUserConnectionId()) {
|
||||
participants = getParticipantUser(docId, cmd.getUserConnectionId());
|
||||
} else {
|
||||
|
||||
@ -518,6 +518,41 @@ async function checkAndReplaceEmptyFile(ctx, fileInfo, wopiSrc, access_token, ac
|
||||
}
|
||||
}
|
||||
}
|
||||
function createDocId(ctx, wopiSrc, mode, fileInfo) {
|
||||
let fileId = wopiSrc.substring(wopiSrc.lastIndexOf('/') + 1);
|
||||
let docId = undefined;
|
||||
if ('view' !== mode) {
|
||||
docId = `${fileId}`;
|
||||
} else {
|
||||
//todo rename operation requires lock
|
||||
fileInfo.SupportsRename = false;
|
||||
//todo change docId to avoid empty cache after editors are gone
|
||||
if (fileInfo.LastModifiedTime) {
|
||||
docId = `view.${fileId}.${fileInfo.LastModifiedTime}`;
|
||||
} else {
|
||||
docId = `view.${fileId}.${fileInfo.Version}`;
|
||||
}
|
||||
return docId;
|
||||
}
|
||||
docId = docId.replace(constants.DOC_ID_REPLACE_REGEX, '_').substring(0, constants.DOC_ID_MAX_LENGTH);
|
||||
return docId;
|
||||
}
|
||||
async function preOpen(ctx, lockId, docId, fileInfo, userAuth, baseUrl, fileType) {
|
||||
//todo move to lock and common info saving to websocket connection
|
||||
//save common info
|
||||
if (undefined === lockId) {
|
||||
//Use deterministic(not random) lockId to fix issues with forgotten openings due to integrator failures
|
||||
lockId = docId;
|
||||
let commonInfo = JSON.stringify({lockId: lockId, fileInfo: fileInfo});
|
||||
await canvasService.commandOpenStartPromise(ctx, docId, baseUrl, commonInfo, fileType);
|
||||
}
|
||||
//Lock
|
||||
if ('view' !== userAuth.mode) {
|
||||
let lockRes = await lock(ctx, 'LOCK', lockId, fileInfo, userAuth);
|
||||
return !!lockRes;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function getEditorHtml(req, res) {
|
||||
return co(function*() {
|
||||
let params = {key: undefined, apiQuery: '', fileInfo: {}, userAuth: {}, queryParams: req.query, token: undefined, documentType: undefined, docs_api_config: {}};
|
||||
@ -567,20 +602,8 @@ function getEditorHtml(req, res) {
|
||||
mode = 'view';
|
||||
}
|
||||
//docId
|
||||
let docId = undefined;
|
||||
if ('view' !== mode) {
|
||||
docId = `${fileId}`;
|
||||
} else {
|
||||
//todo rename operation requires lock
|
||||
fileInfo.SupportsRename = false;
|
||||
//todo change docId to avoid empty cache after editors are gone
|
||||
if (fileInfo.LastModifiedTime) {
|
||||
docId = `view.${fileId}.${fileInfo.LastModifiedTime}`;
|
||||
} else {
|
||||
docId = `view.${fileId}.${fileInfo.Version}`;
|
||||
}
|
||||
}
|
||||
docId = docId.replace(constants.DOC_ID_REPLACE_REGEX, '_').substring(0, constants.DOC_ID_MAX_LENGTH);
|
||||
let docId = createDocId(ctx, wopiSrc, mode, fileInfo);
|
||||
ctx.setDocId(fileId);
|
||||
ctx.logger.debug(`wopiEditor`);
|
||||
params.key = docId;
|
||||
let userAuth = params.userAuth = {
|
||||
@ -590,27 +613,15 @@ function getEditorHtml(req, res) {
|
||||
|
||||
//check and invalidate cache
|
||||
let checkRes = yield checkAndInvalidateCache(ctx, docId, fileInfo);
|
||||
let lockId = checkRes.lockId;
|
||||
if (!checkRes.success) {
|
||||
params.fileInfo = {};
|
||||
return;
|
||||
}
|
||||
if (!shutdownFlag) {
|
||||
//save common info
|
||||
if (undefined === lockId) {
|
||||
//Use deterministic(not random) lockId to fix issues with forgotten openings due to integrator failures
|
||||
lockId = docId;
|
||||
let commonInfo = JSON.stringify({lockId: lockId, fileInfo: fileInfo});
|
||||
yield canvasService.commandOpenStartPromise(ctx, docId, utils.getBaseUrlByRequest(ctx, req), commonInfo, fileType);
|
||||
}
|
||||
|
||||
//Lock
|
||||
if ('view' !== mode) {
|
||||
let lockRes = yield lock(ctx, 'LOCK', lockId, fileInfo, userAuth);
|
||||
if (!lockRes) {
|
||||
params.fileInfo = {};
|
||||
return;
|
||||
}
|
||||
let preOpenRes = yield preOpen(ctx, checkRes.lockId, docId, fileInfo, userAuth, utils.getBaseUrlByRequest(ctx, req), fileType);
|
||||
if (!preOpenRes) {
|
||||
params.fileInfo = {};
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -835,6 +846,47 @@ function renameFile(ctx, wopiParams, name) {
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
async function refreshFile(ctx, wopiParams, baseUrl) {
|
||||
let res = {};
|
||||
try {
|
||||
ctx.logger.info('wopi RefreshFile start');
|
||||
let userAuth = wopiParams.userAuth;
|
||||
if (!userAuth) {
|
||||
return;
|
||||
}
|
||||
const tenTokenEnableBrowser = ctx.getCfg('services.CoAuthoring.token.enable.browser', cfgTokenEnableBrowser);
|
||||
const tenTokenOutboxAlgorithm = ctx.getCfg('services.CoAuthoring.token.outbox.algorithm', cfgTokenOutboxAlgorithm);
|
||||
const tenTokenOutboxExpires = ctx.getCfg('services.CoAuthoring.token.outbox.expires', cfgTokenOutboxExpires);
|
||||
|
||||
const fileInfo = await checkFileInfo(ctx, userAuth.wopiSrc, userAuth.access_token);
|
||||
const fileType = getFileTypeByInfo(fileInfo);
|
||||
const docId = createDocId(ctx, userAuth.wopiSrc, userAuth.mode, res.fileInfo);
|
||||
res.key = docId;
|
||||
res.userAuth = userAuth;
|
||||
res.fileInfo = fileInfo;
|
||||
res.queryParams = undefined;
|
||||
if (tenTokenEnableBrowser) {
|
||||
let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||
let secret = await tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||
res.token = jwt.sign(res, secret, options);
|
||||
}
|
||||
let checkRes = await checkAndInvalidateCache(ctx, docId, fileInfo);
|
||||
if (!checkRes.success) {
|
||||
res = {};
|
||||
return;
|
||||
}
|
||||
let preOpenRes = await preOpen(ctx, checkRes.lockId, docId, fileInfo, userAuth, baseUrl, fileType);
|
||||
if (!preOpenRes) {
|
||||
res = {};
|
||||
}
|
||||
} catch (err) {
|
||||
ctx.logger.error('wopi error RefreshFile:%s', err.stack);
|
||||
} finally {
|
||||
ctx.logger.info('wopi RefreshFile end');
|
||||
}
|
||||
return res;
|
||||
}
|
||||
function checkFileInfo(ctx, wopiSrc, access_token, opt_sc) {
|
||||
return co(function* () {
|
||||
let fileInfo = undefined;
|
||||
@ -1099,6 +1151,7 @@ exports.putFile = putFile;
|
||||
exports.parsePutFileResponse = parsePutFileResponse;
|
||||
exports.putRelativeFile = putRelativeFile;
|
||||
exports.renameFile = renameFile;
|
||||
exports.refreshFile = refreshFile;
|
||||
exports.lock = lock;
|
||||
exports.unlock = unlock;
|
||||
exports.fillStandardHeaders = fillStandardHeaders;
|
||||
|
||||
Reference in New Issue
Block a user