diff --git a/src/github-auth.js b/src/github-auth.js index e7aba8f..bd8036a 100644 --- a/src/github-auth.js +++ b/src/github-auth.js @@ -12,7 +12,8 @@ const GITHUB_CONFIG = { apiBaseUrl: 'https://api.github.com', owner: 'super3', - repo: 'dashban' + repo: 'dashban', + appSlug: 'dashban' }; // Origin of the backend API. The frontend can be served three ways: @@ -72,6 +73,36 @@ async function githubFetch(path, options = {}) { return fetch(url, { ...options, headers }); } +// "Manage GitHub access" deep link. GitHub's only page that lands directly on an +// app's repository access is /settings/installations/, and that +// id is unique to each user's installation — it can't be hardcoded. So we look it +// up once (via the authenticated proxy: GET /user/installations) and cache it, +// falling back to the app's public page until/unless the lookup succeeds. +const MANAGE_ACCESS_FALLBACK_URL = `https://github.com/apps/${GITHUB_CONFIG.appSlug}`; +let manageAccessUrl = MANAGE_ACCESS_FALLBACK_URL; + +async function refreshManageAccessUrl() { + // Already resolved to a real installation, or no session to look it up with. + if (manageAccessUrl !== MANAGE_ACCESS_FALLBACK_URL || !isGitHubAuthed()) { + return manageAccessUrl; + } + try { + const response = await githubFetch('/user/installations'); + if (response.ok) { + const data = await response.json(); + const installation = (data.installations || []).find( + (entry) => entry.app_slug === GITHUB_CONFIG.appSlug + ); + if (installation) { + manageAccessUrl = `https://github.com/settings/installations/${installation.id}`; + } + } + } catch { + // Network/parse error — keep the fallback URL. + } + return manageAccessUrl; +} + // Initialize auth UI. Clerk (clerk-auth.js, kicked off by github.js) drives the // actual sign-in and calls back into updateGitHubSignInUI() when the session // changes; here we just render the initial signed-out state. @@ -182,8 +213,14 @@ function toggleUserDropdown() { // Create dropdown const dropdown = document.createElement('div'); - dropdown.className = 'user-dropdown absolute right-0 top-full mt-2 w-48 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50'; + dropdown.className = 'user-dropdown absolute right-0 top-full mt-2 w-56 bg-white rounded-lg shadow-lg border border-gray-200 py-1 z-50'; dropdown.innerHTML = ` + + + Manage GitHub access + +