Skip to content

Commit

Permalink
Introduce AMD style MOVE operation
Browse files Browse the repository at this point in the history
  • Loading branch information
DeepDiver1975 committed Jun 25, 2018
1 parent e9084cf commit 805a99b
Show file tree
Hide file tree
Showing 11 changed files with 592 additions and 1 deletion.
34 changes: 34 additions & 0 deletions apps/dav/appinfo/Migrations/Version20180622095921.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
namespace OCA\dav\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Types\Type;
use OCP\Migration\ISchemaMigration;

class Version20180622095921 implements ISchemaMigration {
public function changeSchema(Schema $schema, array $options) {
$prefix = $options['tablePrefix'];
if ($schema->hasTable("${prefix}dav_job_status")) {
return;
}
$table = $schema->createTable("${prefix}dav_job_status");
$table->addColumn('id', Type::BIGINT, [
'autoincrement' => true,
'notnull' => true,
'length' => 20,
]);
$table->addColumn('uuid', Type::GUID, [
'notnull' => true,
]);
$table->addColumn('user_id', Type::STRING, [
'notnull' => true,
'length' => 64,
]);
$table->addColumn('status_info', Type::STRING, [
'notnull' => true,
'length' => 4000,
]);
$table->setPrimaryKey(['id']);
$table->addUniqueIndex(['uuid']);
}
}
11 changes: 11 additions & 0 deletions apps/dav/lib/Connector/Sabre/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
namespace OCA\DAV\Connector\Sabre;

use OCA\DAV\DAV\CopyPlugin;
use OCA\DAV\DAV\LazyOpsPlugin;
use OCA\DAV\JobStatus\Entity\JobStatusMapper;

/**
* Class \OCA\DAV\Connector\Sabre\Server
Expand All @@ -37,12 +39,21 @@ class Server extends \Sabre\DAV\Server {

/**
* @see \Sabre\DAV\Server
* @param null $treeOrNode
* @throws \OCP\AppFramework\QueryException
* @throws \Sabre\DAV\Exception
*/
public function __construct($treeOrNode = null) {
parent::__construct($treeOrNode);
self::$exposeVersion = false;
$this->enablePropfindDepthInfinity = true;
$this->addPlugin(new CopyPlugin());
$this->addPlugin(new LazyOpsPlugin(
\OC::$server->getUserSession(),
\OC::$server->getURLGenerator(),
\OC::$server->getShutdownHandler(),
\OC::$server->query(JobStatusMapper::class),
\OC::$server->getLogger()
));
}
}
170 changes: 170 additions & 0 deletions apps/dav/lib/DAV/LazyOpsPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\DAV\DAV;

use OCA\DAV\JobStatus\Entity\JobStatus;
use OCA\DAV\JobStatus\Entity\JobStatusMapper;
use OCP\ILogger;
use OCP\IURLGenerator;
use OCP\IUserSession;
use OCP\Shutdown\IShutdownManager;
use Sabre\DAV\Exception;
use Sabre\DAV\Server;
use Sabre\DAV\ServerPlugin;
use Sabre\DAV\UUIDUtil;
use Sabre\HTTP\RequestInterface;
use Sabre\HTTP\Response;
use Sabre\HTTP\ResponseInterface;

