-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Farcaster login #563
Farcaster login #563
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { ProvidersInterface } from '@gitroom/backend/services/auth/providers.interface'; | ||
import { NeynarAPIClient } from '@neynar/nodejs-sdk'; | ||
|
||
const client = new NeynarAPIClient({ | ||
apiKey: process.env.NEYNAR_SECRET_KEY || '00000000-000-0000-000-000000000000', | ||
}); | ||
|
||
export class FarcasterProvider implements ProvidersInterface { | ||
generateLink() { | ||
return ''; | ||
} | ||
|
||
async getToken(code: string) { | ||
const data = JSON.parse(Buffer.from(code, 'base64').toString()); | ||
const status = await client.lookupSigner({signerUuid: data.signer_uuid}); | ||
if (status.status === 'approved') { | ||
return data.signer_uuid; | ||
} | ||
|
||
return ''; | ||
} | ||
|
||
async getUser(providerToken: string) { | ||
const status = await client.lookupSigner({signerUuid: providerToken}); | ||
if (status.status !== 'approved') { | ||
return { | ||
id: '', | ||
email: '', | ||
}; | ||
} | ||
|
||
|
||
// const { client, oauth2 } = clientAndYoutube(); | ||
// client.setCredentials({ access_token: providerToken }); | ||
// const user = oauth2(client); | ||
// const { data } = await user.userinfo.get(); | ||
|
||
return { | ||
id: String('farcaster_' + status.fid), | ||
email: String('farcaster_' + status.fid), | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
'use client'; | ||
|
||
import React, { | ||
useCallback, | ||
useEffect, | ||
useState, | ||
useRef, | ||
FC, | ||
ReactNode, | ||
} from 'react'; | ||
import { useNeynarContext } from '@neynar/react'; | ||
|
||
export const NeynarAuthButton: FC<{ | ||
children: ReactNode; | ||
onLogin: (code: string) => void; | ||
}> = (props) => { | ||
const { children, onLogin } = props; | ||
const { client_id } = useNeynarContext(); | ||
|
||
const [showModal, setShowModal] = useState(false); | ||
|
||
const authWindowRef = useRef<Window | null>(null); | ||
const neynarLoginUrl = `${ | ||
process.env.NEYNAR_LOGIN_URL ?? 'https://app.neynar.com/login' | ||
}?client_id=${client_id}`; | ||
const authOrigin = new URL(neynarLoginUrl).origin; | ||
|
||
const modalRef = useRef<HTMLDivElement>(null); | ||
|
||
const handleMessage = useCallback( | ||
async (event: MessageEvent) => { | ||
if ( | ||
event.origin === authOrigin && | ||
event.data && | ||
event.data.is_authenticated | ||
) { | ||
authWindowRef.current?.close(); | ||
window.removeEventListener('message', handleMessage); // Remove listener here | ||
const _user = { | ||
signer_uuid: event.data.signer_uuid, | ||
...event.data.user, | ||
}; | ||
|
||
onLogin(Buffer.from(JSON.stringify(_user)).toString('base64')); | ||
} | ||
}, | ||
[client_id, onLogin] | ||
Check warning Code scanning / ESLint verifies the list of dependencies for Hooks like useEffect and similar Warning
React Hook useCallback has a missing dependency: 'authOrigin'. Either include it or remove the dependency array.
|
||
); | ||
|
||
const handleSignIn = useCallback(() => { | ||
const width = 600, | ||
height = 700; | ||
const left = window.screen.width / 2 - width / 2; | ||
const top = window.screen.height / 2 - height / 2; | ||
const windowFeatures = `width=${width},height=${height},top=${top},left=${left}`; | ||
|
||
authWindowRef.current = window.open( | ||
neynarLoginUrl, | ||
'_blank', | ||
windowFeatures | ||
); | ||
|
||
if (!authWindowRef.current) { | ||
console.error( | ||
'Failed to open the authentication window. Please check your pop-up blocker settings.' | ||
); | ||
return; | ||
} | ||
|
||
window.addEventListener('message', handleMessage, false); | ||
}, [client_id, handleMessage]); | ||
Check warning Code scanning / ESLint verifies the list of dependencies for Hooks like useEffect and similar Warning
React Hook useCallback has a missing dependency: 'neynarLoginUrl'. Either include it or remove the dependency array.
|
||
|
||
const closeModal = () => setShowModal(false); | ||
|
||
useEffect(() => { | ||
return () => { | ||
window.removeEventListener('message', handleMessage); // Cleanup function to remove listener | ||
}; | ||
}, [handleMessage]); | ||
|
||
const handleOutsideClick = useCallback((event: any) => { | ||
if (modalRef.current && !modalRef.current.contains(event.target)) { | ||
closeModal(); | ||
} | ||
}, []); | ||
|
||
useEffect(() => { | ||
if (showModal) { | ||
document.addEventListener('mousedown', handleOutsideClick); | ||
} else { | ||
document.removeEventListener('mousedown', handleOutsideClick); | ||
} | ||
|
||
return () => { | ||
document.removeEventListener('mousedown', handleOutsideClick); | ||
}; | ||
}, [showModal, handleOutsideClick]); | ||
|
||
return <div onClick={handleSignIn}>{children}</div>; | ||
}; |
Original file line number | Diff line number | Diff line change | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,51 @@ | |||||||||||||||||
import { useCallback } from 'react'; | |||||||||||||||||
import interClass from '@gitroom/react/helpers/inter.font'; | |||||||||||||||||
import { useVariables } from '@gitroom/react/helpers/variable.context'; | |||||||||||||||||
import { NeynarContextProvider, Theme, useNeynarContext } from '@neynar/react'; | |||||||||||||||||
Check warning Code scanning / ESLint Disallow unused variables Warning
'useNeynarContext' is defined but never used.
Copilot Autofix AI 5 days ago To fix the problem, we need to remove the unused import
Suggested changeset
1
apps/frontend/src/components/auth/providers/farcaster.provider.tsx
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
|||||||||||||||||
import { NeynarAuthButton } from '@gitroom/frontend/components/auth/nayner.auth.button'; | |||||||||||||||||
import { useRouter } from 'next/navigation'; | |||||||||||||||||
Check warning Code scanning / ESLint Disallow unused variables Warning
'useRouter' is defined but never used.
Copilot Autofix AI 5 days ago To fix the problem, we need to remove the unused
Suggested changeset
1
apps/frontend/src/components/auth/providers/farcaster.provider.tsx
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
|||||||||||||||||
|
|||||||||||||||||
export const FarcasterProvider = () => { | |||||||||||||||||
const { neynarClientId } = useVariables(); | |||||||||||||||||
|
|||||||||||||||||
const gotoLogin = useCallback(async (code: string) => { | |||||||||||||||||
window.location.href = `/auth?provider=FARCASTER&code=${code}`; | |||||||||||||||||
}, []); | |||||||||||||||||
|
|||||||||||||||||
return ( | |||||||||||||||||
<NeynarContextProvider | |||||||||||||||||
settings={{ | |||||||||||||||||
clientId: neynarClientId, | |||||||||||||||||
defaultTheme: Theme.Dark, | |||||||||||||||||
}} | |||||||||||||||||
> | |||||||||||||||||
<NeynarAuthButton onLogin={gotoLogin}> | |||||||||||||||||
<div | |||||||||||||||||
className={`cursor-pointer bg-[#855ECD] h-[44px] rounded-[4px] flex justify-center items-center text-white ${interClass} gap-[4px]`} | |||||||||||||||||
> | |||||||||||||||||
<svg | |||||||||||||||||
width="21px" | |||||||||||||||||
height="21px" | |||||||||||||||||
viewBox="0 0 1000 1000" | |||||||||||||||||
fill="none" | |||||||||||||||||
xmlns="http://www.w3.org/2000/svg" | |||||||||||||||||
> | |||||||||||||||||
<path | |||||||||||||||||
d="M257.778 155.556H742.222V844.445H671.111V528.889H670.414C662.554 441.677 589.258 373.333 500 373.333C410.742 373.333 337.446 441.677 329.586 528.889H328.889V844.445H257.778V155.556Z" | |||||||||||||||||
fill="white" | |||||||||||||||||
/> | |||||||||||||||||
<path | |||||||||||||||||
d="M128.889 253.333L157.778 351.111H182.222V746.667C169.949 746.667 160 756.616 160 768.889V795.556H155.556C143.283 795.556 133.333 805.505 133.333 817.778V844.445H382.222V817.778C382.222 805.505 372.273 795.556 360 795.556H355.556V768.889C355.556 756.616 345.606 746.667 333.333 746.667H306.667V253.333H128.889Z" | |||||||||||||||||
fill="white" | |||||||||||||||||
/> | |||||||||||||||||
<path | |||||||||||||||||
d="M675.556 746.667C663.282 746.667 653.333 756.616 653.333 768.889V795.556H648.889C636.616 795.556 626.667 805.505 626.667 817.778V844.445H875.556V817.778C875.556 805.505 865.606 795.556 853.333 795.556H848.889V768.889C848.889 756.616 838.94 746.667 826.667 746.667V351.111H851.111L880 253.333H702.222V746.667H675.556Z" | |||||||||||||||||
fill="white" | |||||||||||||||||
/> | |||||||||||||||||
</svg> | |||||||||||||||||
<div>Continue with Farcaster</div> | |||||||||||||||||
</div> | |||||||||||||||||
</NeynarAuthButton> | |||||||||||||||||
</NeynarContextProvider> | |||||||||||||||||
); | |||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -536,6 +536,7 @@ enum Provider { | |
LOCAL | ||
GITHUB | ||
FARCASTER | ||
} | ||
|
||
enum Role { | ||
|
Check warning
Code scanning / ESLint
Disallow non-null assertions using the `!` postfix operator Warning
Copilot Autofix AI 5 days ago
To fix the problem, we need to handle the potential
null
orundefined
value ofprocess.env.NEYNAR_CLIENT_ID
explicitly. One way to do this is to provide a default value or throw an error if the value is not defined. This ensures that the application does not crash unexpectedly and that the developer is aware of the missing environment variable.In this case, we can use a default value or throw an error if
process.env.NEYNAR_CLIENT_ID
is not defined. For example, we can use the??
(nullish coalescing) operator to provide a default value or use a conditional check to throw an error.