Skip to content

Commit 067c1fb

Browse files
authored
Merge pull request #85 from nextcloud/vue-embedded-component
Use embedded vue component for documenso when possible
2 parents 19a3a06 + db13c46 commit 067c1fb

File tree

8 files changed

+290
-66
lines changed

8 files changed

+290
-66
lines changed

lib/AppInfo/Application.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
namespace OCA\Documenso\AppInfo;
66

77
use OCA\Documenso\Dashboard\DocumensoWidget;
8+
use OCA\Documenso\Listener\ContentSecurityPolicyListener;
89
use OCA\Files\Event\LoadAdditionalScriptsEvent;
910
use OCP\AppFramework\App;
1011
use OCP\AppFramework\Bootstrap\IBootContext;
1112
use OCP\AppFramework\Bootstrap\IBootstrap;
1213
use OCP\AppFramework\Bootstrap\IRegistrationContext;
1314
use OCP\EventDispatcher\IEventDispatcher;
15+
use OCP\Security\CSP\AddContentSecurityPolicyEvent;
1416
use OCP\Util;
1517

1618
class Application extends App implements IBootstrap {
@@ -32,6 +34,7 @@ public function __construct(array $urlParams = []) {
3234

3335
public function register(IRegistrationContext $context): void {
3436
$context->registerDashboardWidget(DocumensoWidget::class);
37+
$context->registerEventListener(AddContentSecurityPolicyEvent::class, ContentSecurityPolicyListener::class);
3538
}
3639

3740
public function boot(IBootContext $context): void {

lib/Controller/DocumensoController.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,29 @@ public function signStandalone(int $fileId, array $targetEmails = [], array $tar
7878
}
7979
}
8080

81+
/**
82+
* @param int $documentId
83+
* @return DataResponse
84+
*/
85+
#[NoAdminRequired]
86+
#[FrontpageRoute(verb: 'POST', url: '/documenso/distribute')]
87+
public function distribute(int $documentId): DataResponse {
88+
if ($this->userId === null) {
89+
return new DataResponse(['error' => 'no user in context'], Http::STATUS_UNAUTHORIZED);
90+
}
91+
$token = $this->config->getUserValue($this->userId, Application::APP_ID, 'token');
92+
$url = $this->config->getUserValue($this->userId, Application::APP_ID, 'url');
93+
$isConnected = ($token !== '' && $url !== '');
94+
if (!$isConnected) {
95+
return new DataResponse(['error' => 'Documenso connected account is not configured'], Http::STATUS_UNAUTHORIZED);
96+
}
97+
$result = $this->documensoAPIService->distributeDocument($this->userId, $documentId);
98+
if (isset($result['error'])) {
99+
return new DataResponse($result, Http::STATUS_BAD_REQUEST);
100+
}
101+
return new DataResponse($result);
102+
}
103+
81104
/**
82105
* Set config values
83106
*
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace OCA\Documenso\Listener;
4+
5+
use OCA\Documenso\AppInfo\Application;
6+
use OCP\AppFramework\Http\ContentSecurityPolicy;
7+
use OCP\EventDispatcher\Event;
8+
use OCP\EventDispatcher\IEventListener;
9+
use OCP\IConfig;
10+
use OCP\Security\CSP\AddContentSecurityPolicyEvent;
11+
12+
/**
13+
* @implements IEventListener<AddContentSecurityPolicyEvent>
14+
*/
15+
class ContentSecurityPolicyListener implements IEventListener {
16+
17+
public function __construct(
18+
private IConfig $config,
19+
private ?string $userId,
20+
) {
21+
}
22+
23+
/**
24+
* @inheritDoc
25+
*/
26+
public function handle(Event $event): void {
27+
if (!$event instanceof AddContentSecurityPolicyEvent) {
28+
return;
29+
}
30+
if ($this->userId === null) {
31+
return;
32+
}
33+
34+
$policy = new ContentSecurityPolicy();
35+
$host = $this->config->getUserValue($this->userId, Application::APP_ID, 'url');
36+
$policy->addAllowedFrameDomain($host);
37+
$event->addPolicy($policy);
38+
}
39+
}

lib/Service/DocumensoAPIService.php

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,11 @@ public function emailSignStandalone(int $fileId, string $ccUserId, array $target
9393
if (isset($uploadEndpoint['error'])) {
9494
return $uploadEndpoint;
9595
};
96-
9796
$response = $this->uploadFile($file, $uploadEndpoint, $ccUserId);
9897
$response['missingMailCount'] = $missingMailCount;
98+
$response['embeddingToken'] = $this->requestEmbeddingToken($ccUserId);
99+
$response['host'] = $this->config->getUserValue($ccUserId, Application::APP_ID, 'url');
100+
$response['documentId'] = $uploadEndpoint['documentId'];
99101
return $response;
100102
}
101103

@@ -154,6 +156,41 @@ public function uploadFile(File $file, array $uploadEndpoint, string $ccUserId):
154156
}
155157
}
156158

