Skip to content
This repository has been archived by the owner on Sep 26, 2024. It is now read-only.

Commit

Permalink
[MOC-218] handle login logout gracefully (#162)
Browse files Browse the repository at this point in the history
* fix eslint errors

* open auth tab if no creds are found, else mount extension

* make the code rabbit happy

* check jwt exp

* actually check if jwt is expired

* cleanup

---------

Co-authored-by: Kayla Fitzsimmons <[email protected]>
  • Loading branch information
fitzk and Kayla Fitzsimmons authored Aug 27, 2024
1 parent 66a67e6 commit fd38a37
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 33 deletions.
8 changes: 7 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
// This configuration only applies to the package manager root.
/** @type {import("eslint").Linter.Config} */
module.exports = {
ignorePatterns: ["apps/**", "packages/**"],
extends: ["@repo/eslint-config/library.js"],
ignorePatterns: ["apps/**", "packages/**"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: true,
},
plugins: ["@typescript-eslint"],
root: true,
rules: {
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"no-unused-vars": "off",
},
};
9 changes: 8 additions & 1 deletion apps/mocksi-lite-next/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@
"@typescript-eslint"
],
"rules": {
"react/react-in-jsx-scope": "off"
"react/react-in-jsx-scope": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_"
}
]
},
"globals": {
"chrome": "readonly"
Expand Down
1 change: 1 addition & 0 deletions apps/mocksi-lite-next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"dependencies": {
"@repo/reactor": "workspace:*",
"jwt-decode": "^4.0.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"uuid": "^9.0.1",
Expand Down
56 changes: 35 additions & 21 deletions apps/mocksi-lite-next/src/pages/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { jwtDecode } from "jwt-decode";

console.log("background script loaded");
const MOCKSI_AUTH = "mocksi-auth";

Expand All @@ -7,12 +9,23 @@ const getAuth = async (): Promise<null | {
}> => {
try {
const storageAuth = await chrome.storage.local.get(MOCKSI_AUTH);
if (!storageAuth[MOCKSI_AUTH]) {
return null;
}
const mocksiAuth = JSON.parse(storageAuth[MOCKSI_AUTH]);
const jwtPayload = jwtDecode(mocksiAuth.accessToken);
const isExpired = jwtPayload.exp && Date.now() >= jwtPayload.exp * 1000;

if (isExpired) {
console.log("token expired, clearing chrome storage");
await clearAuth();
return null;
}
return mocksiAuth;
} catch (err) {
console.error(err);
return null;
}
return null;
};

const clearAuth = async (): Promise<void> => {
Expand All @@ -31,19 +44,22 @@ async function getCurrentTab() {
return tab;
}

function showAuthTab() {
return new Promise((resolve: (value?: unknown) => void) => {
async function showAuthTab(force?: boolean) {
return new Promise(async (resolve: (value?: unknown) => void) => {
chrome.tabs.query({}, function (tabs) {
let tabExists = false;
for (const tab of tabs) {
const tabUrlStr = tab.url || tab.pendingUrl || "";
const loadUrl = new URL(import.meta.env.VITE_NEST_APP);
const tabUrl = new URL(tabUrlStr);
if (loadUrl.href === tabUrl.href) {
tabExists = true;
break;
if (!force) {
for (const tab of tabs) {
const tabUrlStr = tab.url || tab.pendingUrl || "";
const loadUrl = new URL(import.meta.env.VITE_NEST_APP);
const tabUrl = new URL(tabUrlStr);
if (loadUrl.href === tabUrl.href) {
tabExists = true;
break;
}
}
}

if (!tabExists) {
chrome.tabs.create({ url: import.meta.env.VITE_NEST_APP }, resolve);
} else {
Expand Down Expand Up @@ -71,7 +87,6 @@ chrome.action.onClicked.addListener((tab) => {

chrome.runtime.onMessage.addListener(
(request, _sender, sendResponse): boolean => {
console.log("Received message:", request);
sendResponse({
data: request.data,
message: request.message,
Expand All @@ -88,7 +103,13 @@ chrome.runtime.onMessageExternal.addListener(
// execute in async block so that we return true
// synchronously, telling chrome to wait for the response
(async () => {
if (request.message === "UNAUTHORIZED") {
if (request.message === "AUTH_ERROR") {
await clearAuth();
sendResponse({
message: "retry",
status: "ok",
});
} else if (request.message === "UNAUTHORIZED") {
const auth = await getAuth();
if (auth) {
const { accessToken, email } = auth;
Expand All @@ -98,25 +119,18 @@ chrome.runtime.onMessageExternal.addListener(
status: "ok",
});
} else {
await showAuthTab();
await showAuthTab(true);
sendResponse({
message: "authenticating",
status: "ok",
});
}
} else if (request.message === "AUTH_ERROR") {
await clearAuth();
await showAuthTab();
sendResponse({
message: "authenticating",
status: "ok",
});
} else {
const tab = await getCurrentTab();
if (!tab.id) {
sendResponse({ message: request.message, status: "no-tab" });
console.log("No active tab found, could not send message");
return;
return true;
}
chrome.tabs.sendMessage(
tab.id,
Expand Down
25 changes: 15 additions & 10 deletions apps/mocksi-lite-next/src/pages/content/mocksi-extension.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import { getHighlighter } from "./highlighter";
const STORAGE_CHANGE_EVENT = "MOCKSI_STORAGE_CHANGE";

const div = document.createElement("div");
div.id = "__root";
div.id = "__mocksi__root";
document.body.appendChild(div);
let mounted = false;
const reactor = new Reactor();

window.addEventListener("message", (event: MessageEvent) => {
const eventData = event.data;

if (event.source !== window || !eventData || !eventData.type) {
return;
}
Expand All @@ -28,7 +29,7 @@ window.addEventListener("message", (event: MessageEvent) => {

chrome.runtime.onMessage.addListener((request) => {
if (request.message === "mount-extension") {
const rootContainer = document.querySelector("#__root");
const rootContainer = document.querySelector("#__mocksi__root");
if (!rootContainer) throw new Error("Can't find Content root element");
const root = createRoot(rootContainer);
const Iframe = () => {
Expand Down Expand Up @@ -84,7 +85,10 @@ chrome.runtime.onMessage.addListener((request) => {
);
}
}
if (request.message === "STOP_EDITING" || request.message === "STOP_PLAYING") {
if (
request.message === "STOP_EDITING" ||
request.message === "STOP_PLAYING"
) {
reactor.detach();
}
// resize iframe
Expand Down Expand Up @@ -162,14 +166,15 @@ chrome.runtime.onMessage.addListener((request) => {
};

// avoid remounting react tree
if (!mounted) {
root.render(<Iframe />);
mounted = true;
try {
console.debug("content script loaded, extension iframe mounted");
} catch (e) {
console.error(e);

try {
if (!mounted) {
root.render(<Iframe />);
mounted = true;
}
console.debug("content script loaded, extension iframe mounted");
} catch (e) {
console.error(e);
}
}
});
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fd38a37

Please sign in to comment.