This commit is contained in:
Manav Rathi
2024-06-07 12:00:29 +05:30
parent dd6f36e037
commit 242c669de4
8 changed files with 73 additions and 8 deletions

View File

@@ -12,7 +12,7 @@ import EnteSpinner from "@ente/shared/components/EnteSpinner";
import { AppNavbar } from "@ente/shared/components/Navbar/app";
import { useLocalState } from "@ente/shared/hooks/useLocalState";
import HTTPService from "@ente/shared/network/HTTPService";
import { LS_KEYS, getData } from "@ente/shared/storage/localStorage";
import { LS_KEYS } from "@ente/shared/storage/localStorage";
import { getTheme } from "@ente/shared/themes";
import { THEME_COLOR } from "@ente/shared/themes/constants";
import { CssBaseline, useMediaQuery } from "@mui/material";
@@ -64,10 +64,10 @@ export default function App({ Component, pageProps }: AppProps) {
}, []);
const setupPackageName = () => {
const pkg = getData(LS_KEYS.CLIENT_PACKAGE);
const pkg = localStorage.getItem("clientPackage");
if (!pkg) return;
HTTPService.setHeaders({
"X-Client-Package": pkg.name,
"X-Client-Package": pkg,
});
};

View File

@@ -96,6 +96,9 @@ export const registerPasskey = async (name: string) => {
};
export const getPasskeyRegistrationOptions = async () => {
const clientPackage = localStorage.getItem("clientPackage")
const token = ensure(getToken());
try {
const token = getToken();
if (!token) return;

View File

@@ -33,6 +33,7 @@ import { useRouter } from "next/router";
import { createContext, useContext, useEffect, useRef, useState } from "react";
import LoadingBar, { type LoadingBarRef } from "react-top-loading-bar";
import "../../public/css/global.css";
import { setAppNameForAuthenticatedRequests } from "@/next/http";
/**
* Properties available via the {@link AppContext} to the Auth app's React tree.
@@ -78,6 +79,7 @@ export default function App({ Component, pageProps }: AppProps) {
const userId = (getData(LS_KEYS.USER) as User)?.id;
logStartupBanner(appName, userId);
logUnhandledErrorsAndRejections(true);
setAppNameForAuthenticatedRequests(appName);
HTTPService.setHeaders({
"X-Client-Package": clientPackageName[appName],
});

View File

@@ -1,5 +1,6 @@
import { WhatsNew } from "@/new/photos/components/WhatsNew";
import { CustomHead } from "@/next/components/Head";
import { setAppNameForAuthenticatedRequests } from "@/next/http";
import { setupI18n } from "@/next/i18n";
import log from "@/next/log";
import {
@@ -155,6 +156,7 @@ export default function App({ Component, pageProps }: AppProps) {
const userId = (getData(LS_KEYS.USER) as User)?.id;
logStartupBanner(appName, userId);
logUnhandledErrorsAndRejections(true);
setAppNameForAuthenticatedRequests(appName);
HTTPService.setHeaders({
"X-Client-Package": clientPackageName[appName],
});

View File

@@ -1,4 +1,5 @@
import { clearBlobCaches } from "@/next/blob-cache";
import { clearHTTPState } from "@/next/http";
import log from "@/next/log";
import InMemoryStore from "@ente/shared/storage/InMemoryStore";
import localForage from "@ente/shared/storage/localForage";
@@ -50,4 +51,9 @@ export const accountLogout = async () => {
} catch (e) {
ignoreError("cache", e);
}
try {
clearHTTPState();
} catch (e) {
ignoreError("http", e);
}
};

View File

@@ -1,10 +1,9 @@
import { isDevBuild } from "@/next/env";
import { authenticatedRequestHeaders } from "@/next/http";
import { localUser } from "@/next/local-user";
import log from "@/next/log";
import { ensure } from "@/utils/ensure";
import { nullToUndefined } from "@/utils/transform";
import { apiOrigin } from "@ente/shared/network/api";
import { getToken } from "@ente/shared/storage/localStorage/helpers";
import { z } from "zod";
let _fetchTimeout: ReturnType<typeof setTimeout> | undefined;
@@ -68,9 +67,7 @@ const fetchAndSaveFeatureFlags = () =>
const fetchFeatureFlags = async () => {
const url = `${apiOrigin()}/remote-store/feature-flags`;
const res = await fetch(url, {
headers: {
"X-Auth-Token": ensure(getToken()),
},
headers: authenticatedRequestHeaders(),
});
if (!res.ok) throw new Error(`Failed to fetch ${url}: HTTP ${res.status}`);
return res;

44
web/packages/next/http.ts Normal file
View File

@@ -0,0 +1,44 @@
import { ensureAuthToken } from "./local-user";
import { clientPackageName, type AppName } from "./types/app";
/**
* The client package name to include as the "X-Client-Package" header in
* authenticated requests.
*/
let _clientPackageName: string | undefined;
/**
* Set the client package name (corresponding to the given {@link appName}) that
* should be included as the "X-Client-Package" header in authenticated
* requests.
*
* This state is persisted in memory, and can be cleared using
* {@link clearHTTPState}.
*
* @param appName The {@link AppName} of the current app.
*/
export const setAppNameForAuthenticatedRequests = (appName: AppName) => {
_clientPackageName = clientPackageName[appName];
};
/**
* Forget the effects of a previous {@link setAppNameForAuthenticatedRequests}.
*/
export const clearHTTPState = () => {
_clientPackageName = undefined;
};
/**
* Return headers that should be passed alongwith (almost) all authenticated
* `fetch` calls that we make to our API servers.
*
* This uses in-memory state initialized using
* {@link setAppNameForAuthenticatedRequests}.
*/
export const authenticatedRequestHeaders = (): Record<string, string> => {
const headers: Record<string, string> = {
"X-Auth-Token": ensureAuthToken(),
};
if (_clientPackageName) headers["X-Client-Package"] = _clientPackageName;
return headers;
};

View File

@@ -38,3 +38,14 @@ export const ensureLocalUser = (): LocalUser => {
if (!user) throw new Error("Not logged in");
return user;
};
/**
* Return the user's auth token, or throw an error.
*
* The user's auth token is stored in local storage after they have successfully
* logged in. This function returns that saved auth token.
*
* If no such token is found (which should only happen if the user is not logged
* in), then it throws an error.
*/
export const ensureAuthToken = (): string => ensureLocalUser().token;