159+
/**
160+
* Request a presigned embedding token for embedded authoring/signing
161+
* See https://openapi.documenso.com/reference#tag/embedding/post/embedding/create-presign-token
162+
*
163+
* @param string $userId
164+
* @return string|null The presign token on success, null on error
165+
*/
166+
public function requestEmbeddingToken(string $userId): ?string {
167+
$baseUrl = $this->config->getUserValue($userId, Application::APP_ID, 'url');
168+
$endPoint = 'api/v2/embedding/create-presign-token';
169+
$result = $this->apiRequest($baseUrl, $userId, $endPoint, ['expiresIn' => 60,'scope' => ''], 'POST');
170+
171+
if (isset($result['error'])) {
172+
$this->logger->warning('Failed to create embedding presign token: ' . $result['error'], ['app' => Application::APP_ID]);
173+
return null;
174+
}
175+
176+
return isset($result['token']) && is_string($result['token']) ? $result['token'] : null;
177+
}
178+
179+
/**
180+
* Distribute a document via Documenso (send for signing).
181+
* See https://openapi.documenso.com/reference#tag/document/post/document/distribute
182+
*
183+
* @param string $userId
184+
* @param int $documentId
185+
* @return array request result or error
186+
*/
187+
public function distributeDocument(string $userId, int $documentId): array {
188+
$baseUrl = $this->config->getUserValue($userId, Application::APP_ID, 'url');
189+
$endPoint = 'api/v2/document/distribute';
190+
$body = ['documentId' => $documentId];
191+
return $this->apiRequest($baseUrl, $userId, $endPoint, $body, 'POST');
192+
}
193+
157194
/**
158195
* Get a list of all documents from Documenso
159196
* @param string $userId
@@ -175,7 +212,7 @@ public function getDocumentList($userId): array {
175212
* @param string $baseUrl
176213
* @param string $token
177214
* @param string $endPoint
178-
* @param array<string, string|string[]> $params
215+
* @param array<string, string[]|string|int|bool> $params
179216
* @param string $method
180217
* @return array request result
181218
* @throws Exception

package-lock.json

Lines changed: 58 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@
3434
"npm": "^11.3.0"
3535
},
3636
"dependencies": {
37+
"@documenso/embed-vue": "^0.5.0",
3738
"@nextcloud/auth": "^2.5.1",
3839
"@nextcloud/axios": "^2.4.0",
3940
"@nextcloud/dialogs": "^7.2.0",
40-
"@nextcloud/files": "^4.0.0-beta.8",
41+
"@nextcloud/files": "^4.0.0",
4142
"@nextcloud/initial-state": "^3.0.0",
4243
"@nextcloud/l10n": "^3.2.0",
4344
"@nextcloud/moment": "^1.3.4",

0 commit comments

Comments
 (0)