Merge pull request #130 from pranavk/readonliness

Add UserCanWrite WOPI property
This commit is contained in:
Andras Timar 2016-10-20 10:39:35 +02:00 committed by GitHub
commit a7f8fb75b3
7 changed files with 112 additions and 88 deletions

View File

@ -320,6 +320,13 @@
<length>512</length> <length>512</length>
<comments>Relative to storage e.g. /welcome.odt</comments> <comments>Relative to storage e.g. /welcome.odt</comments>
</field> </field>
<field>
<name>canwrite</name>
<type>boolean</type>
<default>false</default>
<notnull>true</notnull>
<comments>Can make changes to this file</comments>
</field>
<field> <field>
<name>token</name> <name>token</name>
<type>text</type> <type>text</type>
@ -335,6 +342,15 @@
<length>4</length> <length>4</length>
<comments>Expiration time of the token</comments> <comments>Expiration time of the token</comments>
</field> </field>
<index>
<name>richdocuments_wopi_token_idx</name>
<unique>true</unique>
<field>
<name>token</name>
<sorting>ascending</sorting>
</field>
</index>
</declaration> </declaration>
</table> </table>
</database> </database>

View File

@ -5,7 +5,7 @@
<description>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.</description> <description>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.</description>
<summary>Edit office documents directly in your browser.</summary> <summary>Edit office documents directly in your browser.</summary>
<licence>AGPL</licence> <licence>AGPL</licence>
<version>1.1.6</version> <version>1.1.8</version>
<author>Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk</author> <author>Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk</author>
<bugs>https://github.com/owncloud/richdocuments/issues</bugs> <bugs>https://github.com/owncloud/richdocuments/issues</bugs>
<repository type="git">https://github.com/owncloud/richdocuments.git</repository> <repository type="git">https://github.com/owncloud/richdocuments.git</repository>

View File

@ -95,6 +95,8 @@ class DocumentController extends Controller {
* @param string $userid * @param string $userid
*/ */
private function loginUser($userid) { private function loginUser($userid) {
\OC_Util::tearDownFS();
$users = \OC::$server->getUserManager()->search($userid, 1, 0); $users = \OC::$server->getUserManager()->search($userid, 1, 0);
if (count($users) > 0) { if (count($users) > 0) {
$user = array_shift($users); $user = array_shift($users);
@ -113,6 +115,18 @@ class DocumentController extends Controller {
\OC::$server->getUserSession()->setUser($user); \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 = ''){ private function responseError($message, $hint = ''){
@ -305,9 +319,7 @@ class DocumentController extends Controller {
'uploadMaxHumanFilesize' => \OCP\Util::humanFileSize($maxUploadFilesize), 'uploadMaxHumanFilesize' => \OCP\Util::humanFileSize($maxUploadFilesize),
'allowShareWithLink' => $this->settings->getAppValue('core', 'shareapi_allow_links', 'yes'), 'allowShareWithLink' => $this->settings->getAppValue('core', 'shareapi_allow_links', 'yes'),
'wopi_url' => $webSocket, 'wopi_url' => $webSocket,
'edit_groups' => $this->appConfig->getAppValue('edit_groups'), 'doc_format' => $this->appConfig->getAppValue('doc_format')
'doc_format' => $this->appConfig->getAppValue('doc_format'),
'usergroups' => $usergroups
]); ]);
$policy = new ContentSecurityPolicy(); $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 ]); \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(); $row = new Db\Wopi();
$token = $row->generateFileToken($fileId, $version); $token = $row->generateFileToken($fileId, $version, $updatable);
// Return the token. // Return the token.
return array( return array(
@ -476,13 +521,11 @@ class DocumentController extends Controller {
} }
// Login the user to see his mount locations // Login the user to see his mount locations
$this->loginUser($res['owner']); $this->loginUser($res['editor']);
$view = \OC\Files\Filesystem::getView();
$view = new \OC\Files\View('/' . $res['owner'] . '/files');
$info = $view->getFileInfo($res['path']); $info = $view->getFileInfo($res['path']);
// Close the session created for user login $this->logoutUser();
\OC::$server->getSession()->close();
if (!$info) { if (!$info) {
http_response_code(404); http_response_code(404);
@ -490,13 +533,13 @@ class DocumentController extends Controller {
} }
$editorName = \OC::$server->getUserManager()->get($res['editor'])->getDisplayName(); $editorName = \OC::$server->getUserManager()->get($res['editor'])->getDisplayName();
\OC::$server->getLogger()->debug('File info: {info}.', [ 'app' => $this->appName, 'info' => $info ]);
return array( return array(
'BaseFileName' => $info['name'], 'BaseFileName' => $info['name'],
'Size' => $info['size'], 'Size' => $info['size'],
'Version' => $version, 'Version' => $version,
'UserId' => $res['editor'], 'UserId' => $res['editor'],
'UserFriendlyName' => $editorName 'UserFriendlyName' => $editorName,
'UserCanWrite' => $res['canwrite'] ? 'true' : 'false'
); );
} }
@ -534,10 +577,6 @@ class DocumentController extends Controller {
if ($version !== '0') { if ($version !== '0') {
\OCP\JSON::checkAppEnabled('files_versions'); \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']); list($ownerid, $filename) = \OCA\Files_Versions\Storage::getUidAndFilename($res['path']);
$filename = '/files_versions/' . $filename . '.v' . $version; $filename = '/files_versions/' . $filename . '.v' . $version;
@ -546,8 +585,7 @@ class DocumentController extends Controller {
$filename = '/files' . $res['path']; $filename = '/files' . $res['path'];
} }
// Close the session created for user login $this->logoutUser();
\OC::$server->getSession()->close();
return new DownloadResponse($this->request, $ownerid, $filename); return new DownloadResponse($this->request, $ownerid, $filename);
} }
@ -569,20 +607,18 @@ class DocumentController extends Controller {
$version = $arr[1]; $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 ]); \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 = new Db\Wopi();
$row->loadBy('token', $token); $row->loadBy('token', $token);
$res = $row->getPathForToken($fileId, $version, $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. // Log-in as the user to regiser the change under her name.
$editorid = $res['editor']; $editorid = $res['editor'];
@ -603,14 +639,11 @@ class DocumentController extends Controller {
// Setup the FS which is needed to emit hooks (versioning). // Setup the FS which is needed to emit hooks (versioning).
\OC_Util::tearDownFS(); \OC_Util::tearDownFS();
\OC_Util::setupFS($userid, $root); \OC_Util::setupFS($userid);
$view->file_put_contents($res['path'], $content); $view->file_put_contents($res['path'], $content);
\OC_Util::tearDownFS(); $this->logoutUser();
// clear any session created before
\OC::$server->getSession()->close();
return array( return array(
'status' => 'success' 'status' => 'success'

View File

@ -99,16 +99,9 @@ class SessionController extends Controller{
$view = \OC\Files\Filesystem::getView(); $view = \OC\Files\Filesystem::getView();
$path = $view->getPath($fileId); $path = $view->getPath($fileId);
if ($view->isUpdatable($path)) { $file = new File($fileId);
$file = new File($fileId); $response = Db\Session::start($this->uid, $file);
$response = Db\Session::start($this->uid, $file);
} else {
$info = $view->getFileInfo($path);
$response = [
'permissions' => $info['permissions'],
'id' => $fileId
];
}
$response = array_merge( $response = array_merge(
$response, $response,
[ 'status'=>'success' ] [ 'status'=>'success' ]

View File

@ -17,29 +17,6 @@ $.widget('oc.documentGrid', {
jQuery.when(this._load(fileId)) jQuery.when(this._load(fileId))
.then(function(){ .then(function(){
that._render(); 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; documentsMain.renderComplete = true;
}); });
}, },
@ -658,6 +635,7 @@ var documentsMain = {
documentsMain.esId = response.es_id; documentsMain.esId = response.es_id;
documentsMain.memberId = response.member_id; documentsMain.memberId = response.member_id;
documentsMain.canEdit = response.permissions & OC.PERMISSION_UPDATE;
documentsMain.loadDocument(); documentsMain.loadDocument();

View File

@ -29,8 +29,8 @@ class Wopi extends \OCA\Richdocuments\Db{
protected $tableName = '`*PREFIX*richdocuments_wopi`'; protected $tableName = '`*PREFIX*richdocuments_wopi`';
protected $insertStatement = 'INSERT INTO `*PREFIX*richdocuments_wopi` (`owner_uid`, `editor_uid`, `fileid`, `version`, `path`, `token`, `expiry`) protected $insertStatement = 'INSERT INTO `*PREFIX*richdocuments_wopi` (`owner_uid`, `editor_uid`, `fileid`, `version`, `path`, `canwrite`, `token`, `expiry`)
VALUES (?, ?, ?, ?, ?, ?, ?)'; VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
protected $loadStatement = 'SELECT * FROM `*PREFIX*richdocuments_wopi` WHERE `token`= ?'; 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 * its the version number as stored by files_version app
* Returns the token. * Returns the token.
*/ */
public function generateFileToken($fileId, $version){ public function generateFileToken($fileId, $version, $updatable){
// Get the FS view of the current user. // Get the FS view of the current user.
$view = \OC\Files\Filesystem::getView(); $view = \OC\Files\Filesystem::getView();
@ -49,7 +49,7 @@ class Wopi extends \OCA\Richdocuments\Db{
// Get the virtual path (if the file is shared). // Get the virtual path (if the file is shared).
$path = $view->getPath($fileId); $path = $view->getPath($fileId);
if (!$view->is_file($path) || !$view->isUpdatable($path)) { if (!$view->is_file($path)) {
throw new \Exception('Invalid fileId.'); throw new \Exception('Invalid fileId.');
} }
@ -79,6 +79,7 @@ class Wopi extends \OCA\Richdocuments\Db{
$fileId, $fileId,
$version, $version,
$path, $path,
$updatable,
$token, $token,
time() + self::TOKEN_LIFETIME_SECONDS time() + self::TOKEN_LIFETIME_SECONDS
]); ]);
@ -120,6 +121,11 @@ class Wopi extends \OCA\Richdocuments\Db{
return false; 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']
);
} }
} }

View File

@ -52,5 +52,3 @@ script('files', 'jquery.fileupload');
<input type="hidden" id="previews_enabled" value="<?php p($_['enable_previews']) ?>" /> <input type="hidden" id="previews_enabled" value="<?php p($_['enable_previews']) ?>" />
<?php endif; ?> <?php endif; ?>
<input type="hidden" name="allowShareWithLink" id="allowShareWithLink" value="<?php p($_['allowShareWithLink']) ?>" /> <input type="hidden" name="allowShareWithLink" id="allowShareWithLink" value="<?php p($_['allowShareWithLink']) ?>" />
<input type="hidden" name="edit_groups" id="edit_groups" value="<?php p($_['edit_groups']) ?>" />
<input type="hidden" name="usergroups" id="usergroups" value="<?php p($_['usergroups']) ?>" />