-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added login feature utilizing the grafbase and query using graphql
- Loading branch information
1 parent
06d74fa
commit 9f26216
Showing
12 changed files
with
315 additions
and
18 deletions.
There are no files selected for viewing
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 |
---|---|---|
|
@@ -36,3 +36,6 @@ next-env.d.ts | |
|
||
#text | ||
grafbase.config.text | ||
|
||
#environment | ||
.env |
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,7 @@ | ||
import NextAuth from "next-auth"; | ||
|
||
import { authOptions } from "@/lib/session"; | ||
|
||
const handler = NextAuth(authOptions); | ||
|
||
export { handler as GET, handler as POST } |
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 |
---|---|---|
@@ -1,11 +1,45 @@ | ||
import React from 'react' | ||
'use client' | ||
|
||
import { getProviders, signIn } from 'next-auth/react' | ||
import { useState, useEffect } from 'react' | ||
|
||
type Provider = { | ||
id: string | ||
name: string | ||
type: string | ||
signinUrl: string | ||
callbackUrl: string | ||
signinUrlParams?: Record<string, string> | null; | ||
} | ||
|
||
type Providers = Record<string, Provider> | ||
|
||
const AuthProviders = () => { | ||
return ( | ||
<div> | ||
AuthProvider | ||
</div> | ||
) | ||
const [ providers, setProviders ] = useState<Providers | null>(null) | ||
|
||
useEffect(() => { | ||
const fetchProviders = async () => { | ||
const res = await getProviders() | ||
console.log('res', res) | ||
setProviders(res) | ||
} | ||
fetchProviders() | ||
}, []) | ||
|
||
if(providers) { | ||
return ( | ||
<div> | ||
{Object.values(providers).map((provider: Provider, i) => ( | ||
<button | ||
key={i} | ||
onClick={() => signIn(provider?.id)} | ||
> | ||
{provider.id} | ||
</button> | ||
))} | ||
</div> | ||
) | ||
} | ||
} | ||
|
||
export default AuthProviders |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
"use client" | ||
|
||
import Link from "next/link"; | ||
import Image from "next/image"; | ||
import { signOut } from "next-auth/react"; | ||
import { Fragment, useState } from "react"; | ||
import { Menu, Transition } from "@headlessui/react"; | ||
|
||
import { SessionInterface } from "@/common.types"; | ||
|
||
const ProfileMenu = ({ session }: { session: SessionInterface }) => { | ||
const [ openModal, setOpenModal ] = useState(false); | ||
console.log(session) | ||
return ( | ||
<div className="flexCenter z-10 flex-col relative"> | ||
<Menu as="div"> | ||
<Menu.Button className="flexCenter" onMouseEnter={() => setOpenModal(true)} > | ||
{session?.user?.image && ( | ||
<Image | ||
src={session.user.image} | ||
width={40} | ||
height={40} | ||
className="rounded-full" | ||
alt="user profile image" | ||
/> | ||
)} | ||
</Menu.Button> | ||
|
||
<Transition | ||
show={openModal} | ||
as={Fragment} | ||
enter="transition ease-out duration-200" | ||
enterFrom="transform opacity-0 scale-95" | ||
enterTo="transform opacity-100 scale-100" | ||
leave="transition ease-in duration-75" | ||
leaveFrom="transform opacity-100 scale-100" | ||
leaveTo="transform opacity-0 scale-95" | ||
> | ||
<Menu.Items | ||
static | ||
className="flexStart profile_menu-items" | ||
onMouseLeave={() => setOpenModal(false)} | ||
> | ||
<div className="flex flex-col items-center gap-y-4"> | ||
{session?.user?.image && ( | ||
<Image | ||
src={session?.user?.image} | ||
className="rounded-full" | ||
width={80} | ||
height={80} | ||
alt="profile Image" | ||
/> | ||
)} | ||
<p className="font-semibold">{session?.user?.name}</p> | ||
</div> | ||
|
||
<div className="flex flex-col gap-3 pt-10 items-start w-full"> | ||
<Menu.Item> | ||
<Link href={`/profile/${session?.user?.id}`} className="text-sm">Work Preferences</Link> | ||
</Menu.Item> | ||
<Menu.Item> | ||
<Link href={`/profile/${session?.user?.id}`} className="text-sm">Settings</Link> | ||
</Menu.Item> | ||
<Menu.Item> | ||
<Link href={`/profile/${session?.user?.id}`} className="text-sm">Profile</Link> | ||
</Menu.Item> | ||
</div> | ||
<div className="w-full flexStart border-t border-nav-border mt-5 pt-5"> | ||
<Menu.Item> | ||
<button type="button" className="text-sm" onClick={() => signOut()}> | ||
Sign out | ||
</button> | ||
</Menu.Item> | ||
</div> | ||
</Menu.Items> | ||
</Transition> | ||
</Menu> | ||
</div> | ||
) | ||
} | ||
|
||
export default ProfileMenu |
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 |
---|---|---|
@@ -1 +1 @@ | ||
# KEY=VALUE | ||
NEXTAUTH_SECRET=0+VO7GwqqB+EfNoU+4ezrgrFyqOVeOr8Whp/m1X/cdQ= |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
export const getUserQuery = ` | ||
query GetUser($email: String!) { | ||
user(by: { email: $email }) { | ||
id | ||
name | ||
avatarUrl | ||
description | ||
githubUrl | ||
linkedinUrl | ||
} | ||
} | ||
`; | ||
|
||
|
||
export const createUserMutation = ` | ||
mutation CreateUser($input: UserCreateInput!) { | ||
userCreate(input: $input) { | ||
user { | ||
name | ||
avatarUrl | ||
description | ||
githubUrl | ||
linkedinUrl | ||
id | ||
} | ||
} | ||
} | ||
` |
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,34 @@ | ||
import { createUserMutation, getUserQuery } from "@/grapql"; | ||
import { GraphQLClient } from "graphql-request"; | ||
|
||
const isProduction = process.env.NODE_ENV === 'production' | ||
const apiUrl = isProduction ? process.env.NEXT_PUBLIC_GRAFBASE_API_URL || '' : 'http://127.0.0.1:4000/graphql' | ||
const apiKey = isProduction ? process.env.NEXT_PUBLIC_GRAFBASE_API_KEY || '' : 'letmein' | ||
const serverUrl = isProduction ? process.env.NEXT_PUBLIC_SERVER_URL : 'http://localhost:3000' | ||
|
||
const client = new GraphQLClient(apiUrl) | ||
|
||
const makeGraphQLRequest = async (query: string, variables = {}) => { | ||
try { | ||
// client req | ||
return await client.request(query, variables) | ||
|
||
} catch (error) { | ||
throw error; | ||
} | ||
} | ||
|
||
export const getUser = (email: string) => { | ||
client.setHeader('x-api-key', apiKey) | ||
return makeGraphQLRequest(getUserQuery, { email }) | ||
} | ||
|
||
export const createUser = (name: string, email: string, avatarUrl: string) => { | ||
client.setHeader('x-api-key', apiKey) | ||
const variables = { | ||
input: { | ||
name, email, avatarUrl | ||
} | ||
} | ||
return makeGraphQLRequest(createUserMutation, variables) | ||
} |
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,81 @@ | ||
import { getServerSession } from "next-auth/next"; | ||
import { NextAuthOptions, User } from "next-auth"; | ||
import { AdapterUser } from "next-auth/adapters"; | ||
import GoogleProvider from 'next-auth/providers/google'; | ||
import jsonwebtoken from 'jsonwebtoken' | ||
import { JWT } from 'next-auth/jwt'; | ||
import { SessionInterface, UserProfile } from "@/common.types"; | ||
import { createUser, getUser } from "./actions"; | ||
|
||
export const authOptions: NextAuthOptions = { | ||
providers: [ | ||
GoogleProvider({ | ||
clientId: process.env.GOOGLE_CLIENT_ID!, // could be an undefined | ||
clientSecret: process.env.GOOGLE_CLIENT_SECRET!, // could be an undefined | ||
}) | ||
], | ||
jwt: { | ||
encode: ({ secret, token }) => { | ||
const encodedToken = jsonwebtoken.sign({ | ||
...token, | ||
iss: 'grafbase', | ||
exp: Math.floor(Date.now() / 1000) + 60 * 60 | ||
}, secret); | ||
return encodedToken; | ||
}, | ||
decode: async ({ secret, token }) => { | ||
const decodedToken = jsonwebtoken.verify(token!, secret); | ||
|
||
return decodedToken as JWT; | ||
} | ||
}, | ||
theme: { | ||
colorScheme: 'light', | ||
logo: '/logo.svg' | ||
}, | ||
callbacks: { | ||
async session({ session }) { | ||
const email = session?.user?.email as string; | ||
|
||
try { | ||
const data = await getUser(email) as { user?: UserProfile } | ||
|
||
const newSession = { | ||
...session, | ||
user: { | ||
...session?.user, | ||
...data?.user | ||
} | ||
} | ||
return newSession; | ||
} catch (error) { | ||
console.log('Error retrieving user data', error) | ||
return session; // need to always return a session or something | ||
} | ||
}, | ||
async signIn({ user }: { user: AdapterUser | User }) { | ||
try { | ||
const userExist = await getUser(user?.email as string) as { user?: UserProfile } | ||
|
||
if(!userExist.user) { | ||
await createUser( | ||
user.name as string, | ||
user.email as string, | ||
user.image as string | ||
); | ||
} | ||
|
||
return true | ||
} catch(error: any) { | ||
console.log(error) | ||
return false | ||
} | ||
} | ||
} | ||
} | ||
|
||
export async function getCurrentUser() { | ||
const session = await getServerSession(authOptions) as SessionInterface; | ||
|
||
return session; | ||
} |
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 |
---|---|---|
@@ -1,4 +1,8 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = {} | ||
const nextConfig = { | ||
images: { | ||
domains: ['lh3.googleusercontent.com'], | ||
} | ||
} | ||
|
||
module.exports = nextConfig |
Oops, something went wrong.