mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-06-05 00:32:03 +00:00
Recovery option, fix profile card menu placement
This commit is contained in:
parent
cace835c84
commit
417159aad9
@ -48,7 +48,7 @@ const UserProfileCard = ({ user }) => {
|
||||
const MobileProfileCard = () => (
|
||||
<div className="w-full bg-gray-800 rounded-lg p-2 py-1 border border-gray-700 shadow-md h-[420px] flex flex-col justify-center items-start">
|
||||
<div className="flex flex-col gap-2 pt-4 w-full relative">
|
||||
<div className="absolute top-8 right-[10px]">
|
||||
<div className="absolute top-8 right-[14px]">
|
||||
<i
|
||||
className="pi pi-ellipsis-h text-2xl cursor-pointer"
|
||||
onClick={(e) => menu.current.toggle(e)}
|
||||
@ -145,7 +145,7 @@ const UserProfileCard = ({ user }) => {
|
||||
className="rounded-full my-4"
|
||||
/>
|
||||
<div className="flex flex-col gap-2 pt-4 w-fit relative">
|
||||
<div className="absolute top-[-4px] right-[-30px]">
|
||||
<div className="absolute top-[-1px] right-[-24px]">
|
||||
<i
|
||||
className="pi pi-ellipsis-h text-2xl cursor-pointer"
|
||||
onClick={(e) => menu.current.toggle(e)}
|
||||
|
@ -12,6 +12,7 @@ import { updateUser, getUserByPubkey, createUser, getUserById, getUserByEmail }
|
||||
import { createRole } from "@/db/models/roleModels";
|
||||
import appConfig from "@/config/appConfig";
|
||||
import NDK from "@nostr-dev-kit/ndk";
|
||||
import { nip19 } from 'nostr-tools';
|
||||
|
||||
// Initialize NDK for Nostr interactions
|
||||
const ndk = new NDK({
|
||||
@ -162,6 +163,55 @@ export const authOptions = {
|
||||
avatar: profile.avatar_url
|
||||
};
|
||||
}
|
||||
}),
|
||||
// Recovery provider
|
||||
CredentialsProvider({
|
||||
id: "recovery",
|
||||
name: "Recovery",
|
||||
credentials: {
|
||||
nsec: { label: "Recovery Key (nsec or hex)", type: "text" }
|
||||
},
|
||||
authorize: async (credentials) => {
|
||||
if (!credentials?.nsec) return null;
|
||||
|
||||
try {
|
||||
// Convert nsec to hex if needed
|
||||
let privkeyHex = credentials.nsec;
|
||||
if (credentials.nsec.startsWith('nsec')) {
|
||||
try {
|
||||
const { data: decodedPrivkey } = nip19.decode(credentials.nsec);
|
||||
privkeyHex = Buffer.from(decodedPrivkey).toString('hex');
|
||||
} catch (error) {
|
||||
console.error("Invalid nsec format:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Find user with matching privkey
|
||||
const user = await prisma.user.findFirst({
|
||||
where: { privkey: privkeyHex },
|
||||
include: {
|
||||
role: true,
|
||||
purchased: true,
|
||||
userCourses: true,
|
||||
userLessons: true,
|
||||
nip05: true,
|
||||
lightningAddress: true,
|
||||
userBadges: true
|
||||
}
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
console.error("No user found with provided recovery key");
|
||||
return null;
|
||||
}
|
||||
|
||||
return user;
|
||||
} catch (error) {
|
||||
console.error("Recovery authorization error:", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
callbacks: {
|
||||
|
@ -7,7 +7,9 @@ import { InputText } from 'primereact/inputtext';
|
||||
|
||||
export default function SignIn() {
|
||||
const [email, setEmail] = useState("")
|
||||
const [nsec, setNsec] = useState("")
|
||||
const [showEmailInput, setShowEmailInput] = useState(false)
|
||||
const [showRecoveryInput, setShowRecoveryInput] = useState(false)
|
||||
const {ndk, addSigner} = useNDKContext();
|
||||
const { data: session, status } = useSession();
|
||||
const router = useRouter();
|
||||
@ -68,6 +70,25 @@ export default function SignIn() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleRecoverySignIn = async (e) => {
|
||||
e.preventDefault()
|
||||
try {
|
||||
const result = await signIn("recovery", {
|
||||
nsec,
|
||||
redirect: false,
|
||||
callbackUrl: '/'
|
||||
});
|
||||
|
||||
if (result?.ok) {
|
||||
router.push('/');
|
||||
} else {
|
||||
console.error("Recovery login failed:", result?.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Recovery sign in error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// Redirect if already signed in
|
||||
if (session?.user) {
|
||||
@ -124,6 +145,45 @@ export default function SignIn() {
|
||||
rounded
|
||||
onClick={handleAnonymousSignIn}
|
||||
/>
|
||||
<GenericButton
|
||||
label={"recover account"}
|
||||
icon="pi pi-key"
|
||||
className="text-[#f8f8ff] w-[250px] my-4 mx-auto"
|
||||
rounded
|
||||
onClick={() => setShowRecoveryInput(!showRecoveryInput)}
|
||||
/>
|
||||
{showRecoveryInput && (
|
||||
<form onSubmit={handleRecoverySignIn} className="flex flex-col items-center bg-gray-700 w-fit mx-auto p-4 rounded-lg">
|
||||
<div className="text-center mb-4 max-w-[350px]">
|
||||
<p className="text-yellow-400 mb-2">⚠️ Recovery Notice</p>
|
||||
<p className="text-gray-200 mb-2">
|
||||
🔑 This recovery option is only for accounts created through:
|
||||
</p>
|
||||
<ul className="text-gray-300 mb-2 text-left list-none">
|
||||
<li>📧 Email Login</li>
|
||||
<li>👤 Anonymous Login</li>
|
||||
<li>🐙 GitHub Login</li>
|
||||
</ul>
|
||||
<p className="text-red-400 text-sm">
|
||||
⛔ Do NOT enter your personal Nostr nsec here! Only use the recovery key provided by PlebDevs (available on your profile page).
|
||||
</p>
|
||||
</div>
|
||||
<InputText
|
||||
type="password"
|
||||
value={nsec}
|
||||
onChange={(e) => setNsec(e.target.value)}
|
||||
placeholder="Enter recovery key (nsec or hex)"
|
||||
className="w-[250px] my-4"
|
||||
/>
|
||||
<GenericButton
|
||||
type="submit"
|
||||
label={"Recover Account"}
|
||||
icon="pi pi-lock-open"
|
||||
className="text-[#f8f8ff] w-fit my-4"
|
||||
rounded
|
||||
/>
|
||||
</form>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user