Skip to content

Commit

Permalink
Basic rest implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Ocean15 committed Jan 25, 2018
1 parent a437c7e commit 8d7a91f
Show file tree
Hide file tree
Showing 11 changed files with 597 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .meteor/packages
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ [email protected] # ECMAScript 5 compatibility for older browsers
[email protected] # Enable ECMAScript2015+ syntax in app code
[email protected] # Server-side component of the `meteor shell` command

[email protected] # Publish all data to the clients (for prototyping)
planettraining:material-design-icons-font
react-meteor-data
nimble:restivus
accounts-password
alanning:roles
2 changes: 1 addition & 1 deletion .meteor/versions
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[email protected]
[email protected]
alanning:[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
## REST API

List of REST API Calls
List of REST API Calls for the version 1

### Authentification

You need a valide token for some of the REST calls. Get the token with:

* Url: ``/api/login``
* Url: ``/api/v1/login``
* Parameter:
+ ``username`` - Authentification Username
+ ``password`` - Authentification Password
Expand All @@ -31,7 +31,7 @@ X-User-Id: 8BxFMSZAc7Ez2iiR6

Create SOI
* Auth Required: yes
* Url: ``/api/soi``
* Url: ``/api/v1/soi``
* Parameter:
+ ``recipient`` - Email recipient
+ ``sender`` - Email sender
Expand Down
168 changes: 168 additions & 0 deletions imports/api/namecoin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import { randomBytes } from 'crypto';
import namecoin from "namecoin";
import secp256k1 from 'secp256k1';
import CryptoJS from 'crypto-js';
import Base58 from 'bs58';
import bitcore from 'bitcore-lib';
import Message from 'bitcore-message';

const NAMESPACE = 'e/';
const VERSION_BYTE = '34';
const NETWORK = bitcore.Networks.add({
name: 'namecoin',
alias: 'namecoin',
pubkeyhash: 0x34,
privatekey: 0xB4,
scripthash: 13,
networkMagic: 0xf9beb4fe,
});
const CLIENT = new namecoin.Client({
host: '192.168.99.100',
port: 18332,
user: 'test',
pass: 'test'
});

Meteor.methods({
'getBlockCount'() {
let syncFunc = Meteor.wrapAsync(getBlockCount);
let count;
try {
count = syncFunc();
} catch(error) {
if(error.message.startsWith('connect ETIMEDOUT')) throw new Meteor.Error("Timeout")
else throw error;
}
return count;
},
'getKeys'() {
let privateKey
do {privateKey = randomBytes(32)} while(!secp256k1.privateKeyVerify(privateKey))
let publicKey = secp256k1.publicKeyCreate(privateKey);
let address = getAddress(publicKey);
return {
privateKey: privateKey.toString('hex').toUpperCase(),
publicKey: publicKey.toString('hex').toUpperCase(),
address: address
}
},
'signMessage'(privateKey, message) {
check(privateKey, String);
check(message, String);
let privKey;
try {
privKey = new bitcore.PrivateKey(privateKey);
} catch(error) {throw new Meteor.Error("Invalid private key")}
return Message(message).sign(privKey);
},
'verifySignature'(publicKey, message, signature) {
check(publicKey, String);
check(message, String);
check(signature, String);
let pubKey;
try {
pubKey = new bitcore.PublicKey(publicKey)
} catch(error) {throw new Meteor.Error("Invalid public key")}
let address = bitcore.Address.fromPublicKey(pubKey, NETWORK);
let valid;
try {
valid = Message(message).verify(address, signature);
} catch(error) {throw new Meteor.Error("Invalid signature")}
return valid
},
'getHash'(params) {
check(params, Array);
let string = "";
params.forEach((e) => {
string += e;
})
return CryptoJS.SHA256(string).toString();
},
'nameNew'(hash) {
check(hash, String);
let id = NAMESPACE+hash;
let syncFunc = Meteor.wrapAsync(nameShow);
let nameFound = true;
try {
let result = syncFunc(id);
} catch(error) {
if(error.message.startsWith('connect ETIMEDOUT')) throw new Meteor.Error("Timeout")
if(error.message.startsWith('name not found')) nameFound = false;
else throw error;
}
if(nameFound) throw new Meteor.Error("Already in blockchain")
syncFunc = Meteor.wrapAsync(nameNew);
let result
try {
result = syncFunc(id);
} catch(error) {
if(error.message.startsWith('connect ETIMEDOUT')) throw new Meteor.Error("Timeout")
else throw error;
}
return result;
},
'nameFirstUpdate'(hash, signature, dataHash, rand, tx) {
check(hash, String);
check(signature, String);
check(dataHash, String);
check(rand, String);
check(tx, String);
let id = NAMESPACE+hash;
let value = "{signature: '"+signature+"', data_hash: '"+dataHash+"'}";
let syncFunc = Meteor.wrapAsync(nameFirstUpdate);
let result
try {
result = syncFunc(id, rand, tx, value);
} catch(error) {
if(error.message.startsWith('connect ETIMEDOUT')) throw new Meteor.Error("Timeout")
else throw error;
}
return result;
}
});

function getAddress(publicKey) {
let key = CryptoJS.SHA256(byteArrayToWordArray(publicKey));
key = CryptoJS.RIPEMD160(key);
let address = new Buffer((VERSION_BYTE+key.toString()), 'hex');
key = CryptoJS.SHA256(byteArrayToWordArray(address));
key = CryptoJS.SHA256(key);
let checksum = key.toString().substring(0, 8);
address = new Buffer(address.toString('hex')+checksum,'hex');
address = Base58.encode(address);
return address;
}

function nameFirstUpdate(id, rand, tx, value, callback) {
CLIENT.cmd('name_firstupdate', id, rand, tx, value, function(err, result) {
callback(err, result);
});
}

function nameNew(id, callback) {
CLIENT.cmd('name_new', id, function(err, result) {
callback(err, result);
});
}

function nameShow(id, callback) {
CLIENT.cmd('name_show', id, function(err, balance) {
callback(err, balance);
});
}

function getBlockCount(callback) {
CLIENT.cmd('getblockcount', function(err, count) {
callback(err, count);
});
}

function byteArrayToWordArray(ba) {
let wa = [], i;
for(i = 0; i < ba.length; i++) {
wa[(i / 4) | 0] |= ba[i] << (24 - 8 * i);
}
return CryptoJS.lib.WordArray.create(wa, ba.length);
}
28 changes: 28 additions & 0 deletions imports/api/recipients.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Meteor } from 'meteor/meteor';
import { Accounts } from "meteor/accounts-base"
import { Mongo } from 'meteor/mongo';
import { check } from 'meteor/check';

