cic-staff-client/src/app/_services/user.service.ts

180 lines
7.1 KiB
TypeScript

import {Injectable} from '@angular/core';
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 {ArgPair, Envelope, Syncable, User} from 'cic-client-meta';
import {MetaResponse} from '@app/_models';
import {LoggingService} from '@app/_services/logging.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({
providedIn: 'root'
})
export class UserService {
headers: HttpHeaders = new HttpHeaders({'x-cic-automerge': 'client'});
keystore: MutableKeyStore = new MutablePgpKeyStore();
signer: Signer = new PGPSigner(this.keystore);
registry = new Registry(environment.registryAddress);
accountsMeta = [];
accounts: any = [];
private accountsList = new BehaviorSubject<any>(this.accounts);
accountsSubject = this.accountsList.asObservable();
actions: any = '';
private actionsList = new BehaviorSubject<any>(this.actions);
actionsSubject = this.actionsList.asObservable();
staff: any = '';
private staffList = new BehaviorSubject<any>(this.staff);
staffSubject = this.staffList.asObservable();
constructor(
private httpClient: HttpClient,
private loggingService: LoggingService,
private tokenService: TokenService
) {
}
resetPin(phone: string): Observable<any> {
const params = new HttpParams().set('phoneNumber', phone);
return this.httpClient.get(`${environment.cicUssdUrl}/pin`, {params});
}
getAccountStatus(phone: string): any {
const params = new HttpParams().set('phoneNumber', phone);
return this.httpClient.get(`${environment.cicUssdUrl}/pin`, {params});
}
getLockedAccounts(offset: number, limit: number): any {
return this.httpClient.get(`${environment.cicUssdUrl}/accounts/locked/${offset}/${limit}`);
}
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
): Promise<any> {
let reqBody = metaAccount;
let accountInfo = reqBody.m.data;
accountInfo.vcard.fn[0].value = name;
accountInfo.vcard.n[0].value = name.split(' ');
accountInfo.vcard.tel[0].value = phoneNumber;
accountInfo.products = [bio];
accountInfo.gender = gender;
accountInfo.age = age;
accountInfo.type = type;
accountInfo.category = businessCategory;
accountInfo.location.area = location;
accountInfo.location.area_name = userLocation;
accountInfo.location.area_type = locationType;
accountInfo.vcard = vCard.generate(accountInfo.vcard);
reqBody.m.data = accountInfo;
const accountKey = await User.toKey(address);
this.httpClient.get(`${environment.cicMetaUrl}/${accountKey}`, { headers: this.headers }).pipe(first()).subscribe(async res => {
const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
let update = [];
for (const prop in reqBody) {
update.push(new ArgPair(prop, reqBody[prop]));
}
syncableAccount.update(update, 'client-branch');
await this.updateMeta(syncableAccount, accountKey, this.headers);
}, async error => {
this.loggingService.sendErrorLevelMessage('Can\'t find account info in meta service', this, {error});
const syncableAccount: Syncable = new Syncable(accountKey, accountInfo);
await this.updateMeta(syncableAccount, accountKey, this.headers);
});
return accountKey;
}
async updateMeta(syncableAccount: Syncable, accountKey: string, headers: HttpHeaders): Promise<any> {
const envelope = await this.wrap(syncableAccount , this.signer);
const reqBody = envelope.toJSON();
this.httpClient.put(`${environment.cicMetaUrl}/${accountKey}`, reqBody , { headers }).pipe(first()).subscribe(res => {
this.loggingService.sendInfoLevelMessage(`Response: ${res}`);
});
}
getAccounts(): void {
this.httpClient.get(`${environment.cicCacheUrl}/accounts`).pipe(first()).subscribe(res => this.accountsList.next(res));
}
getAccountById(id: number): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/accounts/${id}`);
}
getActions(): void {
this.httpClient.get(`${environment.cicCacheUrl}/actions`).pipe(first()).subscribe(res => this.actionsList.next(res));
}
getActionById(id: string): any {
return this.httpClient.get(`${environment.cicCacheUrl}/actions/${id}`);
}
approveAction(id: string): Observable<any> {
return this.httpClient.post(`${environment.cicCacheUrl}/actions/${id}`, { approval: true });
}
revokeAction(id: string): Observable<any> {
return this.httpClient.post(`${environment.cicCacheUrl}/actions/${id}`, { approval: false });
}
getHistoryByUser(id: string): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/history/${id}`);
}
getAccountDetailsFromMeta(userKey: string): Observable<any> {
return this.httpClient.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
}
getUser(userKey: string): any {
return this.httpClient.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers })
.pipe(first()).subscribe(async res => {
return Envelope.fromJSON(JSON.stringify(res)).unwrap();
});
}
wrap(syncable: Syncable, signer: Signer): Promise<Envelope> {
return new Promise<Envelope>(async (whohoo, doh) => {
syncable.setSigner(signer);
syncable.onwrap = async (env) => {
if (env === undefined) {
doh();
return;
}
whohoo(env);
};
await syncable.sign();
});
}
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(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) {
this.accounts.length = limit;
}
this.accountsList.next(this.accounts);
});
}
}
resetAccountsList(): void {
this.accounts = [];
this.accountsList.next(this.accounts);
}
}