mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-31 00:16:47 +01:00
fix: add logout as an explicit call (#311)
Co-authored-by: Christopher Kolstad <chriswk@getunleash.ai>
This commit is contained in:
parent
1a63d91f95
commit
e339e5c01f
@ -56,6 +56,7 @@
|
||||
"enzyme-adapter-react-16": "^1.15.6",
|
||||
"enzyme-to-json": "^3.6.1",
|
||||
"fetch-mock": "^9.11.0",
|
||||
"http-proxy-middleware": "^2.0.1",
|
||||
"immutable": "^4.0.0-rc.12",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.flow": "^3.5.0",
|
||||
@ -109,6 +110,5 @@
|
||||
"no-useless-computed-key": "off",
|
||||
"import/no-anonymous-default-export": "off"
|
||||
}
|
||||
},
|
||||
"proxy": "http://localhost:4242"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
export const P = 'P';
|
||||
export const C = 'C';
|
||||
export const RBAC = 'RBAC';
|
||||
export const OIDC = 'OIDC';
|
||||
|
||||
export const PROJECTFILTERING = false;
|
||||
|
@ -83,12 +83,5 @@ Array [
|
||||
"title": "Admin",
|
||||
"type": "protected",
|
||||
},
|
||||
Object {
|
||||
"component": [Function],
|
||||
"layout": "main",
|
||||
"path": "/logout",
|
||||
"title": "Sign out",
|
||||
"type": "unprotected",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { baseRoutes, getRoute } from '../routes';
|
||||
|
||||
test('returns all baseRoutes', () => {
|
||||
expect(baseRoutes.length).toEqual(12);
|
||||
expect(baseRoutes).toHaveLength(11);
|
||||
expect(baseRoutes).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
import React from 'react';
|
||||
import { Divider, Drawer, List } from '@material-ui/core';
|
||||
import PropTypes from 'prop-types';
|
||||
import GitHubIcon from '@material-ui/icons/GitHub';
|
||||
import LibraryBooksIcon from '@material-ui/icons/LibraryBooks';
|
||||
import ExitToApp from '@material-ui/icons/ExitToApp';
|
||||
|
||||
import styles from './drawer.module.scss';
|
||||
|
||||
import { ReactComponent as LogoIcon } from '../../assets/icons/logo_wbg.svg';
|
||||
import NavigationLink from './Header/NavigationLink/NavigationLink';
|
||||
import ConditionallyRender from '../common/ConditionallyRender';
|
||||
import { getBasePath } from '../../utils/format-path';
|
||||
|
||||
export const DrawerMenu = ({
|
||||
links = [],
|
||||
@ -88,7 +91,13 @@ export const DrawerMenu = ({
|
||||
}
|
||||
/>
|
||||
<Divider />
|
||||
<div className={styles.iconLinkList}>{renderLinks()}</div>
|
||||
<div className={styles.iconLinkList}>
|
||||
{renderLinks()}
|
||||
<a className={styles.navigationLink} href={`${getBasePath()}/logout`}>
|
||||
<ExitToApp className={styles.navigationIcon} />
|
||||
Sign out
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
);
|
||||
|
@ -14,7 +14,6 @@ import ApplicationView from '../../page/applications/view';
|
||||
import ContextFields from '../../page/context';
|
||||
import CreateContextField from '../../page/context/create';
|
||||
import EditContextField from '../../page/context/edit';
|
||||
import LogoutFeatures from '../../page/user/logout';
|
||||
import CreateProject from '../../page/project/create';
|
||||
import EditProject from '../../page/project/edit';
|
||||
import ViewProject from '../../page/project/view';
|
||||
@ -342,13 +341,6 @@ export const routes = [
|
||||
type: 'protected',
|
||||
layout: 'main',
|
||||
},
|
||||
{
|
||||
path: '/logout',
|
||||
title: 'Sign out',
|
||||
component: LogoutFeatures,
|
||||
type: 'unprotected',
|
||||
layout: 'main',
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
title: 'Log in',
|
||||
|
@ -14,7 +14,6 @@ const UserProfile = ({
|
||||
location,
|
||||
fetchUser,
|
||||
updateSettingLocation,
|
||||
logoutUser,
|
||||
}) => {
|
||||
const [showProfile, setShowProfile] = useState(false);
|
||||
const [currentLocale, setCurrentLocale] = useState([]);
|
||||
@ -74,7 +73,6 @@ const UserProfile = ({
|
||||
profile={profile}
|
||||
updateSettingLocation={updateSettingLocation}
|
||||
possibleLocales={possibleLocales}
|
||||
logoutUser={logoutUser}
|
||||
location={location}
|
||||
setCurrentLocale={setCurrentLocale}
|
||||
currentLocale={currentLocale}
|
||||
|
@ -17,6 +17,7 @@ import { Alert } from '@material-ui/lab';
|
||||
import EditProfile from '../EditProfile/EditProfile';
|
||||
import legacyStyles from '../../user.module.scss';
|
||||
import usePermissions from '../../../../hooks/usePermissions';
|
||||
import { getBasePath } from '../../../../utils/format-path';
|
||||
|
||||
const UserProfileContent = ({
|
||||
showProfile,
|
||||
@ -26,7 +27,6 @@ const UserProfileContent = ({
|
||||
imageUrl,
|
||||
currentLocale,
|
||||
setCurrentLocale,
|
||||
logoutUser,
|
||||
}) => {
|
||||
const commonStyles = useCommonStyles();
|
||||
const [updatedPassword, setUpdatedPassword] = useState(false);
|
||||
@ -155,7 +155,7 @@ const UserProfileContent = ({
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={logoutUser}
|
||||
href={`${getBasePath()}/logout`}
|
||||
>
|
||||
Logout
|
||||
</Button>
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { connect } from 'react-redux';
|
||||
import UserProfile from './UserProfile';
|
||||
import { fetchUser, logoutUser } from '../../../store/user/actions';
|
||||
import { fetchUser } from '../../../store/user/actions';
|
||||
import { updateSettingForGroup } from '../../../store/settings/actions';
|
||||
|
||||
const mapDispatchToProps = {
|
||||
fetchUser,
|
||||
logoutUser,
|
||||
updateSettingLocation: updateSettingForGroup('location'),
|
||||
};
|
||||
|
||||
|
@ -1,29 +0,0 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Card, CardContent, CardHeader } from '@material-ui/core';
|
||||
import { styles as commonStyles } from '../common';
|
||||
|
||||
const LogoutComponent = ({ logoutUser, user }) => {
|
||||
useEffect(() => {
|
||||
if(user) {
|
||||
logoutUser();
|
||||
}
|
||||
}, [user, logoutUser]);
|
||||
|
||||
return (
|
||||
<Card shadow={0} className={commonStyles.fullwidth}>
|
||||
<CardHeader>Logged out</CardHeader>
|
||||
<CardContent>
|
||||
You have now been successfully logged out of Unleash.
|
||||
<br /> <br />
|
||||
Thank you for using Unleash.{' '}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
LogoutComponent.propTypes = {
|
||||
logoutUser: PropTypes.func.isRequired,
|
||||
user: PropTypes.object,
|
||||
};
|
||||
|
||||
export default LogoutComponent;
|
@ -1,13 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import LogoutComponent from './logout-component';
|
||||
import { logoutUser } from '../../store/user/actions';
|
||||
|
||||
const mapDispatchToProps = {
|
||||
logoutUser,
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
user: state.user.get('profile'),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(LogoutComponent);
|
@ -9,8 +9,12 @@ import TabNav from '../../../component/common/TabNav/TabNav';
|
||||
import PageContent from '../../../component/common/PageContent/PageContent';
|
||||
import ConditionallyRender from '../../../component/common/ConditionallyRender/ConditionallyRender';
|
||||
|
||||
function AdminAuthPage({ authenticationType, history, enableOIDC }) {
|
||||
function AdminAuthPage({ authenticationType, history }) {
|
||||
const tabs = [
|
||||
{
|
||||
label: 'OpenID Connect',
|
||||
component: <OidcAuth />,
|
||||
},
|
||||
{
|
||||
label: 'SAML 2.0',
|
||||
component: <SamlAuth />,
|
||||
@ -21,13 +25,6 @@ function AdminAuthPage({ authenticationType, history, enableOIDC }) {
|
||||
},
|
||||
];
|
||||
|
||||
if(enableOIDC) {
|
||||
tabs.unshift( {
|
||||
label: 'OpenID Connect',
|
||||
component: <OidcAuth />,
|
||||
},)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AdminMenu history={history} />
|
||||
@ -71,7 +68,6 @@ AdminAuthPage.propTypes = {
|
||||
match: PropTypes.object.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
authenticationType: PropTypes.string,
|
||||
enableOIDC: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default AdminAuthPage;
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { connect } from 'react-redux';
|
||||
import component from './authentication';
|
||||
import { OIDC } from '../../../component/common/flags';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
authenticationType: state.uiConfig.toJS().authenticationType,
|
||||
enableOIDC: !!state.uiConfig.toJS().flags[OIDC],
|
||||
});
|
||||
|
||||
const Container = connect(mapStateToProps, { })(component);
|
||||
|
@ -132,7 +132,7 @@ function SamlAuth({ config, getSamlConfig, updateSamlConfig, unleashUrl }) {
|
||||
label="Single Sign-On URL"
|
||||
name="signOnUrl"
|
||||
value={data.signOnUrl || ''}
|
||||
style={{ width: '400px' }}
|
||||
style={{ width: '400px'}}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
required
|
||||
@ -153,11 +153,12 @@ function SamlAuth({ config, getSamlConfig, updateSamlConfig, unleashUrl }) {
|
||||
label="X.509 Certificate"
|
||||
name="certificate"
|
||||
value={data.certificate || ''}
|
||||
style={{
|
||||
width: '100%',
|
||||
fontSize: '0.7em',
|
||||
fontFamily: 'monospace',
|
||||
}}
|
||||
style={{width: '100%'}}
|
||||
InputProps={{
|
||||
style: {
|
||||
fontSize: '0.6em',
|
||||
fontFamily: 'monospace',
|
||||
}}}
|
||||
multiline
|
||||
rows={14}
|
||||
rowsMax={14}
|
||||
@ -167,6 +168,55 @@ function SamlAuth({ config, getSamlConfig, updateSamlConfig, unleashUrl }) {
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<h3>Optional Configuration</h3>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={5}>
|
||||
<strong>Single Sign-out URL</strong>
|
||||
<p>
|
||||
(optional) The url to redirect the user to for
|
||||
signing out of the IDP.
|
||||
</p>
|
||||
</Grid>
|
||||
<Grid item md={6}>
|
||||
<TextField
|
||||
onChange={updateField}
|
||||
label="Single Sign-out URL"
|
||||
name="signOutUrl"
|
||||
value={data.signOutUrl || ''}
|
||||
style={{ width: '400px'}}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={5}>
|
||||
<strong>Service Provider X.509 Certificate</strong>
|
||||
<p>
|
||||
(Optional) The private certificate used by the Service Provider used to sign the SAML 2.0
|
||||
request towards the IDP. E.g. used to sign single logout requests (SLO).
|
||||
</p>
|
||||
</Grid>
|
||||
<Grid item md={7}>
|
||||
<TextField
|
||||
onChange={updateField}
|
||||
label="X.509 Certificate"
|
||||
name="spCertificate"
|
||||
value={data.spCertificate || ''}
|
||||
style={{width: '100%'}}
|
||||
InputProps={{
|
||||
style: {
|
||||
fontSize: '0.6em',
|
||||
fontFamily: 'monospace',
|
||||
}}}
|
||||
multiline
|
||||
rows={14}
|
||||
rowsMax={14}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item md={5}>
|
||||
<strong>Auto-create users</strong>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import ProjectList from '../../component/project/ProjectList';
|
||||
import ProjectList from '../../component/project/ProjectList/ProjectList';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const render = ({ history }) => <ProjectList history={history} />;
|
||||
|
@ -1,6 +0,0 @@
|
||||
import React from 'react';
|
||||
import LogoutContainer from './../../component/user/logout-container';
|
||||
|
||||
const render = () => <LogoutContainer />;
|
||||
|
||||
export default render;
|
27
frontend/src/setupProxy.js
Normal file
27
frontend/src/setupProxy.js
Normal file
@ -0,0 +1,27 @@
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||||
|
||||
const API_URL = process.env.UNLEASH_API || 'http://localhost:4242';
|
||||
|
||||
module.exports = function(app) {
|
||||
app.use(
|
||||
'/api',
|
||||
createProxyMiddleware({
|
||||
target: API_URL,
|
||||
changeOrigin: true,
|
||||
}),
|
||||
);
|
||||
app.use(
|
||||
'/auth',
|
||||
createProxyMiddleware({
|
||||
target: API_URL,
|
||||
changeOrigin: true,
|
||||
}),
|
||||
);
|
||||
app.use(
|
||||
'/logout',
|
||||
createProxyMiddleware({
|
||||
target: API_URL,
|
||||
changeOrigin: true,
|
||||
}),
|
||||
);
|
||||
};
|
@ -1,7 +1,5 @@
|
||||
import api from './api';
|
||||
import { dispatchError } from '../util';
|
||||
import { RESET_LOADING } from '../feature-toggle/actions';
|
||||
import { getBasePath } from '../../utils/format-path';
|
||||
export const USER_CHANGE_CURRENT = 'USER_CHANGE_CURRENT';
|
||||
export const USER_LOGOUT = 'USER_LOGOUT';
|
||||
export const USER_LOGIN = 'USER_LOGIN';
|
||||
@ -62,17 +60,3 @@ export function passwordLogin(path, user) {
|
||||
.then(() => dispatch({ type: USER_LOGIN }));
|
||||
};
|
||||
}
|
||||
|
||||
export function logoutUser() {
|
||||
const basepath = getBasePath();
|
||||
return dispatch => {
|
||||
return api
|
||||
.logoutUser()
|
||||
.then(() => dispatch({ type: USER_LOGOUT }))
|
||||
.then(() => dispatch({ type: RESET_LOADING }))
|
||||
.then(() => {
|
||||
window.location = `${basepath}`;
|
||||
})
|
||||
.catch(handleError);
|
||||
};
|
||||
}
|
||||
|
@ -3,13 +3,6 @@ import { throwIfNotSuccess, headers } from '../api-helper';
|
||||
|
||||
const URI = formatApiPath('api/admin/user');
|
||||
|
||||
function logoutUser() {
|
||||
return fetch(formatApiPath('logout'), {
|
||||
method: 'GET',
|
||||
credentials: 'include',
|
||||
}).then(throwIfNotSuccess);
|
||||
}
|
||||
|
||||
function fetchUser() {
|
||||
return fetch(URI, { credentials: 'include' })
|
||||
.then(throwIfNotSuccess)
|
||||
@ -53,7 +46,6 @@ const api = {
|
||||
fetchUser,
|
||||
insecureLogin,
|
||||
demoLogin,
|
||||
logoutUser,
|
||||
passwordLogin,
|
||||
};
|
||||
|
||||
|
@ -1985,6 +1985,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
|
||||
integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==
|
||||
|
||||
"@types/http-proxy@^1.17.5":
|
||||
version "1.17.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.6.tgz#62dc3fade227d6ac2862c8f19ee0da9da9fd8616"
|
||||
integrity sha512-+qsjqR75S/ib0ig0R9WN+CDoZeOBU6F2XLewgC4KVgdXiNHiKKHFEMRHOrs5PbYE97D5vataw5wPj4KLYfUkuQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
|
||||
@ -6276,7 +6283,18 @@ http-proxy-middleware@0.19.1:
|
||||
lodash "^4.17.11"
|
||||
micromatch "^3.1.10"
|
||||
|
||||
http-proxy@^1.17.0:
|
||||
http-proxy-middleware@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz#7ef3417a479fb7666a571e09966c66a39bd2c15f"
|
||||
integrity sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg==
|
||||
dependencies:
|
||||
"@types/http-proxy" "^1.17.5"
|
||||
http-proxy "^1.18.1"
|
||||
is-glob "^4.0.1"
|
||||
is-plain-obj "^3.0.0"
|
||||
micromatch "^4.0.2"
|
||||
|
||||
http-proxy@^1.17.0, http-proxy@^1.18.1:
|
||||
version "1.18.1"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
|
||||
integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
|
||||
@ -6760,6 +6778,11 @@ is-plain-obj@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
|
||||
|
||||
is-plain-obj@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
|
||||
integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==
|
||||
|
||||
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
||||
@ -12709,4 +12732,4 @@ yargs@^15.4.1:
|
||||
yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
Loading…
Reference in New Issue
Block a user