diff --git a/src/app/backend-api.service.ts b/src/app/backend-api.service.ts index b2afa9e..aead80e 100644 --- a/src/app/backend-api.service.ts +++ b/src/app/backend-api.service.ts @@ -19,6 +19,8 @@ export class User { providedIn: 'root' }) export class BackendAPIService { + walletSyncEndpoint = `https://${environment.walletSyncHostname}/api/v0`; + endpoint = `https://${environment.nodeHostname}/api/v0`; constructor( @@ -67,4 +69,34 @@ export class BackendAPIService { return of(usernames); } } + + // TODO - WIP, not using for now. + + // This isn't what the current wallet sync API looks like, but it will + // likely change anyway. So this is an approximation with a stub for the time being. + WalletSyncLogin( + username: string, + password: string, + ): Observable<{bodyJson: string, signature: string} | null> { + + // A stub for now + const wallet : object | null = this.cryptoService.getWallet(this.globalVars.hostname); + if (wallet === null) { + return of(null) + } + + return of({ + bodyJson: JSON.stringify(wallet, null, 2), + signature: "", + }) + + // Later we'll do something like this... + return this.httpClient.post( + `${this.walletSyncEndpoint}/log-in`, + { + username: username, + password: password, + }, + ); + } } diff --git a/src/app/crypto.service.ts b/src/app/crypto.service.ts index 00336da..a0e498f 100644 --- a/src/app/crypto.service.ts +++ b/src/app/crypto.service.ts @@ -1,12 +1,9 @@ import { Injectable } from '@angular/core'; -import HDNode from 'hdkey'; -import * as bip39 from 'bip39'; -import HDKey from 'hdkey'; import {ec as EC} from 'elliptic'; import bs58check from 'bs58check'; import {CookieService} from 'ngx-cookie'; import {createHmac, createCipher, createDecipher, randomBytes} from 'crypto'; -import {AccessLevel, Network} from '../types/identity'; +import {AccessLevel, PrivateAccountInfo} from '../types/identity'; import { GlobalVarsService } from './global-vars.service'; @Injectable({ @@ -76,7 +73,8 @@ export class CryptoService { } } - getWallet(hostname: string): object | null { + // TODO define a wallet type, and/or use a type defined by json-schema + getWallet(hostname: string): {accounts: [PrivateAccountInfo]} | null { const storageKey = this.walletStorageKey(hostname); let walletStr if (this.mustUseStorageAccess()) { @@ -169,4 +167,16 @@ export class CryptoService { return new Buffer(publicKeyEC.getPublic('array')); } + + // TODO check that the signature for the walletStr is valid + checkSig(walletStr: string, walletSignature: string): boolean { + throw "implement me" + return true + } + + // TODO find errors in the wallet. missing fields, etc. json-schema + validateWallet(wallet: object): string | null { + throw "implement me" + return null + } } diff --git a/src/app/test-lbry-log-in/test-lbry-log-in.component.html b/src/app/test-lbry-log-in/test-lbry-log-in.component.html index 069dac2..a2da138 100644 --- a/src/app/test-lbry-log-in/test-lbry-log-in.component.html +++ b/src/app/test-lbry-log-in/test-lbry-log-in.component.html @@ -1,3 +1,51 @@ -

- wallet me: -

+ + +
+ + + +
+ Paste your wallet directly +
+ +

+ + +

+
diff --git a/src/app/test-lbry-log-in/test-lbry-log-in.component.ts b/src/app/test-lbry-log-in/test-lbry-log-in.component.ts index 09df5a3..d09efa0 100644 --- a/src/app/test-lbry-log-in/test-lbry-log-in.component.ts +++ b/src/app/test-lbry-log-in/test-lbry-log-in.component.ts @@ -1,8 +1,17 @@ -import { Component, OnInit } from '@angular/core'; -import { CryptoService } from '../crypto.service'; -import { SigningService } from '../signing.service'; -import { IdentityService } from '../identity.service'; -import { GlobalVarsService } from '../global-vars.service'; +import {BackendAPIService} from '../backend-api.service'; +import {Component, OnInit} from '@angular/core'; +import {CryptoService} from '../crypto.service'; +import {GlobalVarsService} from '../global-vars.service'; +import {Router} from '@angular/router'; +import {RouteNames} from '../app-routing.module'; +import {of} from 'rxjs'; + +// This is logging into the wallet sync, not the app +// TODO rename this component to wallet-sync-log-in + +// This component handles two ways of logging in: +// * Wallet Sync (currently commented out) +// * Paste Wallet (temporary measure for initial version) @Component({ selector: 'app-test-lbry-log-in', @@ -10,32 +19,90 @@ import { GlobalVarsService } from '../global-vars.service'; styleUrls: ['./test-lbry-log-in.component.scss'] }) export class TestLbryLogInComponent implements OnInit { + walletDumpInitial = this.getWalletDumpInitial(); + + loginError = ''; + loginUsername = ''; + loginPassword = ''; constructor( + private backendApi: BackendAPIService, private cryptoService: CryptoService, - private signingService: SigningService, - private identityService: IdentityService, - private globalVars: GlobalVarsService, + public globalVars: GlobalVarsService, + private router: Router, ) { } - ngOnInit(): void { - const wallet : object | null = this.cryptoService.getWallet(this.globalVars.hostname); - (document.getElementById("wallet")).value = JSON.stringify(wallet, null, 2) || ""; + ngOnInit(): void {} + + // Wallet Sync (WIP, unused atm) + + clickLogin() { + // Store username and password locally because we clear them below and otherwise + // they don't get saved in local storage reliably + const loginUsername = this.loginUsername; + const loginPassword = this.loginPassword; + + if (loginUsername.length === 0) { + this.loginError = 'Enter a username'; + return of(); + } + + if (loginPassword.length === 0) { + this.loginError = 'Enter a password'; + return of(); + } + + // Returning the observable only because I'm in the habit of returning + // promises. But maybe it's not needed here. + return this.backendApi.WalletSyncLogin(loginUsername, loginPassword).subscribe( + (res => { + if (res === null) { + this.loginError = "Login Error. Try again?" + return + } + + const walletStr = res.bodyJson + const walletSignature = res.signature + + if (!this.cryptoService.checkSig(walletStr, walletSignature)) { + this.loginError = 'Wallet signature failed!'; + return + } + const wallet = JSON.parse(res.bodyJson) + const walletError: string | null = this.cryptoService.validateWallet(wallet); + + if (walletError !== null) { + this.loginError = "Wallet error: " + walletError; + return + } + + this.cryptoService.putWallet(this.globalVars.hostname, wallet); + + // Clear the form + this.loginUsername = ''; + this.loginPassword = ''; + + this.router.navigate(['/', RouteNames.LOG_IN], {queryParamsHandling: 'merge'}); + }), + (() => { + this.loginError = "Login Error. Try again?" + }) + ); } - saveWallet(): void { - const walletStr = (document.getElementById("wallet")).value; + // Paste Wallet (temporary measure for initial version) + + getWalletDumpInitial() { + const wallet : object | null = this.cryptoService.getWallet(this.globalVars.hostname); + return JSON.stringify(wallet, null, 2) || "" + } + + loginWithWalletDump(): void { + const walletStr = (document.getElementById("wallet-dump")).value; const wallet = JSON.parse(walletStr) this.cryptoService.putWallet(this.globalVars.hostname, wallet); - const addresses = this.signingService.getAddresses(wallet) - this.finishFlow(addresses) + this.router.navigate(['/', RouteNames.LOG_IN], {queryParamsHandling: 'merge'}); } - finishFlow(addresses: string[]): void { - this.identityService.login({ - accounts: this.accountService.getPublicAccounts(), - addresses, - }); - } } diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 1be5e3b..5b06ca5 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -6,6 +6,7 @@ export const environment = { production: false, hostname: 'localhost:4201', nodeHostname: 'node.deso.org', // TODO deleteme + walletSyncHostname: 'localhost:8091', }; /*