fix: change useBackendUrl to possibly be undefined, add checks to avoid useless requests to nonexistent backend

This commit is contained in:
qtchaos 2024-02-24 02:08:01 +02:00
parent b18269b40e
commit fcf42a4e8a
No known key found for this signature in database
GPG Key ID: 7DA98B2B9EF06A90
15 changed files with 42 additions and 14 deletions

View File

@ -2,7 +2,6 @@ import { ofetch } from "ofetch";
import { getAuthHeaders } from "@/backend/accounts/auth";
import { ProgressResponse } from "@/backend/accounts/user";
import { BACKEND_URL } from "@/setup/constants";
import { AccountWithToken } from "@/stores/auth";
import { ProgressMediaItem, ProgressUpdateItem } from "@/stores/progress";
@ -104,7 +103,6 @@ export async function removeProgress(
episodeId?: string,
seasonId?: string,
) {
if (!BACKEND_URL) return;
await ofetch(`/users/${account.userId}/progress/${id}`, {
method: "DELETE",
headers: getAuthHeaders(account.token),

View File

@ -63,6 +63,7 @@ export function useAuth() {
const login = useCallback(
async (loginData: LoginData) => {
if (!backendUrl) return;
const keys = await keysFromMnemonic(loginData.mnemonic);
const publicKeyBase64Url = bytesToBase64Url(keys.publicKey);
const { challenge } = await getLoginChallengeToken(
@ -87,7 +88,7 @@ export function useAuth() {
);
const logout = useCallback(async () => {
if (!currentAccount) return;
if (!currentAccount || !backendUrl) return;
try {
await removeSession(
backendUrl,
@ -102,6 +103,7 @@ export function useAuth() {
const register = useCallback(
async (registerData: RegistrationData) => {
if (!backendUrl) return;
const { challenge } = await getRegisterChallengeToken(
backendUrl,
registerData.recaptchaToken,
@ -134,6 +136,7 @@ export function useAuth() {
progressItems: Record<string, ProgressMediaItem>,
bookmarks: Record<string, BookmarkMediaItem>,
) => {
if (!backendUrl) return;
if (
Object.keys(progressItems).length === 0 &&
Object.keys(bookmarks).length === 0
@ -159,6 +162,7 @@ export function useAuth() {
const restore = useCallback(
async (account: AccountWithToken) => {
if (!backendUrl) return;
let user: { user: UserResponse; session: SessionResponse };
try {
user = await getUser(backendUrl, account.token);

View File

@ -1,7 +1,7 @@
import { conf } from "@/setup/config";
import { useAuthStore } from "@/stores/auth";
export function useBackendUrl() {
export function useBackendUrl(): string | undefined {
const backendUrl = useAuthStore((s) => s.backendUrl);
return backendUrl ?? conf().BACKEND_URL;
}

View File

@ -70,6 +70,7 @@ export function AccountSettings(props: {
const url = useBackendUrl();
const { account } = props;
const [sessionsResult, execSessions] = useAsyncFn(() => {
if (!url) return Promise.resolve([]);
return getSessions(url, account);
}, [account, url]);
useEffect(() => {
@ -144,7 +145,7 @@ export function SettingsPage() {
);
const saveChanges = useCallback(async () => {
if (account) {
if (account && backendUrl) {
if (
state.appLanguage.changed ||
state.theme.changed ||

View File

@ -43,7 +43,7 @@ export function OnboardingProxyPage() {
throw new Error("onboarding.proxy.input.errorNotProxy");
setProxySet([url]);
if (account) {
if (account && backendUrl) {
await updateSettings(backendUrl, account, {
proxyUrls: [url],
});

View File

@ -32,13 +32,21 @@ export function BackendTestPart() {
value: null,
});
if (!backendUrl) {
return setStatus({
hasTested: true,
success: false,
errorText: "Backend URL is not set",
value: null,
});
}
try {
const backendData = await getBackendMeta(backendUrl);
return setStatus({
hasTested: true,
success: true,
errorText:
"Failed to call backend, double check the URL key and your internet connection",
errorText: "",
value: backendData,
});
} catch (err) {
@ -46,7 +54,7 @@ export function BackendTestPart() {
hasTested: true,
success: false,
errorText:
"Failed to call backend, double check the URL key and your internet connection",
"Failed to call backend, double check the URL, your internet connection, and ensure CORS is properly configured on your backend.",
value: null,
});
}

View File

@ -52,6 +52,9 @@ export function LoginFormPart(props: LoginFormPartProps) {
throw err;
}
if (!account)
throw new Error(t("auth.login.validationError") ?? undefined);
await importData(account, progressItems, bookmarkItems);
await restore(account);

View File

@ -22,8 +22,12 @@ interface TrustBackendPartProps {
export function TrustBackendPart(props: TrustBackendPartProps) {
const navigate = useNavigate();
const backendUrl = useBackendUrl();
const hostname = useMemo(() => new URL(backendUrl).hostname, [backendUrl]);
const hostname = useMemo(
() => (backendUrl ? new URL(backendUrl).hostname : ""),
[backendUrl],
);
const result = useAsync(() => {
if (!backendUrl) return Promise.resolve(null);
return getBackendMeta(backendUrl);
}, [backendUrl]);
const { t } = useTranslation();

View File

@ -47,6 +47,8 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
const [result, execute] = useAsyncFn(
async (inputMnemonic: string) => {
if (!backendUrl)
throw new Error(t("auth.verify.noBackendUrl") ?? undefined);
if (!props.mnemonic || !props.userData)
throw new Error(t("auth.verify.invalidData") ?? undefined);
@ -68,6 +70,9 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
recaptchaToken,
});
if (!account)
throw new Error(t("auth.verify.registrationFailed") ?? undefined);
await importData(account, progressItems, bookmarkItems);
await updateSettings(backendUrl, account, {

View File

@ -18,7 +18,7 @@ export function AccountActionsPart() {
const deleteModal = useModal("account-delete");
const [deleteResult, deleteExec] = useAsyncFn(async () => {
if (!account) return;
if (!account || !url) return;
await deleteUser(url, account);
await logout();
deleteModal.hide();

View File

@ -24,6 +24,7 @@ export function Device(props: {
const token = useAuthStore((s) => s.account?.token);
const [result, exec] = useAsyncFn(async () => {
if (!token) throw new Error("No token present");
if (!url) throw new Error("No backend set");
await removeSession(url, token, props.id);
props.onRemove?.();
}, [url, token, props.id]);

View File

@ -14,9 +14,9 @@ import { useAuthStore } from "@/stores/auth";
const rem = 16;
function SecureBadge(props: { url: string }) {
function SecureBadge(props: { url: string | undefined }) {
const { t } = useTranslation();
const secure = props.url.startsWith("https://");
const secure = props.url ? props.url.startsWith("https://") : false;
return (
<div className="flex items-center gap-1 -mx-1 ml-3 px-1 rounded bg-largeCard-background font-bold">
<Icon icon={secure ? Icons.LOCK : Icons.UNLOCK} />
@ -68,6 +68,7 @@ export function SidebarPart() {
const backendUrl = useBackendUrl();
const backendMeta = useAsync(async () => {
if (!backendUrl) return;
return getBackendMeta(backendUrl);
}, [backendUrl]);
@ -159,7 +160,7 @@ export function SidebarPart() {
<SecureBadge url={backendUrl} />
</div>
<p className="text-white">
{backendUrl.replace(/https?:\/\//, "")}
{backendUrl?.replace(/https?:\/\//, "") ?? "—"}
</p>
</div>

View File

@ -60,6 +60,7 @@ export function BookmarkSyncer() {
useEffect(() => {
const interval = setInterval(() => {
(async () => {
if (!url) return;
const state = useBookmarkStore.getState();
const user = useAuthStore.getState();
await syncBookmarks(

View File

@ -62,6 +62,7 @@ export function ProgressSyncer() {
useEffect(() => {
const interval = setInterval(() => {
(async () => {
if (!url) return;
const state = useProgressStore.getState();
const user = useAuthStore.getState();
await syncProgress(

View File

@ -16,6 +16,7 @@ export function SettingsSyncer() {
useEffect(() => {
const interval = setInterval(() => {
(async () => {
if (!url) return;
const state = useSubtitleStore.getState();
const user = useAuthStore.getState();
if (state.lastSync.lastSelectedLanguage === state.lastSelectedLanguage)