mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-03 05:10:16 +03:00
Disable Portal UI for guests (#6936)
# Description of Changes Disallow SaaS guests from accessing the portal. One day we might want to make this better so they can go there but then have to sign up before doing anything useful, but this is the easiest way to disallow it for now.
This commit is contained in:
@@ -4,9 +4,14 @@ import { render, screen } from "@testing-library/react";
|
||||
import { allowConsole } from "@app/tests/failOnConsole";
|
||||
|
||||
// Controllable auth state for the mocked provider.
|
||||
const authState: { session: unknown; loading: boolean } = {
|
||||
const authState: {
|
||||
session: unknown;
|
||||
loading: boolean;
|
||||
isAnonymous: boolean;
|
||||
} = {
|
||||
session: null,
|
||||
loading: false,
|
||||
isAnonymous: false,
|
||||
};
|
||||
|
||||
vi.mock("@app/auth", () => ({
|
||||
@@ -23,9 +28,10 @@ describe("PortalAuthBoundary — SaaS", () => {
|
||||
beforeEach(() => {
|
||||
authState.session = null;
|
||||
authState.loading = false;
|
||||
authState.isAnonymous = false;
|
||||
});
|
||||
|
||||
it("renders the portal when a Supabase session is present (no login)", () => {
|
||||
it("renders the portal when a real (non-guest) Supabase session is present", () => {
|
||||
authState.session = { user: { id: "u1" }, access_token: "tok" };
|
||||
render(
|
||||
<PortalAuthBoundary>
|
||||
@@ -35,6 +41,20 @@ describe("PortalAuthBoundary — SaaS", () => {
|
||||
expect(screen.getByTestId("portal")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("gates (does not render the portal) for an anonymous guest session", () => {
|
||||
authState.session = { user: { id: "guest" }, access_token: "tok" };
|
||||
authState.isAnonymous = true;
|
||||
// The gate bounces a guest to the editor; jsdom doesn't implement
|
||||
// navigation, so absorb that incidental warning.
|
||||
allowConsole.error(/not implemented|navigation/i);
|
||||
render(
|
||||
<PortalAuthBoundary>
|
||||
<div data-testid="portal">PORTAL</div>
|
||||
</PortalAuthBoundary>,
|
||||
);
|
||||
expect(screen.queryByTestId("portal")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("gates (does not render the portal) when there is no session", () => {
|
||||
authState.session = null;
|
||||
// The gate bounces to /login; jsdom doesn't implement navigation, so absorb
|
||||
|
||||
@@ -3,6 +3,7 @@ import { AuthProvider } from "@app/auth";
|
||||
import { useAuth } from "@app/auth/context";
|
||||
import { Spinner } from "@app/ui";
|
||||
import { ensureSaasSupabase } from "@portal/auth/saasSupabase";
|
||||
import { EDITOR_URL } from "@portal/auth/editorUrl";
|
||||
|
||||
function FullScreen({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
@@ -20,19 +21,22 @@ function FullScreen({ children }: { children: ReactNode }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* SaaS gate: viewing your own usage is not admin-gated, so require only a session
|
||||
* (not portalAccess). No session → bounce to the editor's Supabase login, which
|
||||
* returns here signed in. This is deliberately laxer than the self-hosted
|
||||
* RequirePortalAccess admin gate.
|
||||
* SaaS gate: viewing your own usage is not admin-gated, so any real (signed-in,
|
||||
* non-guest) account may enter - deliberately laxer than the self-hosted
|
||||
* RequirePortalAccess admin gate. But an anonymous guest session has no account
|
||||
* to view or manage, so it is not eligible: bounce it to the editor (where a
|
||||
* guest can sign up), mirroring the self-hosted forbidden path. No session at
|
||||
* all -> the editor's Supabase login, which returns here signed in.
|
||||
*/
|
||||
function SaasPortalGate({ children }: { children: ReactNode }) {
|
||||
const { session, loading } = useAuth();
|
||||
const { session, loading, isAnonymous } = useAuth();
|
||||
const blocked = !loading && (!session || isAnonymous);
|
||||
useEffect(() => {
|
||||
if (!loading && !session) {
|
||||
window.location.href = "/login";
|
||||
}
|
||||
}, [loading, session]);
|
||||
if (loading || !session) {
|
||||
if (!blocked) return;
|
||||
// Guest (has a session but anonymous) -> editor; no session -> login.
|
||||
window.location.href = session ? EDITOR_URL : "/login";
|
||||
}, [blocked, session]);
|
||||
if (loading || blocked) {
|
||||
return (
|
||||
<FullScreen>
|
||||
<Spinner size="lg" />
|
||||
|
||||
Reference in New Issue
Block a user