diff --git a/src/app/components/auth/register/register.component.ts b/src/app/components/auth/register/register.component.ts index 73b1a83..93764cd 100644 --- a/src/app/components/auth/register/register.component.ts +++ b/src/app/components/auth/register/register.component.ts @@ -16,6 +16,9 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { Router, RouterLink } from '@angular/router'; import { angorAnimations } from '@angor/animations'; import { AngorAlertComponent, AngorAlertType } from '@angor/components/alert'; +import { SecurityService } from 'app/services/security.service'; +import { SignerService } from 'app/services/signer.service'; +import { CommonModule } from '@angular/common'; @Component({ selector: 'auth-register', @@ -34,6 +37,7 @@ import { AngorAlertComponent, AngorAlertType } from '@angor/components/alert'; MatIconModule, MatCheckboxModule, MatProgressSpinnerModule, + CommonModule ], }) export class RegisterComponent implements OnInit { @@ -46,7 +50,11 @@ export class RegisterComponent implements OnInit { registerForm: UntypedFormGroup; showAlert: boolean = false; - constructor(private _formBuilder: UntypedFormBuilder, private _router: Router) {} + constructor( + private _formBuilder: UntypedFormBuilder, + private _router: Router, + private _signerService: SignerService + ) {} ngOnInit(): void { this.registerForm = this._formBuilder.group({ @@ -68,17 +76,46 @@ export class RegisterComponent implements OnInit { this.showAlert = false; + // Get form values const name = this.registerForm.get('name')?.value; const username = this.registerForm.get('username')?.value; const about = this.registerForm.get('about')?.value; const avatarUrl = this.registerForm.get('avatarUrl')?.value; const password = this.registerForm.get('password')?.value; - console.log({ name, username, about, avatarUrl, password }); + // Generate keys using the security service + const keys = this._signerService.generateAndStoreKeys(); + if (!keys) { + // If key generation failed, enable the form and show an error + this.registerForm.enable(); + this.alert = { type: 'error', message: 'Error generating keys. Please try again.' }; + this.showAlert = true; + return; + } + + const { privateKeyHex, publicKey, npub, nsec } = keys; + + // Simulate saving user metadata along with keys + const userMetadata = { + name, + username, + about, + avatarUrl, + password, + publicKey, + npub, + nsec, + }; + + console.log('User Metadata:', userMetadata); + + // Display success alert this.alert = { type: 'success', message: 'Account created successfully!' }; this.showAlert = true; + // Redirect to home this._router.navigateByUrl('/home'); } + } diff --git a/src/app/services/signer.service.ts b/src/app/services/signer.service.ts index 9f954c5..61c4c1c 100644 --- a/src/app/services/signer.service.ts +++ b/src/app/services/signer.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { UnsignedEvent, nip19, getPublicKey, nip04, Event } from 'nostr-tools'; +import { UnsignedEvent, nip19, getPublicKey, nip04, Event, generateSecretKey } from 'nostr-tools'; import { Buffer } from 'buffer'; import { privateKeyFromSeedWords, accountFromSeedWords } from 'nostr-tools/nip06'; @@ -11,6 +11,8 @@ export class SignerService { localStorageSecretKeyName: string = "secretKey"; localStoragePublicKeyName: string = "publicKey"; + localStorageNpubName: string = "npub"; + localStorageNsecName: string = "nsec"; constructor() { } @@ -187,11 +189,11 @@ export class SignerService { savePublicKeyToSession(publicKey: string): void { const npub = nip19.npubEncode(publicKey); window.localStorage.setItem(this.localStoragePublicKeyName, publicKey); - window.localStorage.setItem('npub', npub); + window.localStorage.setItem(this.localStorageNpubName, npub); } getNpub(): string { - return window.localStorage.getItem('npub') || ''; + return window.localStorage.getItem(this.localStorageNpubName) || ''; } removePublicKeyToSession() { @@ -234,9 +236,9 @@ export class SignerService { let npub: string; try { - if (key.startsWith('nsec')) { + if (key.startsWith(this.localStorageNsecName)) { const decoded = nip19.decode(key); - if (decoded.type !== 'nsec') { + if (decoded.type !== this.localStorageNsecName) { throw new Error('Invalid nsec key.'); } const secretKeyUint8Array = decoded.data as Uint8Array; @@ -253,8 +255,8 @@ export class SignerService { nsec = nip19.nsecEncode(secretKeyUint8Array); this.saveSecretKeyToSession(secretKey); this.savePublicKeyToSession(pubkey); - localStorage.setItem('npub', npub); - localStorage.setItem('nsec', nsec); + localStorage.setItem(this.localStorageNpubName, npub); + localStorage.setItem(this.localStorageNsecName, nsec); console.log("Public Key (npub): ", npub); console.log("Private Key (hex): ", secretKey); console.log("nsec: ", nsec); @@ -275,7 +277,7 @@ export class SignerService { const nsec = nip19.nsecEncode(privateKeyUint8Array); this.saveSecretKeyToSession(privateKey); this.savePublicKeyToSession(publicKey); - window.localStorage.setItem('nsec', nsec); + window.localStorage.setItem(this.localStorageNsecName, nsec); console.log("Login with mnemonic successful!"); console.log("Public Key:", publicKey); console.log("Private Key (hex):", privateKey); @@ -289,6 +291,19 @@ export class SignerService { } } + + logout(): void { + // Remove keys from localStorage + window.localStorage.removeItem(this.localStorageSecretKeyName); + window.localStorage.removeItem(this.localStoragePublicKeyName); + window.localStorage.removeItem(this.localStorageNpubName); + window.localStorage.removeItem(this.localStorageNsecName); + + console.log("User logged out and keys removed from localStorage."); + } + + + usingNostrBrowserExtension() { if (this.usingSecretKey()) { return false; @@ -300,6 +315,38 @@ export class SignerService { return false; } + + generateAndStoreKeys(): { privateKeyHex: string, publicKey: string, npub: string, nsec: string } | null { + try { + // Generate a new private key (as Uint8Array) + const privateKeyUint8Array = generateSecretKey(); // Custom method to generate private key + + // Convert private key (Uint8Array) to hex string for storage + const privateKeyHex = Buffer.from(privateKeyUint8Array).toString('hex'); + + // Generate the public key from the private key + const publicKey = getPublicKey(privateKeyUint8Array); + + // Encode the public key as npub and the private key as nsec + const npub = nip19.npubEncode(publicKey); + const nsec = nip19.nsecEncode(privateKeyUint8Array); + + // Store the private key, public key, npub, and nsec in session/localStorage + this.saveSecretKeyToSession(privateKeyHex); // Save private key as hex string + this.savePublicKeyToSession(publicKey); // Save public key + window.localStorage.setItem(this.localStorageNpubName, npub); // Save npub to localStorage + window.localStorage.setItem(this.localStorageNsecName, nsec); // Save nsec to localStorage + + // Return keys to be used in the component + return { privateKeyHex, publicKey, npub, nsec }; + } catch (error) { + console.error("Error during key generation:", error); + return null; + } + } + + + async handleLoginWithExtension(): Promise { const globalContext = globalThis as unknown as { nostr?: { getPublicKey?: Function } }; if (!globalContext.nostr) {