chore: export credentials individually

This commit is contained in:
Danish Arora 2025-04-02 16:26:56 +05:30
parent ecb136a612
commit ff894d6464
No known key found for this signature in database
GPG Key ID: 1C6EF37CDAE1426E
2 changed files with 71 additions and 29 deletions

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import React from 'react'; import React, { useState } from 'react';
import { useKeystore } from '../../../contexts/keystore'; import { useKeystore } from '../../../contexts/keystore';
import { useAppState } from '../../../contexts/AppStateContext'; import { useAppState } from '../../../contexts/AppStateContext';
import { useRLN } from '../../../contexts/rln'; import { useRLN } from '../../../contexts/rln';
@ -11,12 +11,14 @@ export function KeystoreManagement() {
hasStoredCredentials, hasStoredCredentials,
storedCredentialsHashes, storedCredentialsHashes,
error, error,
exportKeystore, exportCredential,
importKeystore, importKeystore,
removeCredential removeCredential
} = useKeystore(); } = useKeystore();
const { setGlobalError } = useAppState(); const { setGlobalError } = useAppState();
const { isInitialized, isStarted } = useRLN(); const { isInitialized, isStarted } = useRLN();
const [exportPassword, setExportPassword] = useState<string>('');
const [selectedCredential, setSelectedCredential] = useState<string | null>(null);
React.useEffect(() => { React.useEffect(() => {
if (error) { if (error) {
@ -24,12 +26,18 @@ export function KeystoreManagement() {
} }
}, [error, setGlobalError]); }, [error, setGlobalError]);
const handleExport = () => { const handleExportCredential = async (hash: string) => {
try { try {
const keystoreJson = exportKeystore(); if (!exportPassword) {
saveKeystoreToFile(keystoreJson); setGlobalError('Please enter your keystore password to export');
return;
}
const keystoreJson = await exportCredential(hash, exportPassword);
saveKeystoreToFile(keystoreJson, `waku-rln-credential-${hash.slice(0, 8)}.json`);
setExportPassword('');
setSelectedCredential(null);
} catch (err) { } catch (err) {
setGlobalError(err instanceof Error ? err.message : 'Failed to export keystore'); setGlobalError(err instanceof Error ? err.message : 'Failed to export credential');
} }
}; };
@ -61,14 +69,8 @@ export function KeystoreManagement() {
</h2> </h2>
<div className="space-y-6"> <div className="space-y-6">
{/* Import/Export Actions */} {/* Import Action */}
<div className="flex space-x-4"> <div>
<button
onClick={handleExport}
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
>
Export Keystore
</button>
<button <button
onClick={handleImport} onClick={handleImport}
className="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800" className="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
@ -99,18 +101,46 @@ export function KeystoreManagement() {
key={hash} key={hash}
className="p-4 rounded-lg border border-gray-200 dark:border-gray-700" className="p-4 rounded-lg border border-gray-200 dark:border-gray-700"
> >
<div className="flex flex-col space-y-3">
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<code className="text-sm text-gray-600 dark:text-gray-400 break-all"> <code className="text-sm text-gray-600 dark:text-gray-400 break-all">
{hash} {hash}
</code> </code>
<div className="flex space-x-2">
<button
onClick={() => setSelectedCredential(hash === selectedCredential ? null : hash)}
className="text-blue-600 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300"
>
Export
</button>
<button <button
onClick={() => handleRemoveCredential(hash)} onClick={() => handleRemoveCredential(hash)}
className="ml-4 text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300" className="text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
> >
Remove Remove
</button> </button>
</div> </div>
</div> </div>
{selectedCredential === hash && (
<div className="mt-2 space-y-2">
<input
type="password"
value={exportPassword}
onChange={(e) => setExportPassword(e.target.value)}
placeholder="Enter keystore password"
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100"
/>
<button
onClick={() => handleExportCredential(hash)}
className="w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800"
>
Export Credential
</button>
</div>
)}
</div>
</div>
))} ))}
</div> </div>
) : ( ) : (

View File

@ -11,7 +11,7 @@ interface KeystoreContextType {
hasStoredCredentials: boolean; hasStoredCredentials: boolean;
storedCredentialsHashes: string[]; storedCredentialsHashes: string[];
saveCredentials: (credentials: KeystoreEntity, password: string) => Promise<string>; saveCredentials: (credentials: KeystoreEntity, password: string) => Promise<string>;
exportKeystore: () => string; exportCredential: (hash: string, password: string) => Promise<string>;
importKeystore: (keystoreJson: string) => boolean; importKeystore: (keystoreJson: string) => boolean;
removeCredential: (hash: string) => void; removeCredential: (hash: string) => void;
} }
@ -82,12 +82,24 @@ export function KeystoreProvider({ children }: { children: ReactNode }) {
} }
}; };
const exportKeystore = (): string => { const exportCredential = async (hash: string, password: string): Promise<string> => {
if (!keystore) { if (!keystore) {
throw new Error("Keystore not initialized"); throw new Error("Keystore not initialized");
} }
return keystore.toString(); // Create a new keystore instance for the single credential
const singleCredentialKeystore = Keystore.create();
// Get the credential from the main keystore
const credential = await keystore.readCredential(hash, password);
if (!credential) {
throw new Error("Credential not found");
}
// Add the credential to the new keystore
await singleCredentialKeystore.addCredential(credential, password);
return singleCredentialKeystore.toString();
}; };
const importKeystore = (keystoreJson: string): boolean => { const importKeystore = (keystoreJson: string): boolean => {
@ -124,7 +136,7 @@ export function KeystoreProvider({ children }: { children: ReactNode }) {
hasStoredCredentials: storedCredentialsHashes.length > 0, hasStoredCredentials: storedCredentialsHashes.length > 0,
storedCredentialsHashes, storedCredentialsHashes,
saveCredentials, saveCredentials,
exportKeystore, exportCredential,
importKeystore, importKeystore,
removeCredential removeCredential
}; };