diff --git a/backend/.env.dist b/backend/.env.dist index db01cf4cc..780e60e5a 100644 --- a/backend/.env.dist +++ b/backend/.env.dist @@ -3,7 +3,7 @@ CONFIG_VERSION=v8.2022-06-20 # Server PORT=4000 JWT_SECRET=secret123 -JWT_EXPIRES_IN=30m +JWT_EXPIRES_IN=10m GRAPHIQL=false GDT_API_URL=https://gdt.gradido.net diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index a9cae6770..aa4197a43 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -25,7 +25,7 @@ const constants = { const server = { PORT: process.env.PORT || 4000, JWT_SECRET: process.env.JWT_SECRET || 'secret123', - JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '30m', + JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '10m', GRAPHIQL: process.env.GRAPHIQL === 'true' || false, GDT_API_URL: process.env.GDT_API_URL || 'https://gdt.gradido.net', PRODUCTION: process.env.NODE_ENV === 'production' || false, diff --git a/deployment/bare_metal/.env.dist b/deployment/bare_metal/.env.dist index 67c153661..edb878040 100644 --- a/deployment/bare_metal/.env.dist +++ b/deployment/bare_metal/.env.dist @@ -28,7 +28,7 @@ COMMUNITY_DESCRIPTION="Gradido Development Stage1 Test Community" # backend BACKEND_CONFIG_VERSION=v8.2022-06-20 -JWT_EXPIRES_IN=30m +JWT_EXPIRES_IN=10m GDT_API_URL=https://gdt.gradido.net TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log diff --git a/frontend/package.json b/frontend/package.json index 0aeb7c353..7bf370802 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -45,6 +45,7 @@ "jest": "^26.6.3", "jest-canvas-mock": "^2.3.1", "jest-environment-jsdom-sixteen": "^2.0.0", + "jwt-decode": "^3.1.2", "portal-vue": "^2.1.7", "prettier": "^2.2.1", "qrcanvas-vue": "2.1.1", @@ -59,6 +60,7 @@ "vue-loading-overlay": "^3.4.2", "vue-moment": "^4.1.0", "vue-router": "^3.0.6", + "vue-timers": "^2.0.4", "vue2-transitions": "^0.2.3", "vuex": "^3.6.0", "vuex-persistedstate": "^4.0.0-beta.3" diff --git a/frontend/src/components/SessionLogoutTimeout.spec.js b/frontend/src/components/SessionLogoutTimeout.spec.js new file mode 100644 index 000000000..0f5d21d36 --- /dev/null +++ b/frontend/src/components/SessionLogoutTimeout.spec.js @@ -0,0 +1,99 @@ +import { mount } from '@vue/test-utils' +import SessionLogoutTimeout from './SessionLogoutTimeout' + +const localVue = global.localVue + +const apolloQueryMock = jest.fn() + +const setTokenTime = (seconds) => { + const now = new Date() + return Math.floor(new Date(now.setSeconds(now.getSeconds() + seconds)).getTime() / 1000) +} + +const mocks = { + $store: { + state: { + token: '1234', + tokenTime: setTokenTime(120), + }, + }, + $i18n: { + locale: 'en', + }, + $t: jest.fn((t) => t), + $apollo: { + query: apolloQueryMock, + }, + $route: { + meta: { + requiresAuth: true, + }, + }, +} + +describe('SessionLogoutTimeout', () => { + let wrapper, spy + + const Wrapper = () => { + return mount(SessionLogoutTimeout, { localVue, mocks }) + } + + describe('mount', () => { + beforeEach(() => { + jest.clearAllMocks() + wrapper = Wrapper() + }) + + it('renders the component div.session-logout-timeout', () => { + expect(wrapper.find('div.session-logout-timeout').exists()).toBe(true) + }) + + describe('timers', () => { + it('has a token expires timer', () => { + expect(wrapper.vm.$options.timers).toEqual({ + tokenExpires: expect.objectContaining({ + name: 'tokenExpires', + time: 15000, + repeat: true, + immediate: true, + autostart: true, + isSwitchTab: false, + }), + }) + }) + + describe('token is expired', () => { + beforeEach(() => { + mocks.$store.state.tokenTime = setTokenTime(-60) + wrapper = Wrapper() + }) + + it('emits logout', () => { + expect(wrapper.emitted('logout')).toBeTruthy() + }) + }) + + describe('token time less than 75 seconds', () => { + beforeEach(() => { + mocks.$store.state.tokenTime = setTokenTime(60) + jest.useFakeTimers() + wrapper = Wrapper() + spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm') + spy.mockImplementation(() => Promise.resolve(true)) + }) + + it('sets the timer to 1000', () => { + expect(wrapper.vm.timers.tokenExpires.time).toBe(1000) + }) + + it.skip('opens the modal', () => { + jest.advanceTimersByTime(1000) + jest.advanceTimersByTime(1000) + jest.advanceTimersByTime(1000) + jest.advanceTimersByTime(1000) + expect(spy).toBeCalled() + }) + }) + }) + }) +}) diff --git a/frontend/src/components/SessionLogoutTimeout.vue b/frontend/src/components/SessionLogoutTimeout.vue new file mode 100644 index 000000000..1e5a27998 --- /dev/null +++ b/frontend/src/components/SessionLogoutTimeout.vue @@ -0,0 +1,100 @@ + + diff --git a/frontend/src/components/TransactionLinks/TransactionLink.spec.js b/frontend/src/components/TransactionLinks/TransactionLink.spec.js index ad9e4860e..13aaea900 100644 --- a/frontend/src/components/TransactionLinks/TransactionLink.spec.js +++ b/frontend/src/components/TransactionLinks/TransactionLink.spec.js @@ -92,6 +92,17 @@ describe('TransactionLink', () => { expect(toastSuccessSpy).toBeCalledWith('gdd_per_link.link-copied') }) }) + + describe('copy with error', () => { + beforeEach(async () => { + navigatorClipboardMock.mockRejectedValue() + await wrapper.find('.test-copy-link .dropdown-item').trigger('click') + }) + + it('toasts an error', () => { + expect(toastErrorSpy).toBeCalledWith('gdd_per_link.not-copied') + }) + }) }) describe('qr code modal', () => { diff --git a/frontend/src/layouts/AuthLayout.spec.js b/frontend/src/layouts/AuthLayout.spec.js index 2246793d5..30c858ea5 100644 --- a/frontend/src/layouts/AuthLayout.spec.js +++ b/frontend/src/layouts/AuthLayout.spec.js @@ -35,9 +35,10 @@ describe('AuthLayout', () => { beforeEach(() => { wrapper = Wrapper() }) + describe('Mobile Version Start', () => { beforeEach(() => { - wrapper.vm.mobileStart = true + wrapper.findComponent({ name: 'AuthMobileStart' }).vm.$emit('set-mobile-start', true) }) it('has Component AuthMobileStart', () => { diff --git a/frontend/src/layouts/DashboardLayout.vue b/frontend/src/layouts/DashboardLayout.vue index cd8794c40..8e778ab01 100755 --- a/frontend/src/layouts/DashboardLayout.vue +++ b/frontend/src/layouts/DashboardLayout.vue @@ -32,6 +32,7 @@ + @@ -39,6 +40,7 @@