Skip to content

Commit 2d0c593

Browse files
authored
Merge pull request #5994 from LibreSign/feature/footer-service-api
feature: footer service api
2 parents 6f73d6b + a820e11 commit 2d0c593

File tree

9 files changed

+1296
-0
lines changed

9 files changed

+1296
-0
lines changed

lib/Controller/AdminController.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use OCA\Libresign\ResponseDefinitions;
1818
use OCA\Libresign\Service\Certificate\ValidateService;
1919
use OCA\Libresign\Service\CertificatePolicyService;
20+
use OCA\Libresign\Service\FooterService;
2021
use OCA\Libresign\Service\Install\ConfigureCheckService;
2122
use OCA\Libresign\Service\Install\InstallService;
2223
use OCA\Libresign\Service\ReminderService;
@@ -27,6 +28,7 @@
2728
use OCP\AppFramework\Http\Attribute\ApiRoute;
2829
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
2930
use OCP\AppFramework\Http\ContentSecurityPolicy;
31+
use OCP\AppFramework\Http\DataDownloadResponse;
3032
use OCP\AppFramework\Http\DataResponse;
3133
use OCP\AppFramework\Http\FileDisplayResponse;
3234
use OCP\Files\SimpleFS\InMemoryFile;
@@ -61,6 +63,7 @@ public function __construct(
6163
private CertificatePolicyService $certificatePolicyService,
6264
private ValidateService $validateService,
6365
private ReminderService $reminderService,
66+
private FooterService $footerService,
6467
) {
6568
parent::__construct(Application::APP_ID, $request);
6669
$this->eventSource = $this->eventSourceFactory->create();
@@ -782,4 +785,74 @@ public function deleteTsaConfig(): DataResponse {
782785

783786
return new DataResponse(['status' => 'success']);
784787
}
788+
789+
/**
790+
* Get footer template
791+
*
792+
* Returns the current footer template if set, otherwise returns the default template.
793+
*
794+
* @return DataResponse<Http::STATUS_OK, array{template: string, isDefault: bool}, array{}>
795+
*
796+
* 200: OK
797+
*/
798+
#[ApiRoute(verb: 'GET', url: '/api/{apiVersion}/admin/footer-template', requirements: ['apiVersion' => '(v1)'])]
799+
public function getFooterTemplate(): DataResponse {
800+
return new DataResponse([
801+
'template' => $this->footerService->getTemplate(),
802+
'isDefault' => $this->footerService->isDefaultTemplate(),
803+
]);
804+
}
805+
806+
/**
807+
* Save footer template and render preview
808+
*
809+
* Saves the footer template and returns the rendered PDF preview.
810+
*
811+
* @param string $template The Twig template to save
812+
* @param int $width Width of preview in points (default: 595 - A4 width)
813+
* @param int $height Height of preview in points (default: 50)
814+
* @return DataDownloadResponse<Http::STATUS_OK, 'application/pdf', array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error: string}, array{}>
815+
*
816+
* 200: OK
817+
* 400: Bad request
818+
*/
819+
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/admin/footer-template', requirements: ['apiVersion' => '(v1)'])]
820+
public function saveFooterTemplate(string $template, int $width = 595, int $height = 50) {
821+
try {
822+
$this->footerService->saveTemplate($template);
823+
$pdf = $this->footerService->renderPreviewPdf(null, $width, $height);
824+
825+
return new DataDownloadResponse($pdf, 'footer-preview.pdf', 'application/pdf');
826+
} catch (\Exception $e) {
827+
return new DataResponse([
828+
'error' => $e->getMessage(),
829+
], Http::STATUS_BAD_REQUEST);
830+
}
831+
}
832+
833+
/**
834+
* Preview footer template as PDF
835+
*
836+
* @NoAdminRequired
837+
* @NoCSRFRequired
838+
*
839+
* @param string $template Template to preview
840+
* @param int $width Width of preview in points (default: 595 - A4 width)
841+
* @param int $height Height of preview in points (default: 50)
842+
* @return DataDownloadResponse<Http::STATUS_OK, 'application/pdf', array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{error: string}, array{}>
843+
*
844+
* 200: OK
845+
* 400: Bad request
846+
*/
847+
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/admin/footer-template/preview-pdf', requirements: ['apiVersion' => '(v1)'])]
848+
public function footerTemplatePreviewPdf(string $template = '', int $width = 595, int $height = 50) {
849+
try {
850+
$pdf = $this->footerService->renderPreviewPdf($template ?: null, $width, $height);
851+
return new DataDownloadResponse($pdf, 'footer-preview.pdf', 'application/pdf');
852+
} catch (\Exception $e) {
853+
return new DataResponse([
854+
'error' => $e->getMessage(),
855+
], Http::STATUS_BAD_REQUEST);
856+
}
857+
}
785858
}

