From 9e537d9052114cee9a7e6c9c3416fb2406274b8d Mon Sep 17 00:00:00 2001 From: Nitai Heeb Date: Wed, 8 Oct 2025 14:56:12 +0200 Subject: [PATCH 1/3] Having OAuth for jugit and helmholtz --- public/gitlab-setup/index.html | 6 ++ public/gitlab-setup/main.js | 120 +++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) diff --git a/public/gitlab-setup/index.html b/public/gitlab-setup/index.html index 6e568f1..df33429 100644 --- a/public/gitlab-setup/index.html +++ b/public/gitlab-setup/index.html @@ -32,6 +32,12 @@

GitLab Account Setup

+

+

OAUTH!

+ + +

Access Token:

+
(noch kein Token)

diff --git a/public/gitlab-setup/main.js b/public/gitlab-setup/main.js index bc278c2..bc515e4 100644 --- a/public/gitlab-setup/main.js +++ b/public/gitlab-setup/main.js @@ -44,4 +44,124 @@ window.onload = async function () { return; } }; + + const GITLAB_APP_URLS = { + "helmholtz": "https://codebase.helmholtz.cloud", + "jugit": "https://jugit.fz-juelich.de", + }; + const GITLAB_APP_IDS = { + "helmholtz": "24722afbaa0d7c09566902879811c6552afa6a0bbd2cc421ab3e89af4faa2ed8", + "jugit": "7a61209bc6348b8f53820b16a4a86e012ce64965fbf4581f86c22b455e3b5488", + }; + + const REDIRECT_URI = location.origin + location.pathname; + const SCOPE = "read_api"; + + // PKCE Stuff + const b64url = ab => btoa(String.fromCharCode(...new Uint8Array(ab))) + .replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""); + async function sha256(input) { + const data = new TextEncoder().encode(input); + return await crypto.subtle.digest("SHA-256", data); + } + function randUrlSafe(len=64){ + const b = crypto.getRandomValues(new Uint8Array(len)); + return b64url(b).slice(0, len); + } + + function buildUrl(base, path, params) { + const u = new URL(path, base); + u.search = params.toString(); + return u.href; + } + + async function startLogin(app_name) { + const base_url = GITLAB_APP_URLS[app_name] + const client_id = GITLAB_APP_IDS[app_name] + + if (!base_url || !client_id) throw new Error("baseUrl and clientId are required."); + + const state = randUrlSafe(24); + const code_verifier = randUrlSafe(96); + const code_challenge = b64url(await sha256(code_verifier)); + + sessionStorage.setItem(`pkce_${state}`, JSON.stringify({ + code_verifier, client_id, base_url, REDIRECT_URI, last_app_name: app_name + })); + + const params = new URLSearchParams({ + client_id: client_id, + redirect_uri: REDIRECT_URI, + response_type: "code", + scope: SCOPE, + state, + code_challenge, + code_challenge_method: "S256", + }); + + const auth_url = buildUrl(base_url, "/oauth/authorize", params); + console.debug("Authorize URL:", auth_url); + location.assign(auth_url); + } + + // Callback + async function handleCallback() { + const url = new URL(location.href); + const code = url.searchParams.get("code"); + const state = url.searchParams.get("state"); + + const savedState = JSON.parse(sessionStorage.getItem(`pkce_${state}`)); + if (!savedState) return; + const codeVerifier = savedState["code_verifier"]; + const app_name = savedState["last_app_name"]; + + console.debug("Callback:", { savedState, origin: location.origin, state, storageKeys: Object.keys(sessionStorage), code, url, codeVerifier, app_name }); + + if (!code) return; + if (!app_name) return; + + const base_url = GITLAB_APP_URLS[app_name] + const client_id = GITLAB_APP_IDS[app_name] + + console.debug("Getting token from", app_name) + + document.querySelector("#token-output").textContent = "Waiting for token ..." + + const body = new URLSearchParams({ + client_id: client_id, + grant_type: "authorization_code", + code, + redirect_uri: REDIRECT_URI, + code_verifier: codeVerifier, + }); + + const resp = await fetch(`${base_url}/oauth/token`, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body + }); + if (!resp.ok) { + console.debug("Fail: ", app_name) + document.querySelector("#token-output").textContent = "Token exchange failed:\n" + await resp.text(); + return; + } + const token = await resp.json(); + + // clean up url + history.replaceState({}, "", REDIRECT_URI); + + // show token + document.querySelector("#token-output").textContent = token.access_token ?? "(no access_token)"; + if (token.access_token) { + return; + } + } + + document.getElementById("oauth-helmholtz-button").onclick = () => startLogin("helmholtz"); + + document.getElementById("oauth-jugit-button").onclick = () => startLogin("jugit"); + + handleCallback().catch(err => { + document.querySelector("#token-output").textContent = "Error:\n" + (err?.message || err); + }); }; From f62555e9423b554b073b7be9f00a1045cf040078 Mon Sep 17 00:00:00 2001 From: Nitai Heeb Date: Fri, 7 Nov 2025 13:35:54 +0100 Subject: [PATCH 2/3] OAuth saves the token directly --- public/gitlab-setup/index.html | 10 ++++----- public/gitlab-setup/main.js | 38 ++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/public/gitlab-setup/index.html b/public/gitlab-setup/index.html index df33429..f75484b 100644 --- a/public/gitlab-setup/index.html +++ b/public/gitlab-setup/index.html @@ -33,12 +33,12 @@

GitLab Account Setup



-

OAUTH!

- - -

Access Token:

-
(noch kein Token)

+

+ Alternatively you can use OAuth: +

+ + diff --git a/public/gitlab-setup/main.js b/public/gitlab-setup/main.js index 8bc3b65..cb127f4 100644 --- a/public/gitlab-setup/main.js +++ b/public/gitlab-setup/main.js @@ -19,14 +19,14 @@ window.onload = async function () { return; } - if (!token.startsWith("glpat")) { - alert("Token is invalid"); - location.reload(); - return; - } + // if (!token.startsWith("glpat")) { + // alert("Token is invalid"); + // location.reload(); + // return; + // } const response = await fetch("https://codebase.helmholtz.cloud/api/v4/user", { - headers: { "Content-Type": "application/json", "PRIVATE-TOKEN": token } + headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}`, "PRIVATE-TOKEN": token } }); if (!response.ok) { @@ -75,6 +75,7 @@ window.onload = async function () { return u.href; } + // Start OAuth async function startLogin(app_name) { const base_url = GITLAB_APP_URLS[app_name] const client_id = GITLAB_APP_IDS[app_name] @@ -104,7 +105,7 @@ window.onload = async function () { location.assign(auth_url); } - // Callback + // OAuth Callback async function handleCallback() { const url = new URL(location.href); const code = url.searchParams.get("code"); @@ -125,8 +126,6 @@ window.onload = async function () { console.debug("Getting token from", app_name) - document.querySelector("#token-output").textContent = "Waiting for token ..." - const body = new URLSearchParams({ client_id: client_id, grant_type: "authorization_code", @@ -141,8 +140,8 @@ window.onload = async function () { body }); if (!resp.ok) { - console.debug("Fail: ", app_name) - document.querySelector("#token-output").textContent = "Token exchange failed:\n" + await resp.text(); + alert("Token exchange failed"); + location.reload(); return; } const token = await resp.json(); @@ -150,18 +149,21 @@ window.onload = async function () { // clean up url history.replaceState({}, "", REDIRECT_URI); - // show token - document.querySelector("#token-output").textContent = token.access_token ?? "(no access_token)"; - if (token.access_token) { - return; - } + // save token + var tokenInput = document.getElementById("token-input"); + var saveButton = document.getElementById("token-save-button"); + console.debug("Token received: ", token.access_token) + tokenInput.value = token.access_token; + saveButton.onclick(); } + // connect buttons document.getElementById("oauth-helmholtz-button").onclick = () => startLogin("helmholtz"); - document.getElementById("oauth-jugit-button").onclick = () => startLogin("jugit"); handleCallback().catch(err => { - document.querySelector("#token-output").textContent = "Error:\n" + (err?.message || err); + alert("Error:\n" + (err?.message || err)); + location.reload(); + return; }); }; From 4ed11be8f533f61c4208d0e24ab384f711a09698 Mon Sep 17 00:00:00 2001 From: Nitai Heeb Date: Tue, 25 Nov 2025 14:48:35 +0100 Subject: [PATCH 3/3] Renamed gitlab-setup site to git-login. Added oauth for gitlab instances. Added module for user and git platform info --- public/git-login/index.html | 53 +++++++ public/git-login/main.js | 280 +++++++++++++++++++++++++++++++++ public/gitlab-setup/index.html | 44 ------ public/gitlab-setup/main.js | 169 -------------------- public/index.html | 2 +- public/main.js | 7 +- public/modules/user.js | 68 ++++++++ public/style.css | 4 + 8 files changed, 410 insertions(+), 217 deletions(-) create mode 100644 public/git-login/index.html create mode 100644 public/git-login/main.js delete mode 100644 public/gitlab-setup/index.html delete mode 100644 public/gitlab-setup/main.js create mode 100644 public/modules/user.js diff --git a/public/git-login/index.html b/public/git-login/index.html new file mode 100644 index 0000000..b19978c --- /dev/null +++ b/public/git-login/index.html @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + GitLab Account Setup | Software CaRD + + + +

Software CaRD

+

GitLab Account Setup

+
+ + +

+
+ + + + diff --git a/public/git-login/main.js b/public/git-login/main.js new file mode 100644 index 0000000..fd4b8f8 --- /dev/null +++ b/public/git-login/main.js @@ -0,0 +1,280 @@ +import * as User from "/modules/user.js" + +window.onload = async function () { + // setup site when user is already logged in + const savedToken = User.getApiToken(); + if (savedToken) { + document.getElementById("token-input").value = savedToken; + const alreadyKnownText = document.getElementById("already-known"); + const name = User.getName(); + const username = User.getUsername(); + // TODO: This feels like a good use case for a web component... + alreadyKnownText.innerHTML = `You are already authenticated as ${name} (${username}).`; + } + + // token save button onclick + var saveButton = document.getElementById("token-save-button"); + saveButton.onclick = async function () { + var tokenInput = document.getElementById("token-input"); + const token = tokenInput.value.trim(); + if (token) { + if (token === savedToken) { + window.location = "../"; + return; + } + const platform_name = User.getGitPlatformName(); + const platform = User.getGitPlatform(); + if (!platform) { + console.debug("No platform saved."); + return; + } + const headers = { "Content-Type": "application/json" }; + if (token.startsWith("glpat")) { + headers["PRIVATE-TOKEN"] = token; + } else { + headers["Authorization"] = `Bearer ${token}`; + } + + const response = await fetch(platform.apiUrl + "/user", { headers }); + + if (!response.ok) { + alert("Could not authenticate"); + location.reload(); + return; + } + + const userData = await response.json(); + + if (platform.host == "gitlab") { + localStorage.setItem("gitlab-username", userData["username"]); + localStorage.setItem("gitlab-name", userData["name"]); + localStorage.setItem("gitlab-api-token", token); + User.setUser(platform_name, token, userData["username"], userData["name"]); + } else { + localStorage.setItem("gitlab-username", userData["login"]); + localStorage.setItem("gitlab-name", userData["name"]); + localStorage.setItem("gitlab-api-token", token); + User.setUser(platform_name, token, userData["login"], userData["name"]); + } + + window.location = "../"; + return; + } + }; + + // Show the authorization UI and update button caption & token link + async function onPlatformSelected(key) { + const select = document.getElementById("platform-select"); + if (key && select.value != key) { + select.value = key; + } + const platform = User.getGitPlatform(key); + const authUI = document.getElementById("auth-ui"); + const oauthBtn = document.getElementById("oauth-button"); + const tokenA = document.getElementById("token-link"); + + // Hide everything if nothing valid is selected + if (!platform) { + authUI.classList.add("hidden"); + console.log("hidden"); + } else { + console.log("show"); + User.setGitPlatform(key); + // show ui + authUI.classList.remove("hidden"); + // Update button caption + oauthBtn.textContent = `Connect to ${platform.shortUrl}`; + // Update token link + if (platform.host == "github") { // github + tokenA.href = `${platform.baseUrl}/settings/personal-access-tokens` + // diable oauth for GitHub for now + document.getElementById("oauth-button").disabled = true; + } else { // gitlab + tokenA.href = `${platform.baseUrl}/-/user_settings/personal_access_tokens`; + document.getElementById("oauth-button").disabled = false; + } + } + } + + const REDIRECT_URI = location.origin + location.pathname; + const SCOPE_GL = "read_api"; + const SCOPE_GH = "read:user user:email repo"; + + // PKCE + const b64url = ab => btoa(String.fromCharCode(...new Uint8Array(ab))) + .replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""); + async function sha256(input) { + const data = new TextEncoder().encode(input); + return await crypto.subtle.digest("SHA-256", data); + } + function randUrlSafe(len=64){ + const b = crypto.getRandomValues(new Uint8Array(len)); + return b64url(b).slice(0, len); + } + + function buildUrl(base, path, params) { + const u = new URL(path, base); + u.search = params.toString(); + return u.href; + } + + // Start OAuth + async function startLoginWithOAuth() { + const platform = User.getGitPlatform(); + if (!platform) {return;} + const base_url = platform.baseUrl; + const client_id = platform.clientId; + const host = platform.host; + + if (!base_url || !client_id) throw new Error("baseUrl and clientId are required."); + + if (host == "github") { + const state = randUrlSafe(24); + const code_verifier = randUrlSafe(96); + const code_challenge = b64url(await sha256(code_verifier)); + + sessionStorage.setItem(`pkce_${state}`, JSON.stringify({ + code_verifier, client_id, base_url, REDIRECT_URI + })); + + const params = new URLSearchParams({ + client_id: client_id, + redirect_uri: REDIRECT_URI, + response_type: "code", + scope: SCOPE_GH, + state, + code_challenge, + code_challenge_method: "S256", + }); + + const auth_url = new URL("/login/oauth/authorize", base_url); + auth_url.search = params.toString(); + console.debug("Authorize URL:", auth_url); + location.assign(auth_url.toString()); + + } else if (host == "gitlab") { + const state = randUrlSafe(24); + const code_verifier = randUrlSafe(96); + const code_challenge = b64url(await sha256(code_verifier)); + + sessionStorage.setItem(`pkce_${state}`, JSON.stringify({ + code_verifier, client_id, base_url, REDIRECT_URI + })); + + const params = new URLSearchParams({ + client_id: client_id, + redirect_uri: REDIRECT_URI, + response_type: "code", + scope: SCOPE_GL, + state, + code_challenge, + code_challenge_method: "S256", + }); + + const auth_url = buildUrl(base_url, "/oauth/authorize", params); + console.debug("Authorize URL:", auth_url); + location.assign(auth_url); + } + } + + // OAuth Callback + async function handleCallback() { + const url = new URL(location.href); + const code = url.searchParams.get("code"); + const state = url.searchParams.get("state"); + + const savedState = JSON.parse(sessionStorage.getItem(`pkce_${state}`)); + if (!savedState) return; + const codeVerifier = savedState["code_verifier"]; + + console.debug("Callback:", { savedState, origin: location.origin, state, storageKeys: Object.keys(sessionStorage), code, url, codeVerifier }); + + if (!code) return; + + console.debug("Got code", code) + + const platform = User.getGitPlatform(); + if (!platform) { + console.debug("No Git Platform saved. Callback invalid."); + location.reload(); + return; + } + + const base_url = platform.baseUrl + const client_id = platform.clientId + + console.debug("Getting token from", platform.label) + + const body = new URLSearchParams({ + client_id: client_id, + grant_type: "authorization_code", + code, + redirect_uri: REDIRECT_URI, + code_verifier: codeVerifier, + }); + let tokenUrl = `${base_url}/oauth/token`; + if (platform.host == "github") { + // tokenUrl = "/cgi-bin/github-token.py"; + // tokenUrl = "https://github.com/login/oauth/access_token" + throw new Error("GitHub Oauth callbacks are not supported"); + } + console.debug("Fetching from ", tokenUrl); + const resp = await fetch(tokenUrl, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json" }, + body + }); + + // Check response + const raw = await resp.text(); + console.debug("Token raw response:", raw || "(empty)"); + if (!resp.ok) { + throw new Error(`Git Host Error ${resp.status}: ${raw || "(empty body)"}`); + } + if (!raw) { + throw new Error("Git Host returned empty body"); + } + + // Get token from response + let token; + try { + token = JSON.parse(raw); + } catch (e) { + throw new Error("Token response is not valid JSON: " + raw); + } + + // clean up url + history.replaceState({}, "", REDIRECT_URI); + + // save token + var tokenInput = document.getElementById("token-input"); + var saveButton = document.getElementById("token-save-button"); + console.debug("Token received: ", token.access_token) + tokenInput.value = token.access_token; + saveButton.onclick(); + } + + // Connect OAuth button + document.getElementById("oauth-button").onclick = () => startLoginWithOAuth(); + + // build platform selection + const select = document.getElementById("platform-select"); + for (const [key, entry] of Object.entries(User.PLATFORMS)) { + const opt = document.createElement("option"); + opt.value = key; + opt.textContent = entry.label; + select.appendChild(opt); + } + // call once to enforce the default hidden state + onPlatformSelected(User.getGitPlatformName() || select.value || null); + // update when the user changes the selection + select.addEventListener("change", (e) => { + onPlatformSelected(e.target.value || null); + }); + + handleCallback().catch(err => { + alert("Error:\n" + (err?.message || err)); + location.reload(); + return; + }); +}; diff --git a/public/gitlab-setup/index.html b/public/gitlab-setup/index.html deleted file mode 100644 index f75484b..0000000 --- a/public/gitlab-setup/index.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - GitLab Account Setup | Software CaRD - - - -

Software CaRD

-

GitLab Account Setup

-

- Please click here to create a personal access token. - Copy it, paste it in the box below, and click "Save". - The token should start with glpat-. -

-

- The token will be saved in the browser. - Do not use this feature on a shared computer account. -

-

-

- - - -

-

-

- Alternatively you can use OAuth: -

- - - - - diff --git a/public/gitlab-setup/main.js b/public/gitlab-setup/main.js deleted file mode 100644 index cb127f4..0000000 --- a/public/gitlab-setup/main.js +++ /dev/null @@ -1,169 +0,0 @@ -window.onload = async function () { - const savedToken = localStorage.getItem("gitlab-api-token"); - if (savedToken) { - document.getElementById("token-input").value = savedToken; - const alreadyKnownText = document.getElementById("already-known"); - const name = localStorage.getItem("gitlab-name"); - const username = localStorage.getItem("gitlab-username"); - // TODO: This feels like a good use case for a web component... - alreadyKnownText.innerHTML = `You are already authenticated as ${name} (${username}).`; - } - - var saveButton = document.getElementById("token-save-button"); - saveButton.onclick = async function () { - var tokenInput = document.getElementById("token-input"); - const token = tokenInput.value.trim(); - if (token) { - if (token === savedToken) { - window.location = "../"; - return; - } - - // if (!token.startsWith("glpat")) { - // alert("Token is invalid"); - // location.reload(); - // return; - // } - - const response = await fetch("https://codebase.helmholtz.cloud/api/v4/user", { - headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}`, "PRIVATE-TOKEN": token } - }); - - if (!response.ok) { - alert("Could not authenticate"); - location.reload(); - return; - } - - const userData = await response.json(); - localStorage.setItem("gitlab-username", userData["username"]); - localStorage.setItem("gitlab-name", userData["name"]); - localStorage.setItem("gitlab-api-token", token); - - window.location = "../"; - return; - } - }; - - const GITLAB_APP_URLS = { - "helmholtz": "https://codebase.helmholtz.cloud", - "jugit": "https://jugit.fz-juelich.de", - }; - const GITLAB_APP_IDS = { - "helmholtz": "24722afbaa0d7c09566902879811c6552afa6a0bbd2cc421ab3e89af4faa2ed8", - "jugit": "7a61209bc6348b8f53820b16a4a86e012ce64965fbf4581f86c22b455e3b5488", - }; - - const REDIRECT_URI = location.origin + location.pathname; - const SCOPE = "read_api"; - - // PKCE Stuff - const b64url = ab => btoa(String.fromCharCode(...new Uint8Array(ab))) - .replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""); - async function sha256(input) { - const data = new TextEncoder().encode(input); - return await crypto.subtle.digest("SHA-256", data); - } - function randUrlSafe(len=64){ - const b = crypto.getRandomValues(new Uint8Array(len)); - return b64url(b).slice(0, len); - } - - function buildUrl(base, path, params) { - const u = new URL(path, base); - u.search = params.toString(); - return u.href; - } - - // Start OAuth - async function startLogin(app_name) { - const base_url = GITLAB_APP_URLS[app_name] - const client_id = GITLAB_APP_IDS[app_name] - - if (!base_url || !client_id) throw new Error("baseUrl and clientId are required."); - - const state = randUrlSafe(24); - const code_verifier = randUrlSafe(96); - const code_challenge = b64url(await sha256(code_verifier)); - - sessionStorage.setItem(`pkce_${state}`, JSON.stringify({ - code_verifier, client_id, base_url, REDIRECT_URI, last_app_name: app_name - })); - - const params = new URLSearchParams({ - client_id: client_id, - redirect_uri: REDIRECT_URI, - response_type: "code", - scope: SCOPE, - state, - code_challenge, - code_challenge_method: "S256", - }); - - const auth_url = buildUrl(base_url, "/oauth/authorize", params); - console.debug("Authorize URL:", auth_url); - location.assign(auth_url); - } - - // OAuth Callback - async function handleCallback() { - const url = new URL(location.href); - const code = url.searchParams.get("code"); - const state = url.searchParams.get("state"); - - const savedState = JSON.parse(sessionStorage.getItem(`pkce_${state}`)); - if (!savedState) return; - const codeVerifier = savedState["code_verifier"]; - const app_name = savedState["last_app_name"]; - - console.debug("Callback:", { savedState, origin: location.origin, state, storageKeys: Object.keys(sessionStorage), code, url, codeVerifier, app_name }); - - if (!code) return; - if (!app_name) return; - - const base_url = GITLAB_APP_URLS[app_name] - const client_id = GITLAB_APP_IDS[app_name] - - console.debug("Getting token from", app_name) - - const body = new URLSearchParams({ - client_id: client_id, - grant_type: "authorization_code", - code, - redirect_uri: REDIRECT_URI, - code_verifier: codeVerifier, - }); - - const resp = await fetch(`${base_url}/oauth/token`, { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body - }); - if (!resp.ok) { - alert("Token exchange failed"); - location.reload(); - return; - } - const token = await resp.json(); - - // clean up url - history.replaceState({}, "", REDIRECT_URI); - - // save token - var tokenInput = document.getElementById("token-input"); - var saveButton = document.getElementById("token-save-button"); - console.debug("Token received: ", token.access_token) - tokenInput.value = token.access_token; - saveButton.onclick(); - } - - // connect buttons - document.getElementById("oauth-helmholtz-button").onclick = () => startLogin("helmholtz"); - document.getElementById("oauth-jugit-button").onclick = () => startLogin("jugit"); - - handleCallback().catch(err => { - alert("Error:\n" + (err?.message || err)); - location.reload(); - return; - }); -}; diff --git a/public/index.html b/public/index.html index 11e3a09..c4da6c5 100644 --- a/public/index.html +++ b/public/index.html @@ -19,7 +19,7 @@

Welcome

You can do the following:

    -
  1. Set up the connection to your GitLab account.
  2. +
  3. Set up the connection to your GitLab account.
  4. Load an example CI pipeline.
  5. Load the diff --git a/public/main.js b/public/main.js index d52c67c..d54c9f4 100644 --- a/public/main.js +++ b/public/main.js @@ -1,10 +1,11 @@ import { deleteAllPipelines } from "./modules/storage.js"; +import * as User from "/modules/user.js" window.onload = async function () { - const gitLabName = localStorage.getItem("gitlab-name"); - if (gitLabName) { + const username = User.getName() || User.getUsername(); + if (username) { const welcomeUsernameSpan = document.getElementById("welcome-username"); - welcomeUsernameSpan.innerText = ", " + gitLabName; + welcomeUsernameSpan.innerText = ", " + username; } const clearAllDataButton = document.getElementById("clear-all-data-button"); diff --git a/public/modules/user.js b/public/modules/user.js new file mode 100644 index 0000000..fec04c6 --- /dev/null +++ b/public/modules/user.js @@ -0,0 +1,68 @@ +export const PLATFORMS = { + jugit: { + label: "Jugit GitLab", + host: "gitlab", + baseUrl: "https://jugit.fz-juelich.de", + shortUrl: "jugit.fz-juelich.de", + apiUrl: "https://jugit.fz-juelich.de/api/v4", + clientId: "7a61209bc6348b8f53820b16a4a86e012ce64965fbf4581f86c22b455e3b5488", + }, + helmholtz: { + label: "Helmholtz GitLab", + host: "gitlab", + baseUrl: "https://codebase.helmholtz.cloud", + shortUrl: "codebase.helmholtz.cloud", + apiUrl: "https://codebase.helmholtz.cloud/api/v4", + clientId: "24722afbaa0d7c09566902879811c6552afa6a0bbd2cc421ab3e89af4faa2ed8", + }, + gitlab: { + label: "Global GitLab", + host: "gitlab", + baseUrl: "https://gitlab.com", + shortUrl: "gitlab.com", + apiUrl: "https://gitlab.com/api/v4", + clientId: "1133e9cee188c31bd68c9d0e8531774a4aae9d2458e13d83e67991213f868007", + }, + github: { + label: "GitHub", + host: "github", + baseUrl: "https://github.com", + shortUrl: "github.com", + apiUrl: "https://api.github.com", + clientId: "Ov23liQZskHsZ2MKgYhB", + }, + }; + +export function setUser(gitPlatform, apiToken, username, name) { + for (const [key, val] of [ + ["username", username], + ["name", name], + ["api-token", apiToken], + ["git-platform", gitPlatform], + ]) { + if (val == null) { + localStorage.removeItem(key) + } else { + localStorage.setItem(key, String(val)); + } + } +} + +export function setGitPlatform(platform_name) { + localStorage.setItem("git-platform-name", String(platform_name)); +} + +export function getUsername() { return localStorage.getItem("username"); } +export function getName() { return localStorage.getItem("name"); } +export function getApiToken() { return localStorage.getItem("api-token"); } +export function getGitPlatformName() { return localStorage.getItem("git-platform-name"); } + +export function getGitPlatform(platform = getGitPlatformName()) { + const key = (platform ?? "").toLowerCase().trim(); + if (!key) return null; + + const entry = PLATFORMS[key]; + if (!entry) return null; + + return entry; +} \ No newline at end of file diff --git a/public/style.css b/public/style.css index 368f3ea..a5e83fc 100644 --- a/public/style.css +++ b/public/style.css @@ -94,3 +94,7 @@ opacity: 1; .error{ color: red; } + +.hidden { + display: none; +}