github signup, creates user and kind0, can open nostr profile from plebdevs profile now

This commit is contained in:
austinkelsay 2024-11-18 16:42:40 -06:00
parent 91cfd7a3cb
commit c9d702576e
No known key found for this signature in database
GPG Key ID: 44CB4EC6D9F2FA02
5 changed files with 80 additions and 19 deletions

View File

@ -56,7 +56,7 @@ const UserAvatar = () => {
return null; // Or return a loader/spinner/placeholder return null; // Or return a loader/spinner/placeholder
} else if (user && Object.keys(user).length > 0) { } else if (user && Object.keys(user).length > 0) {
// User exists, show username or pubkey // User exists, show username or pubkey
const displayName = user.username || user?.email || user?.pubkey.slice(0, 10) + '...'; const displayName = user.username || user?.name || user?.email || user?.pubkey.slice(0, 10) + '...' || "Anon";
const items = [ const items = [
{ {

View File

@ -70,6 +70,11 @@ const UserProfile = () => {
copyToClipboard(nip19.npubEncode(user?.pubkey)); copyToClipboard(nip19.npubEncode(user?.pubkey));
} }
} }
},
{
label: 'Open Nostr Profile',
icon: 'pi pi-external-link',
command: () => window.open(`https://nostr.com/${nip19.npubEncode(user?.pubkey)}`, '_blank')
} }
]; ];
@ -106,7 +111,7 @@ const UserProfile = () => {
<h1 className="text-center text-2xl my-2"> <h1 className="text-center text-2xl my-2">
{user.username || user?.email || "Anon"} {user.username || user?.name || user?.email || "Anon"}
</h1> </h1>
{user.pubkey && ( {user.pubkey && (
<h2 className="text-center text-xl my-2 truncate max-tab:px-4 max-mob:px-4"> <h2 className="text-center text-xl my-2 truncate max-tab:px-4 max-mob:px-4">

View File

@ -176,6 +176,11 @@ const UserSettings = () => {
command: () => { command: () => {
copyToClipboard(nip19.npubEncode(user?.pubkey)); copyToClipboard(nip19.npubEncode(user?.pubkey));
} }
},
{
label: 'Open Nostr Profile',
icon: 'pi pi-external-link',
command: () => window.open(`https://nostr.com/${nip19.npubEncode(user?.pubkey)}`, '_blank')
} }
]; ];
@ -211,7 +216,7 @@ const UserSettings = () => {
</div> </div>
<h1 className="text-center text-2xl my-2"> <h1 className="text-center text-2xl my-2">
{user.username || user?.email || "Anon"} {user.username || user?.name || user?.email || "Anon"}
</h1> </h1>
{user.pubkey && ( {user.pubkey && (
<h2 className="text-center text-xl my-2 truncate max-tab:px-4 max-mob:px-4"> <h2 className="text-center text-xl my-2 truncate max-tab:px-4 max-mob:px-4">

View File

@ -1,23 +1,21 @@
import NextAuth from "next-auth"; import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials"; import CredentialsProvider from "next-auth/providers/credentials";
import EmailProvider from "next-auth/providers/email"; import EmailProvider from "next-auth/providers/email";
import NDK from "@nostr-dev-kit/ndk";
import { PrismaAdapter } from "@next-auth/prisma-adapter"; import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "@/db/prisma"; import prisma from "@/db/prisma";
import nodemailer from 'nodemailer'; import nodemailer from 'nodemailer';
import { findKind0Fields } from "@/utils/nostr"; import { findKind0Fields } from "@/utils/nostr";
import { generateSecretKey, getPublicKey } from 'nostr-tools/pure' import { generateSecretKey, getPublicKey } from 'nostr-tools/pure'
import { bytesToHex } from '@noble/hashes/utils' import { bytesToHex } from '@noble/hashes/utils'
import { updateUser, getUserByPubkey, createUser, getUserByEmail } from "@/db/models/userModels"; import { updateUser, getUserByPubkey, createUser } from "@/db/models/userModels";
import { createRole } from "@/db/models/roleModels"; import { createRole } from "@/db/models/roleModels";
import appConfig from "@/config/appConfig"; import appConfig from "@/config/appConfig";
import GithubProvider from "next-auth/providers/github";
import { SimplePool } from "nostr-tools";
import { finalizeEvent } from "nostr-tools";
// todo: currently email accounts ephemeral privkey gets saved to db but not anon user, is this required at all given the newer auth setup? // todo: currently email accounts ephemeral privkey gets saved to db but not anon user, is this required at all given the newer auth setup?
const ndk = new NDK({
explicitRelayUrls: [...appConfig.defaultRelayUrls]
});
const authorize = async (pubkey) => { const authorize = async (pubkey) => {
await ndk.connect(); await ndk.connect();
const user = ndk.getUser({ pubkey }); const user = ndk.getUser({ pubkey });
@ -125,6 +123,10 @@ export const authOptions = {
}); });
} }
}), }),
GithubProvider({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET
}),
CredentialsProvider({ CredentialsProvider({
id: "anonymous", id: "anonymous",
name: "Anonymous", name: "Anonymous",
@ -148,7 +150,7 @@ export const authOptions = {
// Check if user exists in the database // Check if user exists in the database
let dbUser = await getUserByPubkey(pubkey); let dbUser = await getUserByPubkey(pubkey);
if (!dbUser) { if (!dbUser) {
// Create new user if not exists // Create new user if not exists
dbUser = await createUser({ dbUser = await createUser({
@ -156,7 +158,7 @@ export const authOptions = {
username: pubkey.slice(0, 8), // Use first 8 characters of pubkey as username username: pubkey.slice(0, 8), // Use first 8 characters of pubkey as username
}); });
} }
// Return user object with pubkey and privkey // Return user object with pubkey and privkey
return { ...dbUser, pubkey, privkey }; return { ...dbUser, pubkey, privkey };
}, },
@ -175,18 +177,60 @@ export const authOptions = {
const sk = generateSecretKey(); const sk = generateSecretKey();
const pubkey = getPublicKey(sk); const pubkey = getPublicKey(sk);
const privkey = bytesToHex(sk); const privkey = bytesToHex(sk);
// Update the user in the database // Update the user in the database
await prisma.user.update({ await prisma.user.update({
where: { id: user.id }, where: { id: user.id },
data: { pubkey, privkey } data: { pubkey, privkey }
}); });
// Update the user object // Update the user object
user.pubkey = pubkey; user.pubkey = pubkey;
user.privkey = privkey; user.privkey = privkey;
} }
// Add new condition for first-time GitHub sign up
if (trigger === "signUp" && account?.provider === "github") {
const sk = generateSecretKey();
const pubkey = getPublicKey(sk);
const privkey = bytesToHex(sk);
// Update the user in the database
await prisma.user.update({
where: { id: user.id },
data: { pubkey, privkey, name: user.name, username: user.name, avatar: user.image || null }
});
// Publish kind0 event to nostr
try {
const pool = new SimplePool();
const relays = [
"wss://relay.damus.io",
"wss://relay.nostr.band",
"wss://relay.primal.net",
"wss://relay.devs.tools"
];
const event = finalizeEvent({
kind: 0,
created_at: Math.floor(Date.now() / 1000),
tags: [],
content: JSON.stringify({
name: user.name,
picture: user.image
})
}, privkey);
await Promise.any(pool.publish(relays, event));
} catch (error) {
console.error('Failed to publish kind0 event:', error);
}
// Update user object with nostr keys
user.pubkey = pubkey;
user.privkey = privkey;
}
if (user) { if (user) {
token.user = user; token.user = user;
if (user.pubkey && user.privkey) { if (user.pubkey && user.privkey) {
@ -218,14 +262,14 @@ export const authOptions = {
}, },
async signIn({ user, account }) { async signIn({ user, account }) {
if (account.provider === 'anonymous') { if (account.provider === 'anonymous') {
return { return {
...user, ...user,
pubkey: user.pubkey, pubkey: user.pubkey,
privkey: user.privkey, privkey: user.privkey,
}; };
} }
return true; return true;
}, },
}, },
secret: process.env.NEXTAUTH_SECRET, secret: process.env.NEXTAUTH_SECRET,
session: { strategy: "jwt" }, session: { strategy: "jwt" },

View File

@ -78,6 +78,13 @@ export default function SignIn() {
rounded rounded
onClick={() => setShowEmailInput(!showEmailInput)} onClick={() => setShowEmailInput(!showEmailInput)}
/> />
<GenericButton
label={"login with github"}
icon="pi pi-github"
className="text-[#f8f8ff] w-[250px] my-4 mx-auto"
rounded
onClick={() => signIn("github")}
/>
{showEmailInput && ( {showEmailInput && (
<form onSubmit={handleEmailSignIn} className="flex flex-col items-center bg-gray-700 w-fit mx-auto p-4 rounded-lg"> <form onSubmit={handleEmailSignIn} className="flex flex-col items-center bg-gray-700 w-fit mx-auto p-4 rounded-lg">
<InputText <InputText