lib/Service/FooterService.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
6+
* SPDX-License-Identifier: AGPL-3.0-or-later
7+
*/
8+
9+
namespace OCA\Libresign\Service;
10+
11+
use OCA\Libresign\AppInfo\Application;
12+
use OCA\Libresign\Handler\FooterHandler;
13+
use OCP\IAppConfig;
14+
15+
class FooterService {
16+
public function __construct(
17+
private IAppConfig $appConfig,
18+
private FooterHandler $footerHandler,
19+
) {
20+
}
21+
22+
public function isDefaultTemplate(): bool {
23+
$customTemplate = $this->appConfig->getValueString(Application::APP_ID, 'footer_template', '');
24+
return empty($customTemplate);
25+
}
26+
27+
public function getTemplate(): string {
28+
return $this->appConfig->getValueString(Application::APP_ID, 'footer_template', '');
29+
}
30+
31+
public function saveTemplate(string $template): void {
32+
$this->appConfig->setValueString(Application::APP_ID, 'footer_template', $template);
33+
}
34+
35+
public function renderPreviewPdf(?string $template = null, int $width = 595, int $height = 50): string {
36+
if ($template !== null) {
37+
$this->saveTemplate($template);
38+
}
39+
40+
return $this->footerHandler
41+
->setTemplateVar('uuid', 'preview-' . bin2hex(random_bytes(8)))
42+
->setTemplateVar('signers', [
43+
[
44+
'displayName' => 'Preview Signer',
45+
'signed' => date('c'),
46+
],
47+
])
48+
->getFooter([['w' => $width, 'h' => $height]]);
49+
}
50+
}

