This commit is contained in:
Manav Rathi
2025-06-05 19:40:47 +05:30
parent ed2a98b341
commit 60a2febe46
11 changed files with 82 additions and 80 deletions

View File

@@ -1,6 +1,6 @@
import type { User } from "ente-accounts/services/user";
import { encryptMetadataJSON, sharedCryptoWorker } from "ente-base/crypto";
import { ensureLocalUser } from "ente-base/local-user";
import { ensureLocalUser } from "ente-accounts/services/user";
import log from "ente-base/log";
import { apiURL } from "ente-base/origins";
import { UpdateMagicMetadataRequest } from "ente-gallery/services/file";

View File

@@ -1,14 +1,18 @@
import type { KeyAttributes } from "ente-accounts/services/user";
import { authenticatedRequestHeaders, HTTPError } from "ente-base/http";
import { ensureLocalUser, getAuthToken } from "ente-base/local-user";
import log from "ente-base/log";
import { apiURL } from "ente-base/origins";
import { getAuthToken } from "ente-base/token";
import { getData } from "ente-shared/storage/localStorage";
import { nullToUndefined } from "ente-utils/transform";
import { z } from "zod/v4";
import type { SRPAttributes } from "./srp-remote";
import { getSRPAttributes } from "./srp-remote";
import { putUserKeyAttributes, RemoteKeyAttributes } from "./user";
import {
ensureLocalUser,
putUserKeyAttributes,
RemoteKeyAttributes,
} from "./user";
type SessionValidity =
| { status: "invalid" }

View File

@@ -18,6 +18,49 @@ export interface User {
twoFactorSessionID: string;
}
// TODO: During login the only field present is email. Which makes this
// optionality indicated by these types incorrect.
const LocalUser = z.object({
/** The user's ID. */
id: z.number(),
/** The user's email. */
email: z.string(),
/**
* The user's (plaintext) auth token.
*
* It is used for making API calls on their behalf, by passing this token as
* the value of the X-Auth-Token header in the HTTP request.
*/
token: z.string(),
});
/** Locally available data for the logged in user */
export type LocalUser = z.infer<typeof LocalUser>;
/**
* Return the logged-in user, if someone is indeed logged in. Otherwise return
* `undefined`.
*
* The user's data is stored in the browser's localStorage. Thus, this function
* only works from the main thread, not from web workers (local storage is not
* accessible to web workers).
*/
export const localUser = (): LocalUser | undefined => {
// TODO: duplicate of getData("user")
const s = localStorage.getItem("user");
if (!s) return undefined;
return LocalUser.parse(JSON.parse(s));
};
/**
* A wrapper over {@link localUser} with that throws if no one is logged in.
*/
export const ensureLocalUser = (): LocalUser => {
const user = localUser();
if (!user) throw new Error("Not logged in");
return user;
};
/**
* The user's various encrypted keys and their related attributes.
*

View File

@@ -2,8 +2,8 @@ import { desktopAppVersion, isDesktop } from "ente-base/app";
import { wait } from "ente-utils/promise";
import { z } from "zod/v4";
import { clientPackageName } from "./app";
import { ensureAuthToken } from "./local-user";
import log from "./log";
import { ensureAuthToken } from "./token";
/**
* Return headers that should be passed alongwith (almost) all authenticated

View File

@@ -1,71 +0,0 @@
// TODO: This file belongs to the accounts package
import { z } from "zod/v4";
import { getKVS } from "./kv";
// TODO: During login the only field present is email. Which makes this
// optionality indicated by these types incorrect.
const LocalUser = z.object({
/** The user's ID. */
id: z.number(),
/** The user's email. */
email: z.string(),
/**
* The user's (plaintext) auth token.
*
* It is used for making API calls on their behalf, by passing this token as
* the value of the X-Auth-Token header in the HTTP request.
*/
token: z.string(),
});
/** Locally available data for the logged in user */
export type LocalUser = z.infer<typeof LocalUser>;
/**
* Return the logged-in user, if someone is indeed logged in. Otherwise return
* `undefined`.
*
* The user's data is stored in the browser's localStorage. Thus, this function
* only works from the main thread, not from web workers (local storage is not
* accessible to web workers).
*/
export const localUser = (): LocalUser | undefined => {
// TODO: duplicate of getData("user")
const s = localStorage.getItem("user");
if (!s) return undefined;
return LocalUser.parse(JSON.parse(s));
};
/**
* A wrapper over {@link localUser} with that throws if no one is logged in.
*/
export const ensureLocalUser = (): LocalUser => {
const user = localUser();
if (!user) throw new Error("Not logged in");
return user;
};
/**
* Return the user's auth token, if present.
*
* The user's auth token is stored in KV DB after they have successfully logged
* in. This function returns that saved auth token.
*
* The underlying data is stored in IndexedDB, and can be accessed from web
* workers.
*/
export const getAuthToken = () => getKVS("token");
/**
* Return the user's auth token, or throw an error.
*
* The user's auth token can be retrieved using {@link getAuthToken}. This
* function is a wrapper which throws an error if the token is not found (which
* should only happen if the user is not logged in).
*/
export const ensureAuthToken = async () => {
const token = await getAuthToken();
if (!token) throw new Error("Not logged in");
return token;
};

