Switch to a logged out state when auth tokens expire (#2290)
This commit is contained in:
Родитель
0640cfa76f
Коммит
2f480b474f
|
@ -104,4 +104,9 @@ module.exports = {
|
|||
|
||||
// https://sentry.prod.mozaws.net/operations/addons-frontend-amo-prod/
|
||||
publicSentryDsn: 'https://dbce4e759d8b4dc6a1731d3301fdaab7@sentry.prod.mozaws.net/183',
|
||||
|
||||
// The amount of time (in seconds) that an auth token lives for.
|
||||
// This needs to match the SESSION_COOKIE_AGE in addons-server:
|
||||
// https://github.com/mozilla/addons-server/blob/master/src/olympia/lib/settings_base.py#L990
|
||||
authTokenValidFor: 2592000, // 30 days
|
||||
};
|
||||
|
|
|
@ -66,6 +66,7 @@ module.exports = {
|
|||
//
|
||||
clientConfigKeys: [
|
||||
'allowErrorSimulation',
|
||||
'authTokenValidFor',
|
||||
'amoCDN',
|
||||
'apiHost',
|
||||
'apiPath',
|
||||
|
@ -238,4 +239,8 @@ module.exports = {
|
|||
|
||||
sentryDsn: process.env.SENTRY_DSN || null,
|
||||
publicSentryDsn: null,
|
||||
|
||||
// The amount of time (in seconds) that an auth token lives for. This is
|
||||
// currently only used in AMO.
|
||||
authTokenValidFor: null,
|
||||
};
|
||||
|
|
|
@ -175,6 +175,7 @@
|
|||
"dependencies": {
|
||||
"babel-plugin-dedent": "2.0.0",
|
||||
"babel-polyfill": "6.20.0",
|
||||
"base62": "1.1.2",
|
||||
"base64url": "2.0.0",
|
||||
"better-npm-run": "0.0.15",
|
||||
"bunyan": "1.8.10",
|
||||
|
|
|
@ -167,7 +167,7 @@ export class RatingManagerBase extends React.Component {
|
|||
|
||||
return (
|
||||
<div className="RatingManager">
|
||||
{showTextEntry ?
|
||||
{showTextEntry && isLoggedIn ?
|
||||
<AddonReview
|
||||
onReviewSubmitted={onReviewSubmitted}
|
||||
review={userReview}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/* global navigator, window */
|
||||
/* @flow */
|
||||
/* eslint-disable react/sort-comp */
|
||||
/* global $PropertyType, Event, Navigator, Node, navigator, window */
|
||||
import config from 'config';
|
||||
import React, { PropTypes } from 'react';
|
||||
import { oneLine } from 'common-tags';
|
||||
import React from 'react';
|
||||
import cookie from 'react-cookie';
|
||||
import Helmet from 'react-helmet';
|
||||
import { connect } from 'react-redux';
|
||||
|
@ -8,39 +11,55 @@ import LoadingBar from 'react-redux-loading-bar';
|
|||
import { compose } from 'redux';
|
||||
|
||||
import SearchForm from 'amo/components/SearchForm';
|
||||
import { getErrorComponent } from 'amo/utils';
|
||||
import { getDjangoBase62, getErrorComponent } from 'amo/utils';
|
||||
import Footer from 'amo/components/Footer';
|
||||
import MastHead from 'amo/components/MastHead';
|
||||
import { addChangeListeners } from 'core/addonManager';
|
||||
import { setUserAgent as setUserAgentAction } from 'core/actions';
|
||||
import { INSTALL_STATE } from 'core/constants';
|
||||
import {
|
||||
logOutUser as logOutUserAction, setUserAgent as setUserAgentAction,
|
||||
} from 'core/actions';
|
||||
import { INSTALL_STATE, maximumSetTimeoutDelay } from 'core/constants';
|
||||
import DefaultErrorPage from 'core/components/ErrorPage';
|
||||
import InfoDialog from 'core/containers/InfoDialog';
|
||||
import translate from 'core/i18n/translate';
|
||||
import log from 'core/logger';
|
||||
import type { UrlFormatParams } from 'core/api';
|
||||
import type { ApiStateType } from 'core/reducers/api';
|
||||
import type { DispatchFunc } from 'core/types/redux';
|
||||
import type { InstalledAddon } from 'core/reducers/installations';
|
||||
|
||||
import 'amo/css/App.scss';
|
||||
import 'core/fonts/fira.scss';
|
||||
|
||||
interface MozNavigator extends Navigator {
|
||||
mozAddonManager?: Object,
|
||||
}
|
||||
|
||||
type AppProps = {
|
||||
ErrorPage: typeof DefaultErrorPage,
|
||||
FooterComponent: typeof Footer,
|
||||
InfoDialogComponent: typeof InfoDialog,
|
||||
MastHeadComponent: typeof MastHead,
|
||||
_addChangeListeners: () => void,
|
||||
_navigator: typeof navigator,
|
||||
authToken?: string,
|
||||
authTokenValidFor?: number,
|
||||
children: any,
|
||||
clientApp: string,
|
||||
handleGlobalEvent: () => void,
|
||||
i18n: Object,
|
||||
lang: string,
|
||||
location: UrlFormatParams,
|
||||
logOutUser: () => void,
|
||||
mozAddonManager: $PropertyType<MozNavigator, 'mozAddonManager'>,
|
||||
setUserAgent: () => void,
|
||||
userAgent: string,
|
||||
}
|
||||
|
||||
export class AppBase extends React.Component {
|
||||
static propTypes = {
|
||||
ErrorPage: PropTypes.node.isRequired,
|
||||
FooterComponent: PropTypes.node.isRequired,
|
||||
InfoDialogComponent: PropTypes.node.isRequired,
|
||||
MastHeadComponent: PropTypes.node.isRequired,
|
||||
_addChangeListeners: PropTypes.func,
|
||||
_navigator: PropTypes.object,
|
||||
children: PropTypes.node,
|
||||
clientApp: PropTypes.string.isRequired,
|
||||
handleGlobalEvent: PropTypes.func.isRequired,
|
||||
i18n: PropTypes.object.isRequired,
|
||||
lang: PropTypes.string.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
mozAddonManager: PropTypes.object,
|
||||
setUserAgent: PropTypes.func.isRequired,
|
||||
userAgent: PropTypes.string,
|
||||
}
|
||||
mastHead: Node;
|
||||
props: AppProps;
|
||||
scheduledLogout: number;
|
||||
|
||||
static defaultProps = {
|
||||
ErrorPage: DefaultErrorPage,
|
||||
|
@ -49,7 +68,9 @@ export class AppBase extends React.Component {
|
|||
MastHeadComponent: MastHead,
|
||||
_addChangeListeners: addChangeListeners,
|
||||
_navigator: (typeof navigator !== 'undefined' ? navigator : null),
|
||||
mozAddonManager: config.get('server') ? {} : navigator.mozAddonManager,
|
||||
authTokenValidFor: config.get('authTokenValidFor'),
|
||||
mozAddonManager:
|
||||
config.get('server') ? {} : (navigator: MozNavigator).mozAddonManager,
|
||||
userAgent: null,
|
||||
}
|
||||
|
||||
|
@ -57,6 +78,7 @@ export class AppBase extends React.Component {
|
|||
const {
|
||||
_addChangeListeners,
|
||||
_navigator,
|
||||
authToken,
|
||||
handleGlobalEvent,
|
||||
mozAddonManager,
|
||||
setUserAgent,
|
||||
|
@ -74,13 +96,85 @@ export class AppBase extends React.Component {
|
|||
'userAgent not in state on App load; using navigator.userAgent.');
|
||||
setUserAgent(_navigator.userAgent);
|
||||
}
|
||||
|
||||
if (authToken) {
|
||||
this.setLogOutTimer(authToken);
|
||||
}
|
||||
}
|
||||
|
||||
onViewDesktop = (event, { window_ = window, cookie_ = cookie } = {}) => {
|
||||
componentWillReceiveProps(nextProps: AppProps) {
|
||||
const { authToken } = nextProps;
|
||||
if (authToken) {
|
||||
this.setLogOutTimer(authToken);
|
||||
}
|
||||
}
|
||||
|
||||
setLogOutTimer(authToken: string) {
|
||||
const { authTokenValidFor, logOutUser } = this.props;
|
||||
const expiresAt = authTokenValidFor;
|
||||
if (!expiresAt) {
|
||||
log.warn(oneLine`configured authTokenValidFor is falsey, not
|
||||
checking for auth expiration`);
|
||||
return;
|
||||
}
|
||||
|
||||
const parts = authToken.split(':');
|
||||
const encodedTimestamp = parts[1];
|
||||
const base62 = getDjangoBase62();
|
||||
let createdAt;
|
||||
try {
|
||||
// This is a UTC Unix timestamp.
|
||||
createdAt = base62.decode(encodedTimestamp);
|
||||
} catch (base62Error) {
|
||||
log.error(
|
||||
`Auth token "${encodedTimestamp}" triggered this base62 error: "${base62Error}"`);
|
||||
return;
|
||||
}
|
||||
// If the encoded timestamp was malformed it will be 0 or negative.
|
||||
if (createdAt <= 0) {
|
||||
log.error(oneLine`Got an invalid timestamp from auth token;
|
||||
encoded value: ${encodedTimestamp}; decoded value: ${createdAt}`);
|
||||
return;
|
||||
}
|
||||
const readableCreatedAt = new Date(createdAt * 1000).toString();
|
||||
log.debug(`Auth token was created at: ${readableCreatedAt}`);
|
||||
|
||||
// Get the current UTC Unix timestamp.
|
||||
const now = Date.now() / 1000;
|
||||
// Set the expiration time in seconds.
|
||||
const expirationTime = (createdAt + expiresAt) - now;
|
||||
const readableExpiration =
|
||||
new Date((now + expirationTime) * 1000).toString();
|
||||
log.debug(`Auth token expires at ${readableExpiration}`);
|
||||
|
||||
const setTimeoutDelay = expirationTime * 1000;
|
||||
if (setTimeoutDelay >= maximumSetTimeoutDelay) {
|
||||
log.debug(oneLine`No logout was scheduled because the expiration
|
||||
exceeded the setTimeout limit`);
|
||||
return;
|
||||
}
|
||||
if (this.scheduledLogout) {
|
||||
clearTimeout(this.scheduledLogout);
|
||||
}
|
||||
log.info('Setting a logout timer for when the token expires');
|
||||
this.scheduledLogout = setTimeout(() => {
|
||||
log.info('Logging out because the auth token has expired');
|
||||
logOutUser();
|
||||
}, setTimeoutDelay);
|
||||
}
|
||||
|
||||
onViewDesktop = (
|
||||
event: Event,
|
||||
{
|
||||
_window = window, _cookie = cookie,
|
||||
}: {|
|
||||
_window: typeof window, _cookie: typeof cookie,
|
||||
|} = {}
|
||||
) => {
|
||||
event.preventDefault();
|
||||
if (window_ && window_.location) {
|
||||
cookie_.save('mamo', 'off', { path: '/' });
|
||||
window_.location.reload();
|
||||
if (_window && _window.location) {
|
||||
_cookie.save('mamo', 'off', { path: '/' });
|
||||
_window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,18 +214,22 @@ export class AppBase extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export const mapStateToProps = (state) => ({
|
||||
export const mapStateToProps = (state: { api: ApiStateType }) => ({
|
||||
authToken: state.api && state.api.token,
|
||||
clientApp: state.api.clientApp,
|
||||
lang: state.api.lang,
|
||||
userAgent: state.api.userAgent,
|
||||
});
|
||||
|
||||
export function mapDispatchToProps(dispatch) {
|
||||
export function mapDispatchToProps(dispatch: DispatchFunc) {
|
||||
return {
|
||||
handleGlobalEvent(payload) {
|
||||
logOutUser() {
|
||||
dispatch(logOutUserAction());
|
||||
},
|
||||
handleGlobalEvent(payload: InstalledAddon) {
|
||||
dispatch({ type: INSTALL_STATE, payload });
|
||||
},
|
||||
setUserAgent(userAgent) {
|
||||
setUserAgent(userAgent: string) {
|
||||
dispatch(setUserAgentAction(userAgent));
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import base62 from 'base62';
|
||||
|
||||
import {
|
||||
FEATURED_ADDONS_TO_LOAD,
|
||||
LANDING_PAGE_ADDON_COUNT,
|
||||
|
@ -73,3 +75,17 @@ export function getErrorComponent(status) {
|
|||
return ServerError;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a base62 object that encodes/decodes just like how Django does it
|
||||
* for cookie timestamps.
|
||||
*
|
||||
* See:
|
||||
* https://github.com/django/django/blob/0b9f366c60134a0ca2873c156b9c80acb7ffd8b5/django/core/signing.py#L180
|
||||
*/
|
||||
export function getDjangoBase62() {
|
||||
// This is the alphabet used by Django.
|
||||
base62.setCharacterSet(
|
||||
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
|
||||
return base62;
|
||||
}
|
||||
|
|
|
@ -173,3 +173,9 @@ export const ERROR_UNKNOWN = 'ERROR_UNKNOWN';
|
|||
export const API_ERROR_DECODING_SIGNATURE = 'ERROR_DECODING_SIGNATURE';
|
||||
export const API_ERROR_INVALID_HEADER = 'ERROR_INVALID_HEADER';
|
||||
export const API_ERROR_SIGNATURE_EXPIRED = 'ERROR_SIGNATURE_EXPIRED';
|
||||
|
||||
// This is the limit in milleseconds for how long a setTimeout delay can be.
|
||||
// No setTimeout should be scheduled for this time because it
|
||||
// will be triggered immediately.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Maximum_delay_value
|
||||
export const maximumSetTimeoutDelay = 2147483647;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/* @flow */
|
||||
/* global Node, $PropertyType */
|
||||
import {
|
||||
DOWNLOAD_PROGRESS,
|
||||
DOWNLOADING,
|
||||
|
@ -13,86 +15,117 @@ import {
|
|||
UNINSTALLED,
|
||||
UNINSTALL_COMPLETE,
|
||||
} from 'core/constants';
|
||||
import log from 'core/logger';
|
||||
import type { AddonType } from 'core/types/addons';
|
||||
|
||||
export type InstalledAddon = {
|
||||
downloadProgress?: number,
|
||||
error?: string,
|
||||
guid: $PropertyType<AddonType, 'guid'>,
|
||||
isPreviewingTheme?: boolean,
|
||||
needsRestart?: boolean,
|
||||
status?: $PropertyType<AddonType, 'status'>,
|
||||
themePreviewNode?: Node,
|
||||
url?: $PropertyType<AddonType, 'url'>,
|
||||
};
|
||||
|
||||
export function loadAddon({ guid, state }) {
|
||||
if (state[guid]) {
|
||||
return { ...state[guid] };
|
||||
type InstallationAction = {|
|
||||
payload: InstalledAddon,
|
||||
type: string,
|
||||
|};
|
||||
|
||||
type InstallationState = {
|
||||
[guid: $PropertyType<AddonType, 'guid'>]: InstalledAddon,
|
||||
};
|
||||
|
||||
export default function installations(
|
||||
state: InstallationState = {}, { type, payload }: InstallationAction,
|
||||
) {
|
||||
function updateAddon(newProps: Object): InstalledAddon {
|
||||
const guid = payload.guid;
|
||||
const addon = state[guid];
|
||||
if (!addon) {
|
||||
throw new Error(
|
||||
`Cannot reduce type ${type}; no add-on with guid ${guid} found.`);
|
||||
}
|
||||
return {
|
||||
...addon,
|
||||
...newProps,
|
||||
};
|
||||
}
|
||||
|
||||
log.warn(`No add-on with guid ${guid} found.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
export default function installations(state = {}, { type, payload }) {
|
||||
let addon;
|
||||
|
||||
switch (type) {
|
||||
case INSTALL_STATE:
|
||||
addon = {
|
||||
guid: payload.guid,
|
||||
url: payload.url,
|
||||
error: payload.error,
|
||||
downloadProgress: 0,
|
||||
status: payload.status,
|
||||
needsRestart: payload.needsRestart || false,
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: {
|
||||
guid: payload.guid,
|
||||
url: payload.url,
|
||||
error: payload.error,
|
||||
downloadProgress: 0,
|
||||
status: payload.status,
|
||||
needsRestart: payload.needsRestart || false,
|
||||
},
|
||||
};
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
case START_DOWNLOAD:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.status = DOWNLOADING;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
status: DOWNLOADING,
|
||||
}),
|
||||
};
|
||||
case DOWNLOAD_PROGRESS:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.downloadProgress = payload.downloadProgress;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
downloadProgress: payload.downloadProgress,
|
||||
}),
|
||||
};
|
||||
case INSTALL_COMPLETE:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.status = INSTALLED;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
status: INSTALLED,
|
||||
}),
|
||||
};
|
||||
case UNINSTALL_COMPLETE:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.status = UNINSTALLED;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
status: UNINSTALLED,
|
||||
}),
|
||||
};
|
||||
case INSTALL_CANCELLED:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.downloadProgress = 0;
|
||||
addon.status = UNINSTALLED;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
/* istanbul ignore case */
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
downloadProgress: 0,
|
||||
status: UNINSTALLED,
|
||||
}),
|
||||
};
|
||||
case INSTALL_ERROR:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.downloadProgress = 0;
|
||||
addon.status = ERROR;
|
||||
addon.error = payload.error;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
downloadProgress: 0,
|
||||
error: payload.error,
|
||||
status: ERROR,
|
||||
}),
|
||||
};
|
||||
case THEME_PREVIEW:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.isPreviewingTheme = true;
|
||||
addon.themePreviewNode = payload.themePreviewNode;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
isPreviewingTheme: true,
|
||||
themePreviewNode: payload.themePreviewNode,
|
||||
}),
|
||||
};
|
||||
case THEME_RESET_PREVIEW:
|
||||
addon = loadAddon({ guid: payload.guid, state });
|
||||
|
||||
addon.isPreviewingTheme = false;
|
||||
|
||||
return { ...state, [payload.guid]: addon };
|
||||
return {
|
||||
...state,
|
||||
[payload.guid]: updateAddon({
|
||||
isPreviewingTheme: false,
|
||||
}),
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -180,6 +180,22 @@ describe('RatingManager', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('does not render an AddonReview when logged out', () => {
|
||||
const userReview = setReview(fakeReview).payload;
|
||||
const FakeAddonReview = sinon.spy(() => <div />);
|
||||
const userId = null; // logged out
|
||||
const root = render({ AddonReview: FakeAddonReview, userReview, userId });
|
||||
|
||||
assert.equal(FakeAddonReview.called, false,
|
||||
'expected AddonReview to initially not be visible');
|
||||
|
||||
return root.onSelectRating(5)
|
||||
.then(() => {
|
||||
assert.notOk(
|
||||
FakeAddonReview.called, 'AddonReview was rendered unexpectedly');
|
||||
});
|
||||
});
|
||||
|
||||
it('configures a rating component', () => {
|
||||
const userReview = setReview(fakeReview).payload;
|
||||
const RatingStub = sinon.spy(() => (<div />));
|
||||
|
|
|
@ -14,15 +14,16 @@ import {
|
|||
} from 'amo/containers/App';
|
||||
import createStore from 'amo/store';
|
||||
import {
|
||||
logOutUser as logOutUserAction,
|
||||
setClientApp,
|
||||
setLang,
|
||||
setUserAgent as setUserAgentAction,
|
||||
} from 'core/actions';
|
||||
import { createApiError } from 'core/api';
|
||||
import DefaultErrorPage from 'core/components/ErrorPage';
|
||||
import { INSTALL_STATE } from 'core/constants';
|
||||
import { INSTALL_STATE, maximumSetTimeoutDelay } from 'core/constants';
|
||||
import I18nProvider from 'core/i18n/Provider';
|
||||
import { getFakeI18nInst } from 'tests/client/helpers';
|
||||
import { getFakeI18nInst, userAuthToken } from 'tests/client/helpers';
|
||||
|
||||
|
||||
describe('App', () => {
|
||||
|
@ -60,6 +61,7 @@ describe('App', () => {
|
|||
function render({ children = [], ...customProps } = {}) {
|
||||
const props = {
|
||||
i18n: getFakeI18nInst(),
|
||||
logOutUser: sinon.stub(),
|
||||
location: sinon.stub(),
|
||||
isAuthenticated: true,
|
||||
store: createStore(),
|
||||
|
@ -110,7 +112,7 @@ describe('App', () => {
|
|||
};
|
||||
|
||||
const root = render();
|
||||
root.onViewDesktop(fakeEvent, { window_: fakeWindow, cookie_: fakeCookieLib });
|
||||
root.onViewDesktop(fakeEvent, { _window: fakeWindow, _cookie: fakeCookieLib });
|
||||
assert.ok(fakeEvent.preventDefault.called);
|
||||
assert.ok(fakeCookieLib.save.calledWith('mamo', 'off'));
|
||||
assert.ok(fakeWindow.location.reload.called);
|
||||
|
@ -204,4 +206,130 @@ describe('App', () => {
|
|||
|
||||
assert.include(rootNode.textContent, 'Page not found');
|
||||
});
|
||||
|
||||
describe('handling expired auth tokens', () => {
|
||||
let clock;
|
||||
|
||||
function renderAppWithAuth(customProps = {}) {
|
||||
const props = {
|
||||
authToken: userAuthToken(),
|
||||
logOutUser: sinon.stub(),
|
||||
...customProps,
|
||||
};
|
||||
return render(props);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
clock = sinon.useFakeTimers(Date.now());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clock.restore();
|
||||
});
|
||||
|
||||
it('logs out when the token expires', () => {
|
||||
const authTokenValidFor = 10; // seconds
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
renderAppWithAuth({ authTokenValidFor, logOutUser });
|
||||
|
||||
const fuzz = 3; // account for the rounded offset calculation.
|
||||
clock.tick((authTokenValidFor + fuzz) * 1000);
|
||||
assert.ok(logOutUser.called, 'expected logOutUser() to be called');
|
||||
});
|
||||
|
||||
it('only sets one timer when receiving new props', () => {
|
||||
const authTokenValidFor = 10; // seconds
|
||||
const authToken = userAuthToken();
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
const root = render({ authToken, authTokenValidFor, logOutUser });
|
||||
// Simulate updating the component with new properties.
|
||||
root.componentWillReceiveProps({ authToken });
|
||||
|
||||
const fuzz = 3; // account for the rounded offset calculation.
|
||||
clock.tick((authTokenValidFor + fuzz) * 1000);
|
||||
assert.ok(logOutUser.called, 'expected logOutUser() to be called');
|
||||
assert.ok(logOutUser.calledOnce,
|
||||
'logOutUser() should only be called once');
|
||||
});
|
||||
|
||||
it('does not log out until the token expires', () => {
|
||||
const authTokenValidFor = 10; // seconds
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
renderAppWithAuth({ authTokenValidFor, logOutUser });
|
||||
|
||||
clock.tick(5 * 1000); // 5 seconds
|
||||
assert.notOk(logOutUser.called,
|
||||
'expected logOutUser() NOT to be called');
|
||||
});
|
||||
|
||||
it('only starts a timer when authTokenValidFor is configured', () => {
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
renderAppWithAuth({ authTokenValidFor: null, logOutUser });
|
||||
|
||||
clock.tick(100 * 1000);
|
||||
assert.notOk(logOutUser.called,
|
||||
'expected logOutUser() NOT to be called');
|
||||
});
|
||||
|
||||
it('ignores malformed timestamps', () => {
|
||||
const authTokenValidFor = 10; // seconds
|
||||
const authToken = userAuthToken({}, {
|
||||
tokenCreatedAt: 'bogus-timestamp',
|
||||
});
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
render({ authToken, authTokenValidFor, logOutUser });
|
||||
|
||||
clock.tick(authTokenValidFor * 1000);
|
||||
assert.notOk(logOutUser.called,
|
||||
'expected logOutUser() NOT to be called');
|
||||
});
|
||||
|
||||
it('ignores empty timestamps', () => {
|
||||
const authTokenValidFor = 10; // seconds
|
||||
const authToken = 'this-is-a-token-with-an-empty-timestamp';
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
render({ authToken, authTokenValidFor, logOutUser });
|
||||
|
||||
clock.tick(authTokenValidFor * 1000);
|
||||
assert.notOk(logOutUser.called,
|
||||
'expected logOutUser() NOT to be called');
|
||||
});
|
||||
|
||||
it('ignores malformed tokens', () => {
|
||||
const authTokenValidFor = 10; // seconds
|
||||
const authToken = 'not-auth-data:^&invalid-characters:not-a-signature';
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
render({ authToken, authTokenValidFor, logOutUser });
|
||||
|
||||
clock.tick(authTokenValidFor * 1000);
|
||||
assert.notOk(logOutUser.called,
|
||||
'expected logOutUser() NOT to be called');
|
||||
});
|
||||
|
||||
it('does not set a timeout for expirations too far in the future', () => {
|
||||
const authTokenValidFor = (maximumSetTimeoutDelay / 1000) + 1;
|
||||
const logOutUser = sinon.stub();
|
||||
|
||||
renderAppWithAuth({ authTokenValidFor, logOutUser });
|
||||
|
||||
const fuzz = 3; // account for the rounded offset calculation.
|
||||
clock.tick((authTokenValidFor + fuzz) * 1000);
|
||||
assert.notOk(logOutUser.called,
|
||||
'expected logOutUser() NOT to be called');
|
||||
});
|
||||
|
||||
it('maps a logOutUser action', () => {
|
||||
const dispatch = sinon.stub();
|
||||
const { logOutUser } = mapDispatchToProps(dispatch);
|
||||
logOutUser();
|
||||
assert.deepEqual(dispatch.firstCall.args[0], logOutUserAction());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
UNINSTALLED,
|
||||
UNINSTALLING,
|
||||
} from 'core/constants';
|
||||
import installations, { loadAddon } from 'core/reducers/installations';
|
||||
import installations from 'core/reducers/installations';
|
||||
|
||||
describe('installations reducer', () => {
|
||||
it('is an empty object by default', () => {
|
||||
|
@ -337,11 +337,16 @@ describe('installations reducer', () => {
|
|||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('installations loadAddon', () => {
|
||||
it('returns null when no add-on found', () => {
|
||||
const addon = loadAddon({ guid: '302', state: {} });
|
||||
assert.equal(addon, null);
|
||||
it('cannot update a non-existant add-on', () => {
|
||||
assert.throws(
|
||||
() => installations({}, {
|
||||
type: INSTALL_ERROR,
|
||||
payload: {
|
||||
guid: 'my-addon@me.com',
|
||||
error: 'an-error',
|
||||
},
|
||||
}),
|
||||
/no add-on with guid my-addon@me.com found/);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@ import React from 'react';
|
|||
import { createRenderer } from 'react-addons-test-utils';
|
||||
import UAParser from 'ua-parser-js';
|
||||
|
||||
import { getDjangoBase62 } from 'amo/utils';
|
||||
import { ADDON_TYPE_EXTENSION } from 'core/constants';
|
||||
import { makeI18n } from 'core/i18n/utils';
|
||||
import { initialApiState } from 'core/reducers/api';
|
||||
|
@ -13,7 +14,10 @@ import { initialApiState } from 'core/reducers/api';
|
|||
* Return a fake authentication token that can be
|
||||
* at least decoded in a realistic way.
|
||||
*/
|
||||
export function userAuthToken(dataOverrides = {}, { tokenData } = {}) {
|
||||
export function userAuthToken(
|
||||
dataOverrides = {},
|
||||
{ tokenCreatedAt = (Date.now() / 1000).toFixed(0), tokenData } = {},
|
||||
) {
|
||||
const data = {
|
||||
user_id: 102345,
|
||||
...dataOverrides,
|
||||
|
@ -23,10 +27,12 @@ export function userAuthToken(dataOverrides = {}, { tokenData } = {}) {
|
|||
if (!encodedToken) {
|
||||
encodedToken = base64url.encode(JSON.stringify(data));
|
||||
}
|
||||
const authId = base64url.encode('pretend this is an auth ID');
|
||||
const sig = base64url.encode('pretend this is a signature');
|
||||
|
||||
return `${encodedToken}:${authId}:${sig}`;
|
||||
const base62 = getDjangoBase62();
|
||||
const timestamp = base62.encode(tokenCreatedAt);
|
||||
const sig = base64url.encode('pretend-this-is-a-signature');
|
||||
|
||||
return `${encodedToken}:${timestamp}:${sig}`;
|
||||
}
|
||||
|
||||
export function shallowRender(stuff) {
|
||||
|
|
267
yarn.lock
267
yarn.lock
|
@ -36,10 +36,6 @@ acorn-jsx@^3.0.0:
|
|||
dependencies:
|
||||
acorn "^3.0.4"
|
||||
|
||||
acorn@4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a"
|
||||
|
||||
acorn@^3.0.0, acorn@^3.0.4:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
|
||||
|
@ -48,6 +44,10 @@ acorn@^4.0.4:
|
|||
version "4.0.11"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0"
|
||||
|
||||
acorn@^5.0.1:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
|
||||
|
||||
after@0.8.2:
|
||||
version "0.8.2"
|
||||
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
|
||||
|
@ -57,8 +57,8 @@ ajv-keywords@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
|
||||
|
||||
ajv@^4.7.0, ajv@^4.9.1:
|
||||
version "4.11.5"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.5.tgz#b6ee74657b993a01dce44b7944d56f485828d5bd"
|
||||
version "4.11.7"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.7.tgz#8655a5d86d0824985cc471a1d913fb6729a0ec48"
|
||||
dependencies:
|
||||
co "^4.6.0"
|
||||
json-stable-stringify "^1.0.1"
|
||||
|
@ -119,11 +119,11 @@ aproba@^1.0.3:
|
|||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.1.tgz#95d3600f07710aa0e9298c726ad5ecf2eacbabab"
|
||||
|
||||
are-we-there-yet@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3"
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
|
||||
dependencies:
|
||||
delegates "^1.0.0"
|
||||
readable-stream "^2.0.0 || ^1.1.13"
|
||||
readable-stream "^2.0.6"
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.9"
|
||||
|
@ -138,8 +138,8 @@ arr-diff@^2.0.0:
|
|||
arr-flatten "^1.0.1"
|
||||
|
||||
arr-flatten@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b"
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1"
|
||||
|
||||
array-differ@^1.0.0:
|
||||
version "1.0.0"
|
||||
|
@ -245,8 +245,8 @@ async@^0.9.0, async@~0.9.0:
|
|||
resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
|
||||
|
||||
async@^2.1.5:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.2.0.tgz#c324eba010a237e4fbd55a12dee86367d5c0ef32"
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9"
|
||||
dependencies:
|
||||
lodash "^4.14.0"
|
||||
|
||||
|
@ -949,11 +949,7 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.23.0, babel-types@^6.24
|
|||
lodash "^4.2.0"
|
||||
to-fast-properties "^1.0.1"
|
||||
|
||||
babylon@^6.11.0:
|
||||
version "6.16.1"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3"
|
||||
|
||||
babylon@^6.13.0, babylon@^6.15.0, babylon@^6.17.0:
|
||||
babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0, babylon@^6.17.0:
|
||||
version "6.17.0"
|
||||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.0.tgz#37da948878488b9c4e3c4038893fa3314b3fc932"
|
||||
|
||||
|
@ -965,6 +961,10 @@ balanced-match@^0.4.0, balanced-match@^0.4.1, balanced-match@^0.4.2:
|
|||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
|
||||
|
||||
base62@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/base62/-/base62-1.1.2.tgz#22ced6a49913565bc0b8d9a11563a465c084124c"
|
||||
|
||||
base64-arraybuffer@0.1.5:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
|
||||
|
@ -1057,8 +1057,8 @@ boom@2.x.x:
|
|||
hoek "2.x.x"
|
||||
|
||||
brace-expansion@^1.0.0:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59"
|
||||
dependencies:
|
||||
balanced-match "^0.4.1"
|
||||
concat-map "0.0.1"
|
||||
|
@ -1093,14 +1093,14 @@ browserify-zlib@^0.1.4:
|
|||
dependencies:
|
||||
pako "~0.2.0"
|
||||
|
||||
browserslist@^1.0.1, browserslist@^1.1.1, browserslist@^1.1.3, browserslist@^1.5.2, browserslist@^1.7.6:
|
||||
browserslist@^1.1.1, browserslist@^1.1.3, browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
|
||||
version "1.7.7"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9"
|
||||
dependencies:
|
||||
caniuse-db "^1.0.30000639"
|
||||
electron-to-chromium "^1.2.7"
|
||||
|
||||
buffer-shims@^1.0.0:
|
||||
buffer-shims@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
|
||||
|
||||
|
@ -1181,17 +1181,17 @@ camelize@1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
|
||||
|
||||
caniuse-api@^1.5.2:
|
||||
version "1.5.3"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.5.3.tgz#5018e674b51c393e4d50614275dc017e27c4a2a2"
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"
|
||||
dependencies:
|
||||
browserslist "^1.0.1"
|
||||
caniuse-db "^1.0.30000346"
|
||||
lodash.memoize "^4.1.0"
|
||||
lodash.uniq "^4.3.0"
|
||||
browserslist "^1.3.6"
|
||||
caniuse-db "^1.0.30000529"
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000346, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
version "1.0.30000646"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000646.tgz#c724b90d61df24286e015fc528d062073c00def4"
|
||||
caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
version "1.0.30000662"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000662.tgz#616b17a525b52fec14611f88af3d5a9b5438c050"
|
||||
|
||||
caseless@~0.11.0:
|
||||
version "0.11.0"
|
||||
|
@ -1579,8 +1579,8 @@ cookie@0.3.1, cookie@^0.3.1:
|
|||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
|
||||
|
||||
cookiejar@^2.0.6:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.0.tgz#86549689539b6d0e269b6637a304be508194d898"
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.1.tgz#41ad57b1b555951ec171412a81942b1e8200d34a"
|
||||
|
||||
core-js@^1.0.0:
|
||||
version "1.2.7"
|
||||
|
@ -1595,14 +1595,15 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
|
||||
cosmiconfig@^2.1.0, cosmiconfig@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.1.1.tgz#817f2c2039347a1e9bf7d090c0923e53f749ca82"
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.1.2.tgz#c43ae86d238f08f1728a345ed60ceb0aef63c060"
|
||||
dependencies:
|
||||
is-directory "^0.3.1"
|
||||
js-yaml "^3.4.3"
|
||||
json-parse-helpfulerror "^1.0.3"
|
||||
minimist "^1.2.0"
|
||||
object-assign "^4.1.0"
|
||||
os-homedir "^1.0.1"
|
||||
parse-json "^2.2.0"
|
||||
require-from-string "^1.1.0"
|
||||
|
||||
coveralls@~2.11.2:
|
||||
|
@ -1807,8 +1808,8 @@ dashify@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/dashify/-/dashify-0.2.2.tgz#6a07415a01c91faf4a32e38d9dfba71f61cb20fe"
|
||||
|
||||
date-fns@^1.23.0:
|
||||
version "1.28.2"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.2.tgz#19e4192d68875c0bf7c9537e3f296a8ec64853ef"
|
||||
version "1.28.4"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.4.tgz#7938aec34ba31fc8bd134d2344bc2e0bbfd95165"
|
||||
|
||||
date-now@^0.1.4:
|
||||
version "0.1.4"
|
||||
|
@ -1845,11 +1846,11 @@ debug@2.6.1, debug@^2.1.1, debug@^2.2.0, debug@^2.6.0:
|
|||
dependencies:
|
||||
ms "0.7.2"
|
||||
|
||||
debug@2.6.3:
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d"
|
||||
debug@2.6.4:
|
||||
version "2.6.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0"
|
||||
dependencies:
|
||||
ms "0.7.2"
|
||||
ms "0.7.3"
|
||||
|
||||
decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
|
||||
version "1.2.0"
|
||||
|
@ -2063,8 +2064,8 @@ ee-first@1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
|
||||
|
||||
electron-to-chromium@^1.2.7:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.2.tgz#b8ce5c93b308db0e92f6d0435c46ddec8f6363ab"
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.8.tgz#b2c8a2c79bb89fbbfd3724d9555e15095b5f5fb6"
|
||||
|
||||
emojis-list@^2.0.0:
|
||||
version "2.1.0"
|
||||
|
@ -2347,10 +2348,10 @@ eslint@3.19.0:
|
|||
user-home "^2.0.0"
|
||||
|
||||
espree@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.0.tgz#41656fa5628e042878025ef467e78f125cb86e1d"
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.2.tgz#38dbdedbedc95b8961a1fbf04734a8f6a9c8c592"
|
||||
dependencies:
|
||||
acorn "4.0.4"
|
||||
acorn "^5.0.1"
|
||||
acorn-jsx "^3.0.0"
|
||||
|
||||
esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1:
|
||||
|
@ -2422,8 +2423,8 @@ execall@^1.0.0:
|
|||
clone-regexp "^1.0.0"
|
||||
|
||||
exenv@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.1.tgz#75de1c8dee02e952b102aa17f8875973e0df14f9"
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
|
||||
|
||||
exit-hook@^1.0.0:
|
||||
version "1.1.1"
|
||||
|
@ -2616,10 +2617,10 @@ finalhandler@1.0.0:
|
|||
unpipe "~1.0.0"
|
||||
|
||||
finalhandler@~1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.1.tgz#bcd15d1689c0e5ed729b6f7f541a6df984117db8"
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.2.tgz#d0e36f9dbc557f2de14423df6261889e9d60c93a"
|
||||
dependencies:
|
||||
debug "2.6.3"
|
||||
debug "2.6.4"
|
||||
encodeurl "~1.0.1"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "~2.3.0"
|
||||
|
@ -2688,8 +2689,8 @@ forever-agent@~0.6.1:
|
|||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
|
||||
form-data@^2.1.1, form-data@~2.1.1:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4"
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.5"
|
||||
|
@ -2764,8 +2765,8 @@ gather-stream@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/gather-stream/-/gather-stream-1.0.0.tgz#b33994af457a8115700d410f317733cbe7a0904b"
|
||||
|
||||
gauge@~2.7.1:
|
||||
version "2.7.3"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.3.tgz#1c23855f962f17b3ad3d0dc7443f304542edfe09"
|
||||
version "2.7.4"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||
dependencies:
|
||||
aproba "^1.0.3"
|
||||
console-control-strings "^1.0.0"
|
||||
|
@ -2805,8 +2806,8 @@ get-stdin@^5.0.0:
|
|||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
|
||||
|
||||
getpass@^0.1.1:
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6"
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
|
@ -2871,8 +2872,8 @@ glob@^6.0.1:
|
|||
path-is-absolute "^1.0.0"
|
||||
|
||||
global@^4.3.0:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/global/-/global-4.3.1.tgz#5f757908c7cbabce54f386ae440e11e26b7916df"
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
|
||||
dependencies:
|
||||
min-document "^2.19.0"
|
||||
process "~0.5.1"
|
||||
|
@ -3065,8 +3066,8 @@ home-or-tmp@^2.0.0:
|
|||
os-tmpdir "^1.0.1"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.1.tgz#4b0445e41c004a8bd1337773a4ff790ca40318c8"
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67"
|
||||
|
||||
hpack.js@^2.1.6:
|
||||
version "2.1.6"
|
||||
|
@ -3098,8 +3099,8 @@ html-encoding-sniffer@^1.0.1:
|
|||
whatwg-encoding "^1.0.1"
|
||||
|
||||
html-entities@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.0.tgz#41948caf85ce82fed36e4e6a0ed371a6664379e2"
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
|
||||
|
||||
html-tags@^1.1.1:
|
||||
version "1.1.1"
|
||||
|
@ -3202,8 +3203,8 @@ ienoopen@1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.0.0.tgz#346a428f474aac8f50cf3784ea2d0f16f62bda6b"
|
||||
|
||||
ignore@^3.2.0:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.6.tgz#26e8da0644be0bb4cb39516f6c79f0e0f4ffe48c"
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.7.tgz#4810ca5f1d8eca5595213a34b94f2eb4ed926bbd"
|
||||
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
|
@ -3269,8 +3270,8 @@ interpret@^0.6.4:
|
|||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-0.6.6.tgz#fecd7a18e7ce5ca6abfb953e1f86213a49f1625b"
|
||||
|
||||
interpret@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.2.tgz#f4f623f0bb7122f15f5717c8e254b8161b5c5b2d"
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
|
||||
|
||||
invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1:
|
||||
version "2.2.2"
|
||||
|
@ -3304,7 +3305,7 @@ is-binary-path@^1.0.0:
|
|||
dependencies:
|
||||
binary-extensions "^1.0.0"
|
||||
|
||||
is-buffer@^1.0.2:
|
||||
is-buffer@^1.0.2, is-buffer@^1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
|
||||
|
||||
|
@ -3322,6 +3323,10 @@ is-date-object@^1.0.1:
|
|||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
|
||||
|
||||
is-directory@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"
|
||||
|
||||
is-dotfile@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d"
|
||||
|
@ -3551,6 +3556,10 @@ jed@1.1.1:
|
|||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
|
||||
|
||||
jju@^1.1.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/jju/-/jju-1.3.0.tgz#dadd9ef01924bc728b03f2f7979bdbd62f7a2aaa"
|
||||
|
||||
jodid25519@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
|
||||
|
@ -3573,8 +3582,8 @@ js-yaml@3.6.1:
|
|||
esprima "^2.6.0"
|
||||
|
||||
js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.5.1:
|
||||
version "3.8.2"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721"
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.3.tgz#33a05ec481c850c8875929166fe1beb61c728766"
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^3.1.1"
|
||||
|
@ -3626,6 +3635,12 @@ json-loader@0.5.4:
|
|||
version "0.5.4"
|
||||
resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
|
||||
|
||||
json-parse-helpfulerror@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz#13f14ce02eed4e981297b64eb9e3b932e2dd13dc"
|
||||
dependencies:
|
||||
jju "^1.1.0"
|
||||
|
||||
json-schema@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||
|
@ -3689,10 +3704,8 @@ jsprim@^1.2.2:
|
|||
verror "1.3.6"
|
||||
|
||||
jsx-ast-utils@^1.0.0, jsx-ast-utils@^1.3.4:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.0.tgz#5afe38868f56bc8cc7aeaef0100ba8c75bd12591"
|
||||
dependencies:
|
||||
object-assign "^4.1.0"
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1"
|
||||
|
||||
karma-chai@0.1.0:
|
||||
version "0.1.0"
|
||||
|
@ -3790,10 +3803,10 @@ kind-of@^2.0.1:
|
|||
is-buffer "^1.0.2"
|
||||
|
||||
kind-of@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47"
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.0.tgz#b58abe4d5c044ad33726a8c1525b48cf891bff07"
|
||||
dependencies:
|
||||
is-buffer "^1.0.2"
|
||||
is-buffer "^1.1.5"
|
||||
|
||||
klaw@^1.0.0:
|
||||
version "1.3.1"
|
||||
|
@ -3975,7 +3988,7 @@ lodash.map@^4.4.0:
|
|||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
|
||||
|
||||
lodash.memoize@^4.1.0:
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
|
||||
|
@ -4007,7 +4020,7 @@ lodash.tail@^4.1.1:
|
|||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
|
||||
|
||||
lodash.uniq@^4.3.0:
|
||||
lodash.uniq@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
|
||||
|
@ -4155,7 +4168,7 @@ micromatch@^2.1.5, micromatch@^2.3.11:
|
|||
version "1.27.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
|
||||
|
||||
mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.13, mime-types@~2.1.7:
|
||||
mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
|
||||
version "2.1.15"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
|
||||
dependencies:
|
||||
|
@ -4238,6 +4251,10 @@ ms@0.7.2:
|
|||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765"
|
||||
|
||||
ms@0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
|
||||
|
||||
multimatch@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b"
|
||||
|
@ -4260,8 +4277,8 @@ mv@~2:
|
|||
rimraf "~2.4.0"
|
||||
|
||||
nan@^2.3.0, nan@^2.3.2, nan@^2.3.3:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2"
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
|
||||
|
||||
native-promise-only@^0.8.1:
|
||||
version "0.8.1"
|
||||
|
@ -4394,8 +4411,8 @@ nopt@^4.0.1:
|
|||
osenv "^0.1.4"
|
||||
|
||||
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.6.tgz#498fa420c96401f787402ba21e600def9f981fff"
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb"
|
||||
dependencies:
|
||||
hosted-git-info "^2.1.4"
|
||||
is-builtin-module "^1.0.0"
|
||||
|
@ -4660,6 +4677,10 @@ path-is-inside@^1.0.1:
|
|||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
|
||||
|
||||
path-parse@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
|
@ -4687,8 +4708,8 @@ performance-now@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
|
||||
|
||||
photoswipe@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/photoswipe/-/photoswipe-4.1.1.tgz#41b756a2387e220c286598945503014bf622bba9"
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/photoswipe/-/photoswipe-4.1.2.tgz#95c20a75cea23b70d6299641cad82e03cae7f797"
|
||||
|
||||
pify@^2.0.0, pify@^2.3.0:
|
||||
version "2.3.0"
|
||||
|
@ -5060,8 +5081,8 @@ postcss-zindex@^2.0.1:
|
|||
uniqs "^2.0.0"
|
||||
|
||||
postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.18, postcss@^5.0.2, postcss@^5.0.20, postcss@^5.0.21, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.6, postcss@^5.0.8, postcss@^5.2.13, postcss@^5.2.15, postcss@^5.2.16, postcss@^5.2.4:
|
||||
version "5.2.16"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.16.tgz#732b3100000f9ff8379a48a53839ed097376ad57"
|
||||
version "5.2.17"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.17.tgz#cf4f597b864d65c8a492b2eabe9d706c879c388b"
|
||||
dependencies:
|
||||
chalk "^1.1.3"
|
||||
js-base64 "^2.1.9"
|
||||
|
@ -5089,8 +5110,8 @@ process-nextick-args@~1.0.6:
|
|||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
|
||||
|
||||
process@^0.11.0:
|
||||
version "0.11.9"
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.9.tgz#7bd5ad21aa6253e7da8682264f1e11d11c0318c1"
|
||||
version "0.11.10"
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
|
||||
process@~0.5.1:
|
||||
version "0.5.2"
|
||||
|
@ -5158,8 +5179,8 @@ query-string@^3.0.0:
|
|||
strict-uri-encode "^1.0.0"
|
||||
|
||||
query-string@^4.1.0:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.2.tgz#ec0fd765f58a50031a3968c2431386f8947a5cdd"
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
|
||||
dependencies:
|
||||
object-assign "^4.1.0"
|
||||
strict-uri-encode "^1.0.0"
|
||||
|
@ -5210,8 +5231,8 @@ raw-body@~2.2.0:
|
|||
unpipe "1.0.0"
|
||||
|
||||
rc@^1.1.7:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.0.tgz#c7de973b7b46297c041366b2fd3d2363b1697c66"
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
|
||||
dependencies:
|
||||
deep-extend "~0.4.0"
|
||||
ini "~1.3.0"
|
||||
|
@ -5401,16 +5422,16 @@ readable-stream@^1.0.33, readable-stream@~1.1.9:
|
|||
isarray "0.0.1"
|
||||
string_decoder "~0.10.x"
|
||||
|
||||
"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.0, readable-stream@^2.1.4, readable-stream@^2.2.2:
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.6.tgz#8b43aed76e71483938d12a8d46c6cf1a00b1f816"
|
||||
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.6:
|
||||
version "2.2.9"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8"
|
||||
dependencies:
|
||||
buffer-shims "^1.0.0"
|
||||
buffer-shims "~1.0.0"
|
||||
core-util-is "~1.0.0"
|
||||
inherits "~2.0.1"
|
||||
isarray "~1.0.0"
|
||||
process-nextick-args "~1.0.6"
|
||||
string_decoder "~0.10.x"
|
||||
string_decoder "~1.0.0"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readdirp@^2.0.0:
|
||||
|
@ -5513,8 +5534,8 @@ regenerate@^1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
|
||||
|
||||
regenerator-runtime@^0.10.0:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e"
|
||||
version "0.10.4"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.4.tgz#74cb6598d3ba2eb18694e968a40e2b3b4df9cf93"
|
||||
|
||||
regenerator-transform@0.9.11:
|
||||
version "0.9.11"
|
||||
|
@ -5669,10 +5690,16 @@ resolve-from@^2.0.0:
|
|||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
|
||||
|
||||
resolve@1.1.x, resolve@^1.1.6:
|
||||
resolve@1.1.x:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
|
||||
|
||||
resolve@^1.1.6:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5"
|
||||
dependencies:
|
||||
path-parse "^1.0.5"
|
||||
|
||||
restore-cursor@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
|
||||
|
@ -6058,8 +6085,8 @@ sri-stats-webpack-plugin@0.7.3:
|
|||
webpack-custom-stats-patch "^0.3.0"
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.11.0"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.11.0.tgz#2d8d5ebb4a6fab28ffba37fa62a90f4a3ea59d77"
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c"
|
||||
dependencies:
|
||||
asn1 "~0.2.3"
|
||||
assert-plus "^1.0.0"
|
||||
|
@ -6101,12 +6128,12 @@ stream-combiner@^0.2.1:
|
|||
through "~2.3.4"
|
||||
|
||||
stream-http@^2.3.1:
|
||||
version "2.6.3"
|
||||
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.6.3.tgz#4c3ddbf9635968ea2cfd4e48d43de5def2625ac3"
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.0.tgz#cec1f4e3b494bc4a81b451808970f8b20b4ed5f6"
|
||||
dependencies:
|
||||
builtin-status-codes "^3.0.0"
|
||||
inherits "^2.0.1"
|
||||
readable-stream "^2.1.0"
|
||||
readable-stream "^2.2.6"
|
||||
to-arraybuffer "^1.0.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
|
@ -6133,6 +6160,12 @@ string_decoder@^0.10.25, string_decoder@~0.10.x:
|
|||
version "0.10.31"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
|
||||
string_decoder@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667"
|
||||
dependencies:
|
||||
buffer-shims "~1.0.0"
|
||||
|
||||
stringstream@~0.0.4:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
|
||||
|
@ -6523,15 +6556,15 @@ type-detect@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-3.0.0.tgz#46d0cc8553abb7b13a352b0d6dea2fd58f2d9b55"
|
||||
|
||||
type-detect@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.0.tgz#62053883542a321f2f7b25746dc696478b18ff6b"
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea"
|
||||
|
||||
type-is@~1.6.14:
|
||||
version "1.6.14"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2"
|
||||
version "1.6.15"
|
||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410"
|
||||
dependencies:
|
||||
media-typer "0.3.0"
|
||||
mime-types "~2.1.13"
|
||||
mime-types "~2.1.15"
|
||||
|
||||
typedarray@^0.0.6:
|
||||
version "0.0.6"
|
||||
|
@ -6542,8 +6575,8 @@ ua-parser-js@0.7.12, ua-parser-js@^0.7.9:
|
|||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
|
||||
|
||||
uglify-js@^2.6, uglify-js@^2.7.0:
|
||||
version "2.8.18"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.18.tgz#925d14bae48ab62d1883b41afe6e2261662adb8e"
|
||||
version "2.8.22"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
|
||||
dependencies:
|
||||
source-map "~0.5.1"
|
||||
yargs "~3.10.0"
|
||||
|
@ -6841,8 +6874,8 @@ whatwg-fetch@^0.9.0:
|
|||
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0"
|
||||
|
||||
whatwg-url@^4.3.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.6.0.tgz#ef98da442273be04cf9632e176f257d2395a1ae4"
|
||||
version "4.7.1"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-4.7.1.tgz#df4dc2e3f25a63b1fa5b32ed6d6c139577d690de"
|
||||
dependencies:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
|
Загрузка…
Ссылка в новой задаче