Skip to content

changes to support interoperation with kbase-ui (react edition) [URO-193] #198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
74aa71f
changes to support interoperation with kbase-ui (react edition) [URO-…
eapearson Apr 5, 2024
d4866eb
fix message payload assertion [URO-193]
eapearson Apr 5, 2024
e448b3d
add load-narrative page [URO-193]
eapearson Apr 5, 2024
58d6fe9
remove useless comparison [URO-193]
eapearson Apr 5, 2024
f8b0826
don't re-use variable [URO-193]
eapearson Apr 5, 2024
20ebc52
try to satisfy github security in this test [URO-193]
eapearson Apr 5, 2024
38f2584
fix typo [URO-193]
eapearson Apr 5, 2024
5586d42
use unique channel id per send/receive pair [URO-193]
eapearson Apr 5, 2024
45941f9
update tests to match new connection protocol [URO-193]
eapearson Apr 5, 2024
be9c44c
improve connection, monitor and error for lost kbase-ui connection, r…
eapearson Apr 10, 2024
ae704d1
improve error message, protect function with useCallback [URO-193]
eapearson Apr 10, 2024
07d2075
improve timeout monitor [URO-193]
eapearson Apr 10, 2024
9929e34
remove commented out code [URO-193]
eapearson Apr 10, 2024
c4928e3
add attributs to support integration testing [URO-193]
eapearson Apr 10, 2024
00ce946
disable connection monitoring [URO-193]
eapearson Apr 10, 2024
d191d65
improve loading overlay, remove unused constant and support [URO-193]
eapearson Apr 10, 2024
e258f0a
remove default interval (not used) [URO-193]
eapearson Apr 11, 2024
bedf22a
remove periodic tasks and commented out code using it [URO-193]
eapearson Apr 11, 2024
6ca1ade
follow up work on CountdownClock [URO-193]
eapearson Apr 11, 2024
2ef9d14
improve loading message [URO-193]
eapearson Apr 11, 2024
fceee8f
remove unused function [URO-193]
eapearson Apr 11, 2024
be5e33c
add stub test (wip) [URO-193]
eapearson Apr 11, 2024
cee57ce
add some tests, clean up some code [URO-193]
eapearson Apr 11, 2024
d4ed26b
fix test [URO-193]
eapearson Apr 11, 2024
def7e7a
improve messag [URO-193]
eapearson Apr 12, 2024
ceb363f
remove commented-out code [URO-193]
eapearson Apr 12, 2024
4627806
improve message [URO-193]
eapearson Apr 12, 2024
8ea37ed
remove useless test [URO-193]
eapearson Apr 12, 2024
1d546a5
nginx config to prevent caching of index.html in browser [URO-193]
eapearson Apr 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 31 additions & 8 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,41 @@
# for deploy enviroment configurations, see config.json

# Base URL path for the enviroment
PUBLIC_URL = '/dev/'
PUBLIC_URL='/'

# Name of enviroment for build
REACT_APP_KBASE_ENV=ci-europa
# This is used for selection of a config stanza.
REACT_APP_KBASE_ENV='ci-europa'

# Domain of enviroment for build
REACT_APP_KBASE_DOMAIN=ci-europa.kbase.us
REACT_APP_KBASE_DOMAIN='ci-europa.kbase.us'

# The following must be a subdomain of REACT_APP_KBASE_DOMAIN
REACT_APP_KBASE_LEGACY_DOMAIN=legacy.ci-europa.kbase.us
REACT_APP_KBASE_LEGACY_DOMAIN='legacy.ci-europa.kbase.us'

# The base path - the first part of the pathname - for the url used to load kbase-ui
# This must match how kbase-ui is proxied; in KBase environments, this must match
# the path established for kbase-ui; in development, it must match however the
# kbase-ui development proxy is configured.
REACT_APP_KBASE_LEGACY_BASE_PATH=''

# Backup cookie name and domain, empty if unused by enviroment
REACT_APP_KBASE_BACKUP_COOKIE_NAME = 'test_kbase_backup_session'
REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN = 'localhost'
REACT_APP_KBASE_BACKUP_COOKIE_NAME=''
REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN=''

#
# For the local dev server environment
#
EXTEND_ESLINT='true'
SKIP_PREFLIGHT_CHECK='true'

EXTEND_ESLINT=true
SKIP_PREFLIGHT_CHECK=true
# Whether the dev server is running in coordination with kbase-ui and under the
# kbase-ui proxy. This is necessary when running the dev server inside a
# container and behind a proxy, because in that case we want the base url (e.g. set in
# common/api/index.ts) to be the KBase deployment domain (e.g. ci.kbase.us) and
# not localhost:3000, set when running a local, unproxied dev server.
# In other words, `process.env.NODE_ENV` equal to "development" means that the
# development server is running and `process.env.REACT_APP_KBASE_UI_DEV` set to "true"
# means that this development server is running inside a container and coordinated with
# the kbase-ui development proxy.
REACT_APP_KBASE_UI_DEV='true'
23 changes: 15 additions & 8 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,52 @@
"appdev": {
"domain": "appdev.kbase.us",
"legacy": "legacy.appdev.kbase.us",
"legacy_base_path": "",
"public_url": "/"
},

"ci": {
"domain": "ci.kbase.us",
"legacy": "legacy.ci.kbase.us",
"legacy_base_path": "",
"public_url": "/"
},

"ci-europa": {
"domain": "ci-europa.kbase.us",
"legacy": "legacy.ci-europa.kbase.us",
"legacy_base_path": "",
"public_url": "/"
},

"narrative-dev": {
"domain": "narrative-dev.kbase.us",
"legacy": "legacy.narrative-dev.kbase.us",
"legacy_base_path": "",
"public_url": "/"
},

"narrative2": {
"domain": "narrative2.kbase.us",
"legacy": "legacy.narrative2.kbase.us",
"legacy_base_path": "",
"public_url": "/",
"backup_cookie": { "name": "kbase_session_backup", "domain": ".kbase.us" }
"backup_cookie": {
"name": "kbase_session_backup",
"domain": ".kbase.us"
}
},

"next": {
"domain": "next.kbase.us",
"legacy": "legacy.next.kbase.us",
"legacy_base_path": "",
"public_url": "/"
},

"production": {
"domain": "narrative.kbase.us",
"legacy": "legacy.narrative.kbase.us",
"legacy_base_path": "",
"public_url": "/",
"backup_cookie": { "name": "kbase_session_backup", "domain": ".kbase.us" }
"backup_cookie": {
"name": "kbase_session_backup",
"domain": ".kbase.us"
}
}
}
}
40 changes: 40 additions & 0 deletions public/load-narrative.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>KBase Narrative Interface</title>
<link rel="icon" type="image/x-icon" href="/favicon.ico">
</head>

