mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 10:55:06 +03:00
Merge branch 'feat/invite-external-users' of https://github.com/supabase/supabase into feat/invite-external-users
This commit is contained in:
commit
cb28cd7fa4
2 files changed
+59
-48
No files matched your search
@@ -23,7 +23,7 @@ const RouteValidationWrapper: FC = ({ children }) => {
|
||||
// or prompt the user to create an organaization
|
||||
// this is used by database.dev, usually as /new/new-project
|
||||
'/new/[slug]',
|
||||
'/org/[slug]/join',
|
||||
'/join',
|
||||
]
|
||||
|
||||
/**
|
||||
|
||||
+58
-47
@@ -8,7 +8,7 @@ import { API_URL } from 'lib/constants'
|
||||
import { get, post, delete_ } from 'lib/common/fetch'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
interface TokenInfo {
|
||||
interface TokenInfoI {
|
||||
organization_name: string | undefined
|
||||
token_does_not_exist: boolean
|
||||
email_match: boolean
|
||||
@@ -17,12 +17,14 @@ interface TokenInfo {
|
||||
invite_id: number
|
||||
}
|
||||
|
||||
type TokenInfo = TokenInfoI | undefined
|
||||
|
||||
const User = () => {
|
||||
const router = useRouter()
|
||||
const { slug, token } = router.query
|
||||
const { ui } = useStore()
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [tokenValidationInfo, setTokenValidationInfo] = useState<TokenInfo>()
|
||||
const [tokenValidationInfo, setTokenValidationInfo] = useState<TokenInfo>(undefined)
|
||||
const [tokenInfoLoaded, setTokenInfoLoaded] = useState(false)
|
||||
const {
|
||||
token_does_not_exist,
|
||||
@@ -33,30 +35,21 @@ const User = () => {
|
||||
invite_id,
|
||||
} = tokenValidationInfo || {}
|
||||
|
||||
console.log(slug, token)
|
||||
console.log('tokenValidationInfo', tokenValidationInfo)
|
||||
console.log('tokenInfoLoaded', tokenInfoLoaded)
|
||||
|
||||
useEffect(() => {
|
||||
let cancel = false
|
||||
|
||||
async function fetchTokenInfo() {
|
||||
const response = await get(`${API_URL}/organizations/${slug}/members/join?token=${token}`, {})
|
||||
if (!cancel) {
|
||||
try {
|
||||
const response = await get(`${API_URL}/organizations/${slug}/members/join?token=${token}`)
|
||||
setTokenValidationInfo(response)
|
||||
setTokenInfoLoaded(true)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
if (router.query.token) {
|
||||
console.log('i have a tokens')
|
||||
if (router.query.token && !tokenInfoLoaded) {
|
||||
fetchTokenInfo()
|
||||
}
|
||||
|
||||
return () => {
|
||||
cancel = true
|
||||
}
|
||||
}, [])
|
||||
}, [router.query])
|
||||
|
||||
async function handleJoinOrganization() {
|
||||
setIsSubmitting(true)
|
||||
@@ -93,32 +86,23 @@ const User = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-scale-100 flex h-full min-h-screen w-full flex-col place-items-center items-center justify-center gap-8 px-5">
|
||||
{/* <Link
|
||||
passHref
|
||||
href={`/?next=${encodeURIComponent(
|
||||
`/join/?token=${router.query.token}&slug=${router.query.slug}`
|
||||
)}`}
|
||||
>
|
||||
<Button as="a">Sign in / Sign up</Button>
|
||||
</Link> */}
|
||||
<Link href="/">
|
||||
<a className="flex items-center justify-center gap-4">
|
||||
<img
|
||||
src="/img/supabase-logo.svg"
|
||||
alt="Supabase"
|
||||
className="block h-[24px] cursor-pointer rounded"
|
||||
/>
|
||||
{/* <h3 className="text-scale-1200">Supabase</h3> */}
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<div className="bg-scale-200 flex h-full min-h-screen w-full flex-col place-items-center items-center justify-center gap-8 px-5">
|
||||
<div
|
||||
className="
|
||||
bg-scale-200 border-scale-300 mx-auto max-w-md
|
||||
rounded-md border text-center shadow"
|
||||
bg-scale-300 border-scale-400 mx-auto max-w-md
|
||||
overflow-hidden rounded-md border text-center shadow"
|
||||
>
|
||||
<div className="space-y-4 px-6 py-6">
|
||||
<Link href="/">
|
||||
<a className="flex items-center justify-center gap-4">
|
||||
<img
|
||||
src="/img/supabase-logo.svg"
|
||||
alt="Supabase"
|
||||
className="block h-[24px] cursor-pointer rounded"
|
||||
/>
|
||||
{/* <h3 className="text-scale-1200">Supabase</h3> */}
|
||||
</a>
|
||||
</Link>
|
||||
<p className="text-scale-900 text-sm">
|
||||
Join {organization_name && email_match ? organization_name : 'a new organization'}
|
||||
</p>
|
||||
@@ -136,8 +120,8 @@ const User = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="border-scale-300 border-t bg-amber-100">
|
||||
<div className="flex flex-col gap-4 px-6 py-4">
|
||||
<div className="border-scale-400 border-t bg-amber-100">
|
||||
<div className="flex flex-col gap-4 px-6 py-6 ">
|
||||
{authorized_user && !expired_token && email_match && tokenInfoLoaded && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
@@ -163,19 +147,46 @@ const User = () => {
|
||||
|
||||
{tokenInfoLoaded && (
|
||||
<div className="text-amber-1100 flex gap-4 text-base">
|
||||
{token_does_not_exist ||
|
||||
!email_match ||
|
||||
(expired_token && <IconAlertCircle size={24} strokeWidth={2} />)}
|
||||
{(tokenInfoLoaded && token_does_not_exist) ||
|
||||
(tokenInfoLoaded && !email_match) ||
|
||||
(tokenInfoLoaded && expired_token && (
|
||||
<IconAlertCircle size={24} strokeWidth={2} />
|
||||
))}
|
||||
|
||||
{token_does_not_exist
|
||||
{tokenInfoLoaded && token_does_not_exist
|
||||
? 'The invite token is invalid. Try copying and pasting the link from the invite email, or ask the organization owner to invite you again.'
|
||||
: !email_match
|
||||
: tokenInfoLoaded && !email_match
|
||||
? 'The email address does not match. Are you signed in with right GitHub account?'
|
||||
: expired_token
|
||||
: tokenInfoLoaded && expired_token
|
||||
? 'The invite token has expired. Please request a new one from the organization owner.'
|
||||
: ''}
|
||||
</div>
|
||||
)}
|
||||
{authorized_user && !expired_token && email_match && tokenInfoLoaded && (
|
||||
<div className="flex flex-row items-center gap-3">
|
||||
<Button onClick={handleDeclineJoinOrganization} size="small" type="text">
|
||||
Decline
|
||||
</Button>
|
||||
|
||||
<Button onClick={handleJoinOrganization} loading={isSubmitting} size="small">
|
||||
Join this organization
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{!authorized_user && (
|
||||
<div>
|
||||
<Link
|
||||
passHref
|
||||
href={`/?next=${encodeURIComponent(
|
||||
`/join?token=${router.query.token}&slug=${router.query.slug}`
|
||||
)}`}
|
||||
>
|
||||
<Button size="medium" as="a" type="default">
|
||||
Sign in
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user