diff --git a/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php b/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php index 471aec99f..ff22e6046 100644 --- a/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php +++ b/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php @@ -25,6 +25,17 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Security\Core\Security; +/** + * Provide endpoint for editing a document on the desktop using dav. + * + * This controller implements the minimal required methods to edit a document on a desktop software (i.e. LibreOffice) + * and save the document online. + * + * To avoid to ask for a password, the endpoints are protected using a JWT access token, which is inside the + * URL. This avoid the DAV Client (LibreOffice) to keep an access token in query parameter or in some header (which + * they are not able to understand). The JWT Guard is adapted with a dedicated token extractor which is going to read + * the segments (separation of "/"): the first segment must be the string "dav", and the second one must be the JWT. + */ final readonly class WebdavController { private PropfindRequestAnalyzer $requestAnalyzer; @@ -33,23 +44,10 @@ final readonly class WebdavController private \Twig\Environment $engine, private StoredObjectManagerInterface $storedObjectManager, private Security $security, - private ?JWTDavTokenProviderInterface $davTokenProvider = null, ) { $this->requestAnalyzer = new PropfindRequestAnalyzer(); } - /** - * @Route("/chdoc/open/{uuid}") - */ - public function open(StoredObject $storedObject): Response - { - $accessToken = $this->davTokenProvider?->createToken($storedObject, StoredObjectRoleEnum::EDIT); - - return new DavResponse($this->engine->render('@ChillDocStore/Webdav/open_in_browser.html.twig', [ - 'stored_object' => $storedObject, 'access_token' => $accessToken, - ])); - } - /** * @Route("/dav/{access_token}/get/{uuid}/", methods={"GET", "HEAD"}, name="chill_docstore_dav_directory_get") */ diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectRoleEnum.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectRoleEnum.php index 6a5a22da0..af2813240 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectRoleEnum.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectRoleEnum.php @@ -11,6 +11,9 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Security\Authorization; +/** + * Role to edit or see the stored object content. + */ enum StoredObjectRoleEnum: string { case SEE = 'SEE'; diff --git a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter.php b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter.php index 55c9b3ca1..570a2be13 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Authorization/StoredObjectVoter.php @@ -16,6 +16,11 @@ use Chill\DocStoreBundle\Security\Guard\DavTokenAuthenticationEventSubscriber; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\Voter\Voter; +/** + * Voter for the content of a stored object. + * + * This is in use to allow or disallow the edition of the stored object's content. + */ class StoredObjectVoter extends Voter { protected function supports($attribute, $subject): bool diff --git a/src/Bundle/ChillDocStoreBundle/Security/Guard/DavOnUrlTokenExtractor.php b/src/Bundle/ChillDocStoreBundle/Security/Guard/DavOnUrlTokenExtractor.php index eb030f799..0b2cc6a0a 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Guard/DavOnUrlTokenExtractor.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Guard/DavOnUrlTokenExtractor.php @@ -15,6 +15,14 @@ use Lexik\Bundle\JWTAuthenticationBundle\TokenExtractor\TokenExtractorInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; +/** + * Extract the JWT Token from the segment of the dav endpoints. + * + * A segment is a separation inside the string, using the character "/". + * + * For recognizing the JWT, the first segment must be "dav", and the second one must be + * the JWT endpoint. + */ final readonly class DavOnUrlTokenExtractor implements TokenExtractorInterface { public function __construct( diff --git a/src/Bundle/ChillDocStoreBundle/Security/Guard/DavTokenAuthenticationEventSubscriber.php b/src/Bundle/ChillDocStoreBundle/Security/Guard/DavTokenAuthenticationEventSubscriber.php index 3c1b3e2a9..c3f527e71 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Guard/DavTokenAuthenticationEventSubscriber.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Guard/DavTokenAuthenticationEventSubscriber.php @@ -16,6 +16,9 @@ use Lexik\Bundle\JWTAuthenticationBundle\Event\JWTAuthenticatedEvent; use Lexik\Bundle\JWTAuthenticationBundle\Events; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +/** + * Store some data from the JWT's payload inside the token's attributes. + */ class DavTokenAuthenticationEventSubscriber implements EventSubscriberInterface { final public const STORED_OBJECT = 'stored_object'; diff --git a/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTOnDavUrlAuthenticator.php b/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTOnDavUrlAuthenticator.php index b4ae04afc..ceb44949a 100644 --- a/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTOnDavUrlAuthenticator.php +++ b/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTOnDavUrlAuthenticator.php @@ -18,6 +18,9 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInt use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Symfony\Contracts\Translation\TranslatorInterface; +/** + * Alter the base JWTTokenAuthenticator to add the special extractor for dav url endpoints. + */ class JWTOnDavUrlAuthenticator extends JWTTokenAuthenticator { public function __construct(