/**
* Class LazyOpsPlugin
*
* @package OCA\DAV\DAV
*/
class LazyOpsPlugin extends ServerPlugin {

/** @var Server */
private $server;
/** @var string */
private $jobId;
/** @var JobStatus */
private $entity;
/** @var IUserSession */
private $userSession;
/** @var IURLGenerator */
private $urlGenerator;
/** @var IShutdownManager */
private $shutdownManager;
/** @var ILogger */
private $logger;
/** @var JobStatusMapper */
private $mapper;

public function __construct(IUserSession $userSession,
IURLGenerator $urlGenerator,
IShutdownManager $shutdownManager,
JobStatusMapper $jobStatusMapper,
ILogger $logger) {
$this->userSession = $userSession;
$this->urlGenerator = $urlGenerator;
$this->shutdownManager = $shutdownManager;
$this->logger = $logger;
$this->mapper = $jobStatusMapper;
}

/**
* @param Server $server
*/
public function initialize(Server $server) {
$this->server = $server;
$server->on('method:MOVE', [$this, 'httpMove'], 90);
}

/**
* @param RequestInterface $request
* @param ResponseInterface $response
* @return bool
* @throws Exception\NotAuthenticated
*/
public function httpMove(RequestInterface $request, ResponseInterface $response) {
if (!$request->getHeader('OC-LazyOps')) {
return true;
}

$this->jobId = UUIDUtil::getUUID();
$this->setJobStatus([
'status' => 'init'
]);
$userId = $this->getUSerId();
$location = $this->urlGenerator
->linkTo('', 'remote.php') . "/dav/{$userId}/job-status/{$this->jobId}";

$response->setStatus(202);
$response->addHeader('Connection', 'close');
$response->addHeader('OC-JobStatus-Location', $location);

$this->shutdownManager->register(function () use ($request, $response) {
return $this->afterResponse($request, $response);
}, IShutdownManager::HIGH);

return false;
}

public function afterResponse(RequestInterface $request, ResponseInterface $response) {
if (!$request->getHeader('OC-LazyOps')) {
return true;
}

\flush();
$request->removeHeader('OC-LazyOps');
$responseDummy = new Response();
try {
$this->setJobStatus([
'status' => 'started'
]);
$this->server->emit('method:MOVE', [$request, $responseDummy]);

$this->setJobStatus([
'status' => 'finished',
'fileId' => $response->getHeader('OC-FileId'),
'ETag' => $response->getHeader('ETag')
]);
} catch (\Exception $ex) {
$this->logger->logException($ex);

$this->setJobStatus([
'status' => 'error',
'errorCode' => 500,
'errorMessage' => $ex->getMessage()
]);
}
return false;
}

private function setJobStatus(array $status) {

if ($this->entity === null) {
$userId = $this->getUSerId();

$this->entity = new JobStatus();
$this->entity->setStatusInfo(\json_encode($status));
$this->entity->setUserId($userId);
$this->entity->setUuid($this->jobId);
$this->mapper->insert($this->entity);
} else {
$this->entity->setStatusInfo(\json_encode($status));
$this->mapper->update($this->entity);
}
}

/**
* @return string
* @throws Exception\NotAuthenticated
*/
private function getUSerId() {
$user = $this->userSession->getUser();
if ($user === null) {
throw new Exception\NotAuthenticated();
}
return $user->getUID();
}
}
42 changes: 42 additions & 0 deletions apps/dav/lib/JobStatus/Entity/JobStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\DAV\JobStatus\Entity;

use OCP\AppFramework\Db\Entity;

/**
* Class JobStatus
*
* @method string getUuid()
* @method void setUuid(string $uuid)
* @method string getUserId()
* @method void setUserId(string $userId)
* @method string getStatusInfo()
* @method void setStatusInfo(string $statusInfo)
*
* @package OCA\DAV\JobStatus\Entity
*/
class JobStatus extends Entity {
protected $uuid;
protected $userId;
protected $statusInfo;
}
47 changes: 47 additions & 0 deletions apps/dav/lib/JobStatus/Entity/JobStatusMapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php
/**
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2018, ownCloud GmbH
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/

namespace OCA\DAV\JobStatus\Entity;

use OCP\AppFramework\Db\Mapper;
use OCP\IDBConnection;

class JobStatusMapper extends Mapper {
public function __construct(IDBConnection $db) {
parent::__construct($db, 'dav_job_status');
}

/**
* @param string $userId
* @param string $jobId
* @return JobStatus
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
*/
public function findByUserIdAndJobId($userId, $jobId) {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from($this->getTableName())
->where($query->expr()->eq('uuid', $query->createNamedParameter($jobId)))
->andWhere($query->expr()->eq('user_id', $query->createNamedParameter($userId)));
return $this->mapRowToEntity($this->findOneQuery($query->getSQL(), $query->getParameters()));
}
}
Loading

0 comments on commit 805a99b

Please sign in to comment.