Use different entry points for users and guests
This commit is contained in:
parent
a6be42cb26
commit
b8917435f3
@ -19,10 +19,12 @@ $application->registerRoutes($this, [
|
||||
['name' => 'user#disconnectUser', 'url' => 'ajax/user/disconnect', 'verb' => 'POST'],
|
||||
['name' => 'user#disconnectGuest', 'url' => 'ajax/user/disconnectGuest', 'verb' => 'POST'],
|
||||
//session
|
||||
['name' => 'session#joinAsUser', 'url' => 'ajax/session/joinasuser/{fileId}', 'verb' => 'POST'],
|
||||
['name' => 'session#joinAsGuest', 'url' => 'ajax/session/joinasguest/{token}', 'verb' => 'POST'],
|
||||
['name' => 'session#save', 'url' => 'ajax/session/save', 'verb' => 'POST'],
|
||||
['name' => 'session#poll', 'url' => 'ajax/otpoll.php', 'verb' => 'POST'],
|
||||
['name' => 'session#join', 'url' => 'session/user/join/{fileId}', 'verb' => 'POST'],
|
||||
['name' => 'session#poll', 'url' => 'session/user/poll', 'verb' => 'POST'],
|
||||
['name' => 'session#save', 'url' => 'session/user/save', 'verb' => 'POST'],
|
||||
['name' => 'session#joinAsGuest', 'url' => 'session/guest/join/{token}', 'verb' => 'POST'],
|
||||
['name' => 'session#pollAsGuest', 'url' => 'session/guest/poll/{token}', 'verb' => 'POST'],
|
||||
['name' => 'session#saveAsGuest', 'url' => 'session/guest/save/{token}', 'verb' => 'POST'],
|
||||
//documents
|
||||
['name' => 'document#index', 'url' => 'index', 'verb' => 'GET'],
|
||||
['name' => 'document#create', 'url' => 'ajax/documents/create', 'verb' => 'POST'],
|
||||
|
@ -16,7 +16,6 @@ use \OCP\IRequest;
|
||||
use \OCP\AppFramework\Http;
|
||||
use \OCP\AppFramework\Http\JSONResponse;
|
||||
|
||||
|
||||
use \OCA\Documents\Db;
|
||||
use \OCA\Documents\File;
|
||||
use \OCA\Documents\Helper;
|
||||
@ -40,6 +39,7 @@ class SessionController extends Controller{
|
||||
|
||||
protected $uid;
|
||||
protected $logger;
|
||||
protected $shareToken;
|
||||
|
||||
public function __construct($appName, IRequest $request, $logger, $uid){
|
||||
parent::__construct($appName, $request);
|
||||
@ -62,45 +62,11 @@ class SessionController extends Controller{
|
||||
|
||||
$response = array_merge(
|
||||
Db\Session::start($uid, $file),
|
||||
array('status'=>'success')
|
||||
[ 'status'=>'success' ]
|
||||
);
|
||||
} catch (\Exception $e){
|
||||
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), array('app' => $this->appName));
|
||||
$response = array (
|
||||
'status'=>'error'
|
||||
);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function joinAsUser($fileId){
|
||||
try {
|
||||
$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 = array(
|
||||
'permissions' => $info['permissions'],
|
||||
'id' => $fileId
|
||||
);
|
||||
}
|
||||
$response = array_merge(
|
||||
$response,
|
||||
array('status'=>'success')
|
||||
);
|
||||
} catch (\Exception $e){
|
||||
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), array('app' => $this->appName));
|
||||
$response = array (
|
||||
'status'=>'error'
|
||||
);
|
||||
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), ['app' => $this->appName]);
|
||||
$response = [ 'status'=>'error' ];
|
||||
}
|
||||
|
||||
return $response;
|
||||
@ -110,39 +76,71 @@ class SessionController extends Controller{
|
||||
* @NoAdminRequired
|
||||
* @PublicPage
|
||||
*/
|
||||
public function pollAsGuest($command, $args){
|
||||
$this->shareToken = $this->request->getParam('token');
|
||||
return $this->poll($command, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the document content to its origin
|
||||
* @NoAdminRequired
|
||||
* @PublicPage
|
||||
*/
|
||||
public function saveAsGuest(){
|
||||
$this->shareToken = $this->request->getParam('token');
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function join($fileId){
|
||||
try {
|
||||
$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
|
||||
];
|
||||
}
|
||||
$response = array_merge(
|
||||
$response,
|
||||
[ 'status'=>'success' ]
|
||||
);
|
||||
} catch (\Exception $e){
|
||||
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), [ 'app' => $this->appName ]);
|
||||
$response = [ 'status'=>'error' ];
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function poll($command, $args){
|
||||
$response = new JSONResponse();
|
||||
|
||||
try{
|
||||
$esId = isset($args['es_id']) ? $args['es_id'] : null;
|
||||
|
||||
$session = new Db\Session();
|
||||
$session->load($esId);
|
||||
$session = $this->loadSession($esId);
|
||||
|
||||
$memberId = isset($args['member_id']) ? $args['member_id'] : null;
|
||||
$member = new Db\Member();
|
||||
$member->load($memberId);
|
||||
$member = $this->loadMember($memberId);
|
||||
|
||||
if (!$member->getIsGuest()){
|
||||
\OCP\JSON::checkLoggedIn();
|
||||
}
|
||||
|
||||
try {
|
||||
new File($session->getFileId());
|
||||
} catch (\Exception $e){
|
||||
$this->logger->warning('Error. Session no longer exists. ' . $e->getMessage(), array('app' => $this->appName));
|
||||
$ex = new BadRequestException();
|
||||
$ex->setBody(
|
||||
implode(',', $this->request->getParams())
|
||||
);
|
||||
throw $ex;
|
||||
}
|
||||
$this->validateSession($session);
|
||||
|
||||
switch ($command){
|
||||
case 'sync_ops':
|
||||
$seqHead = (string) isset($args['seq_head']) ? $args['seq_head'] : null;
|
||||
if (!is_null($seqHead)){
|
||||
$ops = isset($args['client_ops']) ? $args['client_ops'] : array();
|
||||
$ops = isset($args['client_ops']) ? $args['client_ops'] : [];
|
||||
|
||||
$op = new Db\Op();
|
||||
$currentHead = $op->getHeadSeq($esId);
|
||||
@ -177,33 +175,24 @@ class SessionController extends Controller{
|
||||
} catch (BadRequestException $e){
|
||||
$response->setStatus(Http::STATUS_BAD_REQUEST);
|
||||
$response->setData(
|
||||
array('err' => 'bad request:[' . $e->getBody() . ']')
|
||||
[ 'err' => 'bad request:[' . $e->getBody() . ']' ]
|
||||
);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @PublicPage
|
||||
* Store the document content to its origin
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function save(){
|
||||
$response = new JSONResponse();
|
||||
try {
|
||||
$esId = $this->request->server['HTTP_WEBODF_SESSION_ID'];
|
||||
if (!$esId){
|
||||
throw new \Exception('Session id can not be empty');
|
||||
}
|
||||
$session = $this->loadSession($esId);
|
||||
|
||||
$memberId = $this->request->server['HTTP_WEBODF_MEMBER_ID'];
|
||||
$currentMember = new Db\Member();
|
||||
$currentMember->load($memberId);
|
||||
|
||||
//check if member belongs to the session
|
||||
if ($esId != $currentMember->getEsId()){
|
||||
throw new \Exception($memberId . ' does not belong to session ' . $esId);
|
||||
}
|
||||
$currentMember = $this->loadMember($memberId, $esId);
|
||||
|
||||
// Extra info for future usage
|
||||
// $sessionRevision = $this->request->server['HTTP_WEBODF_SESSION_REVISION'];
|
||||
@ -215,13 +204,6 @@ class SessionController extends Controller{
|
||||
}
|
||||
$content = stream_get_contents($stream);
|
||||
|
||||
$session = new Db\Session();
|
||||
$session->load($esId);
|
||||
|
||||
if (!$session->getEsId()){
|
||||
throw new \Exception('Session does not exist');
|
||||
}
|
||||
|
||||
try {
|
||||
if ($currentMember->getIsGuest()){
|
||||
$file = File::getByShareToken($currentMember->getToken());
|
||||
@ -229,7 +211,8 @@ class SessionController extends Controller{
|
||||
$file = new File($session->getFileId());
|
||||
}
|
||||
|
||||
list($view, $path) = $file->getOwnerViewAndPath(true);
|
||||
$view = $file->getOwnerView(true);
|
||||
$path = $file->getPath(true);
|
||||
} catch (\Exception $e){
|
||||
//File was deleted or unshared. We need to save content as new file anyway
|
||||
//Sorry, but for guests it would be lost :(
|
||||
@ -256,7 +239,7 @@ class SessionController extends Controller{
|
||||
$memberCount = count($memberIds) - 1;
|
||||
|
||||
if ($view->file_exists($path)){
|
||||
$currentHash = sha1($view->file_get_contents($path));
|
||||
$currentHash = $view->hash('sha1', $path, false);
|
||||
|
||||
if (!Helper::isVersionsEnabled() && $currentHash !== $session->getGenesisHash()){
|
||||
// Original file was modified externally. Save to a new one
|
||||
@ -274,7 +257,7 @@ class SessionController extends Controller{
|
||||
// Not a last user
|
||||
if ($memberCount>0){
|
||||
// Update genesis hash to prevent conflicts
|
||||
$this->logger->debug('Update hash', array('app' => $this->appName));
|
||||
$this->logger->debug('Update hash', [ 'app' => $this->appName ]);
|
||||
$session->updateGenesisHash($esId, sha1($data['content']));
|
||||
} else {
|
||||
// Last user. Kill session data
|
||||
@ -283,13 +266,56 @@ class SessionController extends Controller{
|
||||
|
||||
$view->touch($path);
|
||||
}
|
||||
$response = array('status'=>'success');
|
||||
$response->setData(['status'=>'success']);
|
||||
} catch (\Exception $e){
|
||||
$this->logger->warning('Saving failed. Reason:' . $e->getMessage(), array('app' => $this->appName));
|
||||
\OC_Response::setStatus(500);
|
||||
$response = array();
|
||||
$response->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||
$response->setData([]);
|
||||
$this->logger->warning('Saving failed. Reason:' . $e->getMessage(), [ 'app' => $this->appName ]);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function validateSession($session){
|
||||
try {
|
||||
if (is_null($this->shareToken)) {
|
||||
new File($session->getFileId());
|
||||
} else {
|
||||
File::getByShareToken($this->shareToken);
|
||||
}
|
||||
} catch (\Exception $e){
|
||||
$this->logger->warning('Error. Session no longer exists. ' . $e->getMessage(), [ 'app' => $this->appName ]);
|
||||
$ex = new BadRequestException();
|
||||
$ex->setBody(
|
||||
implode(',', $this->request->getParams())
|
||||
);
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
protected function loadSession($esId){
|
||||
if (!$esId){
|
||||
throw new \Exception('Session id can not be empty');
|
||||
}
|
||||
|
||||
$session = new Db\Session();
|
||||
$session->load($esId);
|
||||
if (!$session->getEsId()){
|
||||
throw new \Exception('Session does not exist');
|
||||
}
|
||||
return $session;
|
||||
}
|
||||
|
||||
protected function loadMember($memberId, $expectedEsId = null){
|
||||
if (!$memberId){
|
||||
throw new \Exception('Member id can not be empty');
|
||||
}
|
||||
$member = new Db\Member();
|
||||
$member->load($memberId);
|
||||
//check if member belongs to the session
|
||||
if (!is_null($expectedEsId) && $expectedEsId !== $member->getEsId()){
|
||||
throw new \Exception($memberId . ' does not belong to session ' . $expectedEsId);
|
||||
}
|
||||
return $member;
|
||||
}
|
||||
}
|
||||
|
@ -40,8 +40,6 @@ define("owncloud/ServerFactory", [
|
||||
this.createServer = function (args) {
|
||||
var server;
|
||||
args = args || {};
|
||||
args.url = OC.filePath('documents', 'ajax', 'otpoll.php');
|
||||
args.sessionStateToFileUrl = OC.generateUrl('apps/documents/ajax/session/save');
|
||||
|
||||
server = new PullBoxServer(args);
|
||||
server.getGenesisUrl = function(sid) {
|
||||
|
@ -328,6 +328,13 @@ var documentsMain = {
|
||||
return;
|
||||
}
|
||||
|
||||
var pollUrl = documentsMain.isGuest
|
||||
? OC.generateUrl('apps/documents/session/guest/poll/{token}', {'token' : $("[name='document']").val()})
|
||||
: OC.generateUrl('apps/documents/session/user/poll'),
|
||||
saveUrl = documentsMain.isGuest
|
||||
? OC.generateUrl('apps/documents/session/guest/save/{token}', {'token' : $("[name='document']").val()})
|
||||
: OC.generateUrl('apps/documents/session/user/save')
|
||||
;
|
||||
documentsMain.canShare = !documentsMain.isGuest
|
||||
&& typeof OC.Share !== 'undefined' && response.permissions & OC.PERMISSION_SHARE;
|
||||
require({ }, ["owncloud/ServerFactory", "webodf/editor/Editor"], function (ServerFactory, Editor) {
|
||||
@ -347,8 +354,10 @@ var documentsMain = {
|
||||
documentsMain.memberId = response.member_id;
|
||||
|
||||
// TODO: set webodf translation system, by passing a proper function translate(!string):!string in "runtime.setTranslator(translate);"
|
||||
|
||||
documentsMain.webodfServerInstance = serverFactory.createServer();
|
||||
documentsMain.webodfServerInstance = serverFactory.createServer({
|
||||
url : pollUrl,
|
||||
sessionStateToFileUrl : saveUrl
|
||||
});
|
||||
documentsMain.webodfServerInstance.setToken(oc_requesttoken);
|
||||
documentsMain.webodfEditorInstance = new Editor(
|
||||
{
|
||||
@ -383,9 +392,9 @@ var documentsMain = {
|
||||
console.log('joining session '+fileId);
|
||||
var url;
|
||||
if (documentsMain.isGuest){
|
||||
url = OC.generateUrl('apps/documents/ajax/session/joinasguest/{token}', {token: fileId});
|
||||
url = OC.generateUrl('apps/documents/session/guest/join/{token}', {token: fileId});
|
||||
} else {
|
||||
url = OC.generateUrl('apps/documents/ajax/session/joinasuser/{file_id}', {file_id: fileId});
|
||||
url = OC.generateUrl('apps/documents/session/user/join/{file_id}', {file_id: fileId});
|
||||
}
|
||||
$.post(
|
||||
url,
|
||||
|
@ -50,11 +50,6 @@ class Session extends \OCA\Documents\Db {
|
||||
// Create a directory to store genesis
|
||||
$genesis = new \OCA\Documents\Genesis($file);
|
||||
|
||||
list($ownerView, $path) = $file->getOwnerViewAndPath();
|
||||
$mimetype = $ownerView->getMimeType($path);
|
||||
if (!Filter::isSupportedMimetype($mimetype)){
|
||||
throw new \Exception( $path . ' is ' . $mimetype . ' and is not supported by Documents app');
|
||||
}
|
||||
$oldSession = new Session();
|
||||
$oldSession->loadBy('file_id', $file->getFileId());
|
||||
|
||||
@ -78,14 +73,14 @@ class Session extends \OCA\Documents\Db {
|
||||
;
|
||||
|
||||
$memberColor = \OCA\Documents\Helper::getMemberColor($uid);
|
||||
$member = new \OCA\Documents\Db\Member(array(
|
||||
$member = new \OCA\Documents\Db\Member([
|
||||
$sessionData['es_id'],
|
||||
$uid,
|
||||
$memberColor,
|
||||
time(),
|
||||
intval($file->isPublicShare()),
|
||||
$file->getToken()
|
||||
));
|
||||
]);
|
||||
|
||||
if (!$member->insert()){
|
||||
throw new \Exception('Failed to add member into database');
|
||||
@ -114,9 +109,8 @@ class Session extends \OCA\Documents\Db {
|
||||
$imageUrl
|
||||
);
|
||||
|
||||
$sessionData['title'] = basename($path);
|
||||
$fileInfo = $ownerView->getFileInfo($path);
|
||||
$sessionData['permissions'] = $fileInfo->getPermissions();
|
||||
$sessionData['title'] = basename($file->getPath());
|
||||
$sessionData['permissions'] = $file->getPermissions();
|
||||
|
||||
return $sessionData;
|
||||
}
|
||||
|
60
lib/file.php
60
lib/file.php
@ -28,14 +28,14 @@ class File {
|
||||
protected $fileId;
|
||||
protected $owner;
|
||||
protected $sharing;
|
||||
protected $token ='';
|
||||
protected $token;
|
||||
protected $passwordProtected = false;
|
||||
protected $ownerView;
|
||||
protected $ownerViewFiles;
|
||||
protected $path;
|
||||
protected $pathFiles;
|
||||
|
||||
public function __construct($fileId, $shareOps = null, $token = null){
|
||||
public function __construct($fileId, $shareOps = null, $token = ''){
|
||||
if (!$fileId){
|
||||
throw new \Exception('No valid file has been passed');
|
||||
}
|
||||
@ -43,6 +43,22 @@ class File {
|
||||
$this->fileId = $fileId;
|
||||
$this->sharing = $shareOps;
|
||||
$this->token = $token;
|
||||
|
||||
if ($this->isPublicShare()) {
|
||||
if (isset($this->sharing['uid_owner'])){
|
||||
$this->owner = $this->sharing['uid_owner'];
|
||||
if (!\OC::$server->getUserManager()->userExists($this->sharing['uid_owner'])) {
|
||||
throw new \Exception('Share owner' . $this->sharing['uid_owner'] . ' does not exist ');
|
||||
}
|
||||
|
||||
\OC_Util::tearDownFS();
|
||||
\OC_Util::setupFS($this->sharing['uid_owner']);
|
||||
} else {
|
||||
throw new \Exception($this->fileId . ' is a broken share');
|
||||
}
|
||||
} else {
|
||||
$this->owner = \OC::$server->getUserSession()->getUser()->getUID();
|
||||
}
|
||||
$this->initViews();
|
||||
}
|
||||
|
||||
@ -132,15 +148,6 @@ class File {
|
||||
$this->passwordProtected = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string owner of the current file item
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getOwnerViewAndPath($useDefaultRoot = false){
|
||||
return $useDefaultRoot ? [$this->ownerViewFiles, $this->pathFiles] : [$this->ownerView, $this->path];
|
||||
}
|
||||
|
||||
public function getOwner(){
|
||||
return $this->owner;
|
||||
}
|
||||
@ -153,23 +160,12 @@ class File {
|
||||
return $relativeToFiles ? $this->pathFiles : $this->path;
|
||||
}
|
||||
|
||||
public function getPermissions(){
|
||||
$fileInfo = $this->ownerView->getFileInfo($this->path);
|
||||
return $fileInfo->getPermissions();
|
||||
}
|
||||
|
||||
protected function initViews(){
|
||||
if ($this->isPublicShare()) {
|
||||
if (isset($this->sharing['uid_owner'])){
|
||||
$this->owner = $this->sharing['uid_owner'];
|
||||
if (!\OC::$server->getUserManager()->userExists($this->sharing['uid_owner'])) {
|
||||
throw new \Exception('Share owner' . $this->sharing['uid_owner'] . ' does not exist ');
|
||||
}
|
||||
|
||||
\OC_Util::tearDownFS();
|
||||
\OC_Util::setupFS($this->sharing['uid_owner']);
|
||||
} else {
|
||||
throw new \Exception($this->fileId . ' is a broken share');
|
||||
}
|
||||
} else {
|
||||
$this->owner = \OC::$server->getUserSession()->getUser()->getUID();
|
||||
}
|
||||
|
||||
$this->ownerView = new View('/' . $this->owner);
|
||||
$this->ownerViewFiles = new View('/' . $this->owner . '/files');
|
||||
$this->path = $this->ownerView->getPath($this->fileId);
|
||||
@ -186,6 +182,16 @@ class File {
|
||||
if (!$this->ownerViewFiles->file_exists($this->pathFiles)) {
|
||||
throw new \Exception($this->pathFiles . ' doesn\'t exist');
|
||||
}
|
||||
|
||||
if (!$this->ownerView->is_file($this->path)){
|
||||
throw new \Exception('Object ' . $this->path . ' is not a file.');
|
||||
}
|
||||
//TODO check if it is a valid odt
|
||||
|
||||
$mimetype = $this->ownerView->getMimeType($this->path);
|
||||
if (!Filter::isSupportedMimetype($mimetype)){
|
||||
throw new \Exception( $this->path . ' is ' . $mimetype . ' and is not supported by Documents app');
|
||||
}
|
||||
}
|
||||
|
||||
protected function getPassword(){
|
||||
|
@ -40,7 +40,8 @@ class Genesis {
|
||||
* @param File $file
|
||||
* */
|
||||
public function __construct(File $file){
|
||||
list($view, $path) = $file->getOwnerViewAndPath();
|
||||
$view = $file->getOwnerView();
|
||||
$path = $file->getPath();
|
||||
$owner = $file->getOwner();
|
||||
|
||||
$this->view = new View('/' . $owner);
|
||||
@ -48,8 +49,9 @@ class Genesis {
|
||||
if (!$this->view->file_exists(self::DOCUMENTS_DIRNAME)){
|
||||
$this->view->mkdir(self::DOCUMENTS_DIRNAME );
|
||||
}
|
||||
$this->validate($view, $path);
|
||||
|
||||
$this->hash = $this->getDocumentHash($view, $path);
|
||||
$this->hash = $view->hash('sha1', $path, false);
|
||||
$this->path = self::DOCUMENTS_DIRNAME . '/' . $this->hash . '.odt';
|
||||
if (!$this->view->file_exists($this->path)){
|
||||
//copy new genesis to /user/documents/{hash}.odt
|
||||
@ -76,12 +78,6 @@ class Genesis {
|
||||
return $this->hash;
|
||||
}
|
||||
|
||||
protected function getDocumentHash($view, $path){
|
||||
$this->validate($view, $path);
|
||||
$hash = sha1($view->file_get_contents($path));
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if genesis is valid
|
||||
* @param \OC\Files\View $view
|
||||
|
Loading…
x
Reference in New Issue
Block a user