IntegrationCard.tsx226 lines · main
1import { Check } from 'lucide-react'
2import Image from 'next/image'
3import { Badge, Button } from 'ui'
4
5import { AWS_IDP_REGIONS } from './AwsRegionSelector'
6import {
7 getIntegrationType,
8 getIntegrationTypeIcon,
9 getIntegrationTypeLabel,
10 INTEGRATION_TYPES,
11} from './ThirdPartyAuthForm.utils'
12import { ThirdPartyAuthIntegration } from '@/data/third-party-auth/integrations-query'
13import { DOCS_URL } from '@/lib/constants'
14
15interface IntegrationCardProps {
16 integration: ThirdPartyAuthIntegration
17 canUpdateConfig: boolean
18 onDelete: () => void
19}
20
21export const getIntegrationTypeDescription = (type: INTEGRATION_TYPES) => {
22 switch (type) {
23 case 'firebase':
24 return (
25 <>
26 Allow users to use Briven with Firebase project. You'll need to setup RLS policies for
27 all tables that you want to access with a Firebase JWT token. Additionally, you'll need to
28 add custom code to set the <code>authenticated</code> role to all your present and future
29 users. You can read more in the{' '}
30 <a
31 className="hover:decoration-brand underline hover:text-foreground transition"
32 href={`${DOCS_URL}/guides/auth`}
33 >
34 documentation
35 </a>
36 .
37 </>
38 )
39
40 case 'auth0':
41 return (
42 <>
43 Allow users to use Briven with Auth0 project. Additional setup may be required. You can
44 read more in the{' '}
45 <a
46 className="hover:decoration-brand underline hover:text-foreground transition"
47 href={`${DOCS_URL}/guides/auth`}
48 >
49 documentation
50 </a>
51 .
52 </>
53 )
54 case 'awsCognito':
55 return (
56 <>
57 Allow users to use Briven with an Amazon Cognito. Additional setup may be required. You
58 can read more in the{' '}
59 <a
60 className="hover:decoration-brand underline hover:text-foreground transition"
61 href={`${DOCS_URL}/guides/auth/third-party/aws-cognito`}
62 >
63 documentation
64 </a>
65 .
66 </>
67 )
68
69 case 'clerk':
70 return (
71 <>
72 Allow users to use Briven with Clerk. Additional setup may be required. You can read
73 more in the{' '}
74 <a
75 className="hover:decoration-brand underline hover:text-foreground transition"
76 href={`${DOCS_URL}/guides/auth/third-party/clerk`}
77 >
78 documentation
79 </a>
80 .
81 </>
82 )
83
84 case 'workos':
85 return (
86 <>
87 Allow users to use Briven with WorkOS. Additional setup may be required. You can read
88 more in the{' '}
89 <a
90 className="hover:decoration-brand underline hover:text-foreground transition"
91 href={`${DOCS_URL}/guides/auth/third-party/workos`}
92 >
93 documentation
94 </a>
95 .
96 </>
97 )
98
99 case 'custom':
100 default:
101 return 'Custom'
102 }
103}
104
105export const IntegrationTypeContent = ({
106 type,
107 integration,
108}: {
109 type: INTEGRATION_TYPES
110 integration: ThirdPartyAuthIntegration
111}) => {
112 switch (type) {
113 case 'firebase': {
114 const projectName =
115 integration.oidc_issuer_url?.replace('https://securetoken.google.com/', '') || ''
116
117 return (
118 <div className="text-sm flex flex-row gap-x-4">
119 <span className="text-foreground-light w-36">Firebase Project ID</span>
120 <span className="text-foreground">{projectName}</span>
121 </div>
122 )
123 }
124 case 'auth0':
125 const domainName =
126 integration.oidc_issuer_url?.replace('https://', '').replace('.auth0.com', '') || ''
127
128 return (
129 <div className="text-sm flex flex-row gap-x-4">
130 <span className="text-foreground-light w-36">Auth0 Domain Name</span>
131 <span className="text-foreground">{domainName}</span>
132 </div>
133 )
134 case 'awsCognito': {
135 const region =
136 integration.oidc_issuer_url?.split('.').filter((s) => AWS_IDP_REGIONS.includes(s))[0] || ''
137
138 const userPoolId =
139 integration.oidc_issuer_url?.split('/').filter((s) => s.startsWith(region || ''))[0] || ''
140
141 return (
142 <div className="text-sm flex flex-col gap-y-2">
143 <div className="flex flex-row gap-x-4">
144 <span className="text-foreground-light w-36">Region</span>
145 <span className="text-foreground">{region}</span>
146 </div>
147 <div className="flex flex-row gap-x-4">
148 <span className="text-foreground-light w-36">User Pool ID</span>
149 <span className="text-foreground">{userPoolId}</span>
150 </div>
151 </div>
152 )
153 }
154
155 case 'clerk':
156 return (
157 <div className="text-sm flex flex-row gap-x-4">
158 <span className="text-foreground-light w-36">Domain</span>
159 <span className="text-foreground">{integration?.oidc_issuer_url ?? ''}</span>
160 </div>
161 )
162
163 case 'workos':
164 return (
165 <div className="text-sm flex flex-row gap-x-4">
166 <span className="text-foreground-light w-36">Issuer URL</span>
167 <span className="text-foreground">{integration?.oidc_issuer_url ?? ''}</span>
168 </div>
169 )
170
171 case 'custom':
172 default:
173 return <>Custom</>
174 }
175}
176
177export const IntegrationCard = ({
178 integration,
179 canUpdateConfig,
180 onDelete,
181}: IntegrationCardProps) => {
182 let type = getIntegrationType(integration)
183
184 if (type === 'custom') {
185 return null
186 }
187
188 return (
189 <>
190 <div className="bg-surface-100 border overflow-hidden shadow-sm px-5 py-4 flex flex-row first:rounded-t-md last:rounded-b-md space-x-4">
191 <div className="py-1">
192 <Image src={getIntegrationTypeIcon(type)} width={21} height={21} alt={`${type} icon`} />
193 </div>
194 <div className="flex min-w-0 flex-1 flex-col gap-y-4 overflow-y-auto">
195 <div className="text-sm flex flex-col">
196 <span className="text-foreground">{getIntegrationTypeLabel(type)}</span>
197 <div className="text-foreground-lighter">{getIntegrationTypeDescription(type)}</div>
198 </div>
199
200 <IntegrationTypeContent type={type} integration={integration} />
201 <div>
202 {/* TODO: this should be a configure integration where it would show the sheet and the user can disable or delete the integration
203 but there's no "edit integration" endpoing for now. */}
204 <Button type="danger" disabled={!canUpdateConfig} onClick={() => onDelete()}>
205 Delete integration
206 </Button>
207 </div>
208 </div>
209 <div className="shrink-0">
210 {true ? (
211 <Badge className="space-x-1" variant="success">
212 <div className="h-3.5 w-3.5 bg-brand rounded-full flex justify-center items-center">
213 <Check className="h-2 w-2 text-background-overlay" strokeWidth={6} />
214 </div>
215 <span>Enabled</span>
216 </Badge>
217 ) : (
218 <Badge variant="warning">
219 <span>Disabled</span>
220 </Badge>
221 )}
222 </div>
223 </div>
224 </>
225 )
226}