Skip to content

Conversation

@nicknisi
Copy link
Member

@nicknisi nicknisi commented Apr 3, 2025

capture_20250403_104933.mp4
Example App account route changes (Example)
import { Text, Heading, TextField, Flex, Box, Button } from '@radix-ui/themes';

import { Form, useLoaderData, useActionData, type ActionFunctionArgs, type LoaderFunctionArgs } from 'react-router';
import { authkitLoader, switchToOrganization } from '@workos-inc/authkit-react-router';

const org1 = 'org_01JP5W02BHFAAA5DHQBV837F60';
// const org2 = 'org_01JA4BGY0QWYD7RE16B8PJJT2F';
const org2 = 'org_01JKGH1Z0XBRVEYMRFWCMKQ86Y';

export const loader = (args: LoaderFunctionArgs) => authkitLoader(args, { ensureSignedIn: true });

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const orgId = formData.get('organizationId')?.toString();

  if (!orgId) {
    return { error: 'Organization ID is required' };
  }

  try {
    return await switchToOrganization(request, orgId, {
      returnTo: `/account`,
    });
  } catch (error) {
    return { error: error instanceof Error ? error.message : 'Failed to switch organization' };
  }
}

export default function AccountPage() {
  const { user, role, organizationId } = useLoaderData<typeof loader>();
  const actionData = useActionData();

  const userFields = [
    ['First name', user.firstName],
    ['Last name', user.lastName],
    ['Email', user.email],
    role ? ['Role', role] : [],
    ['Id', user.id],
    ['Org Id', organizationId],
  ].filter((arr) => arr.length > 0);

  return (
    <>
      <Flex direction="column" gap="2" mb="7">
        <Heading size="8" align="center">
          Account details
        </Heading>
        <Text size="5" align="center" color="gray">
          Below are your account details
        </Text>
      </Flex>

      {userFields && (
        <Flex direction="column" justify="center" gap="3" width="400px">
          {userFields.map(([label, value]) => (
            <Flex asChild align="center" gap="6" key={value}>
              <label>
                <Text weight="bold" size="3" style={{ width: 100 }}>
                  {label}
                </Text>

                <Box flexGrow="1">
                  <TextField.Root value={value || ''} readOnly />
                </Box>
              </label>
            </Flex>
          ))}
        </Flex>
      )}

      <Box mt="6" pt="4" style={{ borderTop: '1px solid var(--gray-5)' }}>
        <Heading size="4" mb="3">
          Switch Organization
        </Heading>

        <Flex gap="3">
          <Form method="post">
            <input type="hidden" name="organizationId" value={org1} />
            <Button type="submit" color={organizationId === org1 ? 'gray' : 'blue'} disabled={organizationId === org1}>
              Switch to Organization 1
            </Button>
          </Form>

          <Form method="post">
            <input type="hidden" name="organizationId" value={org2} />
            <Button type="submit" color={organizationId === org2 ? 'gray' : 'blue'} disabled={organizationId === org2}>
              Switch to Organization 2
            </Button>
          </Form>
        </Flex>

        {actionData?.error && (
          <Text color="red" size="2" mt="2">
            {actionData.error}
          </Text>
        )}
      </Box>
    </>
  );
}

@linear
Copy link

linear bot commented Apr 3, 2025

@nicknisi nicknisi requested a review from Copilot April 3, 2025 17:17
@nicknisi nicknisi marked this pull request as ready for review April 3, 2025 17:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds two helper functions—switchToOrganization and refreshSession—to streamline session management and organization switching within the authentication flow. Key changes include:

  • Introducing a new refreshSession function to update session tokens.
  • Exporting several session helper functions including encryptSession, authkitLoader, and terminateSession.
  • Adding a new switchToOrganization function in the auth module and corresponding tests to handle organization switching.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/session.ts Added refreshSession helper and updated exports of session functions.
src/session.spec.ts Added tests for refreshSession covering success, redirect, and error.
src/index.ts Updated re-exports to include the new refreshSession and switchToOrganization.
src/auth.ts Added switchToOrganization with error handling for SSO/MFA and session refresh.
src/auth.spec.ts Added tests for switchToOrganization validating various flows.

Copy link

@losephjambert losephjambert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for putting this together. No notes from me 🙇

@nicknisi nicknisi merged commit dae7e61 into main Apr 8, 2025
6 checks passed
@nicknisi nicknisi deleted the feature/dx-3256-add-switchtoorganization-to-react-router branch April 8, 2025 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants