Skip to content
This repository has been archived by the owner on Oct 21, 2020. It is now read-only.

Commit

Permalink
feat(wallet): require wallet authentication
Browse files Browse the repository at this point in the history
- Authenticate node communication using Authorization header.
- Require wallet password to authenticate wallet.
- Begin saving user-specified wallet and account identifiers.
  • Loading branch information
devinus committed Feb 9, 2018
1 parent 57cabcc commit cbc7533
Show file tree
Hide file tree
Showing 22 changed files with 871 additions and 642 deletions.
12 changes: 12 additions & 0 deletions app/account/model.js
@@ -1,13 +1,25 @@
import DS from 'ember-data';
import { get } from '@ember/object';

import { service } from 'ember-decorators/service';

import { attr, hasMany, belongsTo } from 'ember-decorators/data';

export default DS.Model.extend({
@service settings: null,

@belongsTo() wallet: null,

@hasMany({ async: true, inverse: 'source' }) blocks: null,
@hasMany({ async: true, inverse: 'source' }) history: null,

@attr('big-number') balance: null,
@attr('big-number') pending: null,

toString() {
const id = this.get('id');
const wallet = this.get('wallet.id');
const settings = this.get('settings');
return get(settings, `wallets.${wallet}.accounts.${id}.label`) || id;
},
});
28 changes: 18 additions & 10 deletions app/ajax/service.js
@@ -1,7 +1,9 @@
import { get } from '@ember/object';

import AjaxService from 'ember-ajax/services/ajax';

import { service } from 'ember-decorators/service';
import { readOnly } from 'ember-decorators/object';
import { computed, readOnly } from 'ember-decorators/object';
import { alias } from 'ember-decorators/object/computed';

import { task } from 'ember-concurrency';
Expand All @@ -10,6 +12,7 @@ import retryWithBackoff from 'ember-backoff/retry-with-backoff';

