Org dropdown does not need to perform assume anymore, it will use redirect-path and assume page

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-02-11 10:41:52 +04:00
parent a8d1ce0097
commit d8bb4040a1
2 changed files with 13 additions and 281 deletions

View File

@@ -1,200 +0,0 @@
/**
* @generated SignedSource<<f829648ef4b9a5c0b8c4d62ac844bca0>>
* @lightSyntaxTransform
* @nogrep
*/
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
import { ConcreteRequest } from 'relay-runtime';
export type ReauthenticationReason = "POLICY_REQUIREMENT" | "SENSITIVE_ACTION" | "SESSION_EXPIRED";
export type AssumeOrganizationSessionInput = {
organizationId: string;
redirectPath: string;
};
export type MembershipsDropdownMenuItem_assumeMutation$variables = {
input: AssumeOrganizationSessionInput;
};
export type MembershipsDropdownMenuItem_assumeMutation$data = {
readonly assumeOrganizationSession: {
readonly result: {
readonly __typename: "OrganizationSessionCreated";
readonly membership: {
readonly id: string;
readonly lastSession: {
readonly expiresAt: string;
readonly id: string;
} | null | undefined;
};
} | {
readonly __typename: "PasswordRequired";
readonly reason: ReauthenticationReason;
} | {
readonly __typename: "SAMLAuthenticationRequired";
readonly reason: ReauthenticationReason;
readonly redirectUrl: string;
} | {
// This will never be '%other', but we need some
// value in case none of the concrete values match.
readonly __typename: "%other";
};
} | null | undefined;
};
export type MembershipsDropdownMenuItem_assumeMutation = {
response: MembershipsDropdownMenuItem_assumeMutation$data;
variables: MembershipsDropdownMenuItem_assumeMutation$variables;
};
const node: ConcreteRequest = (function(){
var v0 = [
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "input"
}
],
v1 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "id",
"storageKey": null
},
v2 = {
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "reason",
"storageKey": null
},
v3 = [
{
"alias": null,
"args": [
{
"kind": "Variable",
"name": "input",
"variableName": "input"
}
],
"concreteType": "AssumeOrganizationSessionPayload",
"kind": "LinkedField",
"name": "assumeOrganizationSession",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": null,
"kind": "LinkedField",
"name": "result",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "__typename",
"storageKey": null
},
{
"kind": "InlineFragment",
"selections": [
{
"alias": null,
"args": null,
"concreteType": "Membership",
"kind": "LinkedField",
"name": "membership",
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": null,
"args": null,
"concreteType": "Session",
"kind": "LinkedField",
"name": "lastSession",
"plural": false,
"selections": [
(v1/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "expiresAt",
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
],
"type": "OrganizationSessionCreated",
"abstractKey": null
},
{
"kind": "InlineFragment",
"selections": [
(v2/*: any*/)
],
"type": "PasswordRequired",
"abstractKey": null
},
{
"kind": "InlineFragment",
"selections": [
(v2/*: any*/),
{
"alias": null,
"args": null,
"kind": "ScalarField",
"name": "redirectUrl",
"storageKey": null
}
],
"type": "SAMLAuthenticationRequired",
"abstractKey": null
}
],
"storageKey": null
}
],
"storageKey": null
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Fragment",
"metadata": null,
"name": "MembershipsDropdownMenuItem_assumeMutation",
"selections": (v3/*: any*/),
"type": "Mutation",
"abstractKey": null
},
"kind": "Request",
"operation": {
"argumentDefinitions": (v0/*: any*/),
"kind": "Operation",
"name": "MembershipsDropdownMenuItem_assumeMutation",
"selections": (v3/*: any*/)
},
"params": {
"cacheID": "96111606700d6d57e20584324fac44c3",
"id": null,
"metadata": {},
"name": "MembershipsDropdownMenuItem_assumeMutation",
"operationKind": "mutation",
"text": "mutation MembershipsDropdownMenuItem_assumeMutation(\n $input: AssumeOrganizationSessionInput!\n) {\n assumeOrganizationSession(input: $input) {\n result {\n __typename\n ... on OrganizationSessionCreated {\n membership {\n id\n lastSession {\n id\n expiresAt\n }\n }\n }\n ... on PasswordRequired {\n reason\n }\n ... on SAMLAuthenticationRequired {\n reason\n redirectUrl\n }\n }\n }\n}\n"
}
};
})();
(node as any).hash = "706b7dd33f09edc34377a52682d85037";
export default node;

View File

@@ -6,12 +6,10 @@ import {
IconClock,
IconLock,
} from "@probo/ui";
import { useCallback } from "react";
import { useFragment, useMutation } from "react-relay";
import { useNavigate } from "react-router";
import { useFragment } from "react-relay";
import { Link } from "react-router";
import { graphql } from "relay-runtime";
import type { MembershipsDropdownMenuItem_assumeMutation } from "#/__generated__/iam/MembershipsDropdownMenuItem_assumeMutation.graphql";
import type { MembershipsDropdownMenuItemFragment$key } from "#/__generated__/iam/MembershipsDropdownMenuItemFragment.graphql";
const fragment = graphql`
@@ -29,95 +27,29 @@ const fragment = graphql`
}
`;
const assumeOrganizationSessionMutation = graphql`
mutation MembershipsDropdownMenuItem_assumeMutation(
$input: AssumeOrganizationSessionInput!
) {
assumeOrganizationSession(input: $input) {
result {
__typename
... on OrganizationSessionCreated {
membership {
id
lastSession {
id
expiresAt
}
}
}
... on PasswordRequired {
reason
}
... on SAMLAuthenticationRequired {
reason
redirectUrl
}
}
}
}
`;
export function MembershipsDropdownMenuItem(props: {
fKey: MembershipsDropdownMenuItemFragment$key;
}) {
const { fKey } = props;
const navigate = useNavigate();
const { id, lastSession, organization }
= useFragment<MembershipsDropdownMenuItemFragment$key>(fragment, fKey);
const isAuthenticated = !!lastSession;
const isAssuming = !!lastSession;
const isExpired
= lastSession && parseDate(lastSession.expiresAt) < new Date();
const [assumeOrganizationSession]
= useMutation<MembershipsDropdownMenuItem_assumeMutation>(
assumeOrganizationSessionMutation,
);
const handleAssumeOrganizationSession = useCallback(() => {
if (isAuthenticated) {
void navigate(`/organizations/${organization.id}`);
} else {
assumeOrganizationSession({
variables: {
input: {
organizationId: organization.id,
},
},
onCompleted: ({ assumeOrganizationSession }) => {
if (!assumeOrganizationSession) {
throw new Error("complete mutation result is empty");
}
const { result } = assumeOrganizationSession;
switch (result.__typename) {
case "PasswordRequired":
void navigate("/auth/login");
break;
case "SAMLAuthenticationRequired":
window.location.href = result.redirectUrl;
break;
default:
void navigate(`/organizations/${organization.id}`);
}
},
});
}
}, [assumeOrganizationSession, navigate, organization.id, isAuthenticated]);
return (
<DropdownItem key={id} onClick={handleAssumeOrganizationSession}>
{/* TODO add link or anchor */}
<Avatar name={organization.name} src={organization.logoUrl} />
<span className="flex-1">{organization.name}</span>
{isAuthenticated && (
<IconCheckmark1 size={16} className="text-green-600" />
)}
{isExpired && <IconClock size={16} className="text-orange-600" />}
{!lastSession && <IconLock size={16} className="text-gray-400" />}
<DropdownItem key={id} asChild>
<Link to={`/organizations/${organization.id}`}>
<Avatar name={organization.name} src={organization.logoUrl} />
<span className="flex-1">{organization.name}</span>
{isAssuming && (
<IconCheckmark1 size={16} className="text-green-600" />
)}
{isExpired && <IconClock size={16} className="text-orange-600" />}
{!lastSession && <IconLock size={16} className="text-gray-400" />}
</Link>
</DropdownItem>
);
}