diff --git a/.gitignore b/.gitignore index 14fe5b7..4c55524 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /dist /tmp /out-tsc +/tests # Only exists if Bazel was run /bazel-out diff --git a/angular.json b/angular.json index 2b57cc7..e86534f 100644 --- a/angular.json +++ b/angular.json @@ -37,7 +37,8 @@ "scripts": [ "node_modules/jquery/dist/jquery.js", "node_modules/bootstrap/dist/js/bootstrap.js" - ] + ], + "webWorkerTsConfig": "tsconfig.worker.json" }, "configurations": { "production": { @@ -126,7 +127,8 @@ "tsConfig": [ "tsconfig.app.json", "tsconfig.spec.json", - "e2e/tsconfig.json" + "e2e/tsconfig.json", + "tsconfig.worker.json" ], "exclude": [ "**/node_modules/**" diff --git a/src/app/_services/auth.service.ts b/src/app/_services/auth.service.ts index 53e3d13..9244438 100644 --- a/src/app/_services/auth.service.ts +++ b/src/app/_services/auth.service.ts @@ -48,7 +48,7 @@ export class AuthService { } getWithToken(): Promise { - const sessionToken = this.getSessionToken() + const sessionToken = this.getSessionToken(); const headers = { Authorization: 'Bearer ' + sessionToken, 'Content-Type': 'application/json;charset=utf-8', @@ -94,33 +94,32 @@ export class AuthService { async login(): Promise { if (this.getSessionToken()) { sessionStorage.removeItem(btoa('CICADA_SESSION_TOKEN')); - } + } const o = await this.getChallenge(); const r = await signChallenge( - o.challenge, - o.realm, - environment.cicMetaUrl, - this.mutableKeyStore + o.challenge, + o.realm, + environment.cicMetaUrl, + this.mutableKeyStore ); - const tokenResponse = await this.sendSignedChallenge(r) - .then((response) => { - const token = response.headers.get('Token'); - if (token) { - return token; - } - if (response.status === 401) { - throw new HttpError('You are not authorized to use this system', response.status); - } - if (!response.ok) { - throw new HttpError('Unknown error from authentication server', response.status); - } + const tokenResponse = await this.sendSignedChallenge(r).then((response) => { + const token = response.headers.get('Token'); + if (token) { + return token; + } + if (response.status === 401) { + throw new HttpError('You are not authorized to use this system', response.status); + } + if (!response.ok) { + throw new HttpError('Unknown error from authentication server', response.status); + } }); if (tokenResponse) { this.setSessionToken(tokenResponse); - //this.setState('Click button to log in'); + // this.setState('Click button to log in'); return true; } return false; diff --git a/src/app/_services/user.service.ts b/src/app/_services/user.service.ts index 975dd72..8cb1963 100644 --- a/src/app/_services/user.service.ts +++ b/src/app/_services/user.service.ts @@ -204,17 +204,26 @@ export class UserService { async loadAccounts(limit: number = 100, offset: number = 0): Promise { this.resetAccountsList(); - // const accountIndexAddress: string = await this.registry.getContractAddressByName( - // 'AccountRegistry' - // ); - // const accountIndexQuery = new AccountIndex(accountIndexAddress); - // const accountAddresses: Array = await accountIndexQuery.last(limit); try { const accountRegistry = await RegistryService.getAccountRegistry(); - const accountAddresses: Array = await accountRegistry.last(limit); + const accountAddresses: Array = await accountRegistry.last(offset + limit); this.loggingService.sendInfoLevelMessage(accountAddresses); - for (const accountAddress of accountAddresses.slice(offset, offset + limit)) { - await this.getAccountByAddress(accountAddress, limit); + if (typeof Worker !== 'undefined') { + const worker = new Worker('@app/_workers/fetch-accounts.worker', { type: 'module' }); + worker.onmessage = ({ data }) => { + this.addAccount(data, limit); + }; + worker.postMessage({ + addresses: accountAddresses.slice(offset, offset + limit), + url: environment.cicMetaUrl, + }); + } else { + this.loggingService.sendInfoLevelMessage( + 'Web workers are not supported in this environment' + ); + for (const accountAddress of accountAddresses.slice(offset, offset + limit)) { + await this.getAccountByAddress(accountAddress, limit); + } } } catch (error) { this.loggingService.sendErrorLevelMessage('Unable to load accounts.', 'user.service', error); diff --git a/src/app/_workers/fetch-accounts.worker.ts b/src/app/_workers/fetch-accounts.worker.ts new file mode 100644 index 0000000..ebce013 --- /dev/null +++ b/src/app/_workers/fetch-accounts.worker.ts @@ -0,0 +1,44 @@ +/// + +import { Envelope, Syncable, User } from 'cic-client-meta'; +import { add0x } from '@src/assets/js/ethtx/dist/hex'; +import { personValidation, vcardValidation } from '@app/_helpers/schema-validation'; +// const vCard = require('vcard-parser'); +import * as vCard from 'vcard-parser'; + +const headers = { + 'x-cic-automerge': 'client', +}; +const options = { + headers, +}; + +addEventListener('message', async ({ data }) => { + if (data.addresses instanceof Array) { + for (const accountAddress of data.addresses) { + const account = await getAccountByAddress(accountAddress, data.url); + postMessage(account); + } + } +}); + +async function getAccountByAddress(accountAddress: string, metaUrl: string): Promise { + const userKey = await User.toKey(add0x(accountAddress)); + return new Promise((resolve, reject) => { + fetch(`${metaUrl}/${userKey}`, options).then(async (response) => { + if (!response.ok) { + return reject({ + status: response.status, + statusText: response.statusText, + }); + } else { + const account: Syncable = Envelope.fromJSON(JSON.stringify(response.text())).unwrap(); + const accountInfo = account.m.data; + await personValidation(accountInfo); + accountInfo.vcard = vCard.parse(atob(accountInfo.vcard)); + await vcardValidation(accountInfo.vcard); + return resolve(accountInfo); + } + }); + }); +} diff --git a/src/app/auth/auth.component.ts b/src/app/auth/auth.component.ts index d715fd4..c9fea9d 100644 --- a/src/app/auth/auth.component.ts +++ b/src/app/auth/auth.component.ts @@ -58,7 +58,7 @@ export class AuthComponent implements OnInit { } } catch (HttpError) { this.errorDialogService.openDialog({ - message: "Failed to login please try again.", + message: 'Failed to login please try again.', }); } } diff --git a/tsconfig.worker.json b/tsconfig.worker.json new file mode 100644 index 0000000..22dc454 --- /dev/null +++ b/tsconfig.worker.json @@ -0,0 +1,15 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/worker", + "lib": [ + "es2018", + "webworker" + ], + "types": [] + }, + "include": [ + "src/**/*.worker.ts" + ] +}