<body>
<script>

function main() {
/*
Just intercepts the load-narrative.html request and redirects to
kbase-ui proper.
*/
const url = new URL(window.location.href);
const n = url.searchParams.get('n');
if (!n) {
url.pathname = `/legacy/narrativemanager/start`;
window.location.href = url.toString();
return;
}

for (const key of Array.from(url.searchParams.keys())) {
url.searchParams.delete(key);
}

url.pathname = `/legacy/load-narrative`;
url.searchParams.set('n', n);

window.location.href = url.toString();
}
main();

</script>
</body>

</html>
12 changes: 7 additions & 5 deletions scripts/build_deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,22 @@
# Here we are using bash "here strings"
IFS=$'\n' read -d '' -r -a enviromentsConfig <<< "$(jq -r '.environments
| keys[] as $k
| [($k), (.[$k]["domain"]) , (.[$k]["legacy"]) , (.[$k]["public_url"]) , (.[$k]["backup_cookie"]["name"]) , (.[$k]["backup_cookie"]["domain"])]
| join(" ")' config.json)"
| [($k), (.[$k]["domain"]) , (.[$k]["legacy"]) , (.[$k]["legacy_base_path"]) , (.[$k]["public_url"]) , (.[$k]["backup_cookie"]["name"]) , (.[$k]["backup_cookie"]["domain"])]
| join("|")' config.json)"

for enviro in "${enviromentsConfig[@]}"; do
IFS="|"
read -a envConf <<< "$enviro"
echo "Building static files for enviroment \"${envConf[0]}\"...";

BUILD_PATH="./deploy/${envConf[0]}" \
REACT_APP_KBASE_ENV="${envConf[0]}" \
REACT_APP_KBASE_DOMAIN="${envConf[1]}" \
REACT_APP_KBASE_LEGACY_DOMAIN="${envConf[2]}" \
PUBLIC_URL="${envConf[3]}" \
REACT_APP_KBASE_BACKUP_COOKIE_NAME="${envConf[4]}" \
REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN="${envConf[5]}" \
REACT_APP_KBASE_LEGACY_BASE_PATH="${envConf[3]}" \
PUBLIC_URL="${envConf[4]}" \
REACT_APP_KBASE_BACKUP_COOKIE_NAME="${envConf[5]}" \
REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN="${envConf[6]}" \
npm run build && \
echo "Built static files for enviroment \"${envConf[0]}\".";
done
21 changes: 15 additions & 6 deletions scripts/nginx.conf.tmpl
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
server {
listen 0.0.0.0:8080;
listen 0.0.0.0:8080;

location / {
root /deploy/__ENVIRONMENT__;
index index.html;
try_files $uri $uri/ /index.html =404;
}
root /deploy/__ENVIRONMENT__;

# First try a physical file.
# If not found, go to fallback.
location ~ / {
try_files $uri $uri/ @fallback;
}

# Fallback location is the web app itself.
location @fallback {
# We don't want the browser to cache the
add_header Cache-Control "no-store";
try_files /index.html =404;
}
}
17 changes: 14 additions & 3 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { FC, useEffect } from 'react';
import { isInsideIframe } from '../common';
import { useAppDispatch, useAppSelector } from '../common/hooks';
import { authInitialized, authUsername } from '../features/auth/authSlice';
import { useTokenCookie } from '../features/auth/hooks';
import LeftNavBar from '../features/layout/LeftNavBar';
import TopBar from '../features/layout/TopBar';
import ErrorPage from '../features/layout/ErrorPage';
Expand All @@ -17,12 +16,24 @@ import { ModalDialog } from '../features/layout/Modal';
import { useLoggedInProfileUser } from '../features/profile/profileSlice';
import Routes from './Routes';
import classes from './App.module.scss';
import {
useInitializeAuthStateFromCookie,
useSyncAuthStateFromCookie,
useSyncCookieFromAuthState,
} from '../features/auth/hooks';

