This commit is contained in:
Manav Rathi
2025-07-04 08:08:35 +05:30
parent 70b5b8e682
commit c9521fb626
6 changed files with 58 additions and 57 deletions

View File

@@ -35,7 +35,7 @@ import { useBaseContext } from "ente-base/context";
import log from "ente-base/log";
import {
clearSessionStorage,
haveCredentialsInSession,
haveMasterKeyInSession,
masterKeyFromSession,
} from "ente-base/session";
import { savedAuthToken } from "ente-base/token";
@@ -282,7 +282,7 @@ const Page: React.FC = () => {
let syncIntervalID: ReturnType<typeof setInterval> | undefined;
void (async () => {
if (!haveCredentialsInSession() || !(await savedAuthToken())) {
if (!haveMasterKeyInSession() || !(await savedAuthToken())) {
// If we don't have master key or auth token, reauthenticate.
stashRedirect("/gallery");
router.push("/");
@@ -376,7 +376,7 @@ const Page: React.FC = () => {
}, [activeCollectionID, router.isReady]);
useEffect(() => {
if (router.isReady && haveCredentialsInSession()) {
if (router.isReady && haveMasterKeyInSession()) {
handleSubscriptionCompletionRedirectIfNeeded(
showMiniDialog,
showLoadingBar,

View File

@@ -1,4 +1,4 @@
import { haveCredentialsInSession } from "ente-base/session";
import { haveMasterKeyInSession } from "ente-base/session";
import { useRouter } from "next/router";
import { useEffect } from "react";
import { stashRedirect } from "../../services/redirect";
@@ -16,7 +16,7 @@ export const useRedirectIfNeedsCredentials = (currentPageSlug: string) => {
const router = useRouter();
useEffect(() => {
if (!haveCredentialsInSession()) {
if (!haveMasterKeyInSession()) {
stashRedirect(currentPageSlug);
void router.push("/");
}

View File

@@ -16,7 +16,6 @@ import {
generateSRPSetupAttributes,
setupSRP,
} from "ente-accounts/services/srp";
import type { PartialLocalUser } from "ente-accounts/services/user";
import {
generateAndSaveInteractiveKeyAttributes,
generateKeysAndAttributes,
@@ -28,12 +27,12 @@ import { useBaseContext } from "ente-base/context";
import { deriveKeyInsufficientMemoryErrorMessage } from "ente-base/crypto/types";
import log from "ente-base/log";
import {
haveCredentialsInSession,
haveMasterKeyInSession,
saveMasterKeyInSessionAndSafeStore,
} from "ente-base/session";
import { t } from "i18next";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import {
NewPasswordForm,
type NewPasswordFormProps,
@@ -41,79 +40,76 @@ import {
/**
* A page that allows the user to generate key attributes if needed, and shows
* them their recovery key.
* them their recovery key if they just signed up.
*
* See: [Note: Login pages]
*/
const Page: React.FC = () => {
const { logout, showMiniDialog } = useBaseContext();
const [user, setUser] = useState<PartialLocalUser | undefined>(undefined);
const [userEmail, setUserEmail] = useState("");
const [openRecoveryKey, setOpenRecoveryKey] = useState(false);
const router = useRouter();
useEffect(() => {
const user = savedPartialLocalUser();
if (!user?.token) {
if (!user?.email || !user?.token) {
void router.push("/");
} else if (haveCredentialsInSession()) {
} else if (haveMasterKeyInSession()) {
if (savedJustSignedUp()) {
setOpenRecoveryKey(true);
setUser(user);
} else {
void router.push(appHomeRoute);
}
} else if (savedOriginalKeyAttributes()?.encryptedKey) {
} else if (savedOriginalKeyAttributes()) {
void router.push("/credentials");
} else {
setUser(user);
setUserEmail(user.email);
}
}, [router]);
const handleSubmit: NewPasswordFormProps["onSubmit"] = async (
password,
setPasswordsFieldError,
) => {
try {
const { masterKey, kek, keyAttributes } =
await generateKeysAndAttributes(password);
await putUserKeyAttributes(keyAttributes);
await setupSRP(await generateSRPSetupAttributes(kek));
await generateAndSaveInteractiveKeyAttributes(
password,
keyAttributes,
masterKey,
);
await saveMasterKeyInSessionAndSafeStore(masterKey);
saveJustSignedUp();
setOpenRecoveryKey(true);
} catch (e) {
log.error("failed to generate password", e);
setPasswordsFieldError(
e instanceof Error &&
e.message == deriveKeyInsufficientMemoryErrorMessage
? t("password_generation_failed")
: t("generic_error"),
);
}
};
const handleSubmit: NewPasswordFormProps["onSubmit"] = useCallback(
async (password, setPasswordsFieldError) => {
try {
const { masterKey, kek, keyAttributes } =
await generateKeysAndAttributes(password);
await putUserKeyAttributes(keyAttributes);
await setupSRP(await generateSRPSetupAttributes(kek));
await generateAndSaveInteractiveKeyAttributes(
password,
keyAttributes,
masterKey,
);
await saveMasterKeyInSessionAndSafeStore(masterKey);
saveJustSignedUp();
setOpenRecoveryKey(true);
} catch (e) {
log.error("Could not generate key attributes from password", e);
setPasswordsFieldError(
e instanceof Error &&
e.message == deriveKeyInsufficientMemoryErrorMessage
? t("password_generation_failed")
: t("generic_error"),
);
}
},
[],
);
return (
<>
{!user ? (
<LoadingIndicator />
) : openRecoveryKey ? (
{openRecoveryKey ? (
<RecoveryKey
open={openRecoveryKey}
onClose={() => void router.push(appHomeRoute)}
showMiniDialog={showMiniDialog}
/>
) : (
) : userEmail ? (
<AccountsPageContents>
<AccountsPageTitle>{t("set_password")}</AccountsPageTitle>
<NewPasswordForm
userEmail={user.email!}
userEmail={userEmail}
submitButtonTitle={t("set_password")}
onSubmit={handleSubmit}
/>
@@ -122,6 +118,8 @@ const Page: React.FC = () => {
<LinkButton onClick={logout}>{t("go_back")}</LinkButton>
</AccountsPageFooter>
</AccountsPageContents>
) : (
<LoadingIndicator />
)}
</>
);

View File

@@ -74,14 +74,17 @@ import React, { useCallback, useEffect, useState } from "react";
* complete**.
*
* - "/generate" - A page that allows the user to generate key attributes if
* needed, and shows them their recovery key.
* needed, and shows them their recovery key if they just signed up.
*
* - Redirects to "/" if there is no `email` present in the saved partial
* local user, or after viewing the recovery key, or after the user sets
* their password (if they did no have key attributes).
* - Redirects to "/" if there is no `email` or `token` present in the saved
* partial user.
*
* - Redirects to "/credentials" if they already have the original key
* attributes.
* - Redirects to `appHomeRoute` after viewing the recovery key if they have a
* master key in session, or after setting the password and then viewing the
* recovery key (if they did not have a master key in session store).
*
* - Redirects to "/credentials" if if they don't have a master key in session
* store but have saved original key attributes.
*
* - "/recover" - A page that allows the user to recover their master key using
* their recovery key.

View File

@@ -21,7 +21,7 @@ import { useBaseContext } from "ente-base/context";
import { decryptBox } from "ente-base/crypto";
import log from "ente-base/log";
import {
haveCredentialsInSession,
haveMasterKeyInSession,
saveMasterKeyInSessionAndSafeStore,
} from "ente-base/session";
import { t } from "i18next";
@@ -59,7 +59,7 @@ const Page: React.FC = () => {
const keyAttributes = savedKeyAttributes();
if (!keyAttributes) {
void router.push("/generate");
} else if (haveCredentialsInSession()) {
} else if (haveMasterKeyInSession()) {
void router.push(appHomeRoute);
} else {
setKeyAttributes(keyAttributes);

View File

@@ -51,7 +51,7 @@ export const ensureMasterKeyFromSession = async () => {
* have credentials at hand or not, however it doesn't attempt to verify that
* the key present in the session can actually be decrypted.
*/
export const haveCredentialsInSession = () =>
export const haveMasterKeyInSession = () =>
!!sessionStorage.getItem("encryptionKey");
/**
@@ -140,7 +140,7 @@ export const updateSessionFromElectronSafeStorageIfNeeded = async () => {
const electron = globalThis.electron;
if (!electron) return;
if (haveCredentialsInSession()) return;
if (haveMasterKeyInSession()) return;
let masterKey: string | undefined;
try {