diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 69da8221..6b19fd38 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -30,4 +30,4 @@ services: networks: # This is the network created by gateway to enable communicaton between multiple docker-compose projects sennet_docker_network: - external: false + external: true diff --git a/src/components/custom/js/functions.js b/src/components/custom/js/functions.js index 13ab6e1c..ca6d054b 100644 --- a/src/components/custom/js/functions.js +++ b/src/components/custom/js/functions.js @@ -1,10 +1,13 @@ -import { getAuth, getRootURL } from "../../../config/config"; +import {getAuth, getRootURL} from "../../../config/config"; import {APP_ROUTES, ORGAN_TYPES} from "../../../config/constants"; import log from "loglevel"; export function getRequestHeaders() { var myHeaders = new Headers(); - myHeaders.append("Authorization", "Bearer " + getAuth()); + log.info(getAuth()) + if (getAuth() !== undefined) { + myHeaders.append("Authorization", "Bearer " + getAuth()); + } myHeaders.append("Content-Type", "application/json"); return { method: 'GET', @@ -59,7 +62,7 @@ export function tableDataToTSV(tableData) { } export function displayBodyHeader(header) { - if(header !== undefined) + if (header !== undefined) return (header.charAt(0).toUpperCase() + header.slice(1)).replaceAll('_', ' '); else return "" diff --git a/src/config/config.js b/src/config/config.js index 07a3380b..2da06328 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -51,6 +51,10 @@ export function getIngestLogin() { return process.env.NEXT_PUBLIC_INGEST_LOGIN } +export function getUUIDEndpoint() { + return process.env.NEXT_PUBLIC_UUID_API_ENDPOINT +} + export function getRootURL() { return process.env.NEXT_PUBLIC_APP_ROOT_URL } diff --git a/src/example.env b/src/example.env index 5cad1dbb..389238f0 100644 --- a/src/example.env +++ b/src/example.env @@ -2,8 +2,9 @@ NEXT_PUBLIC_INDEX=entities NEXT_PUBLIC_SEARCH_API_ENDPOINT=http://localhost:4444/ NEXT_PUBLIC_ENTITY_API_ENDPOINT=http://localhost:3333/ NEXT_PUBLIC_INGEST_API_ENDPOINT=http://localhost:8484/ -NEXT_PUBLIC_APP_ROOT_URL=http://localhost:3000/ NEXT_PUBLIC_INGEST_LOGIN=http://localhost:8484/login +NEXT_PUBLIC_UUID_API_ENDPOINT=http://localhost:2222/ +NEXT_PUBLIC_APP_ROOT_URL=http://localhost:3000/ NEXT_PUBLIC_GOOGLE_TAG_MANAGER=GTM-WMT659V #Can be set to "trace", "debug", "info", "warn", or "error" NEXT_PUBLIC_LOG_LEVEL=debug \ No newline at end of file diff --git a/src/lib/services.js b/src/lib/services.js index 39b34a7c..cdfb4985 100644 --- a/src/lib/services.js +++ b/src/lib/services.js @@ -1,4 +1,4 @@ -import {getAuth, getEntityEndPoint, getIngestEndPoint} from "../config/config"; +import {getAuth, getEntityEndPoint, getIngestEndPoint, getUUIDEndpoint} from "../config/config"; import log from "loglevel"; // After creating or updating an entity, send to Entity API. Search API will be triggered during this process automatically @@ -51,6 +51,27 @@ export async function fetchGlobusFilepath(sennet_id) { } +// This function requires the bearer token passed to it as the middleware can't access "getAuth()" +export async function fetch_entity_type(uuid, bearer_token) { + const headers = new Headers(); + headers.append("Authorization", "Bearer " + bearer_token) + const url = getUUIDEndpoint() + "uuid/" + uuid + const request_options = { + method: 'GET', + headers: headers + } + const response = await fetch(url, request_options) + if (response.status === 200) { + const entity = await response.json(); + return (entity["type"]).toLowerCase(); + + } else if (response.status === 400) { + return "404"; + } else { + return "" + } +} + export async function get_read_write_privileges() { log.info('GET READ WRITE PRIVILEGES') const url = getIngestEndPoint() + 'privs' diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 00000000..481c50e7 --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,44 @@ +// middleware.ts +import type {NextRequest} from 'next/server' +import {NextResponse} from 'next/server' +import {fetch_entity_type} from './lib/services.js' + +// Direct the user to the correct entity type view/edit page +export async function middleware(request: NextRequest) { + let uuid = request.nextUrl.searchParams.get("uuid") + + // Check for redirect cookie and if it exists just continue + // Check if user is trying to create entity + if (request.cookies.get('redirect')?.value === "true" || uuid === 'create') { + const response = NextResponse.rewrite(request.url) + response.cookies.delete("redirect") + return response + } + + let entity_type = await fetch_entity_type(uuid, request.cookies.get('groups_token')?.value); + + if (entity_type === "404") { + return NextResponse.rewrite(new URL('/404', request.url)) + } else if (entity_type != "") { + let updated_url = request.url.replace(/(source|sample|dataset)/, entity_type) + const response = NextResponse.redirect(updated_url) + response.cookies.set("redirect", "true") + return response + } + + return NextResponse.rewrite(request.url) +} + +// Match view and edit entity pages and grab the correct entity type +export const config = { + matcher: [ + '/((?:source|sample|dataset).*)', + '/edit/((?:source|sample|dataset).*)' + ], + // Need to make exceptions for lodash + // https://nextjs.org/docs/messages/edge-dynamic-code-evaluation + unstable_allowDynamic: [ + '/node_modules/lodash*/**', + '/node_modules/babel-runtime/**' + ] +} diff --git a/src/pages/401.js b/src/pages/401.js index 3dd96ec9..19412f20 100644 --- a/src/pages/401.js +++ b/src/pages/401.js @@ -10,9 +10,9 @@ export default function Custom401() {
-

