Skip to content

Commit

Permalink
[bug] Fix bug 49714
Browse files Browse the repository at this point in the history
  • Loading branch information
konovalovsergey committed May 4, 2021
1 parent f60c332 commit 57657dc
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 47 deletions.
8 changes: 8 additions & 0 deletions Common/sources/commondefines.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const constants = require('./constants');
function InputCommand(data, copyExplicit) {
//must be set explicitly to prevent vulnerability(downloadAs(with url) creates request to integrator with authorization)
this['withAuthorization'] = undefined;//bool
this['externalChangeInfo'] = undefined;//zero DB changes case: set password, undo all changes
if (data) {
this['c'] = data['c'];
this['id'] = data['id'];
Expand Down Expand Up @@ -100,6 +101,7 @@ function InputCommand(data, copyExplicit) {
this['attempt'] = data['attempt'];
if (copyExplicit) {
this['withAuthorization'] = data['withAuthorization'];
this['externalChangeInfo'] = data['externalChangeInfo'];
}
} else {
this['c'] = undefined;//string command
Expand Down Expand Up @@ -438,6 +440,12 @@ InputCommand.prototype = {
},
setWithAuthorization: function(data) {
this['withAuthorization'] = data;
},
getExternalChangeInfo: function() {
return this['externalChangeInfo'];
},
setExternalChangeInfo: function(data) {
this['externalChangeInfo'] = data;
}
};

Expand Down
15 changes: 11 additions & 4 deletions DocService/sources/DocsCoServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ function* getChangesIndex(docId) {
}

const hasChanges = co.wrap(function*(docId) {
//todo check editorData.getForceSave in case of "undo all changes"
let puckerIndex = yield* getChangesIndex(docId);
if (0 === puckerIndex) {
let selectRes = yield taskResult.select(docId);
Expand Down Expand Up @@ -779,7 +780,7 @@ let startForceSave = co.wrap(function*(docId, type, opt_userdata, opt_userId, op
priority = constants.QUEUE_PRIORITY_LOW;
}
//start new convert
let status = yield* converterService.convertFromChanges(docId, baseUrl, forceSave, opt_userdata,
let status = yield* converterService.convertFromChanges(docId, baseUrl, forceSave, startedForceSave.changeInfo, opt_userdata,
opt_userConnectionId, opt_responseKey, priority, expiration, opt_queue);
if (constants.NO_ERROR === status.err) {
res.time = forceSave.getTime();
Expand All @@ -793,10 +794,13 @@ let startForceSave = co.wrap(function*(docId, type, opt_userdata, opt_userId, op
logger.debug('startForceSave end:docId = %s', docId);
return res;
});
let resetForceSaveAfterChanges = co.wrap(function*(docId, newChangesLastTime, puckerIndex, baseUrl) {
function getExternalChangeInfo(user, date) {
return {user_id: user.id, user_id_original: user.idOriginal, user_name: user.username, change_date: date};
}
let resetForceSaveAfterChanges = co.wrap(function*(docId, newChangesLastTime, puckerIndex, baseUrl, changeInfo) {
//last save
if (newChangesLastTime) {
yield editorData.setForceSave(docId, newChangesLastTime, puckerIndex, baseUrl);
yield editorData.setForceSave(docId, newChangesLastTime, puckerIndex, baseUrl, changeInfo);
if (cfgForceSaveEnable) {
let expireAt = newChangesLastTime + cfgForceSaveInterval;
yield editorData.addForceSaveTimerNX(docId, expireAt);
Expand Down Expand Up @@ -1026,6 +1030,7 @@ function* cleanDocumentOnExit(docId, deleteChanges) {
yield editorData.cleanDocumentOnExit(docId);
//remove changes
if (deleteChanges) {
yield taskResult.restoreInitialPassword(docId);
sqlBase.deleteChanges(docId, null);
//delete forgotten after successful send on callbackUrl
yield storage.deletePath(cfgForgottenFiles + '/' + docId);
Expand Down Expand Up @@ -1208,6 +1213,7 @@ exports.cleanDocumentOnExitNoChangesPromise = co.wrap(cleanDocumentOnExitNoChang
exports.setForceSave = setForceSave;
exports.startForceSave = startForceSave;
exports.resetForceSaveAfterChanges = resetForceSaveAfterChanges;
exports.getExternalChangeInfo = getExternalChangeInfo;
exports.checkJwt = checkJwt;
exports.getRequestParams = getRequestParams;
exports.checkJwtHeader = checkJwtHeader;
Expand Down Expand Up @@ -2561,7 +2567,8 @@ exports.install = function(server, callbackFunction) {
// Автоматически снимаем lock сами и посылаем индекс для сохранения
yield* unSaveLock(conn, changesIndex, newChangesLastTime);
//last save
yield resetForceSaveAfterChanges(docId, newChangesLastTime, puckerIndex, utils.getBaseUrlByConnection(conn));
let changeInfo = getExternalChangeInfo(conn.user, newChangesLastTime);
yield resetForceSaveAfterChanges(docId, newChangesLastTime, puckerIndex, utils.getBaseUrlByConnection(conn), changeInfo);
} else {
let changesToSend = arrNewDocumentChanges;
if(changesToSend.length > cfgPubSubMaxChanges) {
Expand Down
22 changes: 9 additions & 13 deletions DocService/sources/baseConnector.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,33 +317,29 @@ exports.UserCallback = UserCallback;

function DocumentPassword() {
this.password = undefined;
this.userId = undefined;
this.userIndex = undefined;
this.change = undefined;
}
DocumentPassword.prototype.fromString = function(passwordStr){
var parsed = JSON.parse(passwordStr);
this.fromValues(parsed.password, parsed.userId, parsed.userIndex);
this.fromValues(parsed.password, parsed.change);
};
DocumentPassword.prototype.fromValues = function(password, userId, userIndex){
DocumentPassword.prototype.fromValues = function(password, change){
if(null !== password){
this.password = password;
}
if(null !== userId){
this.userId = userId;
}
if(null !== userIndex){
this.userIndex = userIndex;
if(null !== change) {
this.change = change;
}
};
DocumentPassword.prototype.delimiter = String.fromCharCode(5);
DocumentPassword.prototype.toSQLInsert = function(){
return this.delimiter + JSON.stringify(this);
};
DocumentPassword.prototype.isInitial = function(){
return !this.userId;
return !this.change;
};
DocumentPassword.prototype.getDocPassword = function(docId, docPasswordStr) {
let res = {initial: undefined, current: undefined, userId: undefined, userIndex: undefined};
let res = {initial: undefined, current: undefined, change: undefined};
if (docPasswordStr) {
logger.debug("getDocPassword: docId = %s passwords = %s", docId, docPasswordStr);
let passwords = docPasswordStr.split(UserCallback.prototype.delimiter);
Expand All @@ -353,10 +349,10 @@ DocumentPassword.prototype.getDocPassword = function(docId, docPasswordStr) {
password.fromString(passwords[i]);
if (password.isInitial()) {
res.initial = password.password;
} else {
res.change = password.change;
}
res.current = password.password;
res.userId = password.userId;
res.userIndex = password.userIndex;
}
}
return res;
Expand Down
21 changes: 10 additions & 11 deletions DocService/sources/canvasservice.js
Original file line number Diff line number Diff line change
Expand Up @@ -505,9 +505,8 @@ function* commandSfctByCmd(cmd, opt_priority, opt_expiration, opt_queue) {
let docPassword = row && sqlBase.DocumentPassword.prototype.getDocPassword(cmd.getDocId(), row.password);
if (docPassword.current) {
cmd.setSavePassword(docPassword.current);
if (docPassword.userId) {
cmd.setUserId(docPassword.userId);
cmd.setUserIndex(docPassword.userIndex);
if (docPassword.change) {
cmd.setExternalChangeInfo(docPassword.change);
}
}
var queueData = getSaveTask(cmd);
Expand Down Expand Up @@ -714,12 +713,15 @@ function* commandSetPassword(conn, cmd, outputData) {
updateMask.key = cmd.getDocId();
updateMask.status = taskResult.FileStatus.Ok;

let newChangesLastDate = new Date();
newChangesLastDate.setMilliseconds(0);//remove milliseconds avoid issues with MySQL datetime rounding

var task = new taskResult.TaskResultData();
task.key = cmd.getDocId();
task.password = cmd.getPassword() || "";
let changeInfo = null;
if (conn.user) {
task.innerUserId = conn.user.idOriginal;
task.innerUserIndex = utils.getIndexFromUserId(conn.user.id, conn.user.idOriginal);
changeInfo = task.innerPasswordChange = docsCoServer.getExternalChangeInfo(conn.user, newChangesLastDate.getTime());
}

var upsertRes = yield taskResult.updateIf(task, updateMask);
Expand All @@ -728,9 +730,7 @@ function* commandSetPassword(conn, cmd, outputData) {
if (!conn.isEnterCorrectPassword) {
docsCoServer.modifyConnectionForPassword(conn, true);
}
let newChangesLastDate = new Date();
newChangesLastDate.setMilliseconds(0);//remove milliseconds avoid issues with MySQL datetime rounding
yield docsCoServer.resetForceSaveAfterChanges(cmd.getDocId(), newChangesLastDate.getTime(), 0x7FFFFFFF, utils.getBaseUrlByConnection(conn));
yield docsCoServer.resetForceSaveAfterChanges(cmd.getDocId(), newChangesLastDate.getTime(), 0, utils.getBaseUrlByConnection(conn), changeInfo);
} else {
logger.debug('commandSetPassword sql update error: docId = %s', cmd.getDocId());
outputData.setStatus('err');
Expand Down Expand Up @@ -1305,9 +1305,8 @@ exports.saveFromChanges = function(docId, statusInfo, optFormat, opt_userId, opt
let docPassword = row && sqlBase.DocumentPassword.prototype.getDocPassword(cmd.getDocId(), row.password);
if (docPassword.current) {
cmd.setSavePassword(docPassword.current);
if (docPassword.userId) {
cmd.setUserId(docPassword.userId);
cmd.setUserIndex(docPassword.userIndex);
if (docPassword.change) {
cmd.setExternalChangeInfo(docPassword.change);
}
}
yield* addRandomKeyTaskCmd(cmd);
Expand Down
5 changes: 3 additions & 2 deletions DocService/sources/converterservice.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ function* convertByCmd(cmd, async, baseUrl, opt_fileTo, opt_taskExist, opt_prior
return status;
}

function* convertFromChanges(docId, baseUrl, forceSave, opt_userdata, opt_userConnectionId, opt_responseKey, opt_priority,
opt_expiration, opt_queue, opt_redisKey) {
function* convertFromChanges(docId, baseUrl, forceSave, externalChangeInfo, opt_userdata, opt_userConnectionId,
opt_responseKey, opt_priority, opt_expiration, opt_queue, opt_redisKey) {
var cmd = new commonDefines.InputCommand();
cmd.setCommand('sfcm');
cmd.setDocId(docId);
Expand All @@ -158,6 +158,7 @@ function* convertFromChanges(docId, baseUrl, forceSave, opt_userdata, opt_userCo
cmd.setCodepage(commonDefines.c_oAscCodePageUtf8);
cmd.setDelimiter(commonDefines.c_oAscCsvDelimiter.Comma);
cmd.setForceSave(forceSave);
cmd.setExternalChangeInfo(externalChangeInfo);
if (opt_userdata) {
cmd.setUserData(opt_userdata);
}
Expand Down
4 changes: 2 additions & 2 deletions DocService/sources/editorDataMemory.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ EditorData.prototype.getdelSaved = function(docId) {
data.saved = undefined;
return Promise.resolve(res);
};
EditorData.prototype.setForceSave = function(docId, time, index, baseUrl) {
EditorData.prototype.setForceSave = function(docId, time, index, baseUrl, changeInfo) {
let data = this._getDocumentData(docId);
data.forceSave = {time: time, index: index, baseUrl: baseUrl, started: false, ended: false};
data.forceSave = {time: time, index: index, baseUrl: baseUrl, changeInfo: changeInfo, started: false, ended: false};
return Promise.resolve();
};
EditorData.prototype.getForceSave = function(docId) {
Expand Down
40 changes: 31 additions & 9 deletions DocService/sources/taskresult.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ function TaskResultData() {
this.baseurl = null;
this.password = null;

this.innerUserId = null;//not a DB field
this.innerUserIndex = null;//not a DB field
this.innerPasswordChange = null;//not a DB field
}
TaskResultData.prototype.completeDefaults = function() {
if (!this.key) {
Expand Down Expand Up @@ -118,7 +117,7 @@ function select(docId) {
}, undefined, undefined, values);
});
}
function toUpdateArray(task, updateTime, isMask, values) {
function toUpdateArray(task, updateTime, isMask, values, setPassword) {
var res = [];
if (null != task.status) {
let sqlParam = addSqlParam(task.status, values);
Expand Down Expand Up @@ -154,19 +153,22 @@ function toUpdateArray(task, updateTime, isMask, values) {
let sqlParam = addSqlParam(task.baseurl, values);
res.push(`baseurl=${sqlParam}`);
}
if (null != task.password) {
if (setPassword) {
let sqlParam = addSqlParam(task.password, values);
res.push(`password=${sqlParam}`);
} else if (null != task.password || setPassword) {
var documentPassword = new sqlBase.DocumentPassword();
documentPassword.fromValues(task.password, task.innerUserId, task.innerUserIndex);
documentPassword.fromValues(task.password, task.innerPasswordChange);
let sqlParam = addSqlParam(documentPassword.toSQLInsert(), values);
res.push(`password=${concatParams('password', sqlParam)}`);
}
return res;
}

function update(task) {
function update(task, setPassword) {
return new Promise(function(resolve, reject) {
let values = [];
let updateElems = toUpdateArray(task, true, false, values);
let updateElems = toUpdateArray(task, true, false, values, setPassword);
let sqlSet = updateElems.join(', ');
let sqlParam = addSqlParam(task.key, values);
let sqlCommand = `UPDATE task_result SET ${sqlSet} WHERE id=${sqlParam};`;
Expand All @@ -183,8 +185,8 @@ function update(task) {
function updateIf(task, mask) {
return new Promise(function(resolve, reject) {
let values = [];
let commandArg = toUpdateArray(task, true, false, values);
let commandArgMask = toUpdateArray(mask, false, true, values);
let commandArg = toUpdateArray(task, true, false, values, false);
let commandArgMask = toUpdateArray(mask, false, true, values, false);
commandArgMask.push('id=' + addSqlParam(mask.key, values));
let sqlSet = commandArg.join(', ');
let sqlWhere = commandArgMask.join(' AND ');
Expand All @@ -198,6 +200,25 @@ function updateIf(task, mask) {
}, undefined, undefined, values);
});
}
function restoreInitialPassword(docId) {
return select(docId).then(function(selectRes) {
if (selectRes.length > 0) {
var row = selectRes[0];
let docPassword = sqlBase.DocumentPassword.prototype.getDocPassword(docId, row.password);
var updateTask = new TaskResultData();
updateTask.key = docId;
if (docPassword.initial) {
var documentPassword = new sqlBase.DocumentPassword();
documentPassword.fromValues(docPassword.initial);
updateTask.password = documentPassword.toSQLInsert();
return update(updateTask, true);
} else if (docPassword.current) {
updateTask.password = null;
return update(updateTask, true);
}
}
});
}

function addRandomKey(task, opt_prefix, opt_size) {
return new Promise(function(resolve, reject) {
Expand Down Expand Up @@ -291,6 +312,7 @@ exports.upsert = upsert;
exports.select = select;
exports.update = update;
exports.updateIf = updateIf;
exports.restoreInitialPassword = restoreInitialPassword;
exports.addRandomKeyTask = addRandomKeyTask;
exports.remove = remove;
exports.getExpired = getExpired;
27 changes: 21 additions & 6 deletions FileConverter/sources/converter.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,28 @@ function* processChanges(tempDirs, cmd, authorProps) {
forceSaveTime = forceSave.getTime();
forceSaveIndex = forceSave.getIndex();
}
let extChangeInfo = cmd.getExternalChangeInfo();
let extChanges;
if (extChangeInfo) {
extChanges = [{
id: cmd.getDocId(), change_id: 0, change_data: "", user_id: extChangeInfo.user_id,
user_id_original: extChangeInfo.user_id_original, user_name: extChangeInfo.user_name,
change_date: new Date(extChangeInfo.change_date)
}];
}

let streamObj = yield* streamCreate(cmd.getDocId(), changesDir, indexFile++, {highWaterMark: cfgStreamWriterBufferSize});
let curIndexStart = 0;
let curIndexEnd = Math.min(curIndexStart + cfgMaxRequestChanges, forceSaveIndex);
while (curIndexStart < curIndexEnd) {
let changes = yield baseConnector.getChangesPromise(cmd.getDocId(), curIndexStart, curIndexEnd, forceSaveTime);
while (curIndexStart < curIndexEnd || extChanges) {
let changes = [];
if (curIndexStart < curIndexEnd) {
changes = yield baseConnector.getChangesPromise(cmd.getDocId(), curIndexStart, curIndexEnd, forceSaveTime);
}
if (0 === changes.length && extChanges) {
changes = extChanges;
}
extChanges = undefined;
for (let i = 0; i < changes.length; ++i) {
let change = changes[i];
if (change.change_data.startsWith('ENCRYPTED;')) {
Expand Down Expand Up @@ -457,10 +474,8 @@ function* processChanges(tempDirs, cmd, authorProps) {
changesAuthor = forceSave.getAuthorUserId();
changesIndex = forceSave.getAuthorUserIndex();
}
if (null != changesAuthor && null != changesIndex) {
cmd.setUserId(changesAuthor);
cmd.setUserIndex(changesIndex);
}
cmd.setUserId(changesAuthor);
cmd.setUserIndex(changesIndex);
fs.writeFileSync(path.join(tempDirs.result, 'changesHistory.json'), JSON.stringify(changesHistory), 'utf8');
return res;
}
Expand Down

0 comments on commit 57657dc

Please sign in to comment.