From 7a1289662d390dd1ebf0a60f67da41be02396d7a Mon Sep 17 00:00:00 2001 From: Torben Brenner Date: Tue, 16 Jan 2024 12:49:19 +0100 Subject: [PATCH] feat: WIP - project manager connection --- docker-compose.yml | 46 ++++++++++++----- package-lock.json | 4 +- packages/demo/public/options.json | 4 +- packages/demo/src/AppCCP.svelte | 3 +- .../demo/src/AppFragmentDevelopment.svelte | 4 +- packages/demo/src/main.ts | 8 +-- packages/lib/src/stores/auth.ts | 23 +++++++++ packages/lib/src/stores/negotiate.ts | 49 ++++++++++++++++++- 8 files changed, 117 insertions(+), 24 deletions(-) create mode 100644 packages/lib/src/stores/auth.ts diff --git a/docker-compose.yml b/docker-compose.yml index 4f96d67..f90cb6d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,22 +19,34 @@ services: - /var/run/docker.sock:/var/run/docker.sock:ro traefik-forward-auth: - image: thomseddon/traefik-forward-auth:2 + image: quay.io/oauth2-proxy/oauth2-proxy:latest environment: - http_proxy=${http_proxy} - https_proxy=${https_proxy} - - DEFAULT_PROVIDER=oidc - # TODO: https://login.bbmri-eric.eu/oidc/ - - PROVIDERS_OIDC_ISSUER_URL=https://git.verbis.dkfz.de - - PROVIDERS_OIDC_CLIENT_ID=${OAUTH_CLIENT_ID} - - PROVIDERS_OIDC_CLIENT_SECRET=${OAUTH_CLIENT_SECRET} - - SECRET=${AUTHENTICATION_SECRET} - - COOKIE_DOMAIN=${GUI_HOST} + - OAUTH2_PROXY_PROVIDER=oidc + - OAUTH2_PROXY_SKIP_PROVIDER_BUTTON=true + - OAUTH2_PROXY_OIDC_ISSUER_URL=${OAUTH_ISSUER_URL} + - OAUTH2_PROXY_CLIENT_ID=${OAUTH_CLIENT_ID} + - OAUTH2_PROXY_CLIENT_SECRET=${OAUTH_CLIENT_SECRET} + - OAUTH2_PROXY_COOKIE_SECRET=${AUTHENTICATION_SECRET} + - OAUTH2_PROXY_COOKIE_DOMAINS=.${GUI_HOST} + - OAUTH2_PROXY_HTTP_ADDRESS=:4180 + - OAUTH2_PROXY_REVERSE_PROXY=true + - OAUTH2_PROXY_WHITELIST_DOMAINS=.${GUI_HOST} + - OAUTH2_PROXY_UPSTREAMS=static://202 + - OAUTH2_PROXY_EMAIL_DOMAINS=* + - OAUTH2_PROXY_ALLOWED_GROUPS=${ALLOWED_GROUPS} + # For some reason, login.verbis.dkfz.de does not have a "groups" scope but this comes automatically through a + # scope called microprofile-jwt. Remove the following line once we have a "groups" scope. + - OAUTH2_PROXY_SCOPE=openid profile email + - OAUTH2_PROXY_SET_AUTHORIZATION_HEADER=true labels: - "traefik.enable=true" - - "traefik.http.middlewares.traefik-forward-auth.forwardauth.address=http://traefik-forward-auth:4181" + - "traefik.http.middlewares.traefik-forward-auth.forwardauth.address=http://traefik-forward-auth:4180" - "traefik.http.middlewares.traefik-forward-auth.forwardauth.authResponseHeaders=X-Forwarded-User" - - "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4181" + - "traefik.http.services.traefik-forward-auth.loadbalancer.server.port=4180" + - "traefik.http.routers.oauth2.rule=(Host(`${GUI_HOST}`) || Host(`backend.${GUI_HOST}`)) && PathPrefix(`/oauth2/`)" + - "traefik.http.routers.oauth2.tls=true" lens-web-components: image: lens-web-components @@ -53,7 +65,7 @@ services: BEAM_PROXY_ID: ${LOCAL_BEAM_ID} BEAM_BROKER_ID: ${BROKER_HOST} # TODO: Implement Switch between spot and focus - BEAM_APP_ID: "spot" + BEAM_APP_ID: "focus" depends_on: - "beam-proxy" labels: @@ -73,7 +85,7 @@ services: BROKER_URL: https://${BROKER_HOST} PROXY_ID: ${LOCAL_BEAM_ID}.${BROKER_HOST} # TODO: Same for focus here - APP_spot_KEY: ${LOCAL_BEAM_SECRET} + APP_focus_KEY: ${LOCAL_BEAM_SECRET} PRIVKEY_FILE: /run/secrets/proxy.pem ALL_PROXY: ${http_proxy} secrets: @@ -95,6 +107,16 @@ services: command: sh -c "sleep 60 && /app/run.sh" profiles: ["development"] + # project-manager: + # image: project-manager + # labels: + # - "traefik.enable=true" + # - "traefik.http.routers.project-manager.tls=true" + # - "traefik.http.routers.project-manager.rule=Host(`${GUI_HOST}`) && PathPrefix(`/project-manager/`)" + # - "traefik.http.middlewares.project-manager-strip.stripprefix.prefixes=/project-manager" + # - "traefik.http.routers.project-manager.middlewares=project-manager-strip" + # - "traefik.http.services.project-manager.loadbalancer.server.port=8097" + secrets: proxy.pem: # TODO: Key in BBMRI was directly stored in lens directory! diff --git a/package-lock.json b/package-lock.json index 56491de..59b96a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "my-library", + "name": "lens-web-componets", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "my-library", + "name": "lens-web-componets", "version": "0.0.0", "dependencies": { "chart.js": "^4.4.0", diff --git a/packages/demo/public/options.json b/packages/demo/public/options.json index 40fe930..e3bd57c 100644 --- a/packages/demo/public/options.json +++ b/packages/demo/public/options.json @@ -120,11 +120,11 @@ ] }, "negotiateOptions": { - "negotiatorURL": "https://negotiator.bbmri-eric.eu/api/directory/create_query", + "negotiatorURL": "http://localhost:8097/create-query-and-design-project", "siteMapping": [ { "site": "Dresden", - "collection": "bbmri-eric:ID:DE_BBD:collection:DILB" + "collection": "dresden" }, { "site": "Frankfurt", diff --git a/packages/demo/src/AppCCP.svelte b/packages/demo/src/AppCCP.svelte index c8d6710..4b31cd4 100644 --- a/packages/demo/src/AppCCP.svelte +++ b/packages/demo/src/AppCCP.svelte @@ -118,7 +118,7 @@ : "https://backend.demo.lens.samply.de/prod/" const backendConfig = { - url: (import.meta.env.PROD) ? backendUrl : "http://localhost:8080", + url: "http://localhost:8080", backends: [ "mannheim", "freiburg", @@ -212,6 +212,7 @@ title="Ergebnisse" resultSummaryDataTypes={JSON.stringify(resultSummaryConfig)} /> + Diagramme repräsentieren nicht mehr die aktuelle Suche!
diff --git a/packages/demo/src/AppFragmentDevelopment.svelte b/packages/demo/src/AppFragmentDevelopment.svelte index ea30e8d..8de155b 100644 --- a/packages/demo/src/AppFragmentDevelopment.svelte +++ b/packages/demo/src/AppFragmentDevelopment.svelte @@ -118,7 +118,7 @@ : "https://backend.demo.lens.samply.de/prod/" const backendConfig = { - url: (import.meta.env.PROD) ? backendUrl : "http://localhost:8080", + url: "http://localhost:8080", backends: [ "mannheim", "freiburg", @@ -233,4 +233,4 @@
- \ No newline at end of file + diff --git a/packages/demo/src/main.ts b/packages/demo/src/main.ts index fba51e0..226be0a 100644 --- a/packages/demo/src/main.ts +++ b/packages/demo/src/main.ts @@ -1,8 +1,8 @@ -import './fragment-development.css' -import App from './AppFragmentDevelopment.svelte' +// import './fragment-development.css' +// import App from './AppFragmentDevelopment.svelte' -// import './ccp.css' -// import App from './AppCCP.svelte' +import './ccp.css' +import App from './AppCCP.svelte' // import App from './AppBBMRI.svelte' // import './bbmri.css' diff --git a/packages/lib/src/stores/auth.ts b/packages/lib/src/stores/auth.ts new file mode 100644 index 0000000..0362c03 --- /dev/null +++ b/packages/lib/src/stores/auth.ts @@ -0,0 +1,23 @@ +/** + * This stores the current access token used to authenticate with the backend services. + * NOTE: This is not a general solution and is tailored for deployment with oauth2-proxy. + */ +import { writable } from "svelte/store"; + + +export const authStore = writable(""); + +fetchAccessToken(); + +async function fetchAccessToken() { + const response = await fetch( + `/oauth2/auth`, + { + method: "GET", + credentials: "include" + } + ); + const authHeader = response.headers.get("Authorization"); + console.log(authHeader) + authStore.set(authHeader); +} diff --git a/packages/lib/src/stores/negotiate.ts b/packages/lib/src/stores/negotiate.ts index 1f23aca..dd4263e 100644 --- a/packages/lib/src/stores/negotiate.ts +++ b/packages/lib/src/stores/negotiate.ts @@ -8,9 +8,16 @@ import { responseStore } from "./response"; import { v4 as uuidv4 } from 'uuid'; import type { Collection } from "../types/collection"; import type { SendableQuery } from "../types/queryData"; +import { authStore } from "./auth"; export const negotiateStore = writable([]); +let authHeader: string = ""; + +authStore.subscribe((value) => { + authHeader=value; +}) + /** * Recursively builds a human readable query string from the AST @@ -112,6 +119,7 @@ export const getCollections = (sitesToNegotiate: string[]): Collection[] => { sitesToNegotiate.forEach((site: string) => { let collectionId: string = "couldn't map site in search UI" + // TODO: Why is site id mapped to Uppercase? if (siteCollectionMap.has(site) && siteCollectionMap.get(site) !== '') { collectionId = siteCollectionMap[site] } @@ -174,7 +182,10 @@ export const negotiate = async (sitesToNegotiate: string[], queryBase64String: s let humanReadable: string = getHumanReadableQuery(); let collections: Collection[] = getCollections(sitesToNegotiate) - let negotiatorResponse = await sendRequestToNegotiator(sendableQuery, humanReadable, collections, queryBase64String) + // TODO: Implement proper configuration option for the switch between negotiator and project manager + let negotiatorResponse = (false) + ? await sendRequestToNegotiator(sendableQuery, humanReadable, collections, queryBase64String) + : await sendRequestToProjectManager(sendableQuery, humanReadable, collections, queryBase64String) window.location.href = negotiatorResponse.redirect_uri.toString() } @@ -213,3 +224,39 @@ async function sendRequestToNegotiator(sendableQuery: SendableQuery, humanReadab ); return response.json(); } + +/** + * + * @param sendableQuery the query to be sent to the negotiator + * @param humanReadable a human readable query string to view in the negotiator project + * @param collections the collections to negotiate with + * @returns the redirect uri from the negotiator + * */ +async function sendRequestToProjectManager(sendableQuery: SendableQuery, humanReadable: string, collections: Collection[], queryBase64String: string): Promise { + + + let base64Query: string = btoa(JSON.stringify(sendableQuery.query)) + + const returnURL: string = `${window.location.protocol}//${window.location.host}/?query=${base64Query}`; + + console.log(collections) + // TODO: should use collectionId + const negotiationPartners = collections.map(collection => collection.siteId.toLocaleLowerCase()).join(',') + console.log(negotiationPartners) + + const response: Response = await fetch( + `${negotiateOptions.negotiatorURL}?explorerIds=${negotiationPartners}&query-format=CQL_DATA&human-readable=${humanReadable}&explorer-url=${returnURL}`, + { + method: "POST", + headers: { + 'Accept': 'application/json; charset=utf-8', + 'Content-Type': 'application/json', + 'Authorization': authHeader + // NOTE: Workaround then david can't solve the bearer token issue + // 'Cookie': 'JSESSIONID=6C0A111CF969B92606A445E8A5E0FB7' + }, + body: base64Query, + } + ); + return response.json(); +}