View File

@@ -0,0 +1,25 @@
import { getKVS } from "./kv";
/**
* Return the user's auth token, if present.
*
* The user's auth token is stored in KV DB after they have successfully logged
* in. This function returns that saved auth token.
*
* The underlying data is stored in IndexedDB, and can be accessed from web
* workers.
*/
export const getAuthToken = () => getKVS("token");
/**
* Return the user's auth token, or throw an error.
*
* The user's auth token can be retrieved using {@link getAuthToken}. This
* function is a wrapper which throws an error if the token is not found (which
* should only happen if the user is not logged in).
*/
export const ensureAuthToken = async () => {
const token = await getAuthToken();
if (!token) throw new Error("Not logged in");
return token;
};

View File

@@ -17,6 +17,7 @@ import {
Typography,
type ModalProps,
} from "@mui/material";
import type { LocalUser } from "ente-accounts/services/user";
import { isDesktop } from "ente-base/app";
import { SpacedRow } from "ente-base/components/containers";
import { InlineErrorIndicator } from "ente-base/components/ErrorIndicator";
@@ -29,7 +30,6 @@ import { type ModalVisibilityProps } from "ente-base/components/utils/modal";
import { useBaseContext } from "ente-base/context";
import { lowercaseExtension } from "ente-base/file-name";
import { formattedListJoin, ut } from "ente-base/i18n";
import type { LocalUser } from "ente-base/local-user";
import log from "ente-base/log";
import {
FileInfo,

View File

@@ -12,9 +12,9 @@ import {
retryEnsuringHTTPOk,
type PublicAlbumsCredentials,
} from "ente-base/http";
import { ensureAuthToken } from "ente-base/local-user";
import log from "ente-base/log";
import { apiURL, customAPIOrigin } from "ente-base/origins";
import { ensureAuthToken } from "ente-base/token";
import type { EnteFile } from "ente-media/file";
import { FileType } from "ente-media/file-type";
import { decodeLivePhoto } from "ente-media/live-photo";

View File

@@ -1,3 +1,4 @@
import { ensureLocalUser } from "ente-accounts/services/user";
import { isDesktop } from "ente-base/app";
import { assertionFailed } from "ente-base/assert";
import { decryptBlobBytes, encryptBlob } from "ente-base/crypto";
@@ -5,9 +6,9 @@ import type { EncryptedBlob } from "ente-base/crypto/types";
import { ensureElectron } from "ente-base/electron";
import { isHTTP4xxError, type PublicAlbumsCredentials } from "ente-base/http";
import { getKV, getKVB, getKVN, setKV } from "ente-base/kv";
import { ensureAuthToken, ensureLocalUser } from "ente-base/local-user";
import log from "ente-base/log";
import { apiURL } from "ente-base/origins";
import { ensureAuthToken } from "ente-base/token";
import { fileLogID, type EnteFile } from "ente-media/file";
import {
filePublicMagicMetadata,

View File

@@ -1,6 +1,6 @@
import { assertionFailed } from "ente-base/assert";
import { newID } from "ente-base/id";
import { ensureLocalUser } from "ente-base/local-user";
import { ensureLocalUser } from "ente-accounts/services/user";
import type { EnteFile } from "ente-media/file";
import {
filePublicMagicMetadata,

View File

@@ -2,8 +2,8 @@
* @file Storage (in-memory, local, remote) and update of various settings.
*/
import { localUser } from "ente-accounts/services/user";
import { isDevBuild } from "ente-base/env";
import { localUser } from "ente-base/local-user";
import log from "ente-base/log";
import { updateShouldDisableCFUploadProxy } from "ente-gallery/services/upload";
import { nullToUndefined } from "ente-utils/transform";