Skip to content

Commit 43bd67e

Browse files
committed
fix: migrate footer preview states from app config to policies
Signed-off-by: Vitor Mattos <[email protected]>
1 parent 38af4c7 commit 43bd67e

6 files changed

Lines changed: 50 additions & 96 deletions

File tree

lib/Controller/AdminController.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -853,11 +853,14 @@ public function deleteTsaConfig(): DataResponse {
853853
*/
854854
#[ApiRoute(verb: 'GET', url: '/api/{apiVersion}/admin/footer-template', requirements: ['apiVersion' => '(v1)'])]
855855
public function getFooterTemplate(): DataResponse {
856+
$previewSettings = $this->footerService->getPreviewSettings();
857+
856858
return new DataResponse([
857859
'template' => $this->footerService->getTemplate(),
858860
'isDefault' => $this->footerService->isDefaultTemplate(),
859-
'preview_width' => $this->appConfig->getValueInt(Application::APP_ID, 'footer_preview_width', 595),
860-
'preview_height' => $this->appConfig->getValueInt(Application::APP_ID, 'footer_preview_height', 100),
861+
'preview_width' => $previewSettings['preview_width'],
862+
'preview_height' => $previewSettings['preview_height'],
863+
'preview_zoom' => $previewSettings['preview_zoom'],
861864
]);
862865
}
863866

@@ -877,7 +880,7 @@ public function getFooterTemplate(): DataResponse {
877880
#[ApiRoute(verb: 'POST', url: '/api/{apiVersion}/admin/footer-template', requirements: ['apiVersion' => '(v1)'])]
878881
public function saveFooterTemplate(string $template = '', int $width = 595, int $height = 50) {
879882
try {
880-
$this->footerService->saveTemplate($template);
883+
$this->footerService->saveTemplate($template, $width, $height);
881884
$pdf = $this->footerService->renderPreviewPdf('', $width, $height);
882885

883886
return new DataDownloadResponse($pdf, 'footer-preview.pdf', 'application/pdf');

lib/Service/FooterService.php

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,30 +33,52 @@ public function getDefaultTemplate(): string {
3333
return $this->footerHandler->getDefaultTemplate();
3434
}
3535

36-
public function saveTemplate(string $template = ''): void {
36+
/** @return array{preview_width: int, preview_height: int, preview_zoom: int} */
37+
public function getPreviewSettings(): array {
38+
$footerPolicy = $this->getEffectiveFooterPolicy();
39+
40+
return [
41+
'preview_width' => (int)$footerPolicy['previewWidth'],
42+
'preview_height' => (int)$footerPolicy['previewHeight'],
43+
'preview_zoom' => (int)$footerPolicy['previewZoom'],
44+
];
45+
}
46+
47+
public function saveTemplate(string $template = '', ?int $previewWidth = null, ?int $previewHeight = null): void {
3748
$defaultTemplate = $this->footerHandler->getDefaultTemplate();
49+
$currentPolicy = $this->getEffectiveFooterPolicy();
50+
$normalizedPolicy = FooterPolicyValue::normalize($currentPolicy);
51+
52+
if ($previewWidth !== null) {
53+
$normalizedPolicy['previewWidth'] = $previewWidth;
54+
}
55+
56+
if ($previewHeight !== null) {
57+
$normalizedPolicy['previewHeight'] = $previewHeight;
58+
}
3859

3960
if (empty($template)) {
40-
$this->syncFooterPolicyTemplate('', false);
61+
$normalizedPolicy['customizeFooterTemplate'] = false;
62+
$normalizedPolicy['footerTemplate'] = '';
63+
$this->saveSystemFooterPolicy($normalizedPolicy);
4164
return;
4265
}
4366

4467
$isProvidedTemplateEqualsDefault = $template === $defaultTemplate;
4568

4669
if ($isProvidedTemplateEqualsDefault) {
47-
$this->syncFooterPolicyTemplate('', false);
70+
$normalizedPolicy['customizeFooterTemplate'] = false;
71+
$normalizedPolicy['footerTemplate'] = '';
4872
} else {
49-
$this->syncFooterPolicyTemplate($template, true);
73+
$normalizedPolicy['customizeFooterTemplate'] = true;
74+
$normalizedPolicy['footerTemplate'] = $template;
5075
}
51-
}
5276

53-
private function syncFooterPolicyTemplate(string $template, bool $customizeFooterTemplate): void {
54-
$currentPolicy = $this->getEffectiveFooterPolicy();
55-
$normalizedPolicy = FooterPolicyValue::normalize($currentPolicy);
56-
57-
$normalizedPolicy['customizeFooterTemplate'] = $customizeFooterTemplate;
58-
$normalizedPolicy['footerTemplate'] = $customizeFooterTemplate ? $template : '';
77+
$this->saveSystemFooterPolicy($normalizedPolicy);
78+
}
5979

80+
/** @param array{enabled: bool, writeQrcodeOnFooter: bool, validationSite: string, customizeFooterTemplate: bool, footerTemplate: string, previewWidth: int, previewHeight: int, previewZoom: int} $normalizedPolicy */
81+
private function saveSystemFooterPolicy(array $normalizedPolicy): void {
6082
$allowChildOverride = $this->policyService->getSystemPolicy(FooterPolicy::KEY)?->isAllowChildOverride() ?? false;
6183
$this->policyService->saveSystem(
6284
FooterPolicy::KEY,

lib/Settings/Admin.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,6 @@ public function getForm(): TemplateResponse {
6363
$this->initialState->provideInitialState('certificate_policies_cps', $this->certificatePolicyService->getCps());
6464
$this->initialState->provideInitialState('config_path', $this->appConfig->getValueString(Application::APP_ID, 'config_path'));
6565
$this->initialState->provideInitialState('signature_available_variables', $this->signatureTextService->getAvailableVariables());
66-
$this->initialState->provideInitialState('signature_preview_zoom_level', $this->appConfig->getValueFloat(Application::APP_ID, 'signature_preview_zoom_level', 100));
67-
$this->initialState->provideInitialState('footer_preview_zoom_level', $this->appConfig->getValueFloat(Application::APP_ID, 'footer_preview_zoom_level', 100));
68-
$this->initialState->provideInitialState('footer_preview_width', $this->appConfig->getValueInt(Application::APP_ID, 'footer_preview_width', 595));
69-
$this->initialState->provideInitialState('footer_preview_height', $this->appConfig->getValueInt(Application::APP_ID, 'footer_preview_height', 100));
7066
$this->initialState->provideInitialState('footer_template_variables', $this->footerService->getTemplateVariablesMetadata());
7167
$this->initialState->provideInitialState('footer_default_template', $this->footerService->getDefaultTemplate());
7268
$this->initialState->provideInitialState('footer_template', $this->footerService->getTemplate());

src/components/FooterTemplateEditor.vue

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,6 @@ type PdfPreviewRef = {
187187
scale: number
188188
}
189189
190-
type AppConfigApi = {
191-
deleteKey: (app: string, key: string) => void
192-
setValue: (app: string, key: string, value: string | number) => void
193-
}
194-
195190
const DEFAULT_PREVIEW_WIDTH = 595
196191
const DEFAULT_PREVIEW_HEIGHT = 100
197192
@@ -202,7 +197,7 @@ const isDefaultTemplate = ref(loadState('libresign', 'footer_template_is_default
202197
const pdfPreviewFile = ref<File | null>(null)
203198
const loadingPreview = ref(false)
204199
const pdfKey = ref(0)
205-
const zoomLevel = ref(loadState('libresign', 'footer_preview_zoom_level', 100))
200+
const zoomLevel = ref(100)
206201
const previewWidth = ref<number | string>(DEFAULT_PREVIEW_WIDTH)
207202
const previewHeight = ref<number | string>(DEFAULT_PREVIEW_HEIGHT)
208203
const originalWidth = ref<number | string>(DEFAULT_PREVIEW_WIDTH)
@@ -232,8 +227,6 @@ function estimateContainerHeightForFirstRender(height: number, zoom: number): nu
232227
return Math.max(160, Math.round((height * zoom) / 100) + 24)
233228
}
234229
235-
const appConfig = (globalThis as typeof globalThis & { OCP?: { AppConfig: AppConfigApi } }).OCP?.AppConfig
236-
237230
ensurePdfWorker()
238231
239232
function getVariableText(name: string) {
@@ -295,18 +288,9 @@ function resetDimensionsToOriginal() {
295288
function resetDimensions() {
296289
previewWidth.value = DEFAULT_PREVIEW_WIDTH
297290
previewHeight.value = DEFAULT_PREVIEW_HEIGHT
298-
appConfig?.deleteKey('libresign', 'footer_preview_width')
299-
appConfig?.deleteKey('libresign', 'footer_preview_height')
300291
}
301292
302293
function saveDimensions() {
303-
if (Number(previewWidth.value) === DEFAULT_PREVIEW_WIDTH && Number(previewHeight.value) === DEFAULT_PREVIEW_HEIGHT) {
304-
appConfig?.deleteKey('libresign', 'footer_preview_width')
305-
appConfig?.deleteKey('libresign', 'footer_preview_height')
306-
} else {
307-
appConfig?.setValue('libresign', 'footer_preview_width', previewWidth.value)
308-
appConfig?.setValue('libresign', 'footer_preview_height', previewHeight.value)
309-
}
310294
saveFooterTemplate()
311295
}
312296
@@ -386,6 +370,7 @@ onMounted(() => {
386370
const template = response.data.ocs.data.template
387371
const width = response.data.ocs.data.preview_width
388372
const height = response.data.ocs.data.preview_height
373+
const zoom = response.data.ocs.data.preview_zoom ?? 100
389374
390375
footerTemplate.value = template
391376
originalTemplate.value = template
@@ -394,6 +379,7 @@ onMounted(() => {
394379
originalHeight.value = height
395380
previewWidth.value = width
396381
originalWidth.value = width
382+
zoomLevel.value = zoom
397383
saveFooterTemplate()
398384
})
399385
})

src/tests/components/FooterTemplateEditor.spec.ts

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ const axiosGetMock = vi.fn()
1212
const axiosPostMock = vi.fn()
1313
const ensurePdfWorkerMock = vi.fn()
1414

15-
const appConfigMock = {
16-
deleteKey: vi.fn(),
17-
setValue: vi.fn(),
18-
}
19-
2015
const clipboardWriteTextMock = vi.fn()
2116

2217
vi.mock('debounce', () => ({
@@ -32,9 +27,6 @@ vi.mock('@nextcloud/axios', () => ({
3227

3328
vi.mock('@nextcloud/initial-state', () => ({
3429
loadState: vi.fn((_app: string, key: string, defaultValue: unknown) => {
35-
if (key === 'footer_preview_zoom_level') {
36-
return 100
37-
}
3830
if (key === 'footer_template_variables') {
3931
return {
4032
signerName: { description: 'Signer', type: 'string', example: 'Alice' },
@@ -135,8 +127,6 @@ describe('FooterTemplateEditor.vue', () => {
135127
axiosGetMock.mockReset()
136128
axiosPostMock.mockReset()
137129
ensurePdfWorkerMock.mockReset()
138-
appConfigMock.deleteKey.mockReset()
139-
appConfigMock.setValue.mockReset()
140130
clipboardWriteTextMock.mockReset()
141131

142132
axiosGetMock.mockResolvedValue({
@@ -146,13 +136,12 @@ describe('FooterTemplateEditor.vue', () => {
146136
template: 'Footer {{ signerName }}',
147137
preview_height: 120,
148138
preview_width: 640,
139+
preview_zoom: 100,
149140
},
150141
},
151142
},
152143
})
153144
axiosPostMock.mockResolvedValue({ data: new Blob(['pdf'], { type: 'application/pdf' }) })
154-
155-
vi.stubGlobal('OCP', { AppConfig: appConfigMock })
156145
vi.stubGlobal('navigator', {
157146
clipboard: {
158147
writeText: clipboardWriteTextMock,
@@ -182,7 +171,7 @@ describe('FooterTemplateEditor.vue', () => {
182171
expect(wrapper.vm.isCopied('signerName')).toBe(true)
183172
})
184173

185-
it('resets dimensions and clears the stored app config values', async () => {
174+
it('resets dimensions to default values', async () => {
186175
const wrapper = createWrapper()
187176
await flushPromises()
188177

@@ -192,8 +181,6 @@ describe('FooterTemplateEditor.vue', () => {
192181

193182
expect(wrapper.vm.previewWidth).toBe(wrapper.vm.DEFAULT_PREVIEW_WIDTH)
194183
expect(wrapper.vm.previewHeight).toBe(wrapper.vm.DEFAULT_PREVIEW_HEIGHT)
195-
expect(appConfigMock.deleteKey).toHaveBeenCalledWith('libresign', 'footer_preview_width')
196-
expect(appConfigMock.deleteKey).toHaveBeenCalledWith('libresign', 'footer_preview_height')
197184
})
198185

199186
it('updates zoom level through the zoom controls logic', async () => {
@@ -239,8 +226,6 @@ describe('FooterTemplateEditor.vue', () => {
239226
wrapper.vm.saveDimensions()
240227
await flushPromises()
241228

242-
expect(appConfigMock.setValue).toHaveBeenCalledWith('libresign', 'footer_preview_width', 700)
243-
expect(appConfigMock.setValue).toHaveBeenCalledWith('libresign', 'footer_preview_height', 150)
244229
expect(axiosPostMock).toHaveBeenLastCalledWith(
245230
'/ocs/v2.php/apps/libresign/api/v1/admin/footer-template',
246231
{

tests/integration/features/admin/initial_state.feature

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,6 @@ Feature: admin/initial_state
7070
| signature_background_type | default |
7171
| signature_font_size | 20 |
7272
| signature_height | 100 |
73-
| signature_preview_zoom_level | 100 |
74-
| footer_preview_zoom_level | 100 |
75-
| footer_preview_width | 595 |
76-
| footer_preview_height | 100 |
7773
| signature_engine | JSignPdf |
7874
| signature_render_mode | GRAPHIC_AND_DESCRIPTION |
7975
| signature_width | 350 |
@@ -118,22 +114,6 @@ Feature: admin/initial_state
118114
| (jq)has("{{ServerSignatureDate}}") | true |
119115
| (jq)has("{{SignerCommonName}}") | true |
120116
| (jq)has("{{SignerIP}}") | false |
121-
And the response should contain the initial state "libresign-signature_preview_zoom_level" with the following values:
122-
"""
123-
100
124-
"""
125-
And the response should contain the initial state "libresign-footer_preview_zoom_level" with the following values:
126-
"""
127-
100
128-
"""
129-
And the response should contain the initial state "libresign-footer_preview_width" with the following values:
130-
"""
131-
595
132-
"""
133-
And the response should contain the initial state "libresign-footer_preview_height" with the following values:
134-
"""
135-
100
136-
"""
137117
And the response should contain the initial state "libresign-footer_template_variables" json that match with:
138118
| key | value |
139119
| (jq).direction.type | string |
@@ -163,6 +143,9 @@ Feature: admin/initial_state
163143
| (jq).policies.envelope_enabled.effectiveValue | true |
164144
| (jq).policies.show_confetti_after_signing.effectiveValue | true |
165145
| (jq).policies.crl_external_validation_enabled.effectiveValue | true |
146+
| (jq)(.policies.add_footer.effectiveValue \| fromjson).previewWidth | 595 |
147+
| (jq)(.policies.add_footer.effectiveValue \| fromjson).previewHeight | 100 |
148+
| (jq)(.policies.add_footer.effectiveValue \| fromjson).previewZoom | 100 |
166149
| (jq).policies.tsa_settings.policyKey | tsa_settings |
167150
| (jq).policies.tsa_settings.sourceScope | system |
168151
| (jq)(.policies.tsa_settings.effectiveValue \| fromjson).auth_type | none |
@@ -191,10 +174,6 @@ Feature: admin/initial_state
191174
| signature_background_type | deleted |
192175
| signature_font_size | 18.5 |
193176
| signature_height | 140 |
194-
| signature_preview_zoom_level | 125 |
195-
| footer_preview_zoom_level | 85 |
196-
| footer_preview_width | 610 |
197-
| footer_preview_height | 80 |
198177
| signature_engine | PhpNative |
199178
| signature_render_mode | DESCRIPTION_ONLY |
200179
| signature_text_template | Issuer: {{IssuerCommonName}} |
@@ -248,22 +227,6 @@ Feature: admin/initial_state
248227
"""
249228
Issuer: Acme Cooperative
250229
"""
251-
And the response should contain the initial state "libresign-signature_preview_zoom_level" with the following values:
252-
"""
253-
125
254-
"""
255-
And the response should contain the initial state "libresign-footer_preview_zoom_level" with the following values:
256-
"""
257-
85
258-
"""
259-
And the response should contain the initial state "libresign-footer_preview_width" with the following values:
260-
"""
261-
610
262-
"""
263-
And the response should contain the initial state "libresign-footer_preview_height" with the following values:
264-
"""
265-
80
266-
"""
267230
And the response should contain the initial state "libresign-footer_template" with the following values:
268231
"""
269232
Custom footer for {{ uuid }}
@@ -290,6 +253,9 @@ Feature: admin/initial_state
290253
| (jq).policies.envelope_enabled.effectiveValue | false |
291254
| (jq).policies.show_confetti_after_signing.effectiveValue | false |
292255
| (jq).policies.crl_external_validation_enabled.effectiveValue | false |
256+
| (jq)(.policies.add_footer.effectiveValue \| fromjson).previewWidth | 610 |
257+
| (jq)(.policies.add_footer.effectiveValue \| fromjson).previewHeight | 80 |
258+
| (jq)(.policies.add_footer.effectiveValue \| fromjson).previewZoom | 100 |
293259
| (jq).policies.tsa_settings.policyKey | tsa_settings |
294260
| (jq).policies.tsa_settings.sourceScope | global |
295261
| (jq)(.policies.tsa_settings.effectiveValue \| fromjson).url | https://tsa.example.test/tsr |
@@ -316,10 +282,6 @@ Feature: admin/initial_state
316282
| signature_background_type | default |
317283
| signature_font_size | 20 |
318284
| signature_height | 100 |
319-
| signature_preview_zoom_level | 100 |
320-
| footer_preview_zoom_level | 100 |
321-
| footer_preview_width | 595 |
322-
| footer_preview_height | 100 |
323285
| signature_engine | JSignPdf |
324286
| signature_render_mode | GRAPHIC_AND_DESCRIPTION |
325287
| signature_width | 350 |

0 commit comments

Comments
 (0)