From f72e80bbf4e2858e1e732ed8696f1a0c93f3faf2 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:25:43 -0300 Subject: [PATCH 1/9] fix(settings): guard isAdmin access when getCurrentUser returns null Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/components/Settings/Settings.vue | 2 +- .../components/Settings/Settings.spec.ts | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/components/Settings/Settings.vue b/src/components/Settings/Settings.vue index 01f6f672f1..fb49a7b879 100644 --- a/src/components/Settings/Settings.vue +++ b/src/components/Settings/Settings.vue @@ -56,7 +56,7 @@ export default { }, data() { return { - isAdmin: getCurrentUser().isAdmin, + isAdmin: getCurrentUser()?.isAdmin ?? false, } }, methods: { diff --git a/src/tests/components/Settings/Settings.spec.ts b/src/tests/components/Settings/Settings.spec.ts index e8ea29b8c1..4b8b4e7ca2 100644 --- a/src/tests/components/Settings/Settings.spec.ts +++ b/src/tests/components/Settings/Settings.spec.ts @@ -258,6 +258,54 @@ describe('Settings', () => { }) }) + describe('RULE: unauthenticated users (signing via email link) do not crash the component', () => { + const createUnauthenticatedWrapper = () => { + getCurrentUserMock.mockReturnValue(null) + + return mount(Settings, { + global: { + stubs: { + NcAppNavigationItem: { + name: 'NcAppNavigationItem', + props: ['name', 'to', 'href', 'icon'], + template: '
  • {{ name }}
  • ', + }, + AccountIcon: { template: '
    ' }, + StarIcon: { template: '
    ' }, + TuneIcon: { template: '
    ' }, + }, + mocks: { t }, + }, + }) + } + + it('mounts without throwing when getCurrentUser returns null', () => { + expect(() => createUnauthenticatedWrapper()).not.toThrow() + }) + + it('isAdmin is false when getCurrentUser returns null', () => { + wrapper = createUnauthenticatedWrapper() + + expect(getWrapper().vm.isAdmin).toBe(false) + }) + + it('hides the Administration link when user is unauthenticated', () => { + wrapper = createUnauthenticatedWrapper() + const items = getItems() + const adminItem = findItemByName(items, 'Administration') + + expect(adminItem).toBeUndefined() + }) + + it('shows 2 navigation items for unauthenticated user', () => { + wrapper = createUnauthenticatedWrapper() + const items = getItems() + + // Account + Rate = 2 + expect(items.length).toBe(2) + }) + }) + describe('RULE: navigation items count depends on admin status', () => { it('shows 2 items for non-admin', () => { wrapper = createWrapper(false) From 1ec0d5ae1c4b67552f1244fa96f380670d010151 Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:25:43 -0300 Subject: [PATCH 2/9] feat(external): add dedicated ExternalApp without NcContent and reset server.css layout Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/ExternalApp.vue | 40 ++++++++++++++++++++++++++++ src/assets/styles/external-page.scss | 15 +++++++++++ src/external.ts | 3 ++- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/ExternalApp.vue create mode 100644 src/assets/styles/external-page.scss diff --git a/src/ExternalApp.vue b/src/ExternalApp.vue new file mode 100644 index 0000000000..07fd53c6fa --- /dev/null +++ b/src/ExternalApp.vue @@ -0,0 +1,40 @@ + + + + + + + diff --git a/src/assets/styles/external-page.scss b/src/assets/styles/external-page.scss new file mode 100644 index 0000000000..d5ed4db0ef --- /dev/null +++ b/src/assets/styles/external-page.scss @@ -0,0 +1,15 @@ +/** + * SPDX-FileCopyrightText: 2026 LibreCode coop and LibreCode contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +// Override server.css layout rules that assume authenticated header layout. +// `html body #content` beats the specificity of server.css selectors. +html body #content { + position: fixed; + inset: 0; + margin: 0; + width: 100vw; + height: 100vh; + border-radius: 0; +} diff --git a/src/external.ts b/src/external.ts index 78d6490d66..a5c2c87158 100644 --- a/src/external.ts +++ b/src/external.ts @@ -7,8 +7,9 @@ import { createApp } from 'vue' import { createPinia } from 'pinia' import { translate as t, translatePlural as n } from '@nextcloud/l10n' -import App from './App.vue' +import App from './ExternalApp.vue' import router from './router/router' +import './assets/styles/external-page.scss' if (window.OCA && !window.OCA.LibreSign) { Object.assign(window.OCA, { LibreSign: {} }) From 1615798231b6076a85b4d00866b32b4827318b2a Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:25:43 -0300 Subject: [PATCH 3/9] fix(sidebar): add SignPDFExternal to sidebarRoutes to prevent premature close on route change Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/store/sidebar.js | 2 +- src/tests/store/sidebar.spec.ts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/store/sidebar.js b/src/store/sidebar.js index 5c5b056970..ef261fbe5d 100644 --- a/src/store/sidebar.js +++ b/src/store/sidebar.js @@ -9,7 +9,7 @@ export const useSidebarStore = defineStore('sidebar', { state: () => ({ show: false, activeTab: '', - sidebarRoutes: ['fileslist', 'SignPDF', 'ValidationFile', 'IdDocsApprove'], + sidebarRoutes: ['fileslist', 'SignPDF', 'SignPDFExternal', 'ValidationFile', 'IdDocsApprove'], }), getters: { diff --git a/src/tests/store/sidebar.spec.ts b/src/tests/store/sidebar.spec.ts index 7d16da7246..d870076ab8 100644 --- a/src/tests/store/sidebar.spec.ts +++ b/src/tests/store/sidebar.spec.ts @@ -213,6 +213,16 @@ describe('sidebar store - visibility rules', () => { expect(store.show).toBe(true) }) + it('keeps sidebar visible for SignPDFExternal route', () => { + const store = useSidebarStore() + store.show = true + store.activeTab = 'sign-tab' + + store.handleRouteChange('SignPDFExternal') + + expect(store.show).toBe(true) + }) + it('hides sidebar for non-allowed routes', () => { const store = useSidebarStore() store.show = true From f7e832a4fb3e00f1397d0632f2b8f02ce7516eeb Mon Sep 17 00:00:00 2001 From: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:25:43 -0300 Subject: [PATCH 4/9] fix(sidebar): keep NcAppSidebar mounted via open prop to avoid null ref during transition Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com> --- src/components/RightSidebar/RightSidebar.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/RightSidebar/RightSidebar.vue b/src/components/RightSidebar/RightSidebar.vue index cd0f3f1fc9..b0e0b20d02 100644 --- a/src/components/RightSidebar/RightSidebar.vue +++ b/src/components/RightSidebar/RightSidebar.vue @@ -3,8 +3,9 @@ - SPDX-License-Identifier: AGPL-3.0-or-later -->