diff --git a/frontend/src/index.ts b/frontend/src/index.ts index 2936abfcfc..153ccd3be6 100644 --- a/frontend/src/index.ts +++ b/frontend/src/index.ts @@ -13,7 +13,7 @@ import type { NotifyEvent, NavigateEvent } from "./utils/LiteElement"; import LiteElement, { html } from "./utils/LiteElement"; import APIRouter from "./utils/APIRouter"; import AuthService, { AuthState } from "./utils/AuthService"; -import type { LoggedInEvent } from "./utils/AuthService"; +import type { LoggedInEvent, NeedLoginEvent } from "./utils/AuthService"; import type { ViewState } from "./utils/APIRouter"; import type { CurrentUser, UserOrg } from "./types/user"; import type { AuthStorageEventData } from "./utils/AuthService"; @@ -107,6 +107,7 @@ export class App extends LiteElement { } super.connectedCallback(); + window.addEventListener("need-login", this.onNeedLogin); window.addEventListener("popstate", () => { this.syncViewState(); }); @@ -585,7 +586,8 @@ export class App extends LiteElement { @logged-in=${this.onLoggedIn} .authState=${this.authService.authState} .viewState=${this.viewState} - redirectUrl=${this.viewState.params.redirectUrl} + redirectUrl=${this.viewState.params.redirectUrl || + this.viewState.data?.redirectUrl} >`; case "resetPassword": @@ -616,7 +618,6 @@ export class App extends LiteElement { return html``; @@ -632,7 +633,6 @@ export class App extends LiteElement { return html` { e.stopPropagation(); this.updateUserInfo(); @@ -653,7 +653,6 @@ export class App extends LiteElement { class="w-full max-w-screen-lg mx-auto p-2 md:py-8 box-border" @navigate="${this.onNavigateTo}" @logged-in=${this.onLoggedIn} - @need-login="${this.onNeedLogin}" .authState="${this.authService.authState}" .userInfo="${this.userInfo}" >`; @@ -665,7 +664,6 @@ export class App extends LiteElement { class="w-full max-w-screen-lg mx-auto p-2 md:py-8 box-border" @navigate="${this.onNavigateTo}" @logged-in=${this.onLoggedIn} - @need-login="${this.onNeedLogin}" .authState="${this.authService.authState}" .userInfo="${this.userInfo}" >`; @@ -684,7 +682,6 @@ export class App extends LiteElement { return html` { + e.stopPropagation(); + this.clearUser(); - this.navigate(ROUTES.login); - } + const redirectUrl = (e as NeedLoginEvent).detail?.redirectUrl; + this.navigate(ROUTES.login, { + redirectUrl, + }); + this.onNotify( + new CustomEvent("notify", { + detail: { + message: msg("Please log in to continue."), + variant: "warning" as any, + icon: "exclamation-triangle", + }, + }) + ); + }; onNavigateTo(event: NavigateEvent) { event.stopPropagation(); diff --git a/frontend/src/pages/org/index.ts b/frontend/src/pages/org/index.ts index ae51e902e7..deccbb720f 100644 --- a/frontend/src/pages/org/index.ts +++ b/frontend/src/pages/org/index.ts @@ -124,7 +124,7 @@ export class Org extends LiteElement { } async willUpdate(changedProperties: Map) { - if (changedProperties.has("orgId") && this.orgId) { + if (changedProperties.has("orgId") && this.orgId && this.authState) { try { this.org = await this.getOrg(this.orgId); this.checkStorageQuota(); diff --git a/frontend/src/utils/AuthService.ts b/frontend/src/utils/AuthService.ts index b32d357511..9c7a104002 100644 --- a/frontend/src/utils/AuthService.ts +++ b/frontend/src/utils/AuthService.ts @@ -1,3 +1,4 @@ +import { ROUTES } from "../routes"; import { APIError } from "./api"; export type Auth = { @@ -27,6 +28,14 @@ export interface LoggedInEvent extends CustomEvent { readonly detail: T; } +export interface NeedLoginEvent extends CustomEvent { + readonly bubbles: boolean; + readonly composed: boolean; + readonly detail: { + redirectUrl?: string; + }; +} + type AuthRequestEventData = { name: "requesting_auth"; }; @@ -51,6 +60,7 @@ export default class AuthService { static storageKey = "btrix.auth"; static unsupportedAuthErrorCode = "UNSUPPORTED_AUTH_TYPE"; static loggedInEvent = "logged-in"; + static needLoginEvent = "need-login"; static broadcastChannel = new BroadcastChannel(AuthService.storageKey); static storage = { @@ -85,6 +95,14 @@ export default class AuthService { return new CustomEvent(AuthService.loggedInEvent, { detail }); }; + static createNeedLoginEvent = (redirectUrl?: string): NeedLoginEvent => { + return new CustomEvent(AuthService.needLoginEvent, { + bubbles: true, + composed: true, + detail: { redirectUrl }, + }); + }; + static async login({ email, password, @@ -307,6 +325,14 @@ export default class AuthService { }, FRESHNESS_TIMER_INTERVAL); } catch (e) { console.debug(e); + + this.logout(); + const { pathname, search, hash } = window.location; + const redirectUrl = + pathname !== ROUTES.login && pathname !== ROUTES.home + ? `${pathname}${search}${hash}` + : ""; + window.dispatchEvent(AuthService.createNeedLoginEvent(redirectUrl)); } } } diff --git a/frontend/src/utils/LiteElement.ts b/frontend/src/utils/LiteElement.ts index 5220403a2e..5d56bc79f3 100644 --- a/frontend/src/utils/LiteElement.ts +++ b/frontend/src/utils/LiteElement.ts @@ -3,6 +3,7 @@ import type { TemplateResult } from "lit"; import { msg } from "@lit/localize"; import type { Auth } from "../utils/AuthService"; +import AuthService from "../utils/AuthService"; import { APIError } from "./api"; export interface NavigateEvent extends CustomEvent { @@ -147,7 +148,7 @@ export default class LiteElement extends LitElement { switch (resp.status) { case 401: { - this.dispatchEvent(new CustomEvent("need-login")); + this.dispatchEvent(AuthService.createNeedLoginEvent()); errorMessage = msg("Need login"); break; } diff --git a/frontend/src/utils/auth.ts b/frontend/src/utils/auth.ts index 3b6e591b53..8bc1435bca 100644 --- a/frontend/src/utils/auth.ts +++ b/frontend/src/utils/auth.ts @@ -1,6 +1,6 @@ import LiteElement from "../utils/LiteElement"; import type { AuthState } from "../utils/AuthService"; -import type { CurrentUser } from "../types/user"; +import AuthService from "../utils/AuthService"; /** * Block rendering and dispatch event if user is not logged in @@ -27,7 +27,11 @@ export function needLogin( if (this.authState) { super.update(changedProperties); } else { - this.dispatchEvent(new CustomEvent("need-login")); + this.dispatchEvent( + AuthService.createNeedLoginEvent( + `${window.location.pathname}${window.location.search}${window.location.hash}` + ) + ); } } };