-
Notifications
You must be signed in to change notification settings - Fork 131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP neon oauth #1578
Open
evisdrenova
wants to merge
1
commit into
main
Choose a base branch
from
neonoAuthIntegration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
WIP neon oauth #1578
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
frontend/apps/web/app/(mgmt)/[account]/new/connection/neon/NeonForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
'use client'; | ||
import { useAccount } from '@/components/providers/account-provider'; | ||
import { Button } from '@/components/ui/button'; | ||
import { useSession } from 'next-auth/react'; | ||
import { useRouter } from 'next/navigation'; | ||
|
||
export default function NeonForm() { | ||
const { account } = useAccount(); | ||
const router = useRouter(); | ||
const session = useSession(); | ||
|
||
async function onSubmit() { | ||
if (!account) { | ||
return; | ||
} | ||
try { | ||
const res = await CreateNeonIntegration(account.id); | ||
if (res.redirect) { | ||
// open up in a new window that is smaller than the current winow and ideally close when complete | ||
router.replace(res.redirect); | ||
return; | ||
} | ||
|
||
console.log('done'); | ||
} catch (err) { | ||
console.error('Error in form submission:', err); | ||
} | ||
} | ||
// the UI | ||
// projects -> branches -> databases -> role -> host | ||
/* | ||
1. get all projects and list all projects | ||
2. user selects a project | ||
3. get all branches for that project, list all branches | ||
4. user selects a branch | ||
5. get all databases, user selects a database | ||
6. get all roles, list all roles | ||
7. user selects a role | ||
8. get role password from endpoint, get host from endpoint, connect to database, run basic query to validate connections | ||
9. user clicks submit | ||
|
||
*/ | ||
|
||
return ( | ||
<div> | ||
<Button onClick={onSubmit}>Connect your Neon account</Button> | ||
</div> | ||
); | ||
} | ||
|
||
async function CreateNeonIntegration(accountId: string) { | ||
const res = await fetch(`/api/accounts/${accountId}/connections/neon`, { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
|
||
if (!res.ok) { | ||
const body = await res.json(); | ||
throw new Error(body.message); | ||
} | ||
|
||
const data = await res.json(); | ||
|
||
return data; | ||
} |
58 changes: 58 additions & 0 deletions
58
frontend/apps/web/app/(mgmt)/[account]/new/connection/neon/NeonLogo.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
export const NeonLogo = () => { | ||
return ( | ||
<svg | ||
width="48" | ||
height="48" | ||
viewBox="0 0 36 36" | ||
fill="none" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M0 6.207C0 4.5608 0.65395 2.98203 1.81799 1.81799C2.98203 0.65395 4.5608 0 6.207 0L29.793 0C31.4392 0 33.018 0.65395 34.182 1.81799C35.346 2.98203 36 4.5608 36 6.207V26.267C36 29.813 31.512 31.352 29.336 28.553L22.531 19.799V30.414C22.531 31.8955 21.9425 33.3163 20.8949 34.3639C19.8473 35.4115 18.4265 36 16.945 36H6.207C4.5608 36 2.98203 35.346 1.81799 34.182C0.65395 33.018 0 31.4392 0 29.793L0 6.207ZM6.207 4.966C5.521 4.966 4.966 5.521 4.966 6.206V29.793C4.966 30.479 5.521 31.035 6.206 31.035H17.131C17.474 31.035 17.565 30.757 17.565 30.414V16.18C17.565 12.633 22.053 11.094 24.23 13.894L31.035 22.647V6.207C31.035 5.521 31.099 4.966 30.414 4.966H6.207Z" | ||
fill="#12FFF7" | ||
/> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M0 6.207C0 4.5608 0.65395 2.98203 1.81799 1.81799C2.98203 0.65395 4.5608 0 6.207 0L29.793 0C31.4392 0 33.018 0.65395 34.182 1.81799C35.346 2.98203 36 4.5608 36 6.207V26.267C36 29.813 31.512 31.352 29.336 28.553L22.531 19.799V30.414C22.531 31.8955 21.9425 33.3163 20.8949 34.3639C19.8473 35.4115 18.4265 36 16.945 36H6.207C4.5608 36 2.98203 35.346 1.81799 34.182C0.65395 33.018 0 31.4392 0 29.793L0 6.207ZM6.207 4.966C5.521 4.966 4.966 5.521 4.966 6.206V29.793C4.966 30.479 5.521 31.035 6.206 31.035H17.131C17.474 31.035 17.565 30.757 17.565 30.414V16.18C17.565 12.633 22.053 11.094 24.23 13.894L31.035 22.647V6.207C31.035 5.521 31.099 4.966 30.414 4.966H6.207Z" | ||
fill="url(#paint0_linear_3251_1370)" | ||
/> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M0 6.207C0 4.5608 0.65395 2.98203 1.81799 1.81799C2.98203 0.65395 4.5608 0 6.207 0L29.793 0C31.4392 0 33.018 0.65395 34.182 1.81799C35.346 2.98203 36 4.5608 36 6.207V26.267C36 29.813 31.512 31.352 29.336 28.553L22.531 19.799V30.414C22.531 31.8955 21.9425 33.3163 20.8949 34.3639C19.8473 35.4115 18.4265 36 16.945 36H6.207C4.5608 36 2.98203 35.346 1.81799 34.182C0.65395 33.018 0 31.4392 0 29.793L0 6.207ZM6.207 4.966C5.521 4.966 4.966 5.521 4.966 6.206V29.793C4.966 30.479 5.521 31.035 6.206 31.035H17.131C17.474 31.035 17.565 30.757 17.565 30.414V16.18C17.565 12.633 22.053 11.094 24.23 13.894L31.035 22.647V6.207C31.035 5.521 31.099 4.966 30.414 4.966H6.207Z" | ||
fill="url(#paint1_linear_3251_1370)" | ||
/> | ||
<path | ||
d="M29.7933 0C31.4395 0 33.0183 0.65395 34.1823 1.81799C35.3464 2.98203 36.0003 4.5608 36.0003 6.207V26.267C36.0003 29.813 31.5123 31.352 29.3363 28.553L22.5313 19.799V30.414C22.5313 31.8955 21.9428 33.3163 20.8952 34.3639C19.8476 35.4115 18.4268 36 16.9453 36C17.0267 36 17.1074 35.984 17.1826 35.9528C17.2578 35.9216 17.3261 35.876 17.3837 35.8184C17.4413 35.7608 17.487 35.6925 17.5181 35.6173C17.5493 35.542 17.5653 35.4614 17.5653 35.38V16.18C17.5653 12.633 22.0533 11.094 24.2303 13.894L31.0353 22.647V1.241C31.0353 0.556 30.4793 0 29.7933 0Z" | ||
fill="#B9FFB3" | ||
/> | ||
<defs> | ||
<linearGradient | ||
id="paint0_linear_3251_1370" | ||
x1="36" | ||
y1="36" | ||
x2="4.345" | ||
y2="-1.3837e-06" | ||
gradientUnits="userSpaceOnUse" | ||
> | ||
<stop stopColor="#B9FFB3" /> | ||
<stop offset="1" stopColor="#B9FFB3" stopOpacity="0" /> | ||
</linearGradient> | ||
<linearGradient | ||
id="paint1_linear_3251_1370" | ||
x1="36" | ||
y1="36" | ||
x2="14.617" | ||
y2="27.683" | ||
gradientUnits="userSpaceOnUse" | ||
> | ||
<stop stopColor="#1A1A1A" stopOpacity="0.9" /> | ||
<stop offset="1" stopColor="#1A1A1A" stopOpacity="0" /> | ||
</linearGradient> | ||
</defs> | ||
</svg> | ||
); | ||
}; |
21 changes: 21 additions & 0 deletions
21
frontend/apps/web/app/(mgmt)/[account]/new/connection/neon/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import OverviewContainer from '@/components/containers/OverviewContainer'; | ||
import PageHeader from '@/components/headers/PageHeader'; | ||
import NeonForm from './NeonForm'; | ||
import { NeonLogo } from './NeonLogo'; | ||
|
||
export default async function Postgres() { | ||
return ( | ||
<OverviewContainer | ||
Header={ | ||
<PageHeader | ||
header="Neon" | ||
description="Configure a Neon database as a connection" | ||
leftIcon={<NeonLogo />} | ||
/> | ||
} | ||
containerClassName="px-12 md:px-24 lg:px-32" | ||
> | ||
<NeonForm /> | ||
</OverviewContainer> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
frontend/apps/web/app/api/accounts/[accountId]/connections/neon/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { NextRequest, NextResponse } from 'next/server'; | ||
import { Issuer, generators } from 'openid-client'; | ||
|
||
export async function POST( | ||
req: NextRequest, | ||
res: NextResponse | ||
): Promise<NextResponse> { | ||
const state = 'iojeowihfj289yh923h2983hf9'; | ||
|
||
const neonIssue = await Issuer.discover( | ||
'https://oauth2.neon.tech/.well-known/openid-configuration' | ||
); | ||
|
||
// this needs to be stored in a session somewhere | ||
// const code_verifier = generators.codeVerifier(); | ||
const code_verifier = 'thisIsTheCodeVerfiierthisIsTheCodeVerfiiers'; | ||
const code_challenge = generators.codeChallenge(code_verifier); | ||
|
||
console.log('code changelle', code_challenge); | ||
|
||
const client = new neonIssue.Client({ | ||
client_id: 'neosync', | ||
client_secret: 'xxx', | ||
redirect_uris: ['http://localhost:3000/api/integrations/neon/callback'], | ||
response_types: ['code'], | ||
}); | ||
|
||
const authUrl = client.authorizationUrl({ | ||
scope: | ||
'offline offline_access urn:neoncloud:projects:create urn:neoncloud:projects:read', | ||
code_challenge, | ||
code_challenge_method: 'S256', | ||
state: state, | ||
}); | ||
|
||
return NextResponse.json({ redirect: authUrl }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
frontend/apps/web/app/api/integrations/neon/callback/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import axios from 'axios'; | ||
import { NextRequest, NextResponse } from 'next/server'; | ||
|
||
export async function GET( | ||
req: NextRequest, | ||
res: NextResponse | ||
): Promise<NextResponse> { | ||
const { method } = req; | ||
|
||
// Check if the request method is allowed | ||
if (method !== 'GET') { | ||
return NextResponse.json( | ||
{ message: 'Method Not Allowed' }, | ||
{ status: 405 } | ||
); | ||
} | ||
|
||
const url = new URL(req.url); | ||
const params = new URLSearchParams(url.searchParams); | ||
const code_verifier = 'thisIsTheCodeVerfiierthisIsTheCodeVerfiiers'; | ||
console.log('code', params.get('code')); | ||
console.log('params', params); | ||
|
||
// // compare this with the original state valu eto ensure that the original request came from our application and not from a third party | ||
//TODO: figure out a way to get the original state value | ||
/* const state = params.get('state'); | ||
if(state != params.get('state)){ | ||
return NextResponse.json( | ||
{ message: 'State verification codes do not match' }, | ||
{ status: 500 } | ||
); | ||
} | ||
*/ | ||
|
||
const queryParams = new URLSearchParams({ | ||
client_id: 'neosync', | ||
redirect_uri: 'http://localhost:3000/api/integrations/neon/callback', | ||
client_secret: 'xxxx', | ||
grant_type: 'authorization_code', | ||
code_verifier, | ||
code: params.get('code') ?? '', // exchange for access token | ||
}); | ||
|
||
try { | ||
const tokenResponse = await axios.post( | ||
`https://oauth2.neon.tech/oauth2/token`, | ||
queryParams.toString() | ||
); | ||
|
||
return NextResponse.json({ token: tokenResponse }); | ||
} catch (e) { | ||
if (axios.isAxiosError(e)) { | ||
console.error('there was an error', e.response?.data); | ||
} | ||
} | ||
return NextResponse.json(res); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Verfiiers
->Verifiers
looks like misspelling