Refactor auth module.

- Switch from form to text field for passphrase input.
- Refactor error dialog format.
- Send dialog on incorrect parsing of private key.
- Refactor block sync service to take parameters.
This commit is contained in:
Spencer Ofwiti
2021-03-16 13:08:18 +03:00
parent 9fa9852ded
commit 12f4d328bf
15 changed files with 82 additions and 75 deletions

View File

@@ -1,10 +1,11 @@
import { Injectable } from '@angular/core';
import {MutableKeyStore, MutablePgpKeyStore} from '@app/_helpers';
import { hobaParseChallengeHeader } from '@src/assets/js/hoba.js';
import { signChallenge } from '@src/assets/js/hoba-pgp.js';
import {environment} from '@src/environments/environment';
import {LoggingService} from '@app/_services/logging.service';
import {HttpWrapperService} from '@app/_services/http-wrapper.service';
import {MutableKeyStore, MutablePgpKeyStore} from '@app/_pgp';
import {ErrorDialogService} from '@app/_services/error-dialog.service';
import {first} from 'rxjs/operators';
@Injectable({
@@ -18,7 +19,8 @@ export class AuthService {
constructor(
private httpWrapperService: HttpWrapperService,
private loggingService: LoggingService
private loggingService: LoggingService,
private errorDialogService: ErrorDialogService
) {
if (sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'))) {
this.sessionToken = sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'));
@@ -29,7 +31,7 @@ export class AuthService {
}
setState(s): void {
(document.getElementById('state') as HTMLInputElement).value = s;
document.getElementById('state').innerHTML = s;
}
getWithToken(): void {
@@ -44,7 +46,7 @@ export class AuthService {
throw new Error('login rejected');
}
this.sessionLoginCount++;
this.setState('click to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
this.setState('Click button to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
return;
});
xhr.send();
@@ -64,7 +66,7 @@ export class AuthService {
this.sessionToken = xhr.getResponseHeader('Token');
sessionStorage.setItem(btoa('CICADA_SESSION_TOKEN'), this.sessionToken);
this.sessionLoginCount++;
this.setState('click to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
this.setState('Click button to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
return;
});
xhr.send();
@@ -95,8 +97,7 @@ export class AuthService {
}
} else {
try {
const o = this.getChallenge();
return true;
this.getChallenge();
} catch (e) {
this.loggingService.sendErrorLevelMessage('Login challenge failed', this, {error: e});
}
@@ -113,15 +114,19 @@ export class AuthService {
loginView(): void {
document.getElementById('one').style.display = 'none';
document.getElementById('two').style.display = 'block';
this.setState('click to log in with PGP key ' + this.mutableKeyStore.getPrivateKeyId());
this.setState('Click button to log in with PGP key ' + this.mutableKeyStore.getPrivateKeyId());
}
async setKey(privateKeyArmored): Promise<boolean> {
try {
await this.mutableKeyStore.importPrivateKey(privateKeyArmored);
localStorage.setItem(btoa('CICADA_PRIVATE_KEY'), privateKeyArmored);
} catch (e) {
this.loggingService.sendErrorLevelMessage('Failed setting key', this, {error: e});
} catch (err) {
this.loggingService.sendErrorLevelMessage('Failed setting key', this, {error: err});
this.errorDialogService.openDialog({
message: `Failed to set key, Enter your private key again. Reason: ${err.error.message || err.statusText}`,
status: err.status
});
return false;
}
this.loginView();
@@ -134,10 +139,10 @@ export class AuthService {
}
async getPublicKeys(): Promise<void> {
this.httpWrapperService.get(`${environment.publicKeysUrl}/keys.asc`).pipe(first()).subscribe(async res => {
this.httpWrapperService.get(`${environment.publicKeysUrl}`).pipe(first()).subscribe(async res => {
await this.mutableKeyStore.importPublicKey(res.body);
}, error => {
this.loggingService.sendErrorLevelMessage('There was an error!', this, {error});
this.loggingService.sendErrorLevelMessage('There was an error fetching public keys!', this, {error});
});
if (this.privateKey !== undefined) {
await this.mutableKeyStore.importPrivateKey(this.privateKey);

View File

@@ -21,7 +21,8 @@ export class BlockSyncService {
private loggingService: LoggingService
) { }
blockSync(): any {
blockSync(address: string = null, offset: number = 0, limit: number = 100): any {
this.transactionService.resetTransactionsList();
const settings = new Settings(this.scan);
const provider = environment.web3Provider;
const readyStateElements = { network: 2 };
@@ -40,13 +41,13 @@ export class BlockSyncService {
};
settings.registry.onload = (addressReturned: number): void => {
this.loggingService.sendInfoLevelMessage(`Loaded network contracts ${addressReturned}`);
this.readyStateProcessor(settings, readyStateElements.network);
this.readyStateProcessor(settings, readyStateElements.network, address, offset, limit);
};
settings.registry.load();
}
readyStateProcessor(settings, bit): void {
readyStateProcessor(settings: Settings, bit: number, address: string, offset: number, limit: number): void {
this.readyState |= bit;
if (this.readyStateTarget === this.readyState && this.readyStateTarget) {
const wHeadSync = new Worker('./../assets/js/block-sync/head.js');
@@ -56,7 +57,15 @@ export class BlockSyncService {
wHeadSync.postMessage({
w3_provider: settings.w3.provider,
});
this.fetcher(settings);
if (address === null) {
this.transactionService.getAllTransactions(offset, limit).pipe(first()).subscribe(res => {
this.fetcher(settings, res.body);
});
} else {
this.transactionService.getAddressTransactions(address, offset, limit).pipe(first()).subscribe(res => {
this.fetcher(settings, res.body);
});
}
}
}
@@ -93,17 +102,15 @@ export class BlockSyncService {
});
}
fetcher(settings: any, offset: number = 0, limit: number = 100): void {
this.transactionService.getAllTransactions(offset, limit).pipe(first()).subscribe(res => {
const blockFilterBinstr = window.atob(res.body.block_filter);
const bOne = new Uint8Array(blockFilterBinstr.length);
bOne.map((e, i, v) => v[i] = blockFilterBinstr.charCodeAt(i));
fetcher(settings: Settings, transactionsInfo: any): void {
const blockFilterBinstr = window.atob(transactionsInfo.block_filter);
const bOne = new Uint8Array(blockFilterBinstr.length);
bOne.map((e, i, v) => v[i] = blockFilterBinstr.charCodeAt(i));
const blocktxFilterBinstr = window.atob(res.body.blocktx_filter);
const bTwo = new Uint8Array(blocktxFilterBinstr.length);
bTwo.map((e, i, v) => v[i] = blocktxFilterBinstr.charCodeAt(i));
const blocktxFilterBinstr = window.atob(transactionsInfo.blocktx_filter);
const bTwo = new Uint8Array(blocktxFilterBinstr.length);
bTwo.map((e, i, v) => v[i] = blocktxFilterBinstr.charCodeAt(i));
settings.scanFilter(settings, res.body.low, res.body.high, bOne, bTwo, res.body.filter_rounds);
});
settings.scanFilter(settings, transactionsInfo.low, transactionsInfo.high, bOne, bTwo, transactionsInfo.filter_rounds);
}
}

View File

@@ -41,6 +41,7 @@ export class HttpWrapperService {
return Observable.create((observer: any) => {
const requestBeginTime = moment();
this.http.request(new HttpRequest(method, url, body, options)).subscribe((response) => {
this.loggingService.sendInfoLevelMessage(response);
this.logTime(requestBeginTime, `${url}`, method);
observer.next(response);
observer.complete();

View File

@@ -6,3 +6,4 @@ export * from '@app/_services/block-sync.service';
export * from '@app/_services/location.service';
export * from '@app/_services/logging.service';
export * from '@app/_services/http-wrapper.service';
export * from '@app/_services/error-dialog.service';

View File

@@ -1,10 +1,11 @@
import { Injectable } from '@angular/core';
import {environment} from '@src/environments/environment';
import {BehaviorSubject, Observable} from 'rxjs';
import {HttpGetter, Registry, TokenRegistry} from '@app/_helpers';
import {HttpGetter} from '@app/_helpers';
import {CICRegistry} from 'cic-client';
import Web3 from 'web3';
import {HttpWrapperService} from '@app/_services/http-wrapper.service';
import {Registry, TokenRegistry} from '@app/_eth';
@Injectable({
providedIn: 'root'

View File

@@ -11,10 +11,10 @@ import {Tx} from '@src/assets/js/ethtx/dist';
import {toValue} from '@src/assets/js/ethtx/dist/tx';
import * as secp256k1 from 'secp256k1';
import {AuthService} from '@app/_services/auth.service';
import {Registry} from '@app/_helpers';
import {defaultAccount} from '@app/_models';
import {LoggingService} from '@app/_services/logging.service';
import {HttpWrapperService} from '@app/_services/http-wrapper.service';
import {Registry} from '@app/_eth';
const Web3 = require('web3');
const vCard = require('vcard-parser');
@@ -45,22 +45,22 @@ export class TransactionService {
}
async setTransaction(transaction, cacheSize: number): Promise<void> {
if (this.transactions.find(cachedTx => cachedTx.tx.txHash === transaction.tx.txHash)) { return; }
transaction.value = Number(transaction.value);
transaction.type = 'transaction';
if (this.transactions.find(cachedTx => cachedTx.tx.txHash === transaction.tx.txHash)) { return; }
try {
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.from)).pipe(first()).subscribe(async (res) => {
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.from)).pipe(first()).subscribe((res) => {
transaction.sender = this.getAccountInfo(res.body);
}, error => {
transaction.sender = defaultAccount;
});
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.to)).pipe(first()).subscribe(async (res) => {
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.to)).pipe(first()).subscribe((res) => {
transaction.recipient = this.getAccountInfo(res.body);
}, error => {
transaction.recipient = defaultAccount;
});
} finally {
await this.addTransaction(transaction, cacheSize);
this.addTransaction(transaction, cacheSize);
}
}
@@ -70,17 +70,17 @@ export class TransactionService {
conversion.fromValue = Number(conversion.fromValue);
conversion.toValue = Number(conversion.toValue);
try {
this.userService.getAccountDetailsFromMeta(await User.toKey(conversion.trader)).pipe(first()).subscribe(async (res) => {
this.userService.getAccountDetailsFromMeta(await User.toKey(conversion.trader)).pipe(first()).subscribe((res) => {
conversion.sender = conversion.recipient = this.getAccountInfo(res.body);
}, error => {
conversion.sender = conversion.recipient = defaultAccount;
});
} finally {
await this.addTransaction(conversion, cacheSize);
this.addTransaction(conversion, cacheSize);
}
}
async addTransaction(transaction, cacheSize: number): Promise<void> {
addTransaction(transaction, cacheSize: number): void {
this.transactions.unshift(transaction);
if (this.transactions.length > cacheSize) {
this.transactions.length = cacheSize;
@@ -88,6 +88,11 @@ export class TransactionService {
this.transactionList.next(this.transactions);
}
resetTransactionsList(): void {
this.transactions = [];
this.transactionList.next(this.transactions);
}
getAccountInfo(account: string): any {
let accountInfo = Envelope.fromJSON(JSON.stringify(account)).unwrap().m.data;
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));

View File

@@ -3,11 +3,13 @@ import {BehaviorSubject, Observable} from 'rxjs';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {environment} from '@src/environments/environment';
import {first} from 'rxjs/operators';
import {AccountIndex, MutableKeyStore, MutablePgpKeyStore, PGPSigner, Registry, Signer} from '@app/_helpers';
import {ArgPair, Envelope, Syncable, User} from 'cic-client-meta';
import {MetaResponse} from '@app/_models';
import {LoggingService} from '@app/_services/logging.service';
import {HttpWrapperService} from '@app/_services/http-wrapper.service';
import {TokenService} from '@app/_services/token.service';
import {AccountIndex, Registry} from '@app/_eth';
import {MutableKeyStore, MutablePgpKeyStore, PGPSigner, Signer} from '@app/_pgp';
const vCard = require('vcard-parser');
@Injectable({
@@ -35,7 +37,8 @@ export class UserService {
constructor(
private http: HttpClient,
private httpWrapperService: HttpWrapperService,
private loggingService: LoggingService
private loggingService: LoggingService,
private tokenService: TokenService
) {
}
@@ -145,7 +148,7 @@ export class UserService {
}
getAccountDetailsFromMeta(userKey: string): Observable<any> {
return this.httpWrapperService.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
return this.http.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
}
getUser(userKey: string): any {
@@ -169,16 +172,18 @@ export class UserService {
});
}
async loadAccounts(limit: number, offset: number = 0): Promise<void> {
async loadAccounts(limit: number = 100, offset: number = 0): Promise<void> {
this.resetAccountsList();
const accountIndexAddress = await this.registry.addressOf('AccountRegistry');
const accountIndexQuery = new AccountIndex(accountIndexAddress);
const accountAddresses = await accountIndexQuery.last(await accountIndexQuery.totalAccounts());
this.loggingService.sendInfoLevelMessage(accountAddresses);
for (const accountAddress of accountAddresses.slice(offset, offset + limit)) {
this.getAccountDetailsFromMeta(await User.toKey(accountAddress)).pipe(first()).subscribe(res => {
this.getAccountDetailsFromMeta(await User.toKey(accountAddress)).pipe(first()).subscribe(async res => {
const account = Envelope.fromJSON(JSON.stringify(res)).unwrap();
this.accountsMeta.push(account);
const accountInfo = account.m.data;
accountInfo.balance = await this.tokenService.getTokenBalance(accountInfo.identities.evm['bloxberg:8996'][0]);
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
this.accounts.unshift(accountInfo);
if (this.accounts.length > limit) {