From 498c806252cc0802b9c145316d90dc68a9b67fab Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun, 3 Mar 2024 17:56:08 +0000 Subject: [PATCH] chore: rate limit modal and auto login --- .env.example | 3 +- build/esbuild-build.ts | 2 +- cypress/e2e/devpool.cy.ts | 3 +- src/home/fetch-github/fetch-issues-preview.ts | 29 ++++++++++++++++--- src/home/getters/get-github-access-token.ts | 5 ++-- src/home/getters/get-github-user.ts | 3 +- .../rendering/render-github-login-button.ts | 9 +++++- 7 files changed, 43 insertions(+), 11 deletions(-) diff --git a/.env.example b/.env.example index b779b700..72d1813b 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ SUPABASE_URL= -SUPABASE_ANON_KEY= +SUPABASE_REF= +SUPABASE_ANON_KEY= \ No newline at end of file diff --git a/build/esbuild-build.ts b/build/esbuild-build.ts index 741a482d..92a5cd6a 100644 --- a/build/esbuild-build.ts +++ b/build/esbuild-build.ts @@ -7,7 +7,7 @@ const cssEntries = ["static/style/style.css"]; const entries = [...typescriptEntries, ...cssEntries, "static/manifest.json", "static/favicon.svg", "static/icon-512x512.png"]; export const esBuildContext: esbuild.BuildOptions = { - define: createEnvDefines(["SUPABASE_URL", "SUPABASE_ANON_KEY"]), + define: createEnvDefines(["SUPABASE_URL", "SUPABASE_ANON_KEY", "SUPABASE_REF"]), plugins: [invertColors, pwaManifest], sourcemap: true, entryPoints: entries, diff --git a/cypress/e2e/devpool.cy.ts b/cypress/e2e/devpool.cy.ts index 13cc3291..f947d858 100644 --- a/cypress/e2e/devpool.cy.ts +++ b/cypress/e2e/devpool.cy.ts @@ -1,5 +1,6 @@ import { RestEndpointMethodTypes } from "@octokit/rest"; import { OAuthToken } from "../../src/home/getters/get-github-access-token"; +import { getSupabaseRef } from "../../src/home/rendering/render-github-login-button"; describe("DevPool", () => { let issue1: RestEndpointMethodTypes["issues"]["get"]["response"]["data"]; @@ -139,7 +140,7 @@ describe("DevPool", () => { statusCode: 200, }); // Simulate login token - window.localStorage.setItem("sb-wfzpewmlyiozupulbuur-auth-token", JSON.stringify(loginToken)); + window.localStorage.setItem(`sb-${getSupabaseRef()}-auth-token`, JSON.stringify(loginToken)); }).as("githubLogin"); cy.visit("/"); cy.get("#github-login-button").click(); diff --git a/src/home/fetch-github/fetch-issues-preview.ts b/src/home/fetch-github/fetch-issues-preview.ts index 67027552..0958bbca 100644 --- a/src/home/fetch-github/fetch-issues-preview.ts +++ b/src/home/fetch-github/fetch-issues-preview.ts @@ -4,9 +4,12 @@ import { GitHubIssue } from "../github-types"; import { taskManager } from "../home"; import { displayPopupMessage } from "../rendering/display-popup-modal"; import { TaskNoFull } from "./preview-to-full-mapping"; +import { getGitHubUser } from "../getters/get-github-user"; +import { gitHubLoginButtonHandler } from "../rendering/render-github-login-button"; export async function fetchIssuePreviews(): Promise { const octokit = new Octokit({ auth: getGitHubAccessToken() }); + const user = await getGitHubUser(); let freshIssues: GitHubIssue[] = []; try { @@ -17,8 +20,23 @@ export async function fetchIssuePreviews(): Promise { if (403 === error.status) { console.error(`GitHub API rate limit exceeded.`); if (taskManager.getTasks().length == 0) { - // automatically login if there are no issues loaded - automaticLogin(error); + if (!user || user === null) { + // only show rate limit modal if there are no issues loaded and not logged in + rateLimitModal(error); + } else { + // otherwise we have a user and no issues loaded + // this happens processing the auth token it seems + // as it happens on auth callback and local auth token + await gitHubLoginButtonHandler().catch((error) => { + console.error(error); + }); + } + } else if (user && user !== null) { + // Tasks loaded and logged in + rateLimitModal(error, `You have been rate limited. Please try again at `); + } else { + // tasks loaded but not logged in + rateLimitModal(error); } } else { console.error(`Failed to fetch issue previews: ${error}`); @@ -34,12 +52,15 @@ export async function fetchIssuePreviews(): Promise { return tasks; } -function automaticLogin(error: unknown) { + +function rateLimitModal(error: unknown, message?: string) { const resetTime = error.response.headers["x-ratelimit-reset"]; const resetParsed = new Date(resetTime * 1000).toLocaleTimeString(); displayPopupMessage( `GitHub API rate limit exceeded.`, - `You have been rate limited. Please log in to GitHub to increase your GitHub API limits, otherwise you can try again at ${resetParsed}.` + !message + ? `You have been rate limited. Please log in to GitHub to increase your GitHub API limits, otherwise you can try again at ${resetParsed}.` + : message + `${resetParsed}.` ); } diff --git a/src/home/getters/get-github-access-token.ts b/src/home/getters/get-github-access-token.ts index c0bdec51..9af767d0 100644 --- a/src/home/getters/get-github-access-token.ts +++ b/src/home/getters/get-github-access-token.ts @@ -1,12 +1,13 @@ +import { getSupabaseRef } from "../rendering/render-github-login-button"; import { getLocalStore } from "./get-local-store"; export function getGitHubAccessToken(): string | null { - const oauthToken = getLocalStore("sb-wfzpewmlyiozupulbuur-auth-token") as OAuthToken | null; + const oauthToken = getLocalStore(`sb-${getSupabaseRef()}-auth-token`) as OAuthToken | null; const expiresAt = oauthToken?.expires_at; if (expiresAt) { if (expiresAt < Date.now() / 1000) { - localStorage.removeItem("sb-wfzpewmlyiozupulbuur-auth-token"); + localStorage.removeItem(`sb-${getSupabaseRef()}-auth-token`); return null; } } diff --git a/src/home/getters/get-github-user.ts b/src/home/getters/get-github-user.ts index 064c4b36..220ab6af 100644 --- a/src/home/getters/get-github-user.ts +++ b/src/home/getters/get-github-user.ts @@ -2,6 +2,7 @@ import { Octokit } from "@octokit/rest"; import { GitHubUser, GitHubUserResponse } from "../github-types"; import { OAuthToken } from "./get-github-access-token"; import { getLocalStore } from "./get-local-store"; +import { getSupabaseRef } from "../rendering/render-github-login-button"; export async function getGitHubUser(): Promise { const activeSessionToken = await getSessionToken(); @@ -13,7 +14,7 @@ export async function getGitHubUser(): Promise { } async function getSessionToken(): Promise { - const cachedSessionToken = getLocalStore("sb-wfzpewmlyiozupulbuur-auth-token") as OAuthToken | null; + const cachedSessionToken = getLocalStore(`sb-${getSupabaseRef()}-auth-token`) as OAuthToken | null; if (cachedSessionToken) { return cachedSessionToken.provider_token; } diff --git a/src/home/rendering/render-github-login-button.ts b/src/home/rendering/render-github-login-button.ts index 5c724440..1f0d01bc 100644 --- a/src/home/rendering/render-github-login-button.ts +++ b/src/home/rendering/render-github-login-button.ts @@ -6,13 +6,20 @@ if (!supabaseUrl) throw new Error("SUPABASE_URL not found"); const supabaseAnonKey = process.env.SUPABASE_ANON_KEY; if (!supabaseAnonKey) throw new Error("SUPABASE_ANON_KEY not found"); +export function getSupabaseRef(): string { + const supabaseRef = process.env.SUPABASE_REF; + if (!supabaseRef) throw new Error("SUPABASE_REF not found"); + + return supabaseRef; +} + const supabase = createClient(supabaseUrl, supabaseAnonKey); export function getSupabase() { return supabase; } -async function gitHubLoginButtonHandler() { +export async function gitHubLoginButtonHandler() { const { error } = await supabase.auth.signInWithOAuth({ provider: "github" }); if (error) { console.error("Error logging in:", error);