export default AjaxService.extend({
@service session: null,
@service electron: null,
@service hostManager: null,

@readOnly
Expand All @@ -20,15 +23,20 @@ export default AjaxService.extend({

contentType: 'application/json',

// @computed('session.data.authenticated.wallet')
// get headers() {
// const headers = {};
// const wallet = this.get('session.data.authenticated.wallet');
// if (wallet) {
// headers.Authorization = `Bearer ${wallet}`;
// }
// return headers;
// },
@computed('electron.isElectron')
get headers() {
const headers = {};
const electron = this.get('electron');
const isElectron = get(electron, 'isElectron');
if (isElectron) {
const token = electron.authorizationToken();
if (token) {
headers.Authorization = `Bearer ${token}`;
}
}

return headers;
},

requestTask: task(function* requestTask(fn, ...args) {
const promise = fn.apply(this, args);
Expand Down
2 changes: 1 addition & 1 deletion app/components/account-overview/template.hbs
@@ -1,7 +1,7 @@
<div class="card-group">
<div class="card">
<h5 class="card-header text-center text-truncate">
{{account.id}}
{{account}}
</h5>

<div class="card-body">
Expand Down
4 changes: 4 additions & 0 deletions app/electron/service.js
Expand Up @@ -73,6 +73,10 @@ export default Service.extend(Evented, {
return this.getRemoteGlobal('isNodeStarted', false);
},

authorizationToken() {
return this.getRemoteGlobal('authorizationToken', null);
},

download(asset) {
return new Promise((resolve) => {
const config = this.get('config');
Expand Down
21 changes: 8 additions & 13 deletions app/settings/service.js
@@ -1,18 +1,13 @@
import Service from '@ember/service';
import { get, set } from '@ember/object';
import ObjectProxy from '@ember/object/proxy';

import { storageFor } from 'ember-local-storage';

export default Service.extend({
settings: storageFor('settings'),

unknownProperty(keyName) {
const settings = get(this, 'settings');
return get(settings, keyName);
},
const Service = ObjectProxy.extend({
content: storageFor('settings'),
});

setUnknownProperty(keyName, value) {
const settings = get(this, 'settings');
return set(settings, keyName, value);
},
Service.reopenClass({
isServiceFactory: true,
});

export default Service;
4 changes: 3 additions & 1 deletion app/settings/storage.js
Expand Up @@ -4,7 +4,9 @@ const Storage = StorageObject.extend();

Storage.reopenClass({
initialState() {
return {};
return {
wallets: {},
};
},
});

Expand Down
10 changes: 10 additions & 0 deletions app/wallet/model.js
@@ -1,11 +1,21 @@
import DS from 'ember-data';
import { get } from '@ember/object';

import { service } from 'ember-decorators/service';
import { attr, hasMany } from 'ember-decorators/data';

export default DS.Model.extend({
@service settings: null,

@hasMany('account', { async: true }) accounts: null,

@attr('big-number') balance: null,
@attr('big-number') pending: null,
@attr seed: null,

toString() {
const id = this.get('id');
const settings = this.get('settings');
return get(settings, `wallets.${id}.label`) || id;
},
});
16 changes: 16 additions & 0 deletions app/wallets/accounts/route.js
@@ -1,16 +1,32 @@
import Route from '@ember/routing/route';
import { get } from '@ember/object';

import { service } from 'ember-decorators/service';
import { computed } from 'ember-decorators/object';

import { storageFor } from 'ember-local-storage';

export default Route.extend({
@service intl: null,

settings: storageFor('settings'),

@computed('intl.locale')
get breadCrumb() {
return {
title: this.get('intl').t('account'),
path: 'wallets.accounts',
};
},

async afterModel(model) {
const wallet = await get(model, 'wallet.id');
const account = get(model, 'id');
const settings = this.get('settings');
const settingsKey = `wallets.${wallet}.accounts.${account}`;
const accountSettings = get(settings, settingsKey);
if (!accountSettings) {
settings.set(settingsKey, { label: null });
}
},
});
2 changes: 1 addition & 1 deletion app/wallets/accounts/send/route.js
Expand Up @@ -34,6 +34,6 @@ export default Route.extend({
async sendAmount(changeset) {
await changeset.save();
const account = this.modelFor('wallets.accounts');
return this.transitionTo('wallets.accounts', account);
return this.transitionTo('wallets.accounts.history', account.reload());
},
});
20 changes: 19 additions & 1 deletion app/wallets/route.js
@@ -1,5 +1,23 @@
import Route from '@ember/routing/route';
import { get } from '@ember/object';

import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Route.extend(AuthenticatedRouteMixin);
import { storageFor } from 'ember-local-storage';

export default Route.extend(AuthenticatedRouteMixin, {
settings: storageFor('settings'),

async afterModel(model) {
const wallet = get(model, 'id');
const settings = this.get('settings');
const settingsKey = `wallets.${wallet}`;
const walletSettings = get(settings, settingsKey);
if (!walletSettings) {
settings.set(settingsKey, {
label: null,
accounts: {},
});
}
},
});
11 changes: 8 additions & 3 deletions config/environment.js
Expand Up @@ -20,6 +20,7 @@ module.exports = (environment) => {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
// 'ember-improved-instrumentation': true,
},
EXTEND_PROTOTYPES: false,
},
Expand All @@ -29,20 +30,24 @@ module.exports = (environment) => {
// when it is created
},

'ember-service-worker': {
enabled: environment === 'production',
},

flashMessageDefaults: {
preventDuplicates: true,
},

assets: {
node: {
darwin: {
url: 'http://localhost:8080/node.zip',
integrity: 'sha512-9CxTuXbbrpqtOBnCNS5/8cNT9KhBAtxmLqGamMu4TtYhWyS1gL00DLcV0RXizpHpXGVgrQ5L9o8lrxTQTLwt0g==',
url: 'https://devinus.ngrok.io/node.zip',
integrity: 'sha512-0FmIl3YkwW1l12ld0MBjVusuqt9ktBALtVODhE5qWdpLV9l5ptEHTd7y3XnowfAeqw4QqFnrMNj4iOX152YBBw==',
},
},
data: {
darwin: {
url: 'http://localhost:8080/data.zip',
url: 'https://devinus.ngrok.io/data.zip',
integrity: 'sha512-gsda0segATDiX6Cxk4g/mXqj3e+OIKNEL1dbVDJoFn0bbx4ZOQL9qC0I0ynh1xyHT23VuyqCcONhP3w0upnfeg==',
},
},
Expand Down
26 changes: 21 additions & 5 deletions ember-electron/main.js
Expand Up @@ -2,12 +2,15 @@
/* eslint-disable no-console */
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const { spawn } = require('child_process');

const debounceFn = require('debounce-fn');
const ssri = require('ssri');
const decompress = require('decompress');
const debounceFn = require('debounce-fn');
const pathExists = require('path-exists');
const ssri = require('ssri');
const loadJsonFile = require('load-json-file');
const writeJsonFile = require('write-json-file');

const {
app,
Expand All @@ -27,6 +30,8 @@ const { default: installExtension, EMBER_INSPECTOR } = require('electron-devtool

let mainWindow = null;

global.isNodeStarted = false;

// Registering a protocol & schema to serve our Ember application
protocol.registerStandardSchemes(['serve'], { secure: true });
protocolServe({
Expand Down Expand Up @@ -120,17 +125,28 @@ const run = async () => {
await appReady;

const dataPath = path.resolve(app.getPath('userData'));
global.isNodeStarted = false;
const configPath = path.join(dataPath, 'config.json');
const configExists = await pathExists(configPath);
if (!configExists) {
const config = await loadJsonFile(path.join(__dirname, 'config.json'));
config.rpc.authorization_token = crypto.randomBytes(20).toString('hex');
await writeJsonFile(configPath, config);
}

const config = await loadJsonFile(configPath);
global.authorizationToken = config.rpc.authorization_token;

const nodePath = path.join(dataPath, 'rai_node');
Object.defineProperty(global, 'isNodeDownloaded', {
get() {
return pathExists.sync(path.join(dataPath, 'rai_node'));
return pathExists.sync(nodePath);
},
});

const databasePath = path.join(dataPath, 'data.ldb');
Object.defineProperty(global, 'isDataDownloaded', {
get() {
return pathExists.sync(path.join(dataPath, 'data.ldb'));
return pathExists.sync(databasePath);
},
});

Expand Down
14 changes: 0 additions & 14 deletions ember-electron/metadata.json

This file was deleted.

0 comments on commit cbc7533

Please sign in to comment.