diff --git a/appinfo/database.xml b/appinfo/database.xml index 722fc1ee..fe6c0760 100644 --- a/appinfo/database.xml +++ b/appinfo/database.xml @@ -7,7 +7,7 @@ *dbprefix*richdocuments_session - + es_id text @@ -41,7 +41,7 @@ 64 oC user who created the session - + richdocuments_session_ei_idx true @@ -51,14 +51,14 @@ ascending - +
- + *dbprefix*richdocuments_member - + member_id integer @@ -114,14 +114,14 @@ true 1 - +
- + *dbprefix*richdocuments_op - + seq integer @@ -160,7 +160,7 @@ false json-string - + richdocs_seq_pKey true @@ -181,13 +181,13 @@ ascending - +
*dbprefix*richdocuments_invite - + es_id text @@ -214,13 +214,13 @@ true 4 - +
*dbprefix*richdocuments_revisions - + es_id text @@ -257,7 +257,7 @@ true used to lookup revision in documents folder of member, eg hash.odt - + richdocuments_rev_eis_idx true @@ -270,10 +270,10 @@ ascending - +
- + *dbprefix*richdocuments_wopi @@ -320,6 +320,13 @@ 512 Relative to storage e.g. /welcome.odt + + canwrite + boolean + false + true + Can make changes to this file + token text @@ -335,6 +342,15 @@ 4 Expiration time of the token + + + richdocuments_wopi_token_idx + true + + token + ascending + +
diff --git a/appinfo/info.xml b/appinfo/info.xml index c79af661..eeb3a996 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -5,7 +5,7 @@ Collabora Online allows you to to work with all kinds of office documents directly in your browser. This application requires Collabora Cloudsuite to be installed on one of your servers, please read the documentation to learn more about that. Edit office documents directly in your browser. AGPL - 1.1.6 + 1.1.8 Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk https://github.com/owncloud/richdocuments/issues https://github.com/owncloud/richdocuments.git diff --git a/controller/documentcontroller.php b/controller/documentcontroller.php index ec43bdc2..35c3aef1 100644 --- a/controller/documentcontroller.php +++ b/controller/documentcontroller.php @@ -95,6 +95,8 @@ class DocumentController extends Controller { * @param string $userid */ private function loginUser($userid) { + \OC_Util::tearDownFS(); + $users = \OC::$server->getUserManager()->search($userid, 1, 0); if (count($users) > 0) { $user = array_shift($users); @@ -113,6 +115,18 @@ class DocumentController extends Controller { \OC::$server->getUserSession()->setUser($user); } } + + \OC_Util::setupFS(); + } + + /** + * Log out the current user + * This is helpful when we are artifically logged in as someone + */ + private function logoutUser() { + \OC_Util::tearDownFS(); + + \OC::$server->getSession()->close(); } private function responseError($message, $hint = ''){ @@ -305,9 +319,7 @@ class DocumentController extends Controller { 'uploadMaxHumanFilesize' => \OCP\Util::humanFileSize($maxUploadFilesize), 'allowShareWithLink' => $this->settings->getAppValue('core', 'shareapi_allow_links', 'yes'), 'wopi_url' => $webSocket, - 'edit_groups' => $this->appConfig->getAppValue('edit_groups'), - 'doc_format' => $this->appConfig->getAppValue('doc_format'), - 'usergroups' => $usergroups + 'doc_format' => $this->appConfig->getAppValue('doc_format') ]); $policy = new ContentSecurityPolicy(); @@ -438,8 +450,41 @@ class DocumentController extends Controller { \OC::$server->getLogger()->debug('Generating WOPI Token for file {fileId}, version {version}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'version' => $version ]); + $view = \OC\Files\Filesystem::getView(); + $path = $view->getPath($fileId); + $updatable = (bool)$view->isUpdatable($path); + + // Check if the editor (user who is accessing) is in editable group + // UserCanWrite only if + // 1. No edit groups are set or + // 2. if they are set, it is in one of the edit groups + $editorUid = \OC::$server->getUserSession()->getUser()->getUID(); + $editGroups = array_filter(explode('|', $this->appConfig->getAppValue('edit_groups'))); + if ($updatable && count($editGroups) > 0) { + $updatable = false; + foreach($editGroups as $editGroup) { + $editorGroup = \OC::$server->getGroupManager()->get($editGroup); + if (sizeof($editorGroup->searchUsers($editorUid)) > 0) { + \OC::$server->getLogger()->debug("Editor {editor} is in edit group {group}", [ + 'app' => $this->appName, + 'editor' => $editorUid, + 'group' => $editGroup + ]); + $updatable = true; + } + } + } + + // If token is for some versioned file + if ($version !== '0') { + \OC::$server->getLogger()->debug('setting updatable to false'); + $updatable = false; + } + + \OC::$server->getLogger()->debug('File with {fileid} has updatable set to {updatable}', [ 'app' => $this->appName, 'fileid' => $fileId, 'updatable' => $updatable ]); + $row = new Db\Wopi(); - $token = $row->generateFileToken($fileId, $version); + $token = $row->generateFileToken($fileId, $version, $updatable); // Return the token. return array( @@ -476,13 +521,11 @@ class DocumentController extends Controller { } // Login the user to see his mount locations - $this->loginUser($res['owner']); - - $view = new \OC\Files\View('/' . $res['owner'] . '/files'); + $this->loginUser($res['editor']); + $view = \OC\Files\Filesystem::getView(); $info = $view->getFileInfo($res['path']); - // Close the session created for user login - \OC::$server->getSession()->close(); + $this->logoutUser(); if (!$info) { http_response_code(404); @@ -490,13 +533,13 @@ class DocumentController extends Controller { } $editorName = \OC::$server->getUserManager()->get($res['editor'])->getDisplayName(); - \OC::$server->getLogger()->debug('File info: {info}.', [ 'app' => $this->appName, 'info' => $info ]); return array( 'BaseFileName' => $info['name'], 'Size' => $info['size'], 'Version' => $version, 'UserId' => $res['editor'], - 'UserFriendlyName' => $editorName + 'UserFriendlyName' => $editorName, + 'UserCanWrite' => $res['canwrite'] ? 'true' : 'false' ); } @@ -534,10 +577,6 @@ class DocumentController extends Controller { if ($version !== '0') { \OCP\JSON::checkAppEnabled('files_versions'); - // Setup the FS - \OC_Util::tearDownFS(); - \OC_Util::setupFS($ownerid, '/' . $ownerid . '/files'); - list($ownerid, $filename) = \OCA\Files_Versions\Storage::getUidAndFilename($res['path']); $filename = '/files_versions/' . $filename . '.v' . $version; @@ -546,8 +585,7 @@ class DocumentController extends Controller { $filename = '/files' . $res['path']; } - // Close the session created for user login - \OC::$server->getSession()->close(); + $this->logoutUser(); return new DownloadResponse($this->request, $ownerid, $filename); } @@ -569,20 +607,18 @@ class DocumentController extends Controller { $version = $arr[1]; } - // Changing a previous version of the file is not possible - // Ignore WOPI put if such a request is encountered - if ($version !== '0') { - return array( - 'status' => 'success' - ); - } - \OC::$server->getLogger()->debug('Putting contents of file {fileId}, version {version} by token {token}.', [ 'app' => $this->appName, 'fileId' => $fileId, 'version' => $version, 'token' => $token ]); $row = new Db\Wopi(); $row->loadBy('token', $token); $res = $row->getPathForToken($fileId, $version, $token); + if (!$res['canwrite']) { + return array( + 'status' => 'error', + 'message' => 'Permission denied' + ); + } // Log-in as the user to regiser the change under her name. $editorid = $res['editor']; @@ -603,14 +639,11 @@ class DocumentController extends Controller { // Setup the FS which is needed to emit hooks (versioning). \OC_Util::tearDownFS(); - \OC_Util::setupFS($userid, $root); + \OC_Util::setupFS($userid); $view->file_put_contents($res['path'], $content); - \OC_Util::tearDownFS(); - - // clear any session created before - \OC::$server->getSession()->close(); + $this->logoutUser(); return array( 'status' => 'success' diff --git a/controller/sessioncontroller.php b/controller/sessioncontroller.php index 7f63855d..ecdc7345 100644 --- a/controller/sessioncontroller.php +++ b/controller/sessioncontroller.php @@ -99,16 +99,9 @@ class SessionController extends Controller{ $view = \OC\Files\Filesystem::getView(); $path = $view->getPath($fileId); - if ($view->isUpdatable($path)) { - $file = new File($fileId); - $response = Db\Session::start($this->uid, $file); - } else { - $info = $view->getFileInfo($path); - $response = [ - 'permissions' => $info['permissions'], - 'id' => $fileId - ]; - } + $file = new File($fileId); + $response = Db\Session::start($this->uid, $file); + $response = array_merge( $response, [ 'status'=>'success' ] diff --git a/js/documents.js b/js/documents.js index f7495cbb..9806d00e 100644 --- a/js/documents.js +++ b/js/documents.js @@ -17,29 +17,6 @@ $.widget('oc.documentGrid', { jQuery.when(this._load(fileId)) .then(function(){ that._render(); - - if (!documentsMain.isGuest) { - var editGroups = $('#edit_groups').val() - .split('|') - .filter(function(e) { - return e.length !== 0; - }); - var usergroups = $('#usergroups').val() - .split('|') - .filter(function(e) { - return e.length !== 0; - }); - documentsMain.canEdit = (editGroups.length === 0); - if (!documentsMain.canEdit && usergroups.length >= 1) { - for (var idx in usergroups) { - if (editGroups.indexOf(usergroups[idx]) !== -1) { - documentsMain.canEdit = true; - break; - } - } - } - } - documentsMain.renderComplete = true; }); }, @@ -658,6 +635,7 @@ var documentsMain = { documentsMain.esId = response.es_id; documentsMain.memberId = response.member_id; + documentsMain.canEdit = response.permissions & OC.PERMISSION_UPDATE; documentsMain.loadDocument(); diff --git a/lib/db/wopi.php b/lib/db/wopi.php index fcff1c54..c4ea3830 100644 --- a/lib/db/wopi.php +++ b/lib/db/wopi.php @@ -29,8 +29,8 @@ class Wopi extends \OCA\Richdocuments\Db{ protected $tableName = '`*PREFIX*richdocuments_wopi`'; - protected $insertStatement = 'INSERT INTO `*PREFIX*richdocuments_wopi` (`owner_uid`, `editor_uid`, `fileid`, `version`, `path`, `token`, `expiry`) - VALUES (?, ?, ?, ?, ?, ?, ?)'; + protected $insertStatement = 'INSERT INTO `*PREFIX*richdocuments_wopi` (`owner_uid`, `editor_uid`, `fileid`, `version`, `path`, `canwrite`, `token`, `expiry`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)'; protected $loadStatement = 'SELECT * FROM `*PREFIX*richdocuments_wopi` WHERE `token`= ?'; @@ -41,7 +41,7 @@ class Wopi extends \OCA\Richdocuments\Db{ * its the version number as stored by files_version app * Returns the token. */ - public function generateFileToken($fileId, $version){ + public function generateFileToken($fileId, $version, $updatable){ // Get the FS view of the current user. $view = \OC\Files\Filesystem::getView(); @@ -49,7 +49,7 @@ class Wopi extends \OCA\Richdocuments\Db{ // Get the virtual path (if the file is shared). $path = $view->getPath($fileId); - if (!$view->is_file($path) || !$view->isUpdatable($path)) { + if (!$view->is_file($path)) { throw new \Exception('Invalid fileId.'); } @@ -79,6 +79,7 @@ class Wopi extends \OCA\Richdocuments\Db{ $fileId, $version, $path, + $updatable, $token, time() + self::TOKEN_LIFETIME_SECONDS ]); @@ -120,6 +121,11 @@ class Wopi extends \OCA\Richdocuments\Db{ return false; } - return array('owner' => $row['owner_uid'], 'editor' => $row['editor_uid'], 'path' => $row['path']); + return array( + 'owner' => $row['owner_uid'], + 'editor' => $row['editor_uid'], + 'path' => $row['path'], + 'canwrite' => $row['canwrite'] + ); } } diff --git a/templates/documents.php b/templates/documents.php index 3840eafd..1d3556c0 100644 --- a/templates/documents.php +++ b/templates/documents.php @@ -51,6 +51,4 @@ script('files', 'jquery.fileupload'); - - - + \ No newline at end of file