mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-02-12 02:33:09 +00:00
feat(realtime): disconnect user on user login status change
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
9b9eafc948
commit
972ec8c9c5
3 changed files with 104 additions and 1 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
@ -19,6 +19,7 @@ import { useOnImageUploadFromRenderer } from './hooks/image-upload-from-renderer
|
||||||
import { useCodeMirrorTablePasteExtension } from './hooks/table-paste/use-code-mirror-table-paste-extension'
|
import { useCodeMirrorTablePasteExtension } from './hooks/table-paste/use-code-mirror-table-paste-extension'
|
||||||
import { useApplyScrollState } from './hooks/use-apply-scroll-state'
|
import { useApplyScrollState } from './hooks/use-apply-scroll-state'
|
||||||
import { useCursorActivityCallback } from './hooks/use-cursor-activity-callback'
|
import { useCursorActivityCallback } from './hooks/use-cursor-activity-callback'
|
||||||
|
import { useDisconnectOnUserLoginStatusChange } from './hooks/use-disconnect-on-user-login-status-change'
|
||||||
import { useUpdateCodeMirrorReference } from './hooks/use-update-code-mirror-reference'
|
import { useUpdateCodeMirrorReference } from './hooks/use-update-code-mirror-reference'
|
||||||
import { useBindYTextToRedux } from './hooks/yjs/use-bind-y-text-to-redux'
|
import { useBindYTextToRedux } from './hooks/yjs/use-bind-y-text-to-redux'
|
||||||
import { useCodeMirrorYjsExtension } from './hooks/yjs/use-code-mirror-yjs-extension'
|
import { useCodeMirrorYjsExtension } from './hooks/yjs/use-code-mirror-yjs-extension'
|
||||||
|
@ -56,6 +57,9 @@ export const EditorPane: React.FC<EditorPaneProps> = ({ scrollState, onScroll, o
|
||||||
useApplyScrollState(scrollState)
|
useApplyScrollState(scrollState)
|
||||||
|
|
||||||
const messageTransporter = useRealtimeConnection()
|
const messageTransporter = useRealtimeConnection()
|
||||||
|
|
||||||
|
useDisconnectOnUserLoginStatusChange(messageTransporter)
|
||||||
|
|
||||||
const realtimeDoc = useRealtimeDoc()
|
const realtimeDoc = useRealtimeDoc()
|
||||||
const editorScrollExtension = useCodeMirrorScrollWatchExtension(onScroll)
|
const editorScrollExtension = useCodeMirrorScrollWatchExtension(onScroll)
|
||||||
const tablePasteExtensions = useCodeMirrorTablePasteExtension()
|
const tablePasteExtensions = useCodeMirrorTablePasteExtension()
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import type { LoginUserInfo } from '../../../../api/me/types'
|
||||||
|
import * as UseApplicationStateModule from '../../../../hooks/common/use-application-state'
|
||||||
|
import type { ApplicationState } from '../../../../redux/application-state'
|
||||||
|
import { useDisconnectOnUserLoginStatusChange } from './use-disconnect-on-user-login-status-change'
|
||||||
|
import type { MessageTransporter } from '@hedgedoc/commons'
|
||||||
|
import { render } from '@testing-library/react'
|
||||||
|
import React, { Fragment } from 'react'
|
||||||
|
import { Mock } from 'ts-mockery'
|
||||||
|
|
||||||
|
jest.mock('../../../../hooks/common/use-application-state')
|
||||||
|
|
||||||
|
describe('use logout on user change', () => {
|
||||||
|
const TestComponent: React.FC<{ messageTransporter: MessageTransporter }> = ({ messageTransporter }) => {
|
||||||
|
useDisconnectOnUserLoginStatusChange(messageTransporter)
|
||||||
|
return <Fragment />
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockUseApplicationState = (userLoggedIn: boolean) => {
|
||||||
|
jest
|
||||||
|
.spyOn(UseApplicationStateModule, 'useApplicationState')
|
||||||
|
.mockImplementation((fn) =>
|
||||||
|
fn(Mock.of<ApplicationState>({ user: userLoggedIn ? Mock.of<LoginUserInfo>({}) : null }))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let disconnectCallback: jest.Mock
|
||||||
|
let messageTransporter: MessageTransporter
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
disconnectCallback = jest.fn()
|
||||||
|
messageTransporter = Mock.of<MessageTransporter>({ disconnect: disconnectCallback })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("doesn't disconnect if user is logged in before", () => {
|
||||||
|
mockUseApplicationState(true)
|
||||||
|
render(<TestComponent messageTransporter={messageTransporter} />)
|
||||||
|
expect(disconnectCallback).not.toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("doesn't disconnect if user is not logged in before", () => {
|
||||||
|
mockUseApplicationState(false)
|
||||||
|
render(<TestComponent messageTransporter={messageTransporter} />)
|
||||||
|
expect(disconnectCallback).not.toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('disconnects if user switches from logged in to logged out', () => {
|
||||||
|
mockUseApplicationState(true)
|
||||||
|
const view = render(<TestComponent messageTransporter={messageTransporter} />)
|
||||||
|
expect(disconnectCallback).not.toBeCalled()
|
||||||
|
|
||||||
|
mockUseApplicationState(false)
|
||||||
|
view.rerender(<TestComponent messageTransporter={messageTransporter} />)
|
||||||
|
expect(disconnectCallback).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('disconnects if user switches from logged out to logged in', () => {
|
||||||
|
mockUseApplicationState(false)
|
||||||
|
const view = render(<TestComponent messageTransporter={messageTransporter} />)
|
||||||
|
expect(disconnectCallback).not.toBeCalled()
|
||||||
|
|
||||||
|
mockUseApplicationState(true)
|
||||||
|
view.rerender(<TestComponent messageTransporter={messageTransporter} />)
|
||||||
|
expect(disconnectCallback).toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
import { useApplicationState } from '../../../../hooks/common/use-application-state'
|
||||||
|
import type { MessageTransporter } from '@hedgedoc/commons'
|
||||||
|
import { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects the given {@link MessageTransporter message transporter} if the user status changes through log-in or log-out.
|
||||||
|
*
|
||||||
|
* @param messageTransporter the message transporter to disconnect
|
||||||
|
*/
|
||||||
|
export const useDisconnectOnUserLoginStatusChange = (messageTransporter: MessageTransporter): void => {
|
||||||
|
const previousIsLoggedIn = useRef<boolean | undefined>()
|
||||||
|
const isLoggedIn = useApplicationState((state) => state.user !== null)
|
||||||
|
useEffect(() => {
|
||||||
|
if (previousIsLoggedIn.current === undefined) {
|
||||||
|
previousIsLoggedIn.current = isLoggedIn
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (previousIsLoggedIn.current === isLoggedIn) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
previousIsLoggedIn.current = isLoggedIn
|
||||||
|
messageTransporter.disconnect()
|
||||||
|
}, [isLoggedIn, messageTransporter])
|
||||||
|
}
|
Loading…
Reference in a new issue