@@ -164,14 +164,20 @@ export function CloudOrganizationSettings({ orgId }: { orgId: string }) {
164164 const [ newSsoDomain , setNewSsoDomain ] = useState ( '' ) ;
165165 const [ isAddingSsoDomain , setIsAddingSsoDomain ] = useState ( false ) ;
166166
167+ const organizationEntitlementsQuery = useQuery ( {
168+ ...orgApi . organizationEntitlementsGetQuery ( orgId ! ) ,
169+ enabled : ! ! orgId && canManageSso ,
170+ } ) ;
171+ const canUseSso = organizationEntitlementsQuery . data ?. canSSO === true ;
172+
167173 const organizationSsoDomainGetQuery = useQuery ( {
168174 ...orgApi . organizationSsoDomainGetQuery ( orgId ) ,
169- enabled : ! ! orgId && canManageSso ,
175+ enabled : ! ! orgId && canUseSso ,
170176 } ) ;
171177
172178 const organizationSsoConfigGetQuery = useQuery ( {
173179 ...orgApi . organizationSsoConfigGetQuery ( orgId ) ,
174- enabled : ! ! orgId && canManageSso ,
180+ enabled : ! ! orgId && canUseSso ,
175181 } ) ;
176182
177183 const ssoConfigUpdateMutation = useMutation ( {
@@ -947,101 +953,122 @@ export function CloudOrganizationSettings({ orgId }: { orgId: string }) {
947953 </ TabsContent >
948954 { canManageSso && (
949955 < TabsContent value = "sso" >
950- < div className = "space-y-8" >
951- < CreateSSOPage orgId = { orgId } />
952- { /* Force SSO toggle */ }
953- { isOrganizationOwner && (
954- < div className = "flex items-center justify-between rounded-lg border border-border/50 bg-muted/10 p-4" >
955- < div className = "space-y-0.5" >
956- < p className = "text-sm font-medium" > Force SSO</ p >
957- < p className = "text-sm text-muted-foreground" >
958- Require all organization members to sign in with SSO.
959- All other login methods will be disabled.
960- </ p >
961- </ div >
962- < Switch
963- checked = {
964- organizationSsoConfigGetQuery . data ?. forceSSO ?? false
965- }
966- onCheckedChange = { ( checked ) =>
967- ssoConfigUpdateMutation . mutate ( checked )
968- }
969- disabled = {
970- organizationSsoConfigGetQuery . isLoading ||
971- ssoConfigUpdateMutation . isPending
972- }
973- />
974- </ div >
975- ) }
976- { /* SSO Domains Table */ }
977- { organizationSsoDomainGetQuery . isLoading ? (
978- < div className = "flex items-center justify-center py-8" >
979- < Loading />
980- </ div >
981- ) : organizationSsoDomainGetQuery . data &&
982- organizationSsoDomainGetQuery . data . length > 0 ? (
983- < SimpleTable
984- data = { organizationSsoDomainGetQuery . data . map ( ( v ) => ( {
985- domain : v . ssoDomain ,
986- verified : v . verified ,
987- verification_token : v . verificationToken ,
988- } ) ) }
989- columns = { ssoDomainColumns }
990- rowKey = { ( row ) => row . domain }
991- />
992- ) : (
993- < div className = "py-16 text-center" >
994- < KeyIcon className = "mx-auto mb-4 h-12 w-12 text-muted-foreground" />
995- < h3 className = "mb-2 text-lg font-medium" > No SSO Domains</ h3 >
996- < p className = "mb-4 text-muted-foreground" >
997- Add a domain below to enable SSO for your organization.
998- </ p >
999- </ div >
1000- ) }
1001-
1002- { /* Add New SSO Domain */ }
1003- < div className = "space-y-2" >
1004- < div className = "flex gap-2" >
1005- < Input
1006- placeholder = "example.com"
1007- value = { newSsoDomain }
1008- onChange = { ( e ) => setNewSsoDomain ( e . target . value ) }
1009- onKeyDown = { ( e ) => {
1010- if ( e . key === 'Enter' ) {
1011- handleAddSsoDomain ( ) ;
956+ { organizationEntitlementsQuery . isLoading ? (
957+ < div className = "flex items-center justify-center py-8" >
958+ < Loading />
959+ </ div >
960+ ) : canUseSso ? (
961+ < div className = "space-y-8" >
962+ < CreateSSOPage orgId = { orgId } />
963+ { /* Force SSO toggle */ }
964+ { isOrganizationOwner && (
965+ < div className = "flex items-center justify-between rounded-lg border border-border/50 bg-muted/10 p-4" >
966+ < div className = "space-y-0.5" >
967+ < p className = "text-sm font-medium" > Force SSO</ p >
968+ < p className = "text-sm text-muted-foreground" >
969+ Require all organization members to sign in with SSO.
970+ All other login methods will be disabled.
971+ </ p >
972+ </ div >
973+ < Switch
974+ checked = {
975+ organizationSsoConfigGetQuery . data ?. forceSSO ?? false
976+ }
977+ onCheckedChange = { ( checked ) =>
978+ ssoConfigUpdateMutation . mutate ( checked )
1012979 }
1013- } }
1014- className = "max-w-sm"
1015- disabled = { isAddingSsoDomain }
980+ disabled = {
981+ organizationSsoConfigGetQuery . isLoading ||
982+ ssoConfigUpdateMutation . isPending
983+ }
984+ />
985+ </ div >
986+ ) }
987+ { /* SSO Domains Table */ }
988+ { organizationSsoDomainGetQuery . isLoading ? (
989+ < div className = "flex items-center justify-center py-8" >
990+ < Loading />
991+ </ div >
992+ ) : organizationSsoDomainGetQuery . data &&
993+ organizationSsoDomainGetQuery . data . length > 0 ? (
994+ < SimpleTable
995+ data = { organizationSsoDomainGetQuery . data . map ( ( v ) => ( {
996+ domain : v . ssoDomain ,
997+ verified : v . verified ,
998+ verification_token : v . verificationToken ,
999+ } ) ) }
1000+ columns = { ssoDomainColumns }
1001+ rowKey = { ( row ) => row . domain }
10161002 />
1017- < Button
1018- variant = "outline"
1019- size = "sm"
1020- onClick = { handleAddSsoDomain }
1021- disabled = { isAddingSsoDomain || ! newSsoDomain . trim ( ) }
1022- leftIcon = { < PlusIcon className = "size-4" /> }
1023- >
1024- Add Domain
1025- </ Button >
1026- </ div >
1027- </ div >
1028- { organizationSsoDomainGetQuery . data &&
1029- organizationSsoDomainGetQuery . data . length > 0 && (
1030- < div className = "rounded-md border border-muted bg-muted/30 px-4 py-3 text-sm text-muted-foreground" >
1031- < p >
1032- To verify your domain, add a DNS TXT record with the
1033- value:
1034- </ p >
1035- < p className = "mt-1 font-mono" >
1036- hatchet-sso-verify={verification_token}
1037- </ p >
1038- < p className = "mt-2" >
1039- It may take a few minutes for DNS changes to propagate
1040- and for the verified status to update.
1003+ ) : (
1004+ < div className = "py-16 text-center" >
1005+ < KeyIcon className = "mx-auto mb-4 h-12 w-12 text-muted-foreground" />
1006+ < h3 className = "mb-2 text-lg font-medium" >
1007+ No SSO Domains
1008+ </ h3 >
1009+ < p className = "mb-4 text-muted-foreground" >
1010+ Add a domain below to enable SSO for your organization.
10411011 </ p >
10421012 </ div >
10431013 ) }
1044- </ div >
1014+
1015+ { /* Add New SSO Domain */ }
1016+ < div className = "space-y-2" >
1017+ < div className = "flex gap-2" >
1018+ < Input
1019+ placeholder = "example.com"
1020+ value = { newSsoDomain }
1021+ onChange = { ( e ) => setNewSsoDomain ( e . target . value ) }
1022+ onKeyDown = { ( e ) => {
1023+ if ( e . key === 'Enter' ) {
1024+ handleAddSsoDomain ( ) ;
1025+ }
1026+ } }
1027+ className = "max-w-sm"
1028+ disabled = { isAddingSsoDomain }
1029+ />
1030+ < Button
1031+ variant = "outline"
1032+ size = "sm"
1033+ onClick = { handleAddSsoDomain }
1034+ disabled = { isAddingSsoDomain || ! newSsoDomain . trim ( ) }
1035+ leftIcon = { < PlusIcon className = "size-4" /> }
1036+ >
1037+ Add Domain
1038+ </ Button >
1039+ </ div >
1040+ </ div >
1041+ { organizationSsoDomainGetQuery . data &&
1042+ organizationSsoDomainGetQuery . data . length > 0 && (
1043+ < div className = "rounded-md border border-muted bg-muted/30 px-4 py-3 text-sm text-muted-foreground" >
1044+ < p >
1045+ To verify your domain, add a DNS TXT record with the
1046+ value:
1047+ </ p >
1048+ < p className = "mt-1 font-mono" >
1049+ hatchet-sso-verify={verification_token}
1050+ </ p >
1051+ < p className = "mt-2" >
1052+ It may take a few minutes for DNS changes to propagate
1053+ and for the verified status to update.
1054+ </ p >
1055+ </ div >
1056+ ) }
1057+ </ div >
1058+ ) : (
1059+ < div className = "py-16 text-center text-sm text-muted-foreground" >
1060+ SSO is not enabled for this organization. Please{ ' ' }
1061+ < a
1062+ href = { OFFICE_HOURS_URL }
1063+ target = "_blank"
1064+ rel = "noopener noreferrer"
1065+ className = "text-primary underline-offset-4 hover:underline"
1066+ >
1067+ contact us
1068+ </ a > { ' ' }
1069+ to get access.
1070+ </ div >
1071+ ) }
10451072 </ TabsContent >
10461073 ) }
10471074 </ Tabs >
0 commit comments