401

-

Your globus token has expired

-

Please logout and login again

+

401

+

Your globus token has expired

+

Please logout and login again

Logout diff --git a/src/pages/404.js b/src/pages/404.js index bb1b84cd..2d0d62f0 100644 --- a/src/pages/404.js +++ b/src/pages/404.js @@ -10,9 +10,9 @@ export default function Custom404() {
-

404

-

Oops! This page could not be found

-

Sorry but the page you are looking for does not exist, has been removed, or is +

404

+

Oops! This page could not be found

+

Sorry but the page you are looking for does not exist, has been removed, or is temporarily unavailable

diff --git a/src/pages/500.js b/src/pages/500.js index 0618e81b..0a294696 100644 --- a/src/pages/500.js +++ b/src/pages/500.js @@ -10,8 +10,8 @@ export default function Custom500() {
-

500

-

Oops! We've encountered an internal server error

+

500

+

Oops! We've encountered an internal server error

Home diff --git a/src/pages/api/find.js b/src/pages/api/find.js index 629daf9f..9e1f65d1 100644 --- a/src/pages/api/find.js +++ b/src/pages/api/find.js @@ -20,7 +20,9 @@ export default function handler(req, res) { let queryBody = simple_query_builder("uuid", uuid) log.info('QUERY', JSON.stringify(queryBody)) var myHeaders = new Headers(); - myHeaders.append("Authorization", req.headers.authorization); + if(req.headers.authorization !== undefined) { + myHeaders.append("Authorization", req.headers.authorization); + } myHeaders.append("Content-Type", "application/json"); var requestOptions = { method: 'POST', diff --git a/src/pages/api/json/[entity].js b/src/pages/api/json/[entity].js index 556108d7..103d5c97 100644 --- a/src/pages/api/json/[entity].js +++ b/src/pages/api/json/[entity].js @@ -1,17 +1,17 @@ import {getRootURL} from "../../../config/config"; import log from "loglevel"; -import {getCookie} from "cookies-next"; +import {getCookie, hasCookie} from "cookies-next"; export default async function handler(req, res) { const uuid = req.query.uuid let auth = req.headers.authorization + let myHeaders = new Headers(); - if (req.headers.authorization === undefined) { + if (req.headers.authorization === undefined && hasCookie("groups_token", {req, res})) { auth = "Bearer " + getCookie("groups_token", {req, res}) + myHeaders.append("Authorization", auth); } - let myHeaders = new Headers(); - myHeaders.append("Authorization", auth); myHeaders.append("Content-Type", "application/json"); let requestOptions = { method: 'GET', diff --git a/src/pages/dataset.jsx b/src/pages/dataset.jsx index bea2e8ad..df9e28cc 100644 --- a/src/pages/dataset.jsx +++ b/src/pages/dataset.jsx @@ -28,7 +28,6 @@ function ViewDataset() { const [ancestors, setAncestors] = useState(null) const [error, setError] = useState(false) const [errorMessage, setErrorMessage] = useState(null) - const [statusCode, setStatusCode] = useState(null) const [hasWritePrivilege, setHasWritePrivilege] = useState(false) const {isRegisterHidden, isLoggedIn, isUnauthorized, isAuthorizing} = useContext(AppContext) @@ -49,7 +48,7 @@ function ViewDataset() { if (data.hasOwnProperty("error")) { setError(true) setErrorMessage(data["error"]) - setStatusCode(response.statusCode) + setData(false) } else { // set state with the result setData(data); @@ -87,16 +86,16 @@ function ViewDataset() { setAncestors(new_ancestors) } - if (isAuthorizing() || isUnauthorized()) { + if ((isAuthorizing() || isUnauthorized()) && !data) { return ( - isUnauthorized() ? : + data == null ? : ) } else { return ( <> {data &&
} -