export const Recipients = new Mongo.Collection('recipients');

Recipients.deny({
insert() { return true; },
update() { return true; },
remove() { return true; },
});

Meteor.methods({
'recipients.insert'(email) {
check(email, String);

if(!this.userId) {
throw new Meteor.Error('not-authorized');
}


/*Recipients.insert({
email,
createdAt: new Date(),
});*/
}
});
36 changes: 28 additions & 8 deletions imports/api/rest.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
import { Recipients } from '../api/recipients.js';
import { Sois } from './sois.js';

var Api = new Restivus({
apiPath: 'api/',
version: 'v1',
useDefaultAuth: true,
prettyJson: true
});

Api.addRoute('sois', {authRequired: true}, {
post: {
authRequired: true,
roleRequired: ['admin'],
action: () => {
var query = this.queryParams;
console.log(query);
}
post: {
authRequired: true,
roleRequired: ['admin'],
action: function() {
let params = this.queryParams;
if(params.recipient && params.sender) {
let recipient = getRecipient(params.recipient);
console.log(recipient);
return {status: 'success', data: {message: 'SOI added'}};
} else return {
statusCode: 422,
body: {status: 'fail', message: 'Wrong parameters. Parameters: recipient, sender [, data_json]'}
};
}
});
}
});

function getRecipient(email) {
let recipient = Recipients.findOne({email: email});
if(!recipient) {
console.log(this.userId);
Meteor.call('recipients.insert', email);
}
return recipient;
}
7 changes: 7 additions & 0 deletions imports/api/sois.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import { check } from 'meteor/check';

export const Sois = new Mongo.Collection('sois');

if(Meteor.isServer) {
Meteor.publish('sois', function soisPublication() {
if(this.userId) return Sois.find();
else this.ready();
});
}

Meteor.methods({
'sois.insert'(recipient, sender, data_json) {
check(recipient, String);
Expand Down
11 changes: 8 additions & 3 deletions imports/ui/App.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React, { Component } from 'react';

import { withTracker } from 'meteor/react-meteor-data';
import { Sois } from '../api/sois.js';
import { Sois } from '../api/sois.js'
import Login from './Login.js';
import Soi from './Soi.js';

class App extends Component {

renderSois() {
return (
<ul>
Expand All @@ -17,6 +15,10 @@ class App extends Component {
);
}

componentDidMount() {
Meteor.call('recipients.insert', 'email');
}

render() {
return (
<div className="container">
Expand All @@ -31,7 +33,10 @@ class App extends Component {
}

export default withTracker(() => {
Meteor.subscribe('sois');
console.log(Meteor.users);
return {
users: Meteor.users,
sois: Sois.find({}).fetch(),
currentUser: Meteor.user(),
};
Expand Down
Loading

0 comments on commit 8d7a91f

Please sign in to comment.