wip
This commit is contained in:
parent
7b8189b77d
commit
d0f273825f
11 changed files with 228 additions and 21 deletions
|
@ -48,6 +48,7 @@
|
|||
"postinstall:warning": "echo '\n\nWARNING\n\nNot all node modules were installed because NODE_ENV is set to \"production\".\nThis should only be set after installing dependencies with \"yarn\". The app will not work.\n\n'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-keycloak/web": "^3.4.0",
|
||||
"auto-launch": "^5.0.5",
|
||||
"electron-dl": "^1.11.0",
|
||||
"electron-log": "^2.2.12",
|
||||
|
@ -58,6 +59,7 @@
|
|||
"if-env": "^1.0.4",
|
||||
"match-sorter": "^6.3.0",
|
||||
"parse-duration": "^1.0.0",
|
||||
"keycloak-js": "^15.0.2",
|
||||
"react-datetime-picker": "^3.2.1",
|
||||
"react-plastic": "^1.1.1",
|
||||
"react-top-loading-bar": "^2.0.1",
|
||||
|
|
6
static/silent-check-sso.html
Normal file
6
static/silent-check-sso.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<html>
|
||||
<body>
|
||||
<h1>Hi</h1>
|
||||
<script>parent.postMessage(location.href, location.origin)</script>
|
||||
</body>
|
||||
</html>
|
|
@ -29,6 +29,8 @@ import {
|
|||
STATUS_FAILING,
|
||||
STATUS_DOWN,
|
||||
} from 'web/effects/use-degraded-performance';
|
||||
import { useKeycloak } from '@react-keycloak/web';
|
||||
|
||||
// @endif
|
||||
import LANGUAGE_MIGRATIONS from 'constants/language-migrations';
|
||||
|
||||
|
@ -156,6 +158,7 @@ function App(props: Props) {
|
|||
const isRewardApproved = user && user.is_reward_approved;
|
||||
const previousHasVerifiedEmail = usePrevious(hasVerifiedEmail);
|
||||
const previousRewardApproved = usePrevious(isRewardApproved);
|
||||
const { authenticated } = useKeycloak();
|
||||
// @if TARGET='web'
|
||||
const [showAnalyticsNag, setShowAnalyticsNag] = usePersistedState('analytics-nag', true);
|
||||
const [lbryTvApiStatus, setLbryTvApiStatus] = useState(STATUS_OK);
|
||||
|
@ -174,6 +177,7 @@ function App(props: Props) {
|
|||
const fromLbrytvParam = urlParams.get('sunset');
|
||||
const sanitizedReferrerParam = rawReferrerParam && rawReferrerParam.replace(':', '#');
|
||||
const shouldHideNag = pathname.startsWith(`/$/${PAGES.EMBED}`) || pathname.startsWith(`/$/${PAGES.AUTH_VERIFY}`);
|
||||
// KC
|
||||
const userId = user && user.id;
|
||||
const useCustomScrollbar = !IS_MAC;
|
||||
const hasMyChannels = myChannelUrls && myChannelUrls.length > 0;
|
||||
|
@ -194,7 +198,13 @@ function App(props: Props) {
|
|||
setShowAnalyticsNag(false);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (authenticated) {
|
||||
console.log('IS KC AUTHED');
|
||||
}
|
||||
}, [authenticated]);
|
||||
// @endif
|
||||
// TODO KC HOWTO SETUSER
|
||||
useEffect(() => {
|
||||
if (userId) {
|
||||
analytics.setUser(userId);
|
||||
|
@ -317,7 +327,7 @@ function App(props: Props) {
|
|||
if (previousHasVerifiedEmail === false && hasVerifiedEmail) {
|
||||
analytics.emailVerifiedEvent();
|
||||
}
|
||||
}, [previousHasVerifiedEmail, hasVerifiedEmail, signIn]);
|
||||
}, [previousHasVerifiedEmail, hasVerifiedEmail]);
|
||||
|
||||
useEffect(() => {
|
||||
if (previousRewardApproved === false && isRewardApproved) {
|
||||
|
@ -375,12 +385,14 @@ function App(props: Props) {
|
|||
// We know someone is logging in or not when we get their user object
|
||||
// We'll use this to determine when it's time to pull preferences
|
||||
// This will no longer work if desktop users no longer get a user object from lbryinc
|
||||
// KC TODO KEYCLOAK
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
setReadyForPrefs(true);
|
||||
}
|
||||
}, [user, setReadyForPrefs]);
|
||||
|
||||
// TODO KEYCLOAK ISAUTHENTICATED
|
||||
useEffect(() => {
|
||||
if (syncError && isAuthenticated && !pathname.includes(PAGES.AUTH_WALLET_PASSWORD) && !currentModal) {
|
||||
history.push(`/$/${PAGES.AUTH_WALLET_PASSWORD}?redirect=${pathname}`);
|
||||
|
|
32
ui/component/auth/login.jsx
Normal file
32
ui/component/auth/login.jsx
Normal file
|
@ -0,0 +1,32 @@
|
|||
import * as React from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { Redirect, useLocation } from 'react-router-dom';
|
||||
|
||||
import { useKeycloak } from '@react-keycloak/web';
|
||||
|
||||
const LoginPage = () => {
|
||||
const location = useLocation();
|
||||
const currentLocationState = location.state || {
|
||||
from: { pathname: '/home' },
|
||||
};
|
||||
|
||||
const { keycloak } = useKeycloak();
|
||||
|
||||
const login = useCallback(() => {
|
||||
keycloak && keycloak.login().then((x) => console.log('cb', x));
|
||||
}, [keycloak]);
|
||||
|
||||
if (keycloak && keycloak.authenticated) {
|
||||
return <Redirect to={currentLocationState.from} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button type="button" onClick={login}>
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoginPage;
|
45
ui/component/auth/provider.jsx
Normal file
45
ui/component/auth/provider.jsx
Normal file
|
@ -0,0 +1,45 @@
|
|||
// @flow
|
||||
import * as React from 'react';
|
||||
import { ReactKeycloakProvider, useKeycloak } from '@react-keycloak/web';
|
||||
import keycloak from 'util/keycloak';
|
||||
import type { Node } from 'react';
|
||||
import {
|
||||
getTokens,
|
||||
} from 'util/saved-passwords';
|
||||
|
||||
type Props = {
|
||||
children: Node,
|
||||
};
|
||||
|
||||
export const AuthProvider = (props: Props) => {
|
||||
const { children } = props;
|
||||
const tokens = getTokens();
|
||||
|
||||
const eventLogger = (event, error) => {
|
||||
console.log('onKeycloakEvent', event, error, keycloak);
|
||||
// if (event === 'onReady') {
|
||||
// setKeycloakReady(true);
|
||||
// }
|
||||
};
|
||||
if (keycloak && tokens.access_token) {
|
||||
return (
|
||||
<ReactKeycloakProvider
|
||||
authClient={keycloak}
|
||||
onEvent={eventLogger}
|
||||
initOptions={
|
||||
{ onLoad: 'check-sso',
|
||||
silentCheckSsoFallback: false,
|
||||
redirectUri: 'http://localhost:9090/'}
|
||||
} // from npmjs docs for @react-keycloak/web
|
||||
>
|
||||
{children}
|
||||
</ReactKeycloakProvider>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<>{children}</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default AuthProvider;
|
|
@ -10,8 +10,9 @@ import { parseURI, isURIValid } from 'lbry-redux';
|
|||
import { SITE_TITLE, WELCOME_VERSION, SIMPLE_SITE } from 'config';
|
||||
import LoadingBarOneOff from 'component/loadingBarOneOff';
|
||||
import { GetLinksData } from 'util/buildHomepage';
|
||||
|
||||
import { useKeycloak } from '@react-keycloak/web';
|
||||
import HomePage from 'page/home';
|
||||
import Login from 'component/auth/login';
|
||||
|
||||
// @if TARGET='app'
|
||||
const BackupPage = lazyImport(() => import('page/backup' /* webpackChunkName: "backup" */));
|
||||
|
@ -22,7 +23,7 @@ const Code2257Page = lazyImport(() => import('web/page/code2257' /* webpackChunk
|
|||
// @endif
|
||||
|
||||
// Chunk: "secondary"
|
||||
const SignInPage = lazyImport(() => import('page/signIn' /* webpackChunkName: "secondary" */));
|
||||
// const SignInPage = lazyImport(() => import('page/signIn' /* webpackChunkName: "secondary" */));
|
||||
const SignInWalletPasswordPage = lazyImport(() =>
|
||||
import('page/signInWalletPassword' /* webpackChunkName: "secondary" */)
|
||||
);
|
||||
|
@ -86,7 +87,6 @@ const TopPage = lazyImport(() => import('page/top' /* webpackChunkName: "seconda
|
|||
const UpdatePasswordPage = lazyImport(() => import('page/passwordUpdate' /* webpackChunkName: "passwordUpdate" */));
|
||||
const Welcome = lazyImport(() => import('page/welcome' /* webpackChunkName: "secondary" */));
|
||||
const YoutubeSyncPage = lazyImport(() => import('page/youtubeSync' /* webpackChunkName: "secondary" */));
|
||||
|
||||
// Tell the browser we are handling scroll restoration
|
||||
if ('scrollRestoration' in history) {
|
||||
history.scrollRestoration = 'manual';
|
||||
|
@ -128,14 +128,20 @@ function PrivateRoute(props: PrivateRouteProps) {
|
|||
const { component: Component, isAuthenticated, ...rest } = props;
|
||||
const urlSearchParams = new URLSearchParams(props.location.search);
|
||||
const redirectUrl = urlSearchParams.get('redirect');
|
||||
const { keycloak } = useKeycloak();
|
||||
return (
|
||||
<Route
|
||||
{...rest}
|
||||
render={(props) =>
|
||||
isAuthenticated || !IS_WEB ? (
|
||||
(isAuthenticated || (keycloak && keycloak.authenticated)) || !IS_WEB ? (
|
||||
<Component {...props} />
|
||||
) : (
|
||||
<Redirect to={`/$/${PAGES.AUTH}?redirect=${redirectUrl || props.location.pathname}`} />
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: `/$/${PAGES.AUTH}?redirect=${redirectUrl || props.location.pathname}`,
|
||||
state: { from: props.location },
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
@ -264,10 +270,10 @@ function AppRouter(props: Props) {
|
|||
/>
|
||||
))}
|
||||
|
||||
<Route path={`/$/${PAGES.AUTH_SIGNIN}`} exact component={SignInPage} />
|
||||
<Route path={`/$/${PAGES.AUTH_SIGNIN}`} exact component={Login} />
|
||||
<Route path={`/$/${PAGES.AUTH_PASSWORD_RESET}`} exact component={PasswordResetPage} />
|
||||
<Route path={`/$/${PAGES.AUTH_PASSWORD_SET}`} exact component={PasswordSetPage} />
|
||||
<Route path={`/$/${PAGES.AUTH}`} exact component={SignUpPage} />
|
||||
<Route path={`/$/${PAGES.AUTH}`} exact component={Login} />
|
||||
<Route path={`/$/${PAGES.AUTH}/*`} exact component={SignUpPage} />
|
||||
<Route path={`/$/${PAGES.WELCOME}`} exact component={Welcome} />
|
||||
|
||||
|
|
56
ui/index.jsx
56
ui/index.jsx
|
@ -28,7 +28,16 @@ import { formatLbryUrlForWeb, formatInAppUrl } from 'util/url';
|
|||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import analytics from 'analytics';
|
||||
import { doToast } from 'redux/actions/notifications';
|
||||
import { getAuthToken, setAuthToken, doAuthTokenRefresh, deleteAuthToken, getTokens } from 'util/saved-passwords';
|
||||
import { ReactKeycloakProvider } from '@react-keycloak/web';
|
||||
import keycloak from 'util/keycloak';
|
||||
|
||||
import {
|
||||
getAuthToken,
|
||||
setAuthToken,
|
||||
doAuthTokenRefresh,
|
||||
getTokens,
|
||||
deleteAuthToken,
|
||||
} from 'util/saved-passwords';
|
||||
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
|
||||
import { LBRY_WEB_API, DEFAULT_LANGUAGE, LBRY_API_URL, LBRY_WEB_PUBLISH_API } from 'config';
|
||||
|
||||
|
@ -231,6 +240,7 @@ function AppWrapper() {
|
|||
// Splash screen and sdk setup not needed on web
|
||||
const [readyToLaunch, setReadyToLaunch] = useState(IS_WEB);
|
||||
const [persistDone, setPersistDone] = useState(false);
|
||||
const [keycloakReady, setKeycloakReady] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// @if TARGET='app'
|
||||
|
@ -261,13 +271,18 @@ function AppWrapper() {
|
|||
}
|
||||
}, [persistDone]);
|
||||
|
||||
/**
|
||||
* We have assured we have the latest browser persist,
|
||||
* that daemon has started up,
|
||||
* and we have checked with keycloak for a token
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (readyToLaunch && persistDone) {
|
||||
if (readyToLaunch && persistDone && keycloakReady) {
|
||||
if (DEFAULT_LANGUAGE) {
|
||||
app.store.dispatch(doFetchLanguage(DEFAULT_LANGUAGE));
|
||||
}
|
||||
app.store.dispatch(doUpdateIsNightAsync());
|
||||
app.store.dispatch(doLbryReady()); // get tokens, users, startup stuff
|
||||
app.store.dispatch(doLbryReady());
|
||||
app.store.dispatch(doBlackListedOutpointsSubscribe());
|
||||
app.store.dispatch(doFilteredOutpointsSubscribe());
|
||||
|
||||
|
@ -275,7 +290,18 @@ function AppWrapper() {
|
|||
const timeToStart = appReadyTime - startTime;
|
||||
analytics.readyEvent(timeToStart);
|
||||
}
|
||||
}, [readyToLaunch, persistDone]);
|
||||
}, [readyToLaunch, persistDone, keycloakReady]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('keycl', keycloak.token);
|
||||
}, [keycloak])
|
||||
|
||||
const eventLogger = (event, error) => {
|
||||
console.log('onKeycloakEvent', event, error, keycloak);
|
||||
if (event === 'onReady') {
|
||||
setKeycloakReady(true);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
|
@ -286,12 +312,22 @@ function AppWrapper() {
|
|||
>
|
||||
<Fragment>
|
||||
{readyToLaunch ? (
|
||||
<ConnectedRouter history={history}>
|
||||
<ErrorBoundary>
|
||||
<App />
|
||||
<SnackBar />
|
||||
</ErrorBoundary>
|
||||
</ConnectedRouter>
|
||||
<ReactKeycloakProvider
|
||||
authClient={keycloak}
|
||||
onEvent={eventLogger}
|
||||
initOptions={
|
||||
{ onLoad: 'check-sso',
|
||||
silentCheckSsoFallback: false,
|
||||
redirectUri: 'http://localhost:9090/'}
|
||||
} // from npmjs docs for @react-keycloak/web
|
||||
>
|
||||
<ConnectedRouter history={history}>
|
||||
<ErrorBoundary>
|
||||
<App />
|
||||
<SnackBar />
|
||||
</ErrorBoundary>
|
||||
</ConnectedRouter>
|
||||
</ReactKeycloakProvider>
|
||||
) : (
|
||||
<Fragment>
|
||||
<SplashScreen onReadyToLaunch={() => setReadyToLaunch(true)} />
|
||||
|
|
14
ui/util/keycloak.js
Normal file
14
ui/util/keycloak.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import Keycloak from 'keycloak-js';
|
||||
|
||||
// Setup Keycloak instance as needed
|
||||
// Pass initialization options as required or leave blank to load from 'keycloak.json'
|
||||
const keycloak = Keycloak({
|
||||
url: 'https://sso.odysee.com/auth',
|
||||
realm: 'Users',
|
||||
clientId: 'odysee.com',
|
||||
pkceMethod: 'S256',
|
||||
onLoad: 'check-sso',
|
||||
silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html',
|
||||
});
|
||||
|
||||
export default keycloak;
|
|
@ -6,6 +6,7 @@ const domain =
|
|||
typeof window === 'object' && window.location.hostname.includes('localhost') ? window.location.hostname : DOMAIN;
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const maxExpiration = 2147483647;
|
||||
const { default: keycloak } = require('util/keycloak');
|
||||
let sessionPassword;
|
||||
|
||||
function setCookie(name, value, expirationDaysOnWeb) {
|
||||
|
@ -103,8 +104,12 @@ function getAuthToken() {
|
|||
}
|
||||
|
||||
// will take oidc token getter
|
||||
// function getTokens() {
|
||||
// return { auth_token: getAuthToken(), access_token: null };
|
||||
// }
|
||||
|
||||
function getTokens() {
|
||||
return { auth_token: getAuthToken(), access_token: null };
|
||||
return { auth_token: getAuthToken(), access_token: keycloak.token };
|
||||
}
|
||||
|
||||
function setAuthToken(value) {
|
||||
|
|
|
@ -2,6 +2,7 @@ const { getHtml } = require('./html');
|
|||
const { getRss } = require('./rss');
|
||||
const { getHomepageJSON } = require('./getHomepageJSON');
|
||||
const { generateStreamUrl } = require('../../ui/util/web');
|
||||
const { createReadStream } = require('fs');
|
||||
const fetch = require('node-fetch');
|
||||
const Router = require('@koa/router');
|
||||
const { CUSTOM_HOMEPAGE } = require('../../config.js');
|
||||
|
@ -50,6 +51,11 @@ router.get(`/$/api/content/v1/get`, async (ctx) => {
|
|||
}
|
||||
});
|
||||
|
||||
router.get(`/$/sso/silent-check-sso.html`, async (ctx) => {
|
||||
ctx.type = 'html';
|
||||
ctx.body = createReadStream('./silent-check-sso.html');
|
||||
})
|
||||
|
||||
router.get(`/$/download/:claimName/:claimId`, async (ctx) => {
|
||||
const streamUrl = getStreamUrl(ctx);
|
||||
const downloadUrl = `${streamUrl}?download=1`;
|
||||
|
|
47
yarn.lock
47
yarn.lock
|
@ -1141,6 +1141,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.9.0":
|
||||
version "7.15.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
|
||||
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/template@^7.10.1", "@babel/template@^7.8.3", "@babel/template@^7.8.6":
|
||||
version "7.10.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811"
|
||||
|
@ -1558,6 +1565,22 @@
|
|||
dependencies:
|
||||
tslib "^2.0.0"
|
||||
|
||||
"@react-keycloak/core@^3.2.0":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-keycloak/core/-/core-3.2.0.tgz#e46f1951b0d7873f7f2fcd73dd0c270cb0b18db8"
|
||||
integrity sha512-1yzU7gQzs+6E1v6hGqxy0Q+kpMHg9sEcke2yxZR29WoU8KNE8E50xS6UbI8N7rWsgyYw8r9W1cUPCOF48MYjzw==
|
||||
dependencies:
|
||||
react-fast-compare "^3.2.0"
|
||||
|
||||
"@react-keycloak/web@^3.4.0":
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-keycloak/web/-/web-3.4.0.tgz#725d96fab8e5fa47faff9615cc08574e5dff2222"
|
||||
integrity sha512-yKKSCyqBtn7dt+VckYOW1IM5NW999pPkxDZOXqJ6dfXPXstYhOQCkTZqh8l7UL14PkpsoaHDh7hSJH8whah01g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.9.0"
|
||||
"@react-keycloak/core" "^3.2.0"
|
||||
hoist-non-react-statics "^3.3.2"
|
||||
|
||||
"@samverschueren/stream-to-observable@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
|
||||
|
@ -3495,9 +3518,10 @@ balanced-match@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base64-js@^1.0.2:
|
||||
base64-js@1.3.1, base64-js@^1.0.2:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
|
||||
base@^0.11.1:
|
||||
version "0.11.2"
|
||||
|
@ -8294,9 +8318,10 @@ hoek@4.x.x:
|
|||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb"
|
||||
integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==
|
||||
|
||||
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
|
||||
hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
|
@ -9822,6 +9847,11 @@ js-base64@^2.1.9:
|
|||
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
|
||||
integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
|
||||
|
||||
js-sha256@0.9.0:
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966"
|
||||
integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==
|
||||
|
||||
js-tokens@^3.0.0, js-tokens@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
|
||||
|
@ -10062,6 +10092,14 @@ jszip@~2.5.0:
|
|||
dependencies:
|
||||
pako "~0.2.5"
|
||||
|
||||
keycloak-js@^15.0.2:
|
||||
version "15.0.2"
|
||||
resolved "https://registry.yarnpkg.com/keycloak-js/-/keycloak-js-15.0.2.tgz#9d12dd8860953a267b9b18f351ad2e76b8e94a9c"
|
||||
integrity sha512-dv2a4NcPSH3AzGWG3ZtB+VrHpuQLdFBYXtQBj/+oBzm6XNwnVAMdL6LIC0OzCLQpn3rKTQJtNSATAGhbKJgewQ==
|
||||
dependencies:
|
||||
base64-js "1.3.1"
|
||||
js-sha256 "0.9.0"
|
||||
|
||||
keycode@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04"
|
||||
|
@ -13380,6 +13418,11 @@ react-error-overlay@^1.0.9:
|
|||
settle-promise "1.0.0"
|
||||
source-map "0.5.6"
|
||||
|
||||
react-fast-compare@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
|
||||
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
|
||||
|
||||
react-fit@^1.0.3:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react-fit/-/react-fit-1.3.1.tgz#850cb5d554fdfa4b27891f62a9d290d3e7eda57b"
|
||||
|
|
Loading…
Add table
Reference in a new issue