diff --git a/controller/documentcontroller.php b/controller/documentcontroller.php index 61d92d2e..56167e8c 100644 --- a/controller/documentcontroller.php +++ b/controller/documentcontroller.php @@ -79,6 +79,37 @@ class DocumentController extends Controller { return null; } + /** + * Log the user with given $userid. + * This function should only be used from public controller methods where no + * existing session exists, for example, when loolwsd is directly calling a + * public method with its own access token. After validating the access + * token, and retrieving the correct user with help of access token, it can + * be set as current user with help of this method. + * + * @param string $userid + */ + private function loginUser($userid) { + $users = \OC::$server->getUserManager()->search($userid, 1, 0); + if (count($users) > 0) { + $user = array_shift($users); + if (strcasecmp($user->getUID(), $userid) === 0) { + // clear the existing sessions, if any + \OC::$server->getSession()->close(); + + // initialize a dummy memory session + $session = new \OC\Session\Memory(''); + // wrap it + $cryptoWrapper = \OC::$server->getSessionCryptoWrapper(); + $session = $cryptoWrapper->wrapSession($session); + // set our session + \OC::$server->setSession($session); + + \OC::$server->getUserSession()->setUser($user); + } + } + } + private function responseError($message, $hint = ''){ $errors = array('errors' => array(array('error' => $message, 'hint' => $hint))); $response = new TemplateResponse('', 'error', $errors, 'error'); @@ -355,8 +386,6 @@ class DocumentController extends Controller { \OC::$server->getLogger()->debug('Generating WOPI Token for file {fileId}, version {version}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'version' => $version ]); - - $row = new Db\Wopi(); $token = $row->generateFileToken($fileId, $version); @@ -440,23 +469,11 @@ class DocumentController extends Controller { if ($version !== '0') { \OCP\JSON::checkAppEnabled('files_versions'); - // Login as this user - $editorid = $res['editor']; - $users = \OC::$server->getUserManager()->search($editorid, 1, 0); - if (count($users) > 0) - { - $user = array_shift($users); - if (strcasecmp($user->getUID(),$editorid) === 0) - { - \OC::$server->getUserSession()->setUser($user); - } - } - - \OCP\JSON::checkLoggedIn(); + $ownerid = $res['owner']; // Setup the FS \OC_Util::tearDownFS(); - \OC_Util::setupFS($editorid, '/' . $editorid . '/files'); + \OC_Util::setupFS($ownerid, '/' . $ownerid . '/files'); list($owner_uid, $filename) = \OCA\Files_Versions\Storage::getUidAndFilename($res['path']); $versionName = '/files_versions/' . $filename . '.v' . $version; @@ -503,15 +520,11 @@ class DocumentController extends Controller { // Log-in as the user to regiser the change under her name. $editorid = $res['editor']; - $users = \OC::$server->getUserManager()->search($editorid, 1, 0); - if (count($users) > 0) - { - $user = array_shift($users); - if (strcasecmp($user->getUID(),$editorid) === 0) - { - \OC::$server->getUserSession()->setUser($user); - } - } + // This call is made from loolwsd, so we need to initialize the + // session before we can make the user who opened the document + // login. This is necessary to make activity app register the + // change made to this file under this user's (editorid) name. + $this->loginUser($editorid); // Set up the filesystem view for the owner (where the file actually is). $userid = $res['owner']; @@ -530,6 +543,9 @@ class DocumentController extends Controller { \OC_Util::tearDownFS(); + // clear any session created before + \OC::$server->getSession()->close(); + return array( 'status' => 'success' ); diff --git a/css/style.css b/css/style.css index ddac9c16..ee4671c3 100644 --- a/css/style.css +++ b/css/style.css @@ -241,6 +241,10 @@ padding: 10px 0; } +#revisionsContainer li:first-child .restoreVersion{ + display: none; +} + #revisionsContainer a{ padding-left: 15px; } @@ -249,6 +253,11 @@ background-color: rgba(0, 0, 0, 0.1); } +.restoreVersion{ + position: absolute; + right: 15px; +} + #show-more-versions{ width: 100%; padding: 10px; diff --git a/js/documents.js b/js/documents.js index 97b77343..aad8bfa2 100644 --- a/js/documents.js +++ b/js/documents.js @@ -218,6 +218,7 @@ var documentsMain = { revHistoryItemTemplate: '
  • ' + '' + '{{formattedTimestamp}}' + + '' + '' + '
  • ', @@ -281,7 +282,7 @@ var documentsMain = { addRevision: function(fileId, version, relativeTimestamp, documentPath) { var formattedTimestamp = OC.Util.formatDate(parseInt(version) * 1000); var fileName = documentsMain.fileName.substring(0, documentsMain.fileName.indexOf('.')); - var downloadUrl; + var downloadUrl, restoreUrl; if (version === 0) { formattedTimestamp = t('richdocuments', 'Latest revision'); downloadUrl = OC.generateUrl('apps/files/download'+ documentPath); @@ -290,12 +291,16 @@ var documentsMain = { downloadUrl = OC.generateUrl('apps/files_versions/download.php?file={file}&revision={revision}', {file: documentPath, revision: version}); fileId = fileId + '_' + version; + restoreUrl = OC.generateUrl('apps/files_versions/ajax/rollbackVersion.php?file={file}&revision={revision}', + {file: documentPath, revision: version}); } var revHistoryItemTemplate = Handlebars.compile(documentsMain.UI.revHistoryItemTemplate); var html = revHistoryItemTemplate({ downloadUrl: downloadUrl, downloadIconUrl: OC.imagePath('core', 'actions/download'), + restoreUrl: restoreUrl, + restoreIconUrl: OC.imagePath('core', 'actions/history'), relativeTimestamp: relativeTimestamp, formattedTimestamp: formattedTimestamp }); @@ -363,6 +368,42 @@ var documentsMain = { $(e.currentTarget.parentElement).addClass('active'); }); + $('#revisionsContainer').on('click', '.restoreVersion', function(e) { + e.preventDefault(); + + // close the viewer + documentsMain.onCloseViewer(); + + // close the editor + documentsMain.UI.hideEditor(); + + // If there are changes in the opened editor, we need to wait + // for sometime before these changes can be saved and a revision is created for it, + // before restoring to requested version. + documentsMain.overlay.documentOverlay('show'); + setTimeout(function() { + // restore selected version + $.ajax({ + type: 'GET', + url: e.currentTarget.href, + success: function(response) { + if (response.status === 'error') { + documentsMain.UI.notify(t('richdocuments', 'Failed to revert the document to older version')); + } + + // generate file id with returnToDir information in it, if any + var fileid = e.currentTarget.parentElement.dataset.fileid.replace(/_.*/, '') + + (documentsMain.returnToDir ? '_' + documentsMain.returnToDir : ''); + + // load the file again, it should get reverted now + window.location = OC.generateUrl('apps/richdocuments/index#{fileid}', {fileid: fileid}); + window.location.reload(); + documentsMain.overlay.documentOverlay('hide'); + } + }); + }, 1000); + }); + // fake click on first revision (i.e current revision) $('#revisionsContainer li').first().find('.versionPreview').click(); }, @@ -393,7 +434,7 @@ var documentsMain = { function (result) { if (!result || result.status === 'error') { if (result && result.message){ - documentsMain.IU.notify(result.message); + documentsMain.UI.notify(result.message); } documentsMain.onEditorShutdown(t('richdocuments', 'Failed to aquire access token. Please re-login and try again.')); return; @@ -755,7 +796,7 @@ var documentsMain = { function(result) { if (result && result.status === 'error') { if (result.message){ - documentsMain.IU.notify(result.message); + documentsMain.UI.notify(result.message); } return; } @@ -785,7 +826,7 @@ var documentsMain = { }, - onClose: function(force) { + onClose: function() { if (!documentsMain.isEditorMode){ return; } @@ -798,7 +839,7 @@ var documentsMain = { documentsMain.UI.hideEditor(); $('#ocToolbar').remove(); - if (!force && documentsMain.returnToDir) { + if (documentsMain.returnToDir) { window.location = OC.generateUrl('apps/files?dir={dir}', {dir: documentsMain.returnToDir}); } else { documentsMain.show(); @@ -806,9 +847,12 @@ var documentsMain = { }, onCloseViewer: function() { + $('#revisionsContainer *').off(); + $('#revPanelContainer').remove(); $('#revViewerContainer').remove(); documentsMain.isViewerMode = false; + documentsMain.UI.revisionsStart = 0; $('#loleafletframe').focus(); },