prep for live mocks

This commit is contained in:
Matt Hill
2021-06-14 17:02:26 -06:00
committed by Aiden McClelland
parent 8b84bdefac
commit 53a16775fe
11 changed files with 69 additions and 101 deletions

View File

@@ -11,13 +11,24 @@ export function PatchDbModelFactory (
http: ApiService,
): PatchDbModel {
const { patchDb: { usePollOverride, poll, websocket, timeoutForMissingRevision }, isConsulate } = config
const { mocks, patchDb: { poll, timeoutForMissingRevision }, isConsulate, isLan } = config
let source: Source<DataModel>
if (isConsulate || usePollOverride) {
source = new PollSource({ ...poll }, http)
if (mocks.enabled) {
if (mocks.connection === 'poll') {
source = new PollSource({ ...poll }, http)
} else {
source = new WebsocketSource('ws://localhost:8081')
}
} else {
source = new WebsocketSource({ ...websocket })
if (isConsulate) {
source = new PollSource({ ...poll }, http)
} else {
const protocol = window.location.protocol === 'http:' ? 'ws' : 'wss'
const host = window.location.host
source = new WebsocketSource(`${protocol}://${host}/ws/db`)
}
}
return new PatchDbModel({ sources: [source, http], bootstrapper, http, timeoutForMissingRevision })

View File

@@ -30,7 +30,7 @@ export class LoginPage {
async submit () {
try {
await this.loader.displayDuringP(
this.authService.submitPassword(this.password),
this.authService.login(this.password),
)
this.password = ''
await this.navCtrl.navigateForward(['/'])

View File

@@ -16,11 +16,8 @@ export module RR {
// auth
export type SubmitPinReq = { pin: string } // auth.pin - unauthed
export type SubmitPinRes = null
export type SubmitPasswordReq = { password: string } // auth.password - unauthed
export type SubmitPasswordRes = null
export type LoginReq = { password: string } // auth.login - unauthed
export type loginRes = null
export type LogoutReq = { } // auth.logout
export type LogoutRes = null

View File

@@ -4,9 +4,9 @@ import { LiveApiService } from './live-api.service'
import { ConfigService } from '../config.service'
export function ApiServiceFactory (config: ConfigService, http: HttpService) {
if (config.api.mocks) {
return new MockApiService(config)
if (config.mocks.enabled) {
return new MockApiService(http)
} else {
return new LiveApiService(http, config)
return new LiveApiService(http)
}
}

View File

@@ -16,7 +16,7 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
}
// used for determining internet connectivity
abstract ping (): Promise<void>
abstract echo (): Promise<string>
// for getting static files: ex icons, instructions, licenses
abstract getStatic (url: string): Promise<string>
@@ -34,9 +34,7 @@ export abstract class ApiService implements Source<DataModel>, Http<DataModel> {
// auth
abstract submitPin (params: RR.SubmitPinReq): Promise<RR.SubmitPinRes>
abstract submitPassword (params: RR.SubmitPasswordReq): Promise<RR.SubmitPasswordReq>
abstract login (params: RR.LoginReq): Promise<RR.loginRes>
abstract logout (params: RR.LogoutReq): Promise<RR.LogoutRes>

View File

@@ -3,17 +3,15 @@ import { HttpService, Method } from '../http.service'
import { ApiService } from './api.service'
import { RR } from './api-types'
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
import { ConfigService } from '../config.service'
@Injectable()
export class LiveApiService extends ApiService {
constructor (
private readonly http: HttpService,
private readonly config: ConfigService,
) { super() }
async ping (): Promise<void> {
return this.http.rpcRequest({ method: 'ping', params: { } })
async echo (): Promise<string> {
return this.http.rpcRequest({ method: 'echo', params: { } })
}
async getStatic (url: string): Promise<string> {
@@ -36,12 +34,8 @@ export class LiveApiService extends ApiService {
// auth
async submitPin (params: RR.SubmitPinReq): Promise<RR.SubmitPinRes> {
return this.http.rpcRequest({ method: 'auth.pin', params })
}
async submitPassword (params: RR.SubmitPasswordReq): Promise<RR.SubmitPasswordRes> {
return this.http.rpcRequest({ method: 'auth.password', params })
async login (params: RR.LoginReq): Promise<RR.loginRes> {
return this.http.rpcRequest({ method: 'auth.login', params })
}
async logout (params: RR.LogoutReq): Promise<RR.LogoutRes> {

View File

@@ -4,10 +4,10 @@ import { ApiService } from './api.service'
import { Observable } from 'rxjs'
import { PatchOp, Update } from 'patch-db-client'
import { DataModel, PackageDataEntry, PackageMainStatus, PackageState, ServerStatus } from 'src/app/models/patch-db/data-model'
import { ConfigService } from '../config.service'
import { RR } from './api-types'
import { parsePropertiesPermissive } from 'src/app/util/properties.util'
import { Mock } from './mock-app-fixures'
import { HttpService } from '../http.service'
@Injectable()
export class MockApiService extends ApiService {
@@ -15,7 +15,7 @@ export class MockApiService extends ApiService {
welcomeAck = false
constructor (
private readonly config: ConfigService,
private readonly http: HttpService,
) { super() }
// every time a patch is returned from the mock, we override its sequence to be 1 more than the last sequence in the patch-db as provided by `o`.
@@ -24,9 +24,9 @@ export class MockApiService extends ApiService {
return super.watch$()
}
async ping (): Promise<void> {
console.log('pinging server')
return
async echo (): Promise<string> {
console.log('echo...echo')
return ''
}
async getStatic (url: string): Promise<string> {
@@ -36,47 +36,20 @@ export class MockApiService extends ApiService {
// db
async getRevisions (since: number): Promise<RR.GetRevisionsRes> {
await pauseFor(2000)
return {
...Mock.DbDump,
id: this.nextSequence(),
}
return this.http.rpcRequest({ method: 'db.revisions', params: { since } })
}
async getDump (): Promise<RR.GetDumpRes> {
await pauseFor(2000)
return {
...Mock.DbDump,
id: this.nextSequence(),
}
return this.http.rpcRequest({ method: 'db.dump' })
}
async setDbValueRaw (params: RR.SetDBValueReq): Promise<RR.SetDBValueRes> {
await pauseFor(2000)
return {
response: null,
revision: {
id: this.nextSequence(),
patch: [
{
op: PatchOp.REPLACE,
path: params.pointer,
value: params.value,
},
],
expireId: null,
},
}
return this.http.rpcRequest({ method: 'db.put.ui', params })
}
// auth
async submitPin (params: RR.SubmitPinReq): Promise<RR.SubmitPinRes> {
await pauseFor(2000)
return null
}
async submitPassword (params: RR.SubmitPasswordReq): Promise<RR.SubmitPasswordRes> {
async login (params: RR.LoginReq): Promise<RR.loginRes> {
await pauseFor(2000)
return null
}

View File

@@ -38,12 +38,8 @@ export class AuthService {
return this.authState$.pipe(distinctUntilChanged())
}
async submitPin (pin: string): Promise<void> {
await this.api.submitPin({ pin })
}
async submitPassword (password: string): Promise<void> {
await this.api.submitPassword({ password })
async login (password: string): Promise<void> {
await this.api.login({ password })
await this.storage.set(StorageKeys.LOGGED_IN_KEY, true)
this.authState$.next(AuthState.VERIFIED)
}

View File

@@ -1,31 +1,28 @@
import { Injectable } from '@angular/core'
import { InstalledPackageDataEntry, InterfaceDef, Manifest, PackageDataEntry, PackageMainStatus, PackageState } from '../models/patch-db/data-model'
const { patchDb, maskAs, api, skipStartupAlerts } = require('../../../ui-config.json') as UiConfig
const { patchDb, api, mocks } = require('../../../ui-config.json') as UiConfig
type UiConfig = {
patchDb: {
// If this is false (the default), poll will be used if in consulate only. If true it will be on regardless of env. This is useful in concert with api mocks.
usePollOverride: boolean
poll: {
cooldown: number /* in ms */
}
websocket: {
type: 'ws'
url: string
version: number
}
// Wait this long (ms) before asking BE for a dump when out of order messages are received
timeoutForMissingRevision: number
}
api: {
mocks: boolean
url: string
version: string
root: string
}
maskAs: 'tor' | 'lan' | 'none'
skipStartupAlerts: boolean
mocks: {
enabled: boolean
connection: 'ws' | 'poll'
rpcPort: number
wsPort: number
maskAs: 'tor' | 'lan'
skipStartupAlerts: boolean
}
}
@Injectable({
providedIn: 'root',
@@ -36,16 +33,21 @@ export class ConfigService {
patchDb = patchDb
api = api
mocks = mocks
skipStartupAlerts = skipStartupAlerts
skipStartupAlerts = mocks.enabled && mocks.skipStartupAlerts
isConsulate = window['platform'] === 'ios'
isTor () : boolean {
return (maskAs === 'tor') || this.origin.endsWith('.onion')
isTor (): boolean {
return (mocks.enabled && mocks.maskAs === 'tor') || this.origin.endsWith('.onion')
}
isLan () : boolean {
return (maskAs === 'lan') || this.origin.endsWith('.local')
isLan (): boolean {
return (mocks.enabled && mocks.maskAs === 'lan') || this.origin.endsWith('.local')
}
usePoll (): boolean {
return this.isConsulate || (mocks.enabled && mocks.connection === 'poll')
}
isLaunchable (pkg: PackageDataEntry): boolean {

View File

@@ -66,11 +66,11 @@ export class ConnectionService {
// ping server every 10 seconds
this.httpSubscription = timer(0, 10000)
.pipe(
switchMap(() => this.apiService.ping()),
switchMap(() => this.apiService.echo()),
retryWhen(errors =>
errors.pipe(
tap(val => {
console.error('Ping error: ', val)
console.error('Echo error: ', val)
this.currentState.internet = true
this.emitEvent()
}),

View File

@@ -3,20 +3,17 @@
"timeoutForMissingRevision": 5000,
"poll": {
"cooldown": 40000
},
"websocket": {
"type": "ws",
"url": "",
"version": 0
},
"usePollOverride": true
}
},
"api": {
"mocks": true,
"url": "/api",
"version": "v1",
"root": ""
"url": "/rpc",
"version": "v1"
},
"maskAs": "tor",
"skipStartupAlerts": true
"mocks": {
"enabled": true,
"connection": "poll",
"websocketUrl": "",
"maskAs": "tor",
"skipStartupAlerts": true
}
}