openapi-administration.json

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2599,6 +2599,214 @@
25992599
}
26002600
}
26012601
},
2602+
"/ocs/v2.php/apps/libresign/api/{apiVersion}/admin/footer-template": {
2603+
"get": {
2604+
"operationId": "admin-get-footer-template",
2605+
"summary": "Get footer template",
2606+
"description": "Returns the current footer template if set, otherwise returns the default template.\nThis endpoint requires admin access",
2607+
"tags": [
2608+
"admin"
2609+
],
2610+
"security": [
2611+
{
2612+
"bearer_auth": []
2613+
},
2614+
{
2615+
"basic_auth": []
2616+
}
2617+
],
2618+
"parameters": [
2619+
{
2620+
"name": "apiVersion",
2621+
"in": "path",
2622+
"required": true,
2623+
"schema": {
2624+
"type": "string",
2625+
"enum": [
2626+
"v1"
2627+
],
2628+
"default": "v1"
2629+
}
2630+
},
2631+
{
2632+
"name": "OCS-APIRequest",
2633+
"in": "header",
2634+
"description": "Required to be true for the API request to pass",
2635+
"required": true,
2636+
"schema": {
2637+
"type": "boolean",
2638+
"default": true
2639+
}
2640+
}
2641+
],
2642+
"responses": {
2643+
"200": {
2644+
"description": "OK",
2645+
"content": {
2646+
"application/json": {
2647+
"schema": {
2648+
"type": "object",
2649+
"required": [
2650+
"ocs"
2651+
],
2652+
"properties": {
2653+
"ocs": {
2654+
"type": "object",
2655+
"required": [
2656+
"meta",
2657+
"data"
2658+
],
2659+
"properties": {
2660+
"meta": {
2661+
"$ref": "#/components/schemas/OCSMeta"
2662+
},
2663+
"data": {
2664+
"type": "object",
2665+
"required": [
2666+
"template",
2667+
"isDefault"
2668+
],
2669+
"properties": {
2670+
"template": {
2671+
"type": "string"
2672+
},
2673+
"isDefault": {
2674+
"type": "boolean"
2675+
}
2676+
}
2677+
}
2678+
}
2679+
}
2680+
}
2681+
}
2682+
}
2683+
}
2684+
}
2685+
}
2686+
},
2687+
"post": {
2688+
"operationId": "admin-save-footer-template",
2689+
"summary": "Save footer template and render preview",
2690+
"description": "Saves the footer template and returns the rendered PDF preview.\nThis endpoint requires admin access",
2691+
"tags": [
2692+
"admin"
2693+
],
2694+
"security": [
2695+
{
2696+
"bearer_auth": []
2697+
},
2698+
{
2699+
"basic_auth": []
2700+
}
2701+
],
2702+
"requestBody": {
2703+
"required": true,
2704+
"content": {
2705+
"application/json": {
2706+
"schema": {
2707+
"type": "object",
2708+
"required": [
2709+
"template"
2710+
],
2711+
"properties": {
2712+
"template": {
2713+
"type": "string",
2714+
"description": "The Twig template to save"
2715+
},
2716+
"width": {
2717+
"type": "integer",
2718+
"format": "int64",
2719+
"default": 595,
2720+
"description": "Width of preview in points (default: 595 - A4 width)"
2721+
},
2722+
"height": {
2723+
"type": "integer",
2724+
"format": "int64",
2725+
"default": 50,
2726+
"description": "Height of preview in points (default: 50)"
2727+
}
2728+
}
2729+
}
2730+
}
2731+
}
2732+
},
2733+
"parameters": [
2734+
{
2735+
"name": "apiVersion",
2736+
"in": "path",
2737+
"required": true,
2738+
"schema": {
2739+
"type": "string",
2740+
"enum": [
2741+
"v1"
2742+
],
2743+
"default": "v1"
2744+
}
2745+
},
2746+
{
2747+
"name": "OCS-APIRequest",
2748+
"in": "header",
2749+
"description": "Required to be true for the API request to pass",
2750+
"required": true,
2751+
"schema": {
2752+
"type": "boolean",
2753+
"default": true
2754+
}
2755+
}
2756+
],
2757+
"responses": {
2758+
"200": {
2759+
"description": "OK",
2760+
"content": {
2761+
"application/pdf": {
2762+
"schema": {
2763+
"type": "string",
2764+
"format": "binary"
2765+
}
2766+
}
2767+
}
2768+
},
2769+
"400": {
2770+
"description": "Bad request",
2771+
"content": {
2772+
"application/json": {
2773+
"schema": {
2774+
"type": "object",
2775+
"required": [
2776+
"ocs"
2777+
],
2778+
"properties": {
2779+
"ocs": {
2780+
"type": "object",
2781+
"required": [
2782+
"meta",
2783+
"data"
2784+
],
2785+
"properties": {
2786+
"meta": {
2787+
"$ref": "#/components/schemas/OCSMeta"
2788+
},
2789+
"data": {
2790+
"type": "object",
2791+
"required": [
2792+
"error"
2793+
],
2794+
"properties": {
2795+
"error": {
2796+
"type": "string"
2797+
}
2798+
}
2799+
}
2800+
}
2801+
}
2802+
}
2803+
}
2804+
}
2805+
}
2806+
}
2807+
}
2808+
}
2809+
},
26022810
"/ocs/v2.php/apps/libresign/api/{apiVersion}/crl/list": {
26032811
"get": {
26042812
"operationId": "crl_api-list",

0 commit comments

Comments
 (0)