Merge branch 'feat/invite-external-users' of https://github.com/supabase/supabase into feat/invite-external-users

This commit is contained in:
Jonathan Summers-Muir committed 2022-06-22 01:29:42 +08:00
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
View File
@@ -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>