mirror of
https://github.com/idanoo/autobrr
synced 2025-07-25 01:39:13 +00:00
fix(auth): cookie expiry and renewal (#1527)
* fix(auth/web): logout when expired/invalid/no cookie is present * fix(auth/web): specify error message in invalid cookie * fix(auth/web): reset error boundary on login * fix(auth/web): fix onboarding * chore: code cleanup * fix(web): revert tanstack/router to 1.31.0 * refactor(web): remove react-error-boundary * feat(auth): refresh cookie when close to expiry * enhancement(web): specify defaultError message in HttpClient * fix(web): use absolute paths for router links (#1530) * chore(web): bump `@tanstack/react-router` to `1.31.6` * fix(web): settings routes * fix(web): filter routes * fix(web): remove unused ReleasesIndexRoute * chore(web): add documentation for HttpClient * chore(lint): remove unnecessary whitespace
This commit is contained in:
parent
3dab295387
commit
8120c33f6b
19 changed files with 364 additions and 366 deletions
|
@ -4,36 +4,43 @@
|
|||
*/
|
||||
|
||||
import StackTracey from "stacktracey";
|
||||
import type { FallbackProps } from "react-error-boundary";
|
||||
import { ArrowPathIcon } from "@heroicons/react/24/solid";
|
||||
import { ExternalLink } from "@components/ExternalLink";
|
||||
|
||||
export const ErrorPage = ({ error, resetErrorBoundary }: FallbackProps) => {
|
||||
const stack = new StackTracey(error);
|
||||
const summary = stack.clean().asTable({
|
||||
maxColumnWidths: {
|
||||
callee: 48,
|
||||
file: 48,
|
||||
sourceLine: 384
|
||||
}
|
||||
});
|
||||
type ErrorPageProps = {
|
||||
error: unknown;
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
const parseTitle = () => {
|
||||
switch (error?.cause) {
|
||||
case "OFFLINE": {
|
||||
return "Connection to Autobrr failed! Check the application state and verify your connectivity.";
|
||||
export const ErrorPage = ({ error, reset }: ErrorPageProps) => {
|
||||
let pageTitle = "We caught an unrecoverable error!";
|
||||
let errorLine: string, summary ="";
|
||||
|
||||
if (error instanceof Error) {
|
||||
const stack = new StackTracey(error);
|
||||
summary = stack.clean().asTable({
|
||||
maxColumnWidths: {
|
||||
callee: 48,
|
||||
file: 48,
|
||||
sourceLine: 384
|
||||
}
|
||||
});
|
||||
|
||||
if (error.cause === "OFFLINE") {
|
||||
pageTitle = "Connection to Autobrr failed! Check the application state and verify your connectivity.";
|
||||
}
|
||||
default: {
|
||||
return "We caught an unrecoverable error!";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
errorLine = error.toString();
|
||||
} else {
|
||||
errorLine = String(error);
|
||||
// Leave summary blank?
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col justify-center py-12 px-2 sm:px-6 lg:px-8">
|
||||
<div className="sm:mx-auto sm:w-full sm:max-w-screen-md md:max-w-screen-lg lg:max-w-screen-xl">
|
||||
<h1 className="text-3xl font-bold leading-6 text-gray-900 dark:text-gray-200 mt-4 mb-3">
|
||||
{parseTitle()}
|
||||
{pageTitle}
|
||||
</h1>
|
||||
<h3 className="text-xl leading-6 text-gray-700 dark:text-gray-400 mb-4">
|
||||
Please consider reporting this error to our
|
||||
|
@ -60,14 +67,14 @@ export const ErrorPage = ({ error, resetErrorBoundary }: FallbackProps) => {
|
|||
>
|
||||
<div className="flex items-center">
|
||||
<svg className="mr-2 w-5 h-5 text-red-700 dark:text-red-800" fill="currentColor" viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
<h3 className="text-lg font-medium text-red-700 dark:text-red-800">{error.toString()}</h3>
|
||||
<h3 className="text-lg font-medium text-red-700 dark:text-red-800">{errorLine}</h3>
|
||||
</div>
|
||||
{summary ? (
|
||||
<pre className="mt-2 mb-4 text-sm text-red-700 dark:text-red-800 overflow-x-auto">
|
||||
|
@ -83,7 +90,7 @@ export const ErrorPage = ({ error, resetErrorBoundary }: FallbackProps) => {
|
|||
className="text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-3 py-1.5 mr-2 text-center inline-flex items-center dark:bg-red-800 dark:hover:bg-red-900"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
resetErrorBoundary();
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
<ArrowPathIcon className="-ml-0.5 mr-2 h-5 w-5"/>
|
||||
|
|
|
@ -16,13 +16,11 @@ import { LeftNav } from "./LeftNav";
|
|||
import { RightNav } from "./RightNav";
|
||||
import { MobileNav } from "./MobileNav";
|
||||
import { ExternalLink } from "@components/ExternalLink";
|
||||
|
||||
import { AuthIndexRoute } from "@app/routes";
|
||||
import { ConfigQueryOptions, UpdatesQueryOptions } from "@api/queries";
|
||||
import { AuthContext } from "@utils/Context";
|
||||
|
||||
export const Header = () => {
|
||||
const router = useRouter()
|
||||
const { auth } = AuthIndexRoute.useRouteContext()
|
||||
|
||||
const { isError:isConfigError, error: configError, data: config } = useQuery(ConfigQueryOptions(true));
|
||||
if (isConfigError) {
|
||||
|
@ -40,9 +38,8 @@ export const Header = () => {
|
|||
toast.custom((t) => (
|
||||
<Toast type="success" body="You have been logged out. Goodbye!" t={t} />
|
||||
));
|
||||
auth.logout()
|
||||
|
||||
router.history.push("/")
|
||||
AuthContext.reset();
|
||||
router.history.push("/");
|
||||
},
|
||||
onError: (err) => {
|
||||
console.error("logout error", err)
|
||||
|
@ -60,7 +57,7 @@ export const Header = () => {
|
|||
<div className="border-b border-gray-300 dark:border-gray-775">
|
||||
<div className="flex items-center justify-between h-16 px-4 sm:px-0">
|
||||
<LeftNav />
|
||||
<RightNav logoutMutation={logoutMutation.mutate} auth={auth} />
|
||||
<RightNav logoutMutation={logoutMutation.mutate} />
|
||||
<div className="-mr-2 flex sm:hidden">
|
||||
{/* Mobile menu button */}
|
||||
<Disclosure.Button className="bg-gray-200 dark:bg-gray-800 inline-flex items-center justify-center p-2 rounded-md text-gray-600 dark:text-gray-400 hover:text-white hover:bg-gray-700">
|
||||
|
@ -92,7 +89,7 @@ export const Header = () => {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<MobileNav logoutMutation={logoutMutation.mutate} auth={auth} />
|
||||
<MobileNav logoutMutation={logoutMutation.mutate} />
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
|
|
|
@ -13,7 +13,7 @@ import { RightNavProps } from "./_shared";
|
|||
|
||||
import { Cog6ToothIcon, ArrowLeftOnRectangleIcon, MoonIcon, SunIcon } from "@heroicons/react/24/outline";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { SettingsContext } from "@utils/Context";
|
||||
import { AuthContext, SettingsContext } from "@utils/Context";
|
||||
|
||||
export const RightNav = (props: RightNavProps) => {
|
||||
const [settings, setSettings] = SettingsContext.use();
|
||||
|
@ -56,7 +56,7 @@ export const RightNav = (props: RightNavProps) => {
|
|||
<span className="sr-only">
|
||||
Open user menu for{" "}
|
||||
</span>
|
||||
{props.auth.username}
|
||||
{AuthContext.get().username}
|
||||
</span>
|
||||
<UserIcon
|
||||
className="inline ml-1 h-5 w-5"
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
import { AuthCtx } from "@utils/Context";
|
||||
|
||||
interface NavItem {
|
||||
name: string;
|
||||
path: string;
|
||||
|
@ -13,7 +11,6 @@ interface NavItem {
|
|||
|
||||
export interface RightNavProps {
|
||||
logoutMutation: () => void;
|
||||
auth: AuthCtx
|
||||
}
|
||||
|
||||
export const NAV_ROUTES: Array<NavItem> = [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue