Create assume page to redirect to when AssumptionRequired catched in boundary
Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
@@ -15,7 +15,7 @@ export function OrganizationErrorBoundary() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error instanceof AssumptionRequiredError) {
|
if (error instanceof AssumptionRequiredError) {
|
||||||
return <Navigate to="/auth/login" state={{ from: location.pathname, organizationId }} />;
|
return <Navigate to={`/organizations/${organizationId}/assume`} state={{ from: location.pathname }} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <PageError error={error instanceof Error ? error : new Error("unknown error")} />;
|
return <PageError error={error instanceof Error ? error : new Error("unknown error")} />;
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { Card, Logo } from "@probo/ui";
|
import { Card, Logo } from "@probo/ui";
|
||||||
|
import type { PropsWithChildren } from "react";
|
||||||
import { Outlet } from "react-router";
|
import { Outlet } from "react-router";
|
||||||
|
|
||||||
import { IAMRelayProvider } from "#/providers/IAMRelayProvider";
|
import { IAMRelayProvider } from "#/providers/IAMRelayProvider";
|
||||||
|
|
||||||
export default function AuthLayout() {
|
export default function AuthLayout(props: PropsWithChildren) {
|
||||||
|
const { children } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen text-txt-primary bg-level-0 flex flex-col items-center justify-center">
|
<div className="min-h-screen text-txt-primary bg-level-0 flex flex-col items-center justify-center">
|
||||||
<Card className="w-full max-w-lg px-12 py-8 flex flex-col items-center justify-center">
|
<Card className="w-full max-w-lg px-12 py-8 flex flex-col items-center justify-center">
|
||||||
@@ -12,7 +15,7 @@ export default function AuthLayout() {
|
|||||||
<div className="w-full border-t border-t-border-mid" />
|
<div className="w-full border-t border-t-border-mid" />
|
||||||
</div>
|
</div>
|
||||||
<IAMRelayProvider>
|
<IAMRelayProvider>
|
||||||
<Outlet />
|
{children ?? <Outlet />}
|
||||||
</IAMRelayProvider>
|
</IAMRelayProvider>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
35
apps/console/src/pages/iam/organizations/AssumePage.tsx
Normal file
35
apps/console/src/pages/iam/organizations/AssumePage.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import { useTranslate } from "@probo/i18n";
|
||||||
|
import { useLocation, useNavigate } from "react-router";
|
||||||
|
|
||||||
|
import { useAssume } from "#/hooks/iam/useAssume";
|
||||||
|
|
||||||
|
import AuthLayout from "../auth/AuthLayout";
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
from: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AssumePage() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
const state = location.state as State;
|
||||||
|
|
||||||
|
const { __ } = useTranslate();
|
||||||
|
|
||||||
|
useAssume({
|
||||||
|
onSuccess: () => void navigate(state.from),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthLayout>
|
||||||
|
<div className="space-y-6 w-full max-w-md mx-auto pt-8">
|
||||||
|
<div className="space-y-2 text-center">
|
||||||
|
<h1 className="text-3xl font-bold">{__("Sign in Redirection")}</h1>
|
||||||
|
<p className="text-txt-tertiary">
|
||||||
|
{__("Redirecting you to your authentication URL…")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AuthLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -121,7 +121,14 @@ const routes = [
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/organizations/:organizationId/employee",
|
path: "/organizations/:organizationId",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "assume",
|
||||||
|
Component: lazy(() => import("./pages/iam/organizations/AssumePage")),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "employee",
|
||||||
Component: lazy(
|
Component: lazy(
|
||||||
() => import("./pages/organizations/employee/EmployeeLayoutLoader"),
|
() => import("./pages/organizations/employee/EmployeeLayoutLoader"),
|
||||||
),
|
),
|
||||||
@@ -144,14 +151,12 @@ const routes = [
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/organizations/:organizationId",
|
|
||||||
Component: lazy(
|
Component: lazy(
|
||||||
() => import("./pages/iam/organizations/ViewerMembershipLayoutLoader"),
|
() => import("./pages/iam/organizations/ViewerMembershipLayoutLoader"),
|
||||||
),
|
),
|
||||||
ErrorBoundary: OrganizationErrorBoundary,
|
ErrorBoundary: OrganizationErrorBoundary,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
|
||||||
Component: () => {
|
Component: () => {
|
||||||
const { role } = use(CurrentUser);
|
const { role } = use(CurrentUser);
|
||||||
switch (role) {
|
switch (role) {
|
||||||
@@ -233,6 +238,9 @@ const routes = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
// Fallback URL to the NotFound Page
|
// Fallback URL to the NotFound Page
|
||||||
{
|
{
|
||||||
path: "*",
|
path: "*",
|
||||||
|
|||||||
@@ -410,13 +410,9 @@ func (r *mutationResolver) SignIn(ctx context.Context, input types.SignInInput)
|
|||||||
var err error
|
var err error
|
||||||
session, _, err = r.iam.SessionService.OpenPasswordChildSessionForOrganization(ctx, session.ID, *input.OrganizationID)
|
session, _, err = r.iam.SessionService.OpenPasswordChildSessionForOrganization(ctx, session.ID, *input.OrganizationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var errSessionExpired *iam.ErrSessionExpired
|
|
||||||
var errMembershipNotFound *iam.ErrMembershipNotFound
|
var errMembershipNotFound *iam.ErrMembershipNotFound
|
||||||
var errMembershipInactive *iam.ErrMembershipInactive
|
var errMembershipInactive *iam.ErrMembershipInactive
|
||||||
|
|
||||||
if errors.As(err, errSessionExpired) {
|
|
||||||
return nil, gqlutils.Unauthenticated(ctx, err)
|
|
||||||
}
|
|
||||||
if errors.As(err, errMembershipNotFound) || errors.As(err, errMembershipInactive) {
|
if errors.As(err, errMembershipNotFound) || errors.As(err, errMembershipInactive) {
|
||||||
return nil, gqlutils.Forbidden(ctx, err)
|
return nil, gqlutils.Forbidden(ctx, err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user