diff --git a/scm-ui/src/containers/Logout.js b/scm-ui/src/containers/Logout.js index 465e1b156a..27c4902000 100644 --- a/scm-ui/src/containers/Logout.js +++ b/scm-ui/src/containers/Logout.js @@ -3,13 +3,12 @@ import React from "react"; import { connect } from "react-redux"; import { translate } from "react-i18next"; import { Redirect } from "react-router-dom"; -import type { History } from "history"; import { logout, isAuthenticated, isLogoutPending, - getLogoutFailure + getLogoutFailure, isRedirecting } from "../modules/auth"; import { Loading, ErrorPage } from "@scm-manager/ui-components"; import { getLogoutLink } from "../modules/indexResource"; @@ -17,24 +16,24 @@ import { getLogoutLink } from "../modules/indexResource"; type Props = { authenticated: boolean, loading: boolean, + redirecting: boolean, error: Error, logoutLink: string, // dispatcher functions - logout: (link: string, history: History) => void, + logout: (link: string) => void, // context props - history: History, t: string => string }; class Logout extends React.Component { componentDidMount() { - this.props.logout(this.props.logoutLink, this.props.history); + this.props.logout(this.props.logoutLink); } render() { - const { authenticated, loading, error, t } = this.props; + const { authenticated, redirecting, loading, error, t } = this.props; if (error) { return ( { error={error} /> ); - } else if (loading || authenticated) { + } else if (loading || authenticated || redirecting) { return ; } else { return ; @@ -54,11 +53,13 @@ class Logout extends React.Component { const mapStateToProps = state => { const authenticated = isAuthenticated(state); const loading = isLogoutPending(state); + const redirecting = isRedirecting(state); const error = getLogoutFailure(state); const logoutLink = getLogoutLink(state); return { authenticated, loading, + redirecting, error, logoutLink }; @@ -66,7 +67,7 @@ const mapStateToProps = state => { const mapDispatchToProps = dispatch => { return { - logout: (link: string, history: History) => dispatch(logout(link, history)) + logout: (link: string) => dispatch(logout(link)) }; }; diff --git a/scm-ui/src/modules/auth.js b/scm-ui/src/modules/auth.js index 8b22c8a0c5..73ba013fa1 100644 --- a/scm-ui/src/modules/auth.js +++ b/scm-ui/src/modules/auth.js @@ -11,7 +11,6 @@ import { fetchIndexResourcesPending, fetchIndexResourcesSuccess } from "./indexResource"; -import type { History } from "history"; // Action @@ -30,10 +29,7 @@ export const LOGOUT = "scm/auth/LOGOUT"; export const LOGOUT_PENDING = `${LOGOUT}_${types.PENDING_SUFFIX}`; export const LOGOUT_SUCCESS = `${LOGOUT}_${types.SUCCESS_SUFFIX}`; export const LOGOUT_FAILURE = `${LOGOUT}_${types.FAILURE_SUFFIX}`; - -type LogoutRedirection = { - logoutRedirect: string -}; +export const LOGOUT_REDIRECT = `${LOGOUT}_REDIRECT`; // Reducer @@ -59,6 +55,13 @@ export default function reducer( case LOGOUT_SUCCESS: return initialState; + case LOGOUT_REDIRECT: { + // we keep the current state until we are redirected to the new page + return { + ...state, + redirecting: true + }; + } default: return state; } @@ -94,10 +97,16 @@ export const logoutPending = () => { export const logoutSuccess = () => { return { - type: LOGOUT_SUCCESS + type: LOGOUT_SUCCESS, }; }; +export const redirectAfterLogout = () => { + return { + type: LOGOUT_REDIRECT + } +}; + export const logoutFailure = (error: Error) => { return { type: LOGOUT_FAILURE, @@ -190,7 +199,7 @@ export const fetchMe = (link: string) => { }; }; -export const logout = (link: string, history: History) => { +export const logout = (link: string) => { return function(dispatch: any) { dispatch(logoutPending()); return apiClient @@ -199,17 +208,24 @@ export const logout = (link: string, history: History) => { return response.status === 200 ? response.json() : new Promise(function(resolve) { - resolve(undefined); + resolve(); }); }) .then(json => { + let fetchIndex = true; if (json && json.logoutRedirect) { + dispatch(redirectAfterLogout()); window.location.assign(json.logoutRedirect); + fetchIndex = false; + } else { + dispatch(logoutSuccess()); } - dispatch(logoutSuccess()); + return fetchIndex; }) - .then(() => { - dispatch(fetchIndexResources()); + .then((fetchIndex: boolean) => { + if (fetchIndex) { + dispatch(fetchIndexResources()); + } }) .catch(error => { dispatch(logoutFailure(error)); @@ -257,3 +273,8 @@ export const isLogoutPending = (state: Object) => { export const getLogoutFailure = (state: Object) => { return getFailure(state, LOGOUT); }; + +export const isRedirecting = (state: Object) => { + return !!stateAuth(state).redirecting; +}; + diff --git a/scm-ui/src/modules/auth.test.js b/scm-ui/src/modules/auth.test.js index 199d369022..cdf8e7c661 100644 --- a/scm-ui/src/modules/auth.test.js +++ b/scm-ui/src/modules/auth.test.js @@ -26,7 +26,7 @@ import reducer, { FETCH_ME, LOGOUT, getLoginFailure, - getLogoutFailure, + getLogoutFailure, isRedirecting, LOGOUT_REDIRECT, redirectAfterLogout, } from "./auth"; import configureMockStore from "redux-mock-store"; @@ -70,6 +70,17 @@ describe("auth reducer", () => { expect(state.authenticated).toBeUndefined(); }); + it("should keep state and set redirecting to true", () => { + const initialState = { + authenticated: true, + me + }; + const state = reducer(initialState, redirectAfterLogout()); + expect(state.me).toBe(initialState.me); + expect(state.authenticated).toBe(initialState.authenticated); + expect(state.redirecting).toBe(true); + }); + it("should set state authenticated and me after login", () => { const state = reducer(undefined, loginSuccess(me)); expect(state.me).toBe(me); @@ -246,8 +257,7 @@ describe("auth actions", () => { const expectedActions = [ { type: LOGOUT_PENDING }, - { type: LOGOUT_SUCCESS }, - { type: FETCH_INDEXRESOURCES_PENDING } + { type: LOGOUT_REDIRECT } ]; const store = mockStore({}); @@ -257,8 +267,6 @@ describe("auth actions", () => { "http://example.com/cas/logout" ); expect(store.getActions()).toEqual(expectedActions); - - // expect(window.location.href).toEqual("http://example.com/cas/logout"); }); }); @@ -345,4 +353,16 @@ describe("auth selectors", () => { it("should return unknown, if failure state is not set for LOGOUT", () => { expect(getLogoutFailure({})).toBeUndefined(); }); + + it("should return false, if redirecting is not set", () => { + expect(isRedirecting({})).toBe(false); + }); + + it("should return false, if redirecting is false", () => { + expect(isRedirecting({auth: { redirecting: false }})).toBe(false); + }); + + it("should return true, if redirecting is true", () => { + expect(isRedirecting({auth: { redirecting: true }})).toBe(true); + }); });