mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-27 00:19:39 +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-adapter-react-16": "^1.15.6",
|
||||||
"enzyme-to-json": "^3.6.1",
|
"enzyme-to-json": "^3.6.1",
|
||||||
"fetch-mock": "^9.11.0",
|
"fetch-mock": "^9.11.0",
|
||||||
|
"http-proxy-middleware": "^2.0.1",
|
||||||
"immutable": "^4.0.0-rc.12",
|
"immutable": "^4.0.0-rc.12",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"lodash.flow": "^3.5.0",
|
"lodash.flow": "^3.5.0",
|
||||||
@ -109,6 +110,5 @@
|
|||||||
"no-useless-computed-key": "off",
|
"no-useless-computed-key": "off",
|
||||||
"import/no-anonymous-default-export": "off"
|
"import/no-anonymous-default-export": "off"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"proxy": "http://localhost:4242"
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
export const P = 'P';
|
export const P = 'P';
|
||||||
export const C = 'C';
|
export const C = 'C';
|
||||||
export const RBAC = 'RBAC';
|
export const RBAC = 'RBAC';
|
||||||
export const OIDC = 'OIDC';
|
|
||||||
|
|
||||||
export const PROJECTFILTERING = false;
|
export const PROJECTFILTERING = false;
|
||||||
|
@ -83,12 +83,5 @@ Array [
|
|||||||
"title": "Admin",
|
"title": "Admin",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
Object {
|
|
||||||
"component": [Function],
|
|
||||||
"layout": "main",
|
|
||||||
"path": "/logout",
|
|
||||||
"title": "Sign out",
|
|
||||||
"type": "unprotected",
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
`;
|
`;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { baseRoutes, getRoute } from '../routes';
|
import { baseRoutes, getRoute } from '../routes';
|
||||||
|
|
||||||
test('returns all baseRoutes', () => {
|
test('returns all baseRoutes', () => {
|
||||||
expect(baseRoutes.length).toEqual(12);
|
expect(baseRoutes).toHaveLength(11);
|
||||||
expect(baseRoutes).toMatchSnapshot();
|
expect(baseRoutes).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
|
import React from 'react';
|
||||||
import { Divider, Drawer, List } from '@material-ui/core';
|
import { Divider, Drawer, List } from '@material-ui/core';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import GitHubIcon from '@material-ui/icons/GitHub';
|
import GitHubIcon from '@material-ui/icons/GitHub';
|
||||||
import LibraryBooksIcon from '@material-ui/icons/LibraryBooks';
|
import LibraryBooksIcon from '@material-ui/icons/LibraryBooks';
|
||||||
|
import ExitToApp from '@material-ui/icons/ExitToApp';
|
||||||
|
|
||||||
import styles from './drawer.module.scss';
|
import styles from './drawer.module.scss';
|
||||||
|
|
||||||
import { ReactComponent as LogoIcon } from '../../assets/icons/logo_wbg.svg';
|
import { ReactComponent as LogoIcon } from '../../assets/icons/logo_wbg.svg';
|
||||||
import NavigationLink from './Header/NavigationLink/NavigationLink';
|
import NavigationLink from './Header/NavigationLink/NavigationLink';
|
||||||
import ConditionallyRender from '../common/ConditionallyRender';
|
import ConditionallyRender from '../common/ConditionallyRender';
|
||||||
|
import { getBasePath } from '../../utils/format-path';
|
||||||
|
|
||||||
export const DrawerMenu = ({
|
export const DrawerMenu = ({
|
||||||
links = [],
|
links = [],
|
||||||
@ -88,7 +91,13 @@ export const DrawerMenu = ({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Divider />
|
<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>
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
);
|
);
|
||||||
|
@ -14,7 +14,6 @@ import ApplicationView from '../../page/applications/view';
|
|||||||
import ContextFields from '../../page/context';
|
import ContextFields from '../../page/context';
|
||||||
import CreateContextField from '../../page/context/create';
|
import CreateContextField from '../../page/context/create';
|
||||||
import EditContextField from '../../page/context/edit';
|
import EditContextField from '../../page/context/edit';
|
||||||
import LogoutFeatures from '../../page/user/logout';
|
|
||||||
import CreateProject from '../../page/project/create';
|
import CreateProject from '../../page/project/create';
|
||||||
import EditProject from '../../page/project/edit';
|
import EditProject from '../../page/project/edit';
|
||||||
import ViewProject from '../../page/project/view';
|
import ViewProject from '../../page/project/view';
|
||||||
@ -342,13 +341,6 @@ export const routes = [
|
|||||||
type: 'protected',
|
type: 'protected',
|
||||||
layout: 'main',
|
layout: 'main',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/logout',
|
|
||||||
title: 'Sign out',
|
|
||||||
component: LogoutFeatures,
|
|
||||||
type: 'unprotected',
|
|
||||||
layout: 'main',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
title: 'Log in',
|
title: 'Log in',
|
||||||
|
@ -14,7 +14,6 @@ const UserProfile = ({
|
|||||||
location,
|
location,
|
||||||
fetchUser,
|
fetchUser,
|
||||||
updateSettingLocation,
|
updateSettingLocation,
|
||||||
logoutUser,
|
|
||||||
}) => {
|
}) => {
|
||||||
const [showProfile, setShowProfile] = useState(false);
|
const [showProfile, setShowProfile] = useState(false);
|
||||||
const [currentLocale, setCurrentLocale] = useState([]);
|
const [currentLocale, setCurrentLocale] = useState([]);
|
||||||
@ -74,7 +73,6 @@ const UserProfile = ({
|
|||||||
profile={profile}
|
profile={profile}
|
||||||
updateSettingLocation={updateSettingLocation}
|
updateSettingLocation={updateSettingLocation}
|
||||||
possibleLocales={possibleLocales}
|
possibleLocales={possibleLocales}
|
||||||
logoutUser={logoutUser}
|
|
||||||
location={location}
|
location={location}
|
||||||
setCurrentLocale={setCurrentLocale}
|
setCurrentLocale={setCurrentLocale}
|
||||||
currentLocale={currentLocale}
|
currentLocale={currentLocale}
|
||||||
|
@ -17,6 +17,7 @@ import { Alert } from '@material-ui/lab';
|
|||||||
import EditProfile from '../EditProfile/EditProfile';
|
import EditProfile from '../EditProfile/EditProfile';
|
||||||
import legacyStyles from '../../user.module.scss';
|
import legacyStyles from '../../user.module.scss';
|
||||||
import usePermissions from '../../../../hooks/usePermissions';
|
import usePermissions from '../../../../hooks/usePermissions';
|
||||||
|
import { getBasePath } from '../../../../utils/format-path';
|
||||||
|
|
||||||
const UserProfileContent = ({
|
const UserProfileContent = ({
|
||||||
showProfile,
|
showProfile,
|
||||||
@ -26,7 +27,6 @@ const UserProfileContent = ({
|
|||||||
imageUrl,
|
imageUrl,
|
||||||
currentLocale,
|
currentLocale,
|
||||||
setCurrentLocale,
|
setCurrentLocale,
|
||||||
logoutUser,
|
|
||||||
}) => {
|
}) => {
|
||||||
const commonStyles = useCommonStyles();
|
const commonStyles = useCommonStyles();
|
||||||
const [updatedPassword, setUpdatedPassword] = useState(false);
|
const [updatedPassword, setUpdatedPassword] = useState(false);
|
||||||
@ -155,7 +155,7 @@ const UserProfileContent = ({
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={logoutUser}
|
href={`${getBasePath()}/logout`}
|
||||||
>
|
>
|
||||||
Logout
|
Logout
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import UserProfile from './UserProfile';
|
import UserProfile from './UserProfile';
|
||||||
import { fetchUser, logoutUser } from '../../../store/user/actions';
|
import { fetchUser } from '../../../store/user/actions';
|
||||||
import { updateSettingForGroup } from '../../../store/settings/actions';
|
import { updateSettingForGroup } from '../../../store/settings/actions';
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
fetchUser,
|
fetchUser,
|
||||||
logoutUser,
|
|
||||||
updateSettingLocation: updateSettingForGroup('location'),
|
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 PageContent from '../../../component/common/PageContent/PageContent';
|
||||||
import ConditionallyRender from '../../../component/common/ConditionallyRender/ConditionallyRender';
|
import ConditionallyRender from '../../../component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
function AdminAuthPage({ authenticationType, history, enableOIDC }) {
|
function AdminAuthPage({ authenticationType, history }) {
|
||||||
const tabs = [
|
const tabs = [
|
||||||
|
{
|
||||||
|
label: 'OpenID Connect',
|
||||||
|
component: <OidcAuth />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'SAML 2.0',
|
label: 'SAML 2.0',
|
||||||
component: <SamlAuth />,
|
component: <SamlAuth />,
|
||||||
@ -21,13 +25,6 @@ function AdminAuthPage({ authenticationType, history, enableOIDC }) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if(enableOIDC) {
|
|
||||||
tabs.unshift( {
|
|
||||||
label: 'OpenID Connect',
|
|
||||||
component: <OidcAuth />,
|
|
||||||
},)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu history={history} />
|
<AdminMenu history={history} />
|
||||||
@ -71,7 +68,6 @@ AdminAuthPage.propTypes = {
|
|||||||
match: PropTypes.object.isRequired,
|
match: PropTypes.object.isRequired,
|
||||||
history: PropTypes.object.isRequired,
|
history: PropTypes.object.isRequired,
|
||||||
authenticationType: PropTypes.string,
|
authenticationType: PropTypes.string,
|
||||||
enableOIDC: PropTypes.bool,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AdminAuthPage;
|
export default AdminAuthPage;
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import component from './authentication';
|
import component from './authentication';
|
||||||
import { OIDC } from '../../../component/common/flags';
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
authenticationType: state.uiConfig.toJS().authenticationType,
|
authenticationType: state.uiConfig.toJS().authenticationType,
|
||||||
enableOIDC: !!state.uiConfig.toJS().flags[OIDC],
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const Container = connect(mapStateToProps, { })(component);
|
const Container = connect(mapStateToProps, { })(component);
|
||||||
|
@ -132,7 +132,7 @@ function SamlAuth({ config, getSamlConfig, updateSamlConfig, unleashUrl }) {
|
|||||||
label="Single Sign-On URL"
|
label="Single Sign-On URL"
|
||||||
name="signOnUrl"
|
name="signOnUrl"
|
||||||
value={data.signOnUrl || ''}
|
value={data.signOnUrl || ''}
|
||||||
style={{ width: '400px' }}
|
style={{ width: '400px'}}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
size="small"
|
size="small"
|
||||||
required
|
required
|
||||||
@ -153,11 +153,12 @@ function SamlAuth({ config, getSamlConfig, updateSamlConfig, unleashUrl }) {
|
|||||||
label="X.509 Certificate"
|
label="X.509 Certificate"
|
||||||
name="certificate"
|
name="certificate"
|
||||||
value={data.certificate || ''}
|
value={data.certificate || ''}
|
||||||
style={{
|
style={{width: '100%'}}
|
||||||
width: '100%',
|
InputProps={{
|
||||||
fontSize: '0.7em',
|
style: {
|
||||||
|
fontSize: '0.6em',
|
||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
}}
|
}}}
|
||||||
multiline
|
multiline
|
||||||
rows={14}
|
rows={14}
|
||||||
rowsMax={14}
|
rowsMax={14}
|
||||||
@ -167,6 +168,55 @@ function SamlAuth({ config, getSamlConfig, updateSamlConfig, unleashUrl }) {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</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 container spacing={3}>
|
||||||
<Grid item md={5}>
|
<Grid item md={5}>
|
||||||
<strong>Auto-create users</strong>
|
<strong>Auto-create users</strong>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ProjectList from '../../component/project/ProjectList';
|
import ProjectList from '../../component/project/ProjectList/ProjectList';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const render = ({ history }) => <ProjectList history={history} />;
|
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 api from './api';
|
||||||
import { dispatchError } from '../util';
|
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_CHANGE_CURRENT = 'USER_CHANGE_CURRENT';
|
||||||
export const USER_LOGOUT = 'USER_LOGOUT';
|
export const USER_LOGOUT = 'USER_LOGOUT';
|
||||||
export const USER_LOGIN = 'USER_LOGIN';
|
export const USER_LOGIN = 'USER_LOGIN';
|
||||||
@ -62,17 +60,3 @@ export function passwordLogin(path, user) {
|
|||||||
.then(() => dispatch({ type: USER_LOGIN }));
|
.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');
|
const URI = formatApiPath('api/admin/user');
|
||||||
|
|
||||||
function logoutUser() {
|
|
||||||
return fetch(formatApiPath('logout'), {
|
|
||||||
method: 'GET',
|
|
||||||
credentials: 'include',
|
|
||||||
}).then(throwIfNotSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchUser() {
|
function fetchUser() {
|
||||||
return fetch(URI, { credentials: 'include' })
|
return fetch(URI, { credentials: 'include' })
|
||||||
.then(throwIfNotSuccess)
|
.then(throwIfNotSuccess)
|
||||||
@ -53,7 +46,6 @@ const api = {
|
|||||||
fetchUser,
|
fetchUser,
|
||||||
insecureLogin,
|
insecureLogin,
|
||||||
demoLogin,
|
demoLogin,
|
||||||
logoutUser,
|
|
||||||
passwordLogin,
|
passwordLogin,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1985,6 +1985,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
|
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
|
||||||
integrity sha512-giAlZwstKbmvMk1OO7WXSj4OZ0keXAcl2TQq4LWHiiPH2ByaH7WeUzng+Qej8UPxxv+8lRTuouo0iaNDBuzIBA==
|
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":
|
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
|
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"
|
lodash "^4.17.11"
|
||||||
micromatch "^3.1.10"
|
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"
|
version "1.18.1"
|
||||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
|
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
|
||||||
integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
|
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"
|
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||||
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
|
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:
|
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
|
||||||
|
Loading…
Reference in New Issue
Block a user