Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/components/validation/DocumentValidationDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,13 @@ const size = computed(() => {
const documentStatus = computed(() => getStatusLabel(document.value.status))

async function viewDocument() {
if (!document.value.uuid || !document.value.name || typeof document.value.nodeId !== 'number') {
if (!document.value.uuid || !document.value.name) {
return
}
const fileUrl = generateUrl('/apps/libresign/p/pdf/{uuid}', { uuid: document.value.uuid })
await openDocument({
fileUrl,
filename: document.value.name,
nodeId: document.value.nodeId,
})
}

Expand Down
7 changes: 3 additions & 4 deletions src/components/validation/EnvelopeValidation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<template #subname>
<strong>{{ t('libresign', 'Status:') }}</strong> {{ getFileStatusText(file) }}
</template>
<template v-if="!isTouchDevice && file.nodeId" #actions>
<template v-if="!isTouchDevice && file.uuid" #actions>
<NcActionButton @click.stop="viewFile(file)">
<template #icon>
<NcIconSvgWrapper :path="mdiEye" :size="20" />
Expand All @@ -74,7 +74,7 @@
</NcActionButton>
</template>
<template #extra-actions>
<NcButton v-if="isTouchDevice && file.nodeId" variant="tertiary" :aria-label="t('libresign', 'View PDF')" @click.stop="viewFile(file)">
<NcButton v-if="isTouchDevice && file.uuid" variant="tertiary" :aria-label="t('libresign', 'View PDF')" @click.stop="viewFile(file)">
<template #icon>
<NcIconSvgWrapper :path="mdiEye" :size="20" />
</template>
Expand Down Expand Up @@ -343,14 +343,13 @@ function getSignerProgressText(signer: EnvelopeSigner) {
}

function viewFile(file: EnvelopeFile) {
if (!file.uuid || !file.name || typeof file.nodeId !== 'number') {
if (!file.uuid || !file.name) {
return
}
const fileUrl = generateUrl('/apps/libresign/p/pdf/{uuid}', { uuid: file.uuid })
openDocument({
fileUrl,
filename: file.name,
nodeId: file.nodeId,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ describe('DocumentValidationDetails', () => {
expect(wrapper.vm.document.uuid).toBeUndefined()
})

it('calls openDocument with correct parameters', async () => {
it('opens the signed PDF by UUID without passing the owner nodeId', async () => {
wrapper = createWrapper({
document: {
uuid: 'doc-uuid-123',
Expand All @@ -410,9 +410,24 @@ describe('DocumentValidationDetails', () => {
await wrapper.vm.viewDocument()

expect(viewer.openDocument).toHaveBeenCalledWith({
fileUrl: expect.stringContaining('doc-uuid-123'),
fileUrl: '/apps/libresign/p/pdf/doc-uuid-123',
filename: 'Test.pdf',
nodeId: 456,
})
})

it('opens the document when the response has no nodeId', async () => {
wrapper = createWrapper({
document: {
uuid: 'no-node-id',
name: 'No nodeId.pdf',
},
})

await wrapper.vm.viewDocument()

expect(viewer.openDocument).toHaveBeenCalledWith({
fileUrl: '/apps/libresign/p/pdf/no-node-id',
filename: 'No nodeId.pdf',
})
})

Expand Down Expand Up @@ -451,8 +466,8 @@ describe('DocumentValidationDetails', () => {
it('does not open viewer without required viewer data', async () => {
wrapper = createWrapper({
document: {
uuid: 'missing-node-id',
name: 'Missing nodeId.pdf',
name: 'Missing uuid.pdf',
nodeId: 456,
},
})

Expand Down
25 changes: 18 additions & 7 deletions src/tests/components/validation/EnvelopeValidation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,20 +398,33 @@ describe('EnvelopeValidation', () => {
})

expect(viewer.openDocument).toHaveBeenCalledWith({
fileUrl: expect.stringContaining('file-uuid-123'),
fileUrl: '/apps/libresign/p/pdf/file-uuid-123',
filename: 'Document.pdf',
nodeId: 456,
})
})

it('does not open viewer without nodeId', () => {
it('opens the file by UUID when it has no nodeId', () => {
wrapper = createWrapper()

wrapper.vm.viewFile({
uuid: 'file-uuid-123',
name: 'Document.pdf',
})

expect(viewer.openDocument).toHaveBeenCalledWith({
fileUrl: '/apps/libresign/p/pdf/file-uuid-123',
filename: 'Document.pdf',
})
})

it('does not open viewer without uuid', () => {
wrapper = createWrapper()

wrapper.vm.viewFile({
name: 'Document.pdf',
nodeId: 456,
})

expect(viewer.openDocument).not.toHaveBeenCalled()
})
})
Expand Down Expand Up @@ -584,8 +597,8 @@ describe('EnvelopeValidation', () => {
expect(typeof wrapper.vm.isTouchDevice).toBe('boolean')
})

it('renders actions slot when not touch device and file has nodeId', async () => {
const file: EnvelopeFile = { id: 1, nodeId: 123, status: '3', name: 'test.pdf' }
it('renders actions slot when not touch device and file has uuid', async () => {
const file: EnvelopeFile = { id: 1, uuid: 'test-uuid', nodeId: 123, status: '3', name: 'test.pdf' }
wrapper = createWrapper({
document: { files: [file] },
})
Expand All @@ -608,7 +621,6 @@ describe('EnvelopeValidation', () => {
expect(viewer.openDocument).toHaveBeenCalledWith({
fileUrl: '/apps/libresign/p/pdf/test-uuid',
filename: 'test.pdf',
nodeId: 123,
})
})

Expand All @@ -623,7 +635,6 @@ describe('EnvelopeValidation', () => {
expect(viewer.openDocument).toHaveBeenCalledWith({
fileUrl: '/apps/libresign/p/pdf/test-uuid',
filename: 'test.pdf',
nodeId: 123,
})
})
})
Expand Down
20 changes: 20 additions & 0 deletions src/tests/utils/viewer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,24 @@ describe('openDocument', () => {
expect(openedUrl).toContain('/apps/libresign/p/pdf/file-uuid')
expect(openedUrl).toMatch(/_t=\d+$/)
})

it('opens URL directly for authenticated users when no nodeId is given', () => {
const viewerOpen = vi.fn()
;(global as GlobalWithOCA).OCA = {
Viewer: {
open: viewerOpen,
},
}

openDocument({
fileUrl: '/apps/libresign/p/pdf/file-uuid',
filename: 'signed.pdf',
})

expect(viewerOpen).not.toHaveBeenCalled()
expect(openSpy).toHaveBeenCalledTimes(1)
const openedUrl = openSpy.mock.calls[0]?.[0]
expect(openedUrl).toContain('/apps/libresign/p/pdf/file-uuid')
expect(openedUrl).toMatch(/_t=\d+$/)
})
})
9 changes: 7 additions & 2 deletions src/utils/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,20 @@ const extractRelativePath = (url) => {
* the public LibreSign PDF URL from loading. Fall back to a direct window open
* in that case.
*
* Without a node ID the Viewer is skipped as well: some Viewer handlers
* (e.g. Euro-Office/ONLYOFFICE) ignore `source` and resolve `fileid` in the
* current user's filesystem, so they must only receive a node the current
* user can access.
*
* @param {object} options - Options for opening the document
* @param {string} options.fileUrl - The URL of the file to open
* @param {string} options.filename - The name of the file
* @param {number} options.nodeId - The Nextcloud node ID
* @param {number} [options.nodeId] - The Nextcloud node ID, only when accessible by the current user
* @param {string} [options.mime] - The MIME type (defaults to 'application/pdf')
*/
export const openDocument = ({ fileUrl, filename, nodeId, mime = 'application/pdf' }) => {
const source = extractRelativePath(fileUrl)
const canUseViewer = OCA?.Viewer !== undefined && getCurrentUser() !== null
const canUseViewer = OCA?.Viewer !== undefined && getCurrentUser() !== null && typeof nodeId === 'number'

if (canUseViewer) {
const fileInfo = {
Expand Down
3 changes: 1 addition & 2 deletions src/views/Validation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -584,14 +584,13 @@ function getIconValidityPath(signer: ValidationDisplaySigner) {
}

async function viewDocument() {
if (!document.value?.uuid || !document.value?.name || typeof document.value.nodeId !== 'number') {
if (!document.value?.uuid || !document.value?.name) {
return
}
const fileUrl = generateUrl('/apps/libresign/p/pdf/{uuid}', { uuid: document.value.uuid })
await openDocument({
fileUrl,
filename: document.value.name,
nodeId: document.value.nodeId,
})
}

Expand Down