diff --git a/lib/ResponseDefinitions.php b/lib/ResponseDefinitions.php index 096b026be3..6d46e07610 100644 --- a/lib/ResponseDefinitions.php +++ b/lib/ResponseDefinitions.php @@ -142,7 +142,7 @@ * @psalm-type LibresignSignerSummary = array{ * signRequestId: int, * displayName: string, - * email: string, + * email?: ?string, * identifyMethods?: LibresignIdentifyMethod[], * signed: ?string, * status: int, @@ -394,7 +394,7 @@ * statusText: string, * nodeId: non-negative-int, * nodeType: 'file'|'envelope', - * signatureFlow: int, + * signatureFlow: 0|1|2, * docmdpLevel: int, * filesCount: int<0, max>, * files: list, diff --git a/openapi-full.json b/openapi-full.json index 9ab790941c..d56503b4fb 100644 --- a/openapi-full.json +++ b/openapi-full.json @@ -2437,7 +2437,6 @@ "required": [ "signRequestId", "displayName", - "email", "signed", "status", "statusText" @@ -2451,7 +2450,8 @@ "type": "string" }, "email": { - "type": "string" + "type": "string", + "nullable": true }, "identifyMethods": { "type": "array", @@ -2768,7 +2768,12 @@ }, "signatureFlow": { "type": "integer", - "format": "int64" + "format": "int64", + "enum": [ + 0, + 1, + 2 + ] }, "docmdpLevel": { "type": "integer", diff --git a/openapi.json b/openapi.json index 0205a793e2..0c8286187b 100644 --- a/openapi.json +++ b/openapi.json @@ -1839,7 +1839,6 @@ "required": [ "signRequestId", "displayName", - "email", "signed", "status", "statusText" @@ -1853,7 +1852,8 @@ "type": "string" }, "email": { - "type": "string" + "type": "string", + "nullable": true }, "identifyMethods": { "type": "array", @@ -2156,7 +2156,12 @@ }, "signatureFlow": { "type": "integer", - "format": "int64" + "format": "int64", + "enum": [ + 0, + 1, + 2 + ] }, "docmdpLevel": { "type": "integer", diff --git a/playwright/e2e/sign-email-token-unauthenticated.spec.ts b/playwright/e2e/sign-email-token-unauthenticated.spec.ts index c618412eef..237e7ab8c3 100644 --- a/playwright/e2e/sign-email-token-unauthenticated.spec.ts +++ b/playwright/e2e/sign-email-token-unauthenticated.spec.ts @@ -64,6 +64,30 @@ test('sign document with email token as unauthenticated signer', async ({ page } const email = await waitForEmailTo(mailpit, 'signer01@libresign.coop', 'LibreSign: There is a file for you to sign') const signLink = extractSignLink(email.Text) if (!signLink) throw new Error('Sign link not found in email') + + // Regression guard: validation payload can contain signer without email. + // Reuse this existing E2E flow and force `email = null` in the validate response. + await page.route('**/ocs/v2.php/apps/libresign/api/v1/file/validate/uuid/**', async (route) => { + const response = await route.fetch() + const payload = await response.json() as Record + const ocs = payload.ocs as Record | undefined + const data = ocs?.data as Record | undefined + + if (data && Array.isArray(data.signers) && data.signers.length > 0) { + const firstSigner = data.signers[0] as Record + firstSigner.email = null + } + + await route.fulfill({ + status: response.status(), + headers: { + ...response.headers(), + 'content-type': 'application/json', + }, + body: JSON.stringify(payload), + }) + }) + await page.goto(signLink); await page.getByRole('button', { name: 'Sign the document.' }).click(); await page.getByRole('textbox', { name: 'Email' }).click(); @@ -84,6 +108,7 @@ test('sign document with email token as unauthenticated signer', async ({ page } await page.getByRole('button', { name: 'Sign document' }).click(); await page.waitForURL('**/validation/**'); await expect(page.getByText('This document is valid')).toBeVisible(); + await expect(page.getByText('Failed to validate document')).not.toBeVisible(); await expect(page.getByText('Congratulations you have')).toBeVisible(); await expect(page.getByRole('button', { name: 'Sign the document.' })).not.toBeVisible(); }); diff --git a/src/components/Request/SignDetail/partials/SignerRow.vue b/src/components/Request/SignDetail/partials/SignerRow.vue index 391cff8478..b3d9bf4aa7 100644 --- a/src/components/Request/SignDetail/partials/SignerRow.vue +++ b/src/components/Request/SignDetail/partials/SignerRow.vue @@ -11,7 +11,7 @@