Refactor update of data on meta service.

This commit is contained in:
Spencer Ofwiti 2021-04-25 13:32:23 +03:00
parent affffa8ffe
commit a2e320d923
5 changed files with 59 additions and 46 deletions

View File

@ -37,7 +37,7 @@ export class ErrorInterceptor implements HttpInterceptor {
this.router.navigateByUrl('/auth').then(); this.router.navigateByUrl('/auth').then();
break; break;
case 403: // forbidden case 403: // forbidden
location.reload(true); alert('Access to resource is not allowed!');
break; break;
} }
// Return an observable with a user-facing error message. // Return an observable with a user-facing error message.

View File

@ -22,12 +22,17 @@ export class AuthService {
private loggingService: LoggingService, private loggingService: LoggingService,
private errorDialogService: ErrorDialogService private errorDialogService: ErrorDialogService
) { ) {
// TODO setting these together shoulds be atomic }
async init(): Promise<any> {
await this.mutableKeyStore.loadKeyring();
// TODO setting these together should be atomic
if (sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'))) { if (sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'))) {
this.sessionToken = sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN')); this.sessionToken = sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'));
} }
if (localStorage.getItem(btoa('CICADA_PRIVATE_KEY'))) { if (localStorage.getItem(btoa('CICADA_PRIVATE_KEY'))) {
this.privateKey = localStorage.getItem(btoa('CICADA_PRIVATE_KEY')); this.privateKey = localStorage.getItem(btoa('CICADA_PRIVATE_KEY'));
await this.getPrivateKeys();
} }
} }

View File