const useInitApp = () => {
const dispatch = useAppDispatch();

// Pulls token from cookie, syncs cookie to auth state
useTokenCookie(
// Only used to bootstrap auth from the auth cookie, if any, present in the browser.
useInitializeAuthStateFromCookie('kbase_session');

// Updates app auth state from cookie changes after app startup.
useSyncAuthStateFromCookie('kbase_session');

// Ensures the primary auth cookie is set correctly according to app auth state. If a
// backup cookie is configured, ensures that it mirrors the primary auth cookie.
useSyncCookieFromAuthState(
'kbase_session',
process.env.REACT_APP_KBASE_BACKUP_COOKIE_NAME,
process.env.REACT_APP_KBASE_BACKUP_COOKIE_DOMAIN
Expand Down
14 changes: 10 additions & 4 deletions src/app/Routes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { render } from '@testing-library/react';
import { Provider } from 'react-redux';

import {
Route,
Routes as RRRoutes,
Route,
MemoryRouter as Router,
} from 'react-router-dom';
import { TokenInfo } from '../features/auth/authSlice';
import { LEGACY_BASE_ROUTE } from '../features/legacy/Legacy';
import { LEGACY_BASE_ROUTE } from '../features/legacy/constants';
import {
Authed,
HashRouteRedirect,
Expand Down Expand Up @@ -76,7 +76,10 @@ describe('Routing Utils', () => {
<Router initialEntries={['/']}>
<RRRoutes>
<Route path={ROOT_REDIRECT_ROUTE} element={<NarrativePageMock />} />
<Route path={`${LEGACY_BASE_ROUTE}/*`} element={<LegacyPageMock />} />
<Route
path={`${LEGACY_BASE_ROUTE()}/*`}
element={<LegacyPageMock />}
/>
<Route path={'/'} element={<HashRouteRedirect />} />
</RRRoutes>
</Router>
Expand All @@ -92,7 +95,10 @@ describe('Routing Utils', () => {
<Router initialEntries={['/#some-fragment/like/this']}>
<RRRoutes>
<Route path={ROOT_REDIRECT_ROUTE} element={<NarrativePageMock />} />
<Route path={`${LEGACY_BASE_ROUTE}/*`} element={<LegacyPageMock />} />
<Route
path={`${LEGACY_BASE_ROUTE()}/*`}
element={<LegacyPageMock />}
/>
<Route path={'/'} element={<HashRouteRedirect />} />
</RRRoutes>
</Router>
Expand Down
56 changes: 39 additions & 17 deletions src/app/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import {
useLocation,
} from 'react-router-dom';

import Legacy, { LEGACY_BASE_ROUTE } from '../features/legacy/Legacy';
import { Fallback } from '../features/legacy/IFrameFallback';
import Legacy from '../features/legacy/Legacy';
import Navigator, {
navigatorPath,
navigatorPathWithCategory,
Expand All @@ -25,16 +24,29 @@ import {
useFilteredParams,
usePageTracking,
} from '../common/hooks';
import { LEGACY_BASE_ROUTE } from '../features/legacy/constants';
import FallbackNotFound from '../common/components/FallbackNotFound';

export const LOGIN_ROUTE = '/legacy/login';
export const LOGIN_ROUTE = `${LEGACY_BASE_ROUTE()}/login`;
export const ROOT_REDIRECT_ROUTE = '/narratives';

const Routes: FC = () => {
useFilteredParams();
usePageTracking();
return (
<RRRoutes>
<Route path={`${LEGACY_BASE_ROUTE}/*`} element={<Legacy />} />
{/* The legacy route without any path element goes to the default location (probably the
Narratives Navigator)
Note that this replaces the previous behavior, in which the kbase-ui would receive
an empty path, and issue a navigation to /fallback, which would in turn redirect
to /narratives. However, this technique is more direct. */}
<Route
path={`${LEGACY_BASE_ROUTE()}`}
element={<Navigate to={ROOT_REDIRECT_ROUTE} replace />}
/>
{/* Otherwise, legacy routes go to the Legacy component. See the catch-alls at the end for
handling of kbase-ui hash routes. */}
<Route path={`${LEGACY_BASE_ROUTE()}/*`} element={<Legacy />} />
<Route
path="/profile/:usernameRequested/narratives"
element={<Authed element={<ProfileWrapper />} />}
Expand Down Expand Up @@ -77,22 +89,29 @@ const Routes: FC = () => {
<Route path="*" element={<PageNotFound />} />
</Route>

{/* IFrame Fallback Routes */}
{/* IFrame Fallback Routes
When kbase-ui is called with a hashpath which is not handled,
it navigates to
`/fallback/{hashpath}?{params}`
where `{hashpath}` is the original hash path provided to kbase-ui in the iframe
and `{params}` is the original params provided as well.

This can be a way to handle:
- simple errant urls
- extant paths in kbase-ui which have been replaced with the equivalent functionality
in Europa
*/}
<Route path="/fallback">
{/* The fallback issued with no path is equivalent to calling kbase-ui
with no navigation; this simply cannot happen any longer.
TODO: try removing the narratives route
*/}
<Route
path="narratives"
element={<Fallback redirect={() => '/narratives'} />}
/>
<Route
path="narrative/:wsId"
element={
<Fallback
reload
redirect={(params) => `/narrative/${params.wsId}`}
/>
}
element={<Navigate to="/narratives" replace />}
/>
<Route path="*" element={<Fallback redirect={() => null} />} />

<Route path="*" element={<FallbackNotFound />} />
</Route>

<Route path="/" element={<HashRouteRedirect />} />
Expand Down Expand Up @@ -120,7 +139,10 @@ export const HashRouteRedirect = () => {
const location = useLocation();
if (location.hash)
return (
<Navigate to={`${LEGACY_BASE_ROUTE}/${location.hash.slice(1)}`} replace />
<Navigate
to={`${LEGACY_BASE_ROUTE()}/${location.hash.slice(1)}`}
replace
/>
);
return <Navigate to={ROOT_REDIRECT_ROUTE} replace />;
};
Expand Down
3 changes: 3 additions & 0 deletions src/common/api/authService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ export const authApi = baseApi.injectEndpoints({
revokeToken: builder.mutation<boolean, string>({
query: (tokenId) =>
authService({
headers: {
Accept: 'application/json',
},
url: encode`/tokens/revoke/${tokenId}`,
method: 'DELETE',
}),
Expand Down
Loading