some fixes with wopi

This commit is contained in:
Julien Fastré 2022-06-27 23:51:07 +02:00
parent 03bc94178f
commit 5432ce2b0f
4 changed files with 99 additions and 11 deletions

View File

@ -17,11 +17,12 @@ use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Exception\StoredObjectManagerException;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use RuntimeException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Throwable;
@ -150,7 +151,8 @@ final class StoredObjectManager implements StoredObjectManagerInterface
$date = DateTimeImmutable::createFromFormat(
DateTimeImmutable::RFC7231,
$lastModifiedString
$lastModifiedString,
new DateTimeZone('GMT')
);
if (false === $date) {

View File

@ -45,8 +45,7 @@ return static function (ContainerConfigurator $container) {
$services
->set(ChillDocumentLockManager::class)
->decorate(DocumentLockManagerInterface::class)
;
->decorate(DocumentLockManagerInterface::class);
// TODO: Move this into the async bundle (low priority)
$services

View File

@ -19,7 +19,7 @@ use RuntimeException;
class ChillDocumentLockManager implements DocumentLockManagerInterface
{
private const LOCK_DURATION = 60 * 30 * 1000;
private const LOCK_DURATION = 60 * 30;
private int $postDeleteLockDurationMs;

View File

@ -13,6 +13,7 @@ namespace Chill\WopiBundle\Service\Wopi;
use ChampsLibres\WopiLib\Contract\Service\DocumentManagerInterface;
use ChampsLibres\WopiLib\Contract\Service\WopiInterface;
use DateTimeImmutable;
use DateTimeInterface;
use loophp\psr17\Psr17Interface;
use Psr\Cache\CacheItemPoolInterface;
@ -20,6 +21,7 @@ use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use function strlen;
final class ChillWopi implements WopiInterface
{
@ -150,7 +152,97 @@ final class ChillWopi implements WopiInterface
string $xWopiEditors,
RequestInterface $request
): ResponseInterface {
return $this->wopi->putFile($fileId, $accessToken, $xWopiLock, $xWopiEditors, $request);
$document = $this->documentManager->findByDocumentId($fileId);
$version = $this->documentManager->getVersion($document);
// File is unlocked, we must reject the document, except if collabora is autosaving
if (false === $this->documentManager->hasLock($document) && 'true' !== ($request->getHeader('x-lool-wopi-isexitsave') ?? ['false'])[0]) {
if (0 !== $this->documentManager->getSize($document)) {
return $this
->psr17
->createResponse(409)
->withHeader(
WopiInterface::HEADER_ITEM_VERSION,
sprintf('v%s', $version)
);
}
}
// File is locked, we check for the lock
if ($this->documentManager->hasLock($document)) {
if ($xWopiLock !== $currentLock = $this->documentManager->getLock($document)) {
return $this
->psr17
->createResponse(409)
->withHeader(
WopiInterface::HEADER_LOCK,
$currentLock
)
->withHeader(
WopiInterface::HEADER_ITEM_VERSION,
sprintf('v%s', $version)
);
}
}
// for collabora online editor, check timestamp if present
/* delete because it seems that collabora send always the first wopi-timestamp, not the last known one
// example:
// load the doc: the last-wopi is 12:00 in FileInfo
// save the doc: x-cool-wopi-timestamp is 12:00, but we replace the ts with the time of save (12:05)
// save the doc again: x-cool-wopi-timestamp is still 12:00...
if ($request->hasHeader('x-cool-wopi-timestamp')) {
$date = DateTimeImmutable::createFromFormat(
DateTimeImmutable::ATOM,
$request->getHeader('x-cool-wopi-timestamp')[0]
);
if (false === $date) {
throw new RuntimeException('Error parsing date: ' . implode('', DateTimeImmutable::getLastErrors()));
}
if ($this->documentManager->getLastModifiedDate($document)->getTimestamp() < $date->getTimestamp()) {
return $this
->psr17
->createResponse(409)
->withHeader(
WopiInterface::HEADER_LOCK,
$currentLock
)
->withHeader(
WopiInterface::HEADER_ITEM_VERSION,
sprintf('v%s', $version)
)
->withBody(
$this->psr17->createStream(
json_encode(['COOLStatusCode' => 1010])
)
);
}
}
*/
$body = (string) $request->getBody();
$this->documentManager->write(
$document,
[
'content' => $body,
'size' => (string) strlen($body),
]
);
$version = $this->documentManager->getVersion($document);
return $this
->psr17
->createResponse()
->withHeader(
WopiInterface::HEADER_LOCK,
$xWopiLock
)
->withHeader(
WopiInterface::HEADER_ITEM_VERSION,
sprintf('v%s', $version)
);
}
public function putRelativeFile(string $fileId, string $accessToken, ?string $suggestedTarget, ?string $relativeTarget, bool $overwriteRelativeTarget, int $size, RequestInterface $request): ResponseInterface
@ -188,11 +280,6 @@ final class ChillWopi implements WopiInterface
string $xWopiLock,
RequestInterface $request
): ResponseInterface {
// this is because there are a delay between the request which PUT the file content,
// and the unlock: the PUT request last longer and this make the request fails, because
// the unlock terminate before.
sleep(5);
return $this->wopi->unlock($fileId, $accessToken, $xWopiLock, $request);
}