@ -1,16 +1,17 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {BehaviorSubject, Observable, of, Subject} from 'rxjs'; import {BehaviorSubject, Observable, Subject} from 'rxjs';
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http'; import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
import {environment} from '@src/environments/environment'; import {environment} from '@src/environments/environment';
import {first} from 'rxjs/operators'; import {first} from 'rxjs/operators';
import {ArgPair, Envelope, Phone, Syncable, User} from 'cic-client-meta'; import {ArgPair, Envelope, Phone, Syncable, User} from 'cic-client-meta';
import {AccountDetails, MetaResponse} from '@app/_models'; import {AccountDetails} from '@app/_models';
import {LoggingService} from '@app/_services/logging.service'; import {LoggingService} from '@app/_services/logging.service';
import {TokenService} from '@app/_services/token.service'; import {TokenService} from '@app/_services/token.service';
import {AccountIndex} from '@app/_eth'; import {AccountIndex} from '@app/_eth';
import {MutableKeyStore, MutablePgpKeyStore, PGPSigner, Signer} from '@app/_pgp'; import {MutableKeyStore, PGPSigner, Signer} from '@app/_pgp';
import {RegistryService} from '@app/_services/registry.service'; import {RegistryService} from '@app/_services/registry.service';
import {CICRegistry} from 'cic-client'; import {CICRegistry} from 'cic-client';
import {AuthService} from './auth.service';
const vCard = require('vcard-parser'); const vCard = require('vcard-parser');
@Injectable({ @Injectable({
@ -18,8 +19,8 @@ const vCard = require('vcard-parser');
}) })
export class UserService { export class UserService {
headers: HttpHeaders = new HttpHeaders({'x-cic-automerge': 'client'}); headers: HttpHeaders = new HttpHeaders({'x-cic-automerge': 'client'});
keystore: MutableKeyStore = new MutablePgpKeyStore(); keystore: MutableKeyStore;
signer: Signer = new PGPSigner(this.keystore); signer: Signer;
registry: CICRegistry; registry: CICRegistry;
accountsMeta = []; accountsMeta = [];
@ -40,7 +41,12 @@ export class UserService {
private loggingService: LoggingService, private loggingService: LoggingService,
private tokenService: TokenService, private tokenService: TokenService,
private registryService: RegistryService, private registryService: RegistryService,
private authService: AuthService,
) { ) {
this.authService.init().then(() => {
this.keystore = authService.mutableKeyStore;
this.signer = new PGPSigner(this.keystore);
});
this.registry = registryService.getRegistry(); this.registry = registryService.getRegistry();
this.registry.load(); this.registry.load();
} }
@ -60,10 +66,16 @@ export class UserService {
} }
async changeAccountInfo(address: string, name: string, phoneNumber: string, age: string, type: string, bio: string, gender: string, async changeAccountInfo(address: string, name: string, phoneNumber: string, age: string, type: string, bio: string, gender: string,
businessCategory: string, userLocation: string, location: string, locationType: string, metaAccount: MetaResponse businessCategory: string, userLocation: string, location: string, locationType: string,
): Promise<any> { ): Promise<any> {
let reqBody = metaAccount; let accountInfo: any = {
let accountInfo = reqBody.m.data; vcard: {
fn: [{}],
n: [{}],
tel: [{}]
},
location: {}
};
accountInfo.vcard.fn[0].value = name; accountInfo.vcard.fn[0].value = name;
accountInfo.vcard.n[0].value = name.split(' '); accountInfo.vcard.n[0].value = name.split(' ');
accountInfo.vcard.tel[0].value = phoneNumber; accountInfo.vcard.tel[0].value = phoneNumber;
@ -75,14 +87,13 @@ export class UserService {
accountInfo.location.area = location; accountInfo.location.area = location;
accountInfo.location.area_name = userLocation; accountInfo.location.area_name = userLocation;
accountInfo.location.area_type = locationType; accountInfo.location.area_type = locationType;
accountInfo.vcard = vCard.generate(accountInfo.vcard); accountInfo.vcard = btoa(vCard.generate(accountInfo.vcard));
reqBody.m.data = accountInfo;
const accountKey = await User.toKey(address); const accountKey = await User.toKey(address);
this.httpClient.get(`${environment.cicMetaUrl}/${accountKey}`, { headers: this.headers }).pipe(first()).subscribe(async res => { this.getAccountDetailsFromMeta(accountKey).pipe(first()).subscribe(async res => {
const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap(); const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
let update = []; let update = [];
for (const prop in reqBody) { for (const prop in accountInfo) {
update.push(new ArgPair(prop, reqBody[prop])); update.push(new ArgPair(prop, accountInfo[prop]));
} }
syncableAccount.update(update, 'client-branch'); syncableAccount.update(update, 'client-branch');
await this.updateMeta(syncableAccount, accountKey, this.headers); await this.updateMeta(syncableAccount, accountKey, this.headers);
@ -184,7 +195,7 @@ export class UserService {
return accountSubject.asObservable(); return accountSubject.asObservable();
} }
async getAccountByPhone(phoneNumber: string, limit: number = 100): Promise<any> { async getAccountByPhone(phoneNumber: string, limit: number = 100): Promise<Observable<AccountDetails>> {
let accountSubject = new Subject<any>(); let accountSubject = new Subject<any>();
this.getAccountDetailsFromMeta(await Phone.toKey(phoneNumber)).pipe(first()).subscribe(async res => { this.getAccountDetailsFromMeta(await Phone.toKey(phoneNumber)).pipe(first()).subscribe(async res => {
const response = Envelope.fromJSON(JSON.stringify(res)).unwrap(); const response = Envelope.fromJSON(JSON.stringify(res)).unwrap();

View File

@ -14,7 +14,7 @@
<ol class="breadcrumb"> <ol class="breadcrumb">
<li class="breadcrumb-item"><a routerLink="/home">Home</a></li> <li class="breadcrumb-item"><a routerLink="/home">Home</a></li>
<li class="breadcrumb-item"><a routerLink="/accounts">Accounts</a></li> <li class="breadcrumb-item"><a routerLink="/accounts">Accounts</a></li>
<li *ngIf="account !== undefined" class="breadcrumb-item active" aria-current="page">{{account?.vcard?.fn[0].value}}</li> <li *ngIf="account" class="breadcrumb-item active" aria-current="page">{{account?.vcard?.fn[0].value}}</li>
</ol> </ol>
</nav> </nav>
<div *ngIf="!account" class="text-center"> <div *ngIf="!account" class="text-center">
@ -240,7 +240,7 @@
</div> </div>
</div> </div>
<mat-tab-group dynamicHeight mat-align-tabs="start"> <mat-tab-group *ngIf="account" dynamicHeight mat-align-tabs="start">
<mat-tab label="Transactions"> <mat-tab label="Transactions">
<app-transaction-details [transaction]="transaction"></app-transaction-details> <app-transaction-details [transaction]="transaction"></app-transaction-details>
<div class="card mt-1"> <div class="card mt-1">

View File

@ -1,4 +1,4 @@
import {ChangeDetectionStrategy, Component, OnInit, ViewChild} from '@angular/core'; import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
import {MatTableDataSource} from '@angular/material/table'; import {MatTableDataSource} from '@angular/material/table';
import {MatPaginator} from '@angular/material/paginator'; import {MatPaginator} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort'; import {MatSort} from '@angular/material/sort';
@ -7,8 +7,6 @@ import {ActivatedRoute, Params, Router} from '@angular/router';
import {first} from 'rxjs/operators'; import {first} from 'rxjs/operators';
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {CustomErrorStateMatcher, exportCsv} from '@app/_helpers'; import {CustomErrorStateMatcher, exportCsv} from '@app/_helpers';
import {Envelope, User} from 'cic-client-meta';
const vCard = require('vcard-parser');
@Component({ @Component({
selector: 'app-account-details', selector: 'app-account-details',
@ -34,9 +32,7 @@ export class AccountDetailsComponent implements OnInit {
accountInfoForm: FormGroup; accountInfoForm: FormGroup;
account: any; account: any;
accountAddress: string; accountAddress: string;
accountBalance: number;
accountStatus: any; accountStatus: any;
metaAccount: any;
accounts: any[] = []; accounts: any[] = [];
accountsType = 'all'; accountsType = 'all';
locations: any; locations: any;
@ -56,7 +52,8 @@ export class AccountDetailsComponent implements OnInit {
private router: Router, private router: Router,
private tokenService: TokenService, private tokenService: TokenService,
private loggingService: LoggingService, private loggingService: LoggingService,
private blockSyncService: BlockSyncService private blockSyncService: BlockSyncService,
private cdr: ChangeDetectorRef,
) { ) {
this.accountInfoForm = this.formBuilder.group({ this.accountInfoForm = this.formBuilder.group({
name: ['', Validators.required], name: ['', Validators.required],
@ -73,25 +70,27 @@ export class AccountDetailsComponent implements OnInit {
this.route.paramMap.subscribe(async (params: Params) => { this.route.paramMap.subscribe(async (params: Params) => {
this.accountAddress = params.get('id'); this.accountAddress = params.get('id');
this.bloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.accountAddress + '/transactions'; this.bloxbergLink = 'https://blockexplorer.bloxberg.org/address/' + this.accountAddress + '/transactions';
this.userService.getAccountDetailsFromMeta(await User.toKey(this.accountAddress)).pipe(first()).subscribe(async res => { (await this.userService.getAccountByAddress(this.accountAddress, 100)).subscribe(async res => {
this.metaAccount = Envelope.fromJSON(JSON.stringify(res.body)).unwrap(); if (res !== undefined) {
this.account = this.metaAccount.m.data; this.account = res;
this.loggingService.sendInfoLevelMessage(this.account); this.cdr.detectChanges();
this.accountBalance = await this.tokenService.getTokenBalance(this.accountAddress); this.loggingService.sendInfoLevelMessage(this.account);
this.account.vcard = vCard.parse(atob(this.account.vcard)); // this.userService.getAccountStatus(this.account.vcard?.tel[0].value).pipe(first()).subscribe(response => this.accountStatus = response);
this.userService.getAccountStatus(this.account.vcard?.tel[0].value).pipe(first()).subscribe(response => this.accountStatus = response); this.accountInfoForm.patchValue({
this.accountInfoForm.patchValue({ name: this.account.vcard?.fn[0].value,
name: this.account.vcard?.fn[0].value, phoneNumber: this.account.vcard?.tel[0].value,
phoneNumber: this.account.vcard?.tel[0].value, age: this.account.age,
age: this.account.age, type: this.account.type,
type: this.account.type, bio: this.account.products,
bio: this.account.products, gender: this.account.gender,
gender: this.account.gender, businessCategory: this.account.category,
businessCategory: this.account.category, userLocation: this.account.location.area_name,
userLocation: this.account.location.area_name, location: this.account.location.area,
location: this.account.location.area, locationType: this.account.location.area_type,
locationType: this.account.location.area_type, });
}); } else {
alert('Account not found!');
}
}); });
this.blockSyncService.blockSync(this.accountAddress); this.blockSyncService.blockSync(this.accountAddress);
}); });
@ -140,7 +139,7 @@ export class AccountDetailsComponent implements OnInit {
this.submitted = true; this.submitted = true;
if (this.accountInfoForm.invalid || !confirm('Change user\'s profile information?')) { return; } if (this.accountInfoForm.invalid || !confirm('Change user\'s profile information?')) { return; }
const accountKey = await this.userService.changeAccountInfo( const accountKey = await this.userService.changeAccountInfo(
this.account.address, this.accountAddress,
this.accountInfoFormStub.name.value, this.accountInfoFormStub.name.value,
this.accountInfoFormStub.phoneNumber.value, this.accountInfoFormStub.phoneNumber.value,
this.accountInfoFormStub.age.value, this.accountInfoFormStub.age.value,
@ -151,9 +150,7 @@ export class AccountDetailsComponent implements OnInit {
this.accountInfoFormStub.userLocation.value, this.accountInfoFormStub.userLocation.value,
this.accountInfoFormStub.location.value, this.accountInfoFormStub.location.value,
this.accountInfoFormStub.locationType.value, this.accountInfoFormStub.locationType.value,
this.metaAccount
); );
this.loggingService.sendInfoLevelMessage(`Response: ${accountKey}`);
this.submitted = false; this.submitted = false;
} }