1
0
Fork 0
mirror of https://github.com/sussy-code/smov.git synced 2024-12-20 14:37:43 +01:00

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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