Comment all the things and remove unnecessary files

working-state
Garrett Mills 3 years ago
parent 6ba038e4bf
commit f0570a6101
Signed by: garrettmills
GPG Key ID: D2BF5FBA8298F246

@ -12,10 +12,15 @@ export interface FirebaseResourceItem {
seqID: number;
}
/**
* An asynchronous iterable wrapper that enables us to use AsyncCollection
* to interact with the Firebase realtime database.
*/
@Injectable()
export class FirebaseResource<T extends FirebaseResourceItem> extends Iterable<T> {
protected refName!: RTDBRef
/** Get the Reference for this resource. */
ref(): firebase.database.Reference {
return Application.getApplication().make<FirebaseUnit>(FirebaseUnit).ref(this.refName)
}

@ -6,21 +6,30 @@ export default {
gpg: {
key: {
// Contents of the SERVER's GPG public key, armored.
public: fs.readFileSync(env('GPG_KEY_PUB')).toString('utf-8'),
// Contents of the SERVER's GPG private key, armored.
private: fs.readFileSync(env('GPG_KEY_PRIV')).toString('utf-8'),
},
},
firebase: {
// Contents of the Firebase service account credentials file.
credentials: JSON.parse(
fs.readFileSync(env('FIREBASE_CREDENTIALS'))
.toString('utf-8')
),
// Name of the HTTP header to check for the firebase auth token
api_auth_header: env('FIREBASE_API_AUTH_HEADER', 'X-Auth-Token'),
rtdb: {
// URL of the realtime-database this app should use
default: env('FIREBASE_DEFAULT_RTDB', 'https://loc-chain-default-rtdb.firebaseio.com'),
// Mapping of ref-shortname to actual database reference
// If you add a value here, also add it to the RTDBRef type alias
refs: {
peers: 'chain/server/peers',
transaction: 'chain/pending/transactions',

@ -1,5 +0,0 @@
import { env } from "@extollo/lib"
export default {
app_name: env('APP_NAME', 'Extollo'),
}

@ -1,6 +0,0 @@
import {env} from '@extollo/lib'
export default {
welcome_to_extollo: 'Welcome to Extollo!',
viewed_page_num_times: 'You have viewed this page :num: times.',
}

@ -37,7 +37,8 @@ export default {
middleware: {
global: {
pre: ['LogRequest'],
pre: [],
post: [],
},
},
}

@ -1,5 +1,5 @@
import {Controller} from "@extollo/lib"
import {Inject, Injectable} from "@extollo/di"
import {Injectable} from "@extollo/di"
import {TransactionResource, TransactionResourceItem} from "../../../rtdb/TransactionResource"
import {one} from "@extollo/util"
@ -10,7 +10,9 @@ import {one} from "@extollo/util"
*/
@Injectable()
export class Blockchain extends Controller {
/**
* Post a new transaction to the blockchain. This is only intended for testing.
*/
public async postTransaction() {
const item: TransactionResourceItem = {
firebaseID: '',
@ -25,5 +27,4 @@ export class Blockchain extends Controller {
await (<TransactionResource> this.make(TransactionResource)).push(item)
return one(item)
}
}

@ -0,0 +1,20 @@
import {Config, error, Middleware} from "@extollo/lib"
import {Inject, Injectable} from "@extollo/di"
import {HTTPStatus} from "@extollo/util"
/**
* DebugOnly Middleware
* --------------------------------------------
* Only allows the request to proceed if the app is in debug mode.
*/
@Injectable()
export class DebugOnly extends Middleware {
@Inject()
protected readonly config!: Config
public async apply() {
if ( !this.config.get('server.debug', false) ) {
return error('Not found.', HTTPStatus.NOT_FOUND)
}
}
}

@ -1,12 +0,0 @@
import {json, Logging, Middleware} from "@extollo/lib";
import {Inject, Injectable} from "@extollo/di";
@Injectable()
export class LogRequest extends Middleware {
@Inject()
protected readonly logging!: Logging
public async apply() {
this.logging.info(`Incoming request: ${this.request.method} @ ${this.request.path}`)
}
}

@ -16,16 +16,19 @@ export class FirebaseUserOnly extends Middleware {
@Inject()
protected readonly config!: Config
/** Get the name of the API token header. */
get headerName(): string {
return String(this.config.get('app.firebase.api_auth_header'))
}
/** Get the API token from the request header. */
getAuthHeader(): string {
const tokens = this.request.getHeader(this.headerName)
if ( Array.isArray(tokens) ) return tokens[0]
return String(tokens)
}
/** Check if the request contains a valid Firebase API token. */
public async apply() {
const token = this.getAuthHeader()

@ -5,7 +5,8 @@ import {HTTPStatus} from "@extollo/util";
/**
* ValidateEncounterTransaction Middleware
* --------------------------------------------
* Put some description here.
* Errors out the request if it is missing any fields required to create
* a new encounter transaction on the blockchain.
*/
@Injectable()
export class ValidateEncounterTransaction extends Middleware {

@ -2,5 +2,6 @@ import {Route} from "@extollo/lib"
Route.group('/api/v1', () => {
Route.post('/encounter', 'api:Blockchain.postTransaction')
.pre('DebugOnly')
.pre('api:ValidateEncounterTransaction')
})

@ -1,6 +1,5 @@
html
head
title !{locale('app_name')}
title loc-chain
body
h1 !{locale('welcome_to_extollo')}
h2 !{locale('viewed_page_num_times', { interp: { num: app_visits } })}
h1 Welcome to Loc-Chain

@ -23,6 +23,7 @@ export interface BlockInfectionTransaction {
/** Union type of all possible block transactions. */
export type BlockTransaction = BlockInfectionTransaction | BlockEncounterTransaction
/** Returns true if the item is a valid BlockEncounterTransaction. */
export function isBlockEncounterTransaction(what: any): what is BlockEncounterTransaction {
return (
what
@ -32,6 +33,7 @@ export function isBlockEncounterTransaction(what: any): what is BlockEncounterTr
)
}
/** Returns true if the item is a valid BlockInfectionTransaction. */
export function isBlockInfectionTransaction(what: any): what is BlockInfectionTransaction {
return (
what
@ -40,6 +42,7 @@ export function isBlockInfectionTransaction(what: any): what is BlockInfectionTr
)
}
/** Returns true if the item is a valid BlockTransaction. */
export function isBlockTransaction(what: any): what is BlockTransaction {
return isBlockEncounterTransaction(what) || isBlockInfectionTransaction(what)
}
@ -48,14 +51,17 @@ export function isBlockTransaction(what: any): what is BlockTransaction {
* Interface representing a single block in the chain.
*/
export interface BlockResourceItem extends FirebaseResourceItem {
uuid: string;
transactions: BlockTransaction[];
lastBlockHash: string;
lastBlockUUID: string;
proof: string;
timestamp: number;
uuid: string; // Globally unique ID
transactions: BlockTransaction[]; // Transactions validated by this block
lastBlockHash: string; // The combined sha256 hash of the previous block
lastBlockUUID: string; // the UUID of the previous block
proof: string; // the generated proof-of-work string
timestamp: number; // millisecond unix timestamp when this block was created
}
/**
* A Firebase realtime database resource for blocks in the chain.
*/
@Injectable()
export class BlockResource extends FirebaseResource<BlockResourceItem> {
public static collect(): AsyncCollection<BlockResourceItem> {

@ -7,13 +7,16 @@ import {AsyncCollection} from "@extollo/util"
* Interface representing a client-submitted encounter transaction.
*/
export interface TransactionResourceItem extends FirebaseResourceItem {
combinedHash: string;
timestamp: number;
encodedGPSLocation: string;
partnerPublicKey: string;
validationSignature: string;
combinedHash: string; // The salted and hashed combination of the client IDs
timestamp: number; // the unix-time in milliseconds when the interaction occurred
encodedGPSLocation: string; // Encoded GPS location data
partnerPublicKey: string; // The public key of the other client
validationSignature: string; // The transaction validation data
}
/**
* A Firebase realtime-database resource for managing encounter transactions.
*/
@Injectable()
export class TransactionResource extends FirebaseResource<TransactionResourceItem> {
public static collect(): AsyncCollection<TransactionResourceItem> {

@ -19,9 +19,11 @@ export class Block implements BlockResourceItem {
lastBlockHash: string
lastBlockUUID: string
proof: string
get config(): Config {
return Application.getApplication().make(Config)
}
constructor(rec: BlockResourceItem) {
this.firebaseID = rec.firebaseID
this.seqID = rec.seqID

@ -8,10 +8,13 @@ import { Blockchain } from "../Blockchain"
/**
* Transaction Unit
* ---------------------------------------
* Put some description here.
* This unit listens for transactions created on the realtime database.
* When new ones come through, it matches them up, validates them, and pushes
* them onto this server's blockchain.
*/
@Singleton()
export class Transaction extends Unit {
/** True if currently processing transactions. */
private processing: boolean = false
@Inject()
@ -23,6 +26,7 @@ export class Transaction extends Unit {
@Inject()
protected readonly logging!: Logging
/** Claim the right to process transactions. Returns true if the right was granted. */
claim() {
if ( !this.processing ) {
this.processing = true
@ -32,10 +36,17 @@ export class Transaction extends Unit {
return false
}
/** Release the right to claim transactions. */
release() {
this.processing = false
}
/**
* Given two transactions, determine whether the came from a valid interaction.
* That is, do the two transactions vouch for each-other cryptographically.
* @param transaction1
* @param transaction2
*/
public async compareTransactions(transaction1: TransactionResourceItem, transaction2: TransactionResourceItem) {
// verify signature
const result1 = await openpgp.verify({
@ -59,6 +70,9 @@ export class Transaction extends Unit {
return (await result1.signatures[0].verified) && (await result2.signatures[0].verified)
}
/**
* Subscribe to the transactions reference and wait for new transactions to be added.
*/
public async up() {
this.firebase.ref("transaction").on("child_added", async () => {
this.logging.debug('Received child_added event for transactions reference.')
@ -110,6 +124,9 @@ export class Transaction extends Unit {
})
}
/**
* Release listeners and resources before shutdown.
*/
public async down() {
// Release all subscriptions before shutdown
this.firebase.ref("transaction").off()

Loading…
Cancel
Save