From b85892b957721fdfafde6f6342a786883cf3fcaf Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jul 2023 11:19:28 +0530 Subject: [PATCH 1/2] fix: Dev authentication --- src/App.tsx | 8 +-- src/constants.ts | 2 +- src/hooks/useAuth.ts | 70 ++++++++++++++++---------- src/utils/checkAuthentication.ts | 46 +---------------- src/utils/fetchOpenSaucedApiData.ts | 13 +---- src/utils/setAccessToken.ts | 4 +- src/worker/background.ts | 24 --------- test/utils/checkAuthentication.test.ts | 43 ---------------- 8 files changed, 50 insertions(+), 160 deletions(-) delete mode 100644 test/utils/checkAuthentication.test.ts diff --git a/src/App.tsx b/src/App.tsx index 822f4e0b..280afc14 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,25 +1,19 @@ import { useEffect } from "react"; import Start from "./popup/pages/start"; import Home from "./popup/pages/home"; -import Loading from "./popup/pages/loading"; import { useAuth } from "./hooks/useAuth"; import { goTo } from "react-chrome-extension-router"; const App = () => { const { isTokenValid } = useAuth(); - useEffect(() => { if (isTokenValid) { goTo(Home); - } else { - goTo(Start); } }, [isTokenValid]); - return ( - - ); + return ; }; export default App; diff --git a/src/constants.ts b/src/constants.ts index de1727f2..89bd99e8 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,7 +4,7 @@ export const OPEN_SAUCED_API_ENDPOINT = import.meta.env.VITE_OPEN_SAUCED_API_END export const SUPABASE_LOGIN_URL = `https://${import.meta.env.VITE_OPEN_SAUCED_SUPABASE_ID}.supabase.co/auth/v1/authorize?provider=github&redirect_to=https://${OPEN_SAUCED_INSIGHTS_DOMAIN}/`; -export const SUPABASE_AUTH_COOKIE_NAME = "supabase-auth-token"; +export const SUPABASE_AUTH_COOKIE_NAME = import.meta.env.PROD ? "supabase-auth-token" : `sb-${import.meta.env.VITE_OPEN_SAUCED_SUPABASE_ID}-auth-token`; export const OPEN_SAUCED_AUTH_TOKEN_KEY = "os-access-token"; export const OPEN_SAUCED_OPTED_LOG_OUT_KEY = "opted-log-out"; export const AI_PR_DESCRIPTION_CONFIG_KEY = "ai-pr-description-config"; diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts index 5483f901..9da38913 100644 --- a/src/hooks/useAuth.ts +++ b/src/hooks/useAuth.ts @@ -1,49 +1,65 @@ import { useEffect, useState } from "react"; -import { OPEN_SAUCED_AUTH_TOKEN_KEY, OPEN_SAUCED_SESSION_ENDPOINT } from "../constants"; +import { + OPEN_SAUCED_INSIGHTS_DOMAIN, + OPEN_SAUCED_SESSION_ENDPOINT, + SUPABASE_AUTH_COOKIE_NAME, +} from "../constants"; import { cachedFetch } from "../utils/cache"; - -const removeTokenFromStorage = async () => new Promise(resolve => { - chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY, () => { - resolve(true); - }); -}); +import { + hasOptedLogOut, + removeAuthTokenFromStorage, +} from "../utils/checkAuthentication"; +import setAuthTokenInChromeStorage from "../utils/setAccessToken"; export const useAuth = () => { const [authToken, setAuthToken] = useState(null); - const [user, setUser] = useState(null); - const [isTokenValid, setIsTokenValid] = useState(null); + const [user, setUser] = useState( + null, + ); + const [isTokenValid, setIsTokenValid] = useState(false); useEffect(() => { - chrome.storage.sync.get([OPEN_SAUCED_AUTH_TOKEN_KEY], async result => { - if (result[OPEN_SAUCED_AUTH_TOKEN_KEY]) { - setAuthToken(result[OPEN_SAUCED_AUTH_TOKEN_KEY]); + const authenticate = async () => { + try { + if (await hasOptedLogOut()) { + return; + } + const cookie = await chrome.cookies.get({ + name: SUPABASE_AUTH_COOKIE_NAME, + url: `https://${OPEN_SAUCED_INSIGHTS_DOMAIN}`, + }); + + if (!cookie) { + return removeAuthTokenFromStorage(); + } + const token = JSON.parse(decodeURIComponent(cookie.value))[0]; - const resp = await cachedFetch(OPEN_SAUCED_SESSION_ENDPOINT, { + const response = await cachedFetch(OPEN_SAUCED_SESSION_ENDPOINT, { expireInSeconds: 2 * 60 * 60, headers: { - Authorization: `Bearer ${result[OPEN_SAUCED_AUTH_TOKEN_KEY]}`, + Authorization: `Bearer ${token}`, Accept: "application/json", }, }); - if (!resp?.ok) { - removeTokenFromStorage().then(() => { - setAuthToken(null); - setUser(null); - setIsTokenValid(false); - return null; - }) - .catch(console.error); - } else { - const json = await resp.json(); + if (response?.ok) { + const json = await response.json(); setUser(json); setIsTokenValid(true); + setAuthToken(token); + void setAuthTokenInChromeStorage(token); + } else { + await removeAuthTokenFromStorage(); + } + } catch (error) { + if (error instanceof Error) { + console.error(error.message); } - } else { - setIsTokenValid(false); } - }); + }; + + void authenticate(); }, []); return { authToken, user, isTokenValid }; diff --git a/src/utils/checkAuthentication.ts b/src/utils/checkAuthentication.ts index 4fd3b94a..51741f80 100644 --- a/src/utils/checkAuthentication.ts +++ b/src/utils/checkAuthentication.ts @@ -1,57 +1,15 @@ import { OPEN_SAUCED_AUTH_TOKEN_KEY, - OPEN_SAUCED_OPTED_LOG_OUT_KEY, - SUPABASE_AUTH_COOKIE_NAME, - OPEN_SAUCED_INSIGHTS_DOMAIN, - SUPABASE_LOGIN_URL, + OPEN_SAUCED_OPTED_LOG_OUT_KEY, SUPABASE_LOGIN_URL, } from "../constants"; -export const checkAuthentication = async ( - hasOptedLogOut: () => Promise, - getCookie: ( - details: chrome.cookies.Details, - callback: (cookie: chrome.cookies.Cookie | null) => void - ) => void, - checkTokenValidity: (authCookie: any) => Promise, - setAccessTokenInChromeStorage: (authCookie: any) => void, - removeAuthTokenFromStorage: () => void, - logError: (error: string) => void, -) => { - if (await hasOptedLogOut()) { - return removeAuthTokenFromStorage(); - } - - getCookie( - { - name: SUPABASE_AUTH_COOKIE_NAME, - url: `https://${OPEN_SAUCED_INSIGHTS_DOMAIN}`, - }, - async cookie => { - if (!cookie) { - return removeAuthTokenFromStorage(); - } - try { - const authCookie = JSON.parse(decodeURIComponent(cookie.value))[0]; - const isValidToken = await checkTokenValidity(authCookie); - - if (!isValidToken) { - return removeAuthTokenFromStorage(); - } - setAccessTokenInChromeStorage(authCookie); - } catch (error) { - removeAuthTokenFromStorage(); - logError(error as string); - } - }, - ); -}; export const isLoggedIn = async (): Promise => Object.entries(await chrome.storage.sync.get(OPEN_SAUCED_AUTH_TOKEN_KEY)).length !== 0; export const getAuthToken = async (): Promise => (await chrome.storage.sync.get(OPEN_SAUCED_AUTH_TOKEN_KEY))[OPEN_SAUCED_AUTH_TOKEN_KEY]; export const optLogOut = () => { - void chrome.storage.sync.remove(OPEN_SAUCED_AUTH_TOKEN_KEY); + void removeAuthTokenFromStorage(); void chrome.storage.local.set({ [OPEN_SAUCED_OPTED_LOG_OUT_KEY]: true }); }; diff --git a/src/utils/fetchOpenSaucedApiData.ts b/src/utils/fetchOpenSaucedApiData.ts index f71afc10..8c9dc027 100644 --- a/src/utils/fetchOpenSaucedApiData.ts +++ b/src/utils/fetchOpenSaucedApiData.ts @@ -1,8 +1,6 @@ import { cachedFetch } from "./cache"; import { - OPEN_SAUCED_USERS_ENDPOINT, - OPEN_SAUCED_SESSION_ENDPOINT, - OPEN_SAUCED_REPOS_ENDPOINT, + OPEN_SAUCED_USERS_ENDPOINT, OPEN_SAUCED_REPOS_ENDPOINT, OPEN_SAUCED_USER_INSIGHTS_ENDPOINT, OPEN_SAUCED_USER_HIGHLIGHTS_ENDPOINT, OPEN_SAUCED_HIGHLIGHTS_LIST_ENDPOINT, @@ -29,15 +27,6 @@ export const isOpenSaucedUser = async (username: string) => { } }; -export const checkTokenValidity = async (token: string) => { - const response = await fetch(OPEN_SAUCED_SESSION_ENDPOINT, { - method: "GET", - headers: { Authorization: `Bearer ${token}` }, - }); - - return response.status === 200; -}; - export const getUserData = async (userName: string, forceRefresh: boolean = false) => cachedFetch(`${OPEN_SAUCED_USERS_ENDPOINT}/${userName}`, { expireInSeconds: 2 * 60 * 60, forceRefresh, diff --git a/src/utils/setAccessToken.ts b/src/utils/setAccessToken.ts index eb885e4e..92a4a8f5 100644 --- a/src/utils/setAccessToken.ts +++ b/src/utils/setAccessToken.ts @@ -1,6 +1,6 @@ import { OPEN_SAUCED_AUTH_TOKEN_KEY } from "../constants"; -const setAccessTokenInChromeStorage = async (accessToken: string): Promise => new Promise((resolve, reject) => { +const setAuthTokenInChromeStorage = async (accessToken: string): Promise => new Promise((resolve, reject) => { chrome.storage.sync.set({ [OPEN_SAUCED_AUTH_TOKEN_KEY]: accessToken }, () => { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); @@ -10,5 +10,5 @@ const setAccessTokenInChromeStorage = async (accessToken: string): Promise }); }); -export default setAccessTokenInChromeStorage; +export default setAuthTokenInChromeStorage; diff --git a/src/worker/background.ts b/src/worker/background.ts index 48a52a18..1e6e9563 100644 --- a/src/worker/background.ts +++ b/src/worker/background.ts @@ -1,27 +1,3 @@ -import { checkAuthentication, hasOptedLogOut, removeAuthTokenFromStorage } from "../utils/checkAuthentication"; -import { SUPABASE_AUTH_COOKIE_NAME, OPEN_SAUCED_INSIGHTS_DOMAIN } from "../constants"; import { setDefaultDescriptionConfig } from "../utils/ai-utils/descriptionconfig"; -import { checkTokenValidity } from "../utils/fetchOpenSaucedApiData"; -import setAccessTokenInChromeStorage from "../utils/setAccessToken"; - -const checkUserAuthentication = () => { - void checkAuthentication(hasOptedLogOut, chrome.cookies.get, checkTokenValidity, setAccessTokenInChromeStorage, removeAuthTokenFromStorage, console.error); -}; - -chrome.cookies.onChanged.addListener(changeInfo => { - if ( - changeInfo.cookie.name === SUPABASE_AUTH_COOKIE_NAME || - changeInfo.cookie.domain === OPEN_SAUCED_INSIGHTS_DOMAIN - ) { - checkUserAuthentication(); - } -}); - -chrome.runtime.onInstalled.addListener(() => { - checkUserAuthentication(); -}); chrome.runtime.onInstalled.addListener(setDefaultDescriptionConfig); -chrome.runtime.onStartup.addListener(() => { - checkUserAuthentication(); -}); diff --git a/test/utils/checkAuthentication.test.ts b/test/utils/checkAuthentication.test.ts deleted file mode 100644 index 3cb92a3e..00000000 --- a/test/utils/checkAuthentication.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { describe, it, expect, beforeEach, vi } from 'vitest'; -import { checkAuthentication } from '../../src/utils/checkAuthentication'; - - -const hasOptedLogOut = vi.fn().mockResolvedValue(false); -const getCookie = vi.fn(); -const checkTokenValidity = vi.fn().mockResolvedValue(true); -const setAccessTokenInChromeStorage = vi.fn(); -const removeAuthTokenFromStorage = vi.fn(); -const logError = vi.fn(); - -describe('checkAuthentication', () => { - beforeEach(() => { - vi.resetAllMocks(); - }); - - it('should remove auth token from storage if user has opted out', async () => { - hasOptedLogOut.mockResolvedValue(true); - await checkAuthentication( - hasOptedLogOut, - getCookie, - checkTokenValidity, - setAccessTokenInChromeStorage, - removeAuthTokenFromStorage, - logError, - ); - expect(removeAuthTokenFromStorage).toHaveBeenCalled(); - }); - - it('should remove auth token from storage if cookie is not found', async () => { - getCookie.mockImplementation((details, callback) => callback(null)); - await checkAuthentication( - hasOptedLogOut, - getCookie, - checkTokenValidity, - setAccessTokenInChromeStorage, - removeAuthTokenFromStorage, - logError, - ); - expect(removeAuthTokenFromStorage).toHaveBeenCalled(); - }); -}) - \ No newline at end of file From cc76e950a33d30677e2eb37fadb3d318ceca2d5b Mon Sep 17 00:00:00 2001 From: Anush008 Date: Sat, 15 Jul 2023 11:20:04 +0530 Subject: [PATCH 2/2] fix: always truthy check --- src/popup/pages/home.tsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/popup/pages/home.tsx b/src/popup/pages/home.tsx index f31c1036..2d319915 100644 --- a/src/popup/pages/home.tsx +++ b/src/popup/pages/home.tsx @@ -54,7 +54,7 @@ const Home = () => { const emojiResponse = await getEmojis(); const emojis = emojiResponse.data; - if (!emojis) { + if (!emojis.length) { return; } @@ -167,14 +167,12 @@ const Home = () => { .then(data => chrome.tabs.create( { url: "https://www.linkedin.com/in/me/edit/forms/project/new/", active: true }, tab => { - chrome.scripting + void chrome.scripting .executeScript({ target: { tabId: tab.id! }, func: populateDataToLinkedIn, args: [data], - }) - .then(() => console.log("script injected")) - .catch(err => console.log(err)); + }); }, ))