import {Fragment} from 'react'; import styled from '@emotion/styled'; import {logout} from 'sentry/actionCreators/account'; import {Button, LinkButton} from 'sentry/components/button'; import {Alert} from 'sentry/components/core/alert'; import ExternalLink from 'sentry/components/links/externalLink'; import Link from 'sentry/components/links/link'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import NarrowLayout from 'sentry/components/narrowLayout'; import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle'; import {t, tct} from 'sentry/locale'; import ConfigStore from 'sentry/stores/configStore'; import {space} from 'sentry/styles/space'; import {useApiQuery, useMutation} from 'sentry/utils/queryClient'; import useApi from 'sentry/utils/useApi'; import {useParams} from 'sentry/utils/useParams'; import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader'; type InviteDetails = { existingMember: boolean; hasAuthProvider: boolean; needs2fa: boolean; needsAuthentication: boolean; orgSlug: string; requireSso: boolean; ssoProvider?: string; }; function AcceptActions({ inviteDetails, isAccepting, acceptInvite, }: { acceptInvite: () => void; inviteDetails: InviteDetails; isAccepting: boolean; }) { return ( {inviteDetails.hasAuthProvider && !inviteDetails.requireSso && (

{tct( `Note that [orgSlug] has enabled Single Sign-On (SSO) using [authProvider]. You may join the organization by authenticating with the organization's SSO provider or via your standard account authentication.`, { orgSlug: {inviteDetails.orgSlug}, authProvider: inviteDetails.ssoProvider, } )}

)} {inviteDetails.hasAuthProvider && !inviteDetails.requireSso && ( {t('Join with %s', inviteDetails.ssoProvider)} )}
); } function ExistingMemberAlert() { const api = useApi({persistInFlight: true}); const user = ConfigStore.get('user'); return ( {tct( 'Your account ([email]) is already a member of this organization. [switchLink:Switch accounts]?', { email: user.email, switchLink: ( { e.preventDefault(); logout(api); }} /> ), } )} ); } function Warning2fa({inviteDetails}: {inviteDetails: InviteDetails}) { const sentryUrl = ConfigStore.get('links').sentryUrl; return (

{tct( 'To continue, [orgSlug] requires all members to configure two-factor authentication.', {orgSlug: inviteDetails.orgSlug} )}

{t('Configure Two-Factor Auth')}
); } function AuthenticationActions({inviteDetails}: {inviteDetails: InviteDetails}) { return ( {!inviteDetails.requireSso && (

{t( `To continue, you must either create a new account, or login to an existing Sentry account.` )}

)} {inviteDetails.hasAuthProvider && (

{inviteDetails.requireSso ? tct( `Note that [orgSlug] has required Single Sign-On (SSO) using [authProvider]. You may create an account by authenticating with the organization's SSO provider.`, { orgSlug: {inviteDetails.orgSlug}, authProvider: inviteDetails.ssoProvider, } ) : tct( `Note that [orgSlug] has enabled Single Sign-On (SSO) using [authProvider]. You may create an account by authenticating with the organization's SSO provider.`, { orgSlug: {inviteDetails.orgSlug}, authProvider: inviteDetails.ssoProvider, } )}

)} {inviteDetails.hasAuthProvider && ( {t('Join with %s', inviteDetails.ssoProvider)} )} {!inviteDetails.requireSso && ( {t('Create a new account')} )} {!inviteDetails.requireSso && ( {t('Login using an existing account')} )}
); } function AcceptOrganizationInvite() { const api = useApi({persistInFlight: true}); const params = useParams<{memberId: string; token: string; orgId?: string}>(); const orgSlug = params.orgId || ConfigStore.get('customerDomain')?.subdomain || null; const { data: inviteDetails, isPending, isError, } = useApiQuery( orgSlug ? [`/accept-invite/${orgSlug}/${params.memberId}/${params.token}/`] : [`/accept-invite/${params.memberId}/${params.token}/`], { staleTime: Infinity, retry: false, } ); const { mutate: acceptInvite, isPending: isAccepting, isError: isAcceptError, } = useMutation({ mutationFn: () => api.requestPromise( orgSlug ? `/accept-invite/${orgSlug}/${params.memberId}/${params.token}/` : `/accept-invite/${params.memberId}/${params.token}/`, { method: 'POST', } ), onSuccess: () => { if (inviteDetails?.orgSlug) { window.location.href = `/${inviteDetails.orgSlug}/`; } }, }); if (isPending) { return ; } if (isError) { return ( {tct( 'This organization invite link is invalid. It may be expired, or you may need to [switchLink:sign in with a different account].', { switchLink: ( { e.preventDefault(); logout(api, `/accept/${params.memberId}/${params.token}/`); }} /> ), } )} ); } return ( {isAcceptError && ( {t('Failed to join this organization. Please try again')} )} {tct('[orgSlug] is using Sentry to track and debug errors.', { orgSlug: {inviteDetails.orgSlug}, })} {inviteDetails.needsAuthentication ? ( ) : inviteDetails.existingMember ? ( ) : inviteDetails.needs2fa ? ( ) : inviteDetails.requireSso ? ( ) : ( )} ); } const Actions = styled('div')` display: flex; align-items: center; justify-content: space-between; margin-bottom: ${space(3)}; `; const ActionsLeft = styled('span')` > a { margin-right: ${space(1)}; } `; const InviteDescription = styled('p')` font-size: 1.2em; `; export default AcceptOrganizationInvite;