diff --git a/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php b/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php
index ff22e6046..b4624d463 100644
--- a/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php
+++ b/src/Bundle/ChillDocStoreBundle/Controller/WebdavController.php
@@ -15,7 +15,6 @@ use Chill\DocStoreBundle\Dav\Request\PropfindRequestAnalyzer;
use Chill\DocStoreBundle\Dav\Response\DavResponse;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
-use Chill\DocStoreBundle\Security\Guard\JWTDavTokenProviderInterface;
use Chill\DocStoreBundle\Service\StoredObjectManagerInterface;
use DateTimeInterface;
use Symfony\Component\HttpFoundation\Request;
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/module/document_action_buttons_group/index.ts b/src/Bundle/ChillDocStoreBundle/Resources/public/module/document_action_buttons_group/index.ts
index 4180808dd..77eb8c2c9 100644
--- a/src/Bundle/ChillDocStoreBundle/Resources/public/module/document_action_buttons_group/index.ts
+++ b/src/Bundle/ChillDocStoreBundle/Resources/public/module/document_action_buttons_group/index.ts
@@ -17,18 +17,22 @@ window.addEventListener('DOMContentLoaded', function (e) {
canEdit: string,
storedObject: string,
buttonSmall: string,
+ davLink: string,
+ davLinkExpiration: string,
};
const
storedObject = JSON.parse(datasets.storedObject) as StoredObject,
filename = datasets.filename,
canEdit = datasets.canEdit === '1',
- small = datasets.buttonSmall === '1'
+ small = datasets.buttonSmall === '1',
+ davLink = 'davLink' in datasets && datasets.davLink !== '' ? datasets.davLink : null,
+ davLinkExpiration = 'davLinkExpiration' in datasets ? Number.parseInt(datasets.davLinkExpiration) : null
;
- return { storedObject, filename, canEdit, small };
+ return { storedObject, filename, canEdit, small, davLink, davLinkExpiration };
},
- template: '',
+ template: '',
methods: {
onStoredObjectStatusChange: function(newStatus: StoredObjectStatusChange): void {
this.$data.storedObject.status = newStatus.status;
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentActionButtonsGroup.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentActionButtonsGroup.vue
index 88587e90f..284ae0f1f 100644
--- a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentActionButtonsGroup.vue
+++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/DocumentActionButtonsGroup.vue
@@ -7,6 +7,9 @@
+
+
+
@@ -36,6 +39,7 @@ import {
StoredObjectStatusChange,
WopiEditButtonExecutableBeforeLeaveFunction
} from "../types";
+import DesktopEditButton from "ChillDocStoreAssets/vuejs/StoredObjectButton/DesktopEditButton.vue";
interface DocumentActionButtonsGroupConfig {
storedObject: StoredObject,
@@ -57,6 +61,16 @@ interface DocumentActionButtonsGroupConfig {
* If set, will execute this function before leaving to the editor
*/
executeBeforeLeave?: WopiEditButtonExecutableBeforeLeaveFunction,
+
+ /**
+ * a link to download and edit file using webdav
+ */
+ davLink?: string,
+
+ /**
+ * the expiration date of the download, as a unix timestamp
+ */
+ davLinkExpiration?: number,
}
const emit = defineEmits<{
@@ -68,7 +82,7 @@ const props = withDefaults(defineProps(), {
canEdit: true,
canDownload: true,
canConvertPdf: true,
- returnPath: window.location.pathname + window.location.search + window.location.hash,
+ returnPath: window.location.pathname + window.location.search + window.location.hash
});
/**
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DesktopEditButton.vue b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DesktopEditButton.vue
new file mode 100644
index 000000000..ef0d0d376
--- /dev/null
+++ b/src/Bundle/ChillDocStoreBundle/Resources/public/vuejs/StoredObjectButton/DesktopEditButton.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
Veuillez enregistrer vos modifications avant le
+
{{ editionUntilFormatted }}
+
+
Ouvrir le document pour édition
+
+
Le document peut être édité uniquement en utilisant Libre Office.
+
+
En cas d'échec lors de l'enregistrement, sauver le document sur le poste de travail avant de le déposer à nouveau ici.
+
+
Vous pouvez naviguez sur d'autres pages pendant l'édition.
+
+
+
+
+
+
+ Éditer sur le bureau
+
+
+
+
diff --git a/src/Bundle/ChillDocStoreBundle/Resources/views/Button/button_group.html.twig b/src/Bundle/ChillDocStoreBundle/Resources/views/Button/button_group.html.twig
index 2babe1ad9..6248cbd20 100644
--- a/src/Bundle/ChillDocStoreBundle/Resources/views/Button/button_group.html.twig
+++ b/src/Bundle/ChillDocStoreBundle/Resources/views/Button/button_group.html.twig
@@ -3,5 +3,7 @@
data-download-buttons
data-stored-object="{{ document_json|json_encode|escape('html_attr') }}"
data-can-edit="{{ can_edit ? '1' : '0' }}"
+ data-dav-link="{{ dav_link|escape('html_attr') }}"
+ data-dav-link-expiration="{{ dav_link_expiration|escape('html_attr') }}"
{% if options['small'] is defined %}data-button-small="{{ options['small'] ? '1' : '0' }}"{% endif %}
{% if title|default(document.title)|default(null) is not null %}data-filename="{{ title|default(document.title)|escape('html_attr') }}"{% endif %}>
diff --git a/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProvider.php b/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProvider.php
index 30b25dd0b..a297ed613 100644
--- a/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProvider.php
+++ b/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProvider.php
@@ -38,4 +38,11 @@ final readonly class JWTDavTokenProvider implements JWTDavTokenProviderInterface
]);
}
+ public function getTokenExpiration(string $tokenString): \DateTimeImmutable
+ {
+ $jwt = $this->JWTTokenManager->parse($tokenString);
+
+ return \DateTimeImmutable::createFromFormat('U', (string) $jwt['exp']);
+ }
+
}
diff --git a/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProviderInterface.php b/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProviderInterface.php
index 6be91a39c..b93b658b0 100644
--- a/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProviderInterface.php
+++ b/src/Bundle/ChillDocStoreBundle/Security/Guard/JWTDavTokenProviderInterface.php
@@ -20,4 +20,6 @@ use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
interface JWTDavTokenProviderInterface
{
public function createToken(StoredObject $storedObject, StoredObjectRoleEnum $roleEnum): string;
+
+ public function getTokenExpiration(string $tokenString): \DateTimeImmutable;
}
diff --git a/src/Bundle/ChillDocStoreBundle/Templating/WopiEditTwigExtensionRuntime.php b/src/Bundle/ChillDocStoreBundle/Templating/WopiEditTwigExtensionRuntime.php
index f833200c8..be4afd68d 100644
--- a/src/Bundle/ChillDocStoreBundle/Templating/WopiEditTwigExtensionRuntime.php
+++ b/src/Bundle/ChillDocStoreBundle/Templating/WopiEditTwigExtensionRuntime.php
@@ -13,6 +13,10 @@ namespace Chill\DocStoreBundle\Templating;
use ChampsLibres\WopiLib\Contract\Service\Discovery\DiscoveryInterface;
use Chill\DocStoreBundle\Entity\StoredObject;
+use Chill\DocStoreBundle\Security\Authorization\StoredObjectRoleEnum;
+use Chill\DocStoreBundle\Security\Guard\JWTDavTokenProviderInterface;
+use Namshi\JOSE\JWS;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Twig\Environment;
@@ -120,9 +124,12 @@ final readonly class WopiEditTwigExtensionRuntime implements RuntimeExtensionInt
private const TEMPLATE_BUTTON_GROUP = '@ChillDocStore/Button/button_group.html.twig';
- public function __construct(private DiscoveryInterface $discovery, private NormalizerInterface $normalizer)
- {
- }
+ public function __construct(
+ private DiscoveryInterface $discovery,
+ private NormalizerInterface $normalizer,
+ private JWTDavTokenProviderInterface $davTokenProvider,
+ private UrlGeneratorInterface $urlGenerator,
+ ) {}
/**
* return true if the document is editable.
@@ -132,7 +139,7 @@ final readonly class WopiEditTwigExtensionRuntime implements RuntimeExtensionInt
*/
public function isEditable(StoredObject $document): bool
{
- return \in_array($document->getType(), self::SUPPORTED_MIMES, true);
+ return in_array($document->getType(), self::SUPPORTED_MIMES, true);
}
/**
@@ -144,12 +151,26 @@ final readonly class WopiEditTwigExtensionRuntime implements RuntimeExtensionInt
*/
public function renderButtonGroup(Environment $environment, StoredObject $document, ?string $title = null, bool $canEdit = true, array $options = []): string
{
+ $accessToken = $this->davTokenProvider->createToken(
+ $document,
+ $canEdit ? StoredObjectRoleEnum::EDIT : StoredObjectRoleEnum::SEE
+ );
+
return $environment->render(self::TEMPLATE_BUTTON_GROUP, [
'document' => $document,
'document_json' => $this->normalizer->normalize($document, 'json', [AbstractNormalizer::GROUPS => ['read']]),
'title' => $title,
'can_edit' => $canEdit,
'options' => [...self::DEFAULT_OPTIONS_TEMPLATE_BUTTON_GROUP, ...$options],
+ 'dav_link' => $this->urlGenerator->generate(
+ 'chill_docstore_dav_document_get',
+ [
+ 'uuid' => $document->getUuid(),
+ 'access_token' => $accessToken,
+ ],
+ UrlGeneratorInterface::ABSOLUTE_URL,
+ ),
+ 'dav_link_expiration' => $this->davTokenProvider->getTokenExpiration($accessToken)->format('U'),
]);
}