Skip to content

Commit

Permalink
Initial implementation. Fixes tozny#1
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Mann committed Oct 11, 2017
1 parent e6a8fbd commit c4368b8
Show file tree
Hide file tree
Showing 27 changed files with 2,490 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["es2015"]
}
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
root = true

[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
coverage
lib/__tests__
examples
dist
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
coverage
dist
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
semi: false
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
language: node_js
node_js:
- 7
- 6
- 4
after_script: 'cat ./coverage/lcov.info | coveralls'
9 changes: 9 additions & 0 deletions .yo-rc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"generator-node": {
"promptValues": {
"authorName": "Eric Mann",
"authorEmail": "[email protected]",
"authorUrl": "https://tozny.com"
}
}
}
167 changes: 167 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
[![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![NPM version][npm-image]][npm-url] [![Dependency Status][daviddm-image]][daviddm-url]

# Introduction

The Tozny End-to-End Encrypted Database (E3DB) is a storage platform with powerful sharing and consent management features.
[Read more on our blog.](https://tozny.com/blog/announcing-project-e3db-the-end-to-end-encrypted-database/)

E3DB provides a familiar JSON-based NoSQL-style API for reading, writing, and querying data stored securely in the cloud.

# Installation

## NPM

To install with NPM add the following to your `package.json` file:

```
"dependencies": {
"e3db": "1.0.0"
}
```

Then run `npm install`

Alternatively, run:

```
$ npm install --save e3db
```

NPM will automatically amend your `package.json` file for you with the latest package version.

## Registering a client

Register an account with [InnoVault](https://inoovault.io) to get started. From the Admin Console you can create clients directly (and grab their credentials from the console) or create registration tokens to dynamically create clients with `e3db.Client.register()`. Clients registered from within the console will automatically back their credentials up to your account. Clients created dynamically via the SDK can _optionally_ back their credentials up to your account.

For a more complete walkthrough, see [`/examples/registration.js`](https://github.com/tozny/e3db-js/blob/master/examples/registration.js).

### Without Credential Backup

```js
const e3db = require('e3db')

let token = '...'
let clientName = '...'

let [publicKey] = e3db.Client.generateKeypair()
e3db.Client.register(token, clientName, publicKey)
.then(clientInfo => {
// ... Run operations with the client's details here
})
```

The object returned from the server contains the client's UUID, API key, and API secret (as well as echos back the public key passed during registration). It's your responsibility to store this information locally as it _will not be recoverable_ without credential backup.

### With Credential Backup

```js
const e3db = require('e3db')

let token = '...'
let clientName = '...'

let [publicKey, privateKey] = e3db.Client.generateKeypair()
e3db.Client.register(token, clientName, publicKey, privateKey, true)
.then(clientInfo => {
// ... Run operations with the client's details here
})
```

The private key must be passed to the registration handler when backing up credentials as it is used to cryptographically sign the encrypted backup file stored on the server. The private key never leaves the system, and the stored credentials will only be accessible to the newly-registered client itself or the account with which it is registered.

## Loading configuration and creating a client

Configuration is managed at runtime by instantiating an `e3db.Config` object with your client's credentials.

```js
const e3db = require('e3db')

/**
* Assuming your credentials are stored as defined constants in the
* application, pass them each into the configuration constructor as
* follows:
*/
let config = new e3db.Config(
process.env.CLIENT_ID,
process.env.API_KEY_ID,
process.env.API_SECRET,
process.env.PUBLIC_KEY,
process.env.PRIVATE_KEY,
process.env.API_URL
)

/**
* Pass the configuration when building a new client instance.
*/
let client = new e3db.Client(config)
```

# Usage

## Writing a record

To write new records to the database, call the `e3db.Client::write` method with a string describing the type of data to be written, along with an associative array containing the fields of the record. `e3db.Client::write` returns the newly created record.

```js
const e3db = require('e3db')

let client = new e3db.Client(/* config */)

client.write('contact', {
'first_name': 'Jon',
'last_name': 'Snow',
'phone': '555-555-1212',
}).then(record => {
console.log('Wrote record ' + record.meta.recordId)
})
```

## Querying records

E3DB supports many options for querying records based on the fields stored in record metadata. Refer to the API documentation for the complete set of options that can be passed to `e3db.Client::query`.

For example, to list all records of type `contact` and print a simple report containing names and phone numbers:

```js
const e3db = require('e3db')

let client = new e3db.Client(/* config */)

let data = true
let writer = null
let record = null
let type = 'contact'

client.query(data, writer, record, type).next()
.then(records => {
let fullName = record.data.first_name + ' ' + record.data.last_name
console.log(fullName + ' --- ' + record.data.phone)
})
```

In this example, the `e3db.Client::query` method returns an array that contains each record that matches the query.

## More examples

See [the simple example code](https://github.com/tozny/e3db-js/blob/master/examples/simple.js) for runnable detailed examples.

## Documentation

General E3DB documentation is [on our web site](https://tozny.com/documentation/e3db/).

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/tozny/e3db-js.

## License

This library is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

[npm-image]: https://badge.fury.io/js/e3db.svg
[npm-url]: https://npmjs.org/package/e3db
[travis-image]: https://travis-ci.org/tozny/e3db-js.svg?branch=master
[travis-url]: https://travis-ci.org/tozny/e3db-js
[coveralls-image]: https://coveralls.io/repos/github/tozny/e3db-js/badge.svg?branch=master
[coveralls-url]: https://coveralls.io/github/tozny/e3db-js
[daviddm-image]: https://david-dm.org/tozny/e3db-js.svg?theme=shields.io
[daviddm-url]: https://david-dm.org/tozny/e3db-js
85 changes: 85 additions & 0 deletions examples/registration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* This program provides a simple example illustrating how to programmatically
* register a client with InnoVault and e3db. In some situations, it's preferable
* to register a client from the server or system that will be using its
* credentials (to ensure that all data is truly encrypted from end-to-end
* with no possibilities of a credential leak). For more detailed information,
* please see the documentation home page: https://tozny.com/documentation/e3db
*
* @author Eric Mann ([email protected])
* @copyright Copyright (c) 2017 Tozny, LLC
* @license Public Domain
*/

const e3db = require('../dist/index.js')

async function main() {
/**
* ---------------------------------------------------------
* Initialization
* ---------------------------------------------------------
*/

// A registration token is required to set up a client. In this situation,
// we assume an environment variable called REGISTRATION_TOKEN is set
let token = process.env.REGISTRATION_TOKEN

// Clients can either create new cryptographic keypairs, or load in a pre-defined
// pair of Curve25519 keys. In this situation, we will generate a new keypair.
let [publicKey, privateKey] = e3db.Client.generateKeypair();

console.log('Public Key: ' + publicKey)
console.log('Private Key: ' + privateKey)

// Clients must be registered with a name unique to your account to help
// differentiate between different sets of credentials in the Admin Console.
// In this example, the name is set at random
let clientName = 'example_client_' + Math.random().toString(36).substr(2)

console.log('Client Name: ' + clientName)

// Passing all of the data above into the registration routine will create
// a new client with the system. Remember to keep your private key private!
let clientInfo = await e3db.Client.register(token, clientName, publicKey)

// Optionally, you can automatically back up the credentials of the newly-created
// client to your InnoVault account (accessible via https://console.tozny.com) by
// passing your private key and a backup flag when registering. The private key is
// not sent anywhere, but is used by the newly-created client to sign an encrypted
// copy of its credentials that is itself stored in e3db for later use.
//
// Client credentials are not backed up by default.

// let clientInfo = await e3db.Client.register(token, clientName, wrappedKey, privateKey, true)

console.log('Client ID: ' + clientInfo.clientId)
console.log('API Key ID: ' + clientInfo.apiKeyId)
console.log('API Secret: ' + clientInfo.apiSecret)

/**
* ---------------------------------------------------------
* Usage
* ---------------------------------------------------------
*/

// Once the client is registered, you can use it immediately to create the
// configuration used to instantiate a Client that can communicate with
// e3db directly.

let config = new e3db.Config(
clientInfo.clientId,
clientInfo.apiKeyId,
clientInfo.apiSecret,
publicKey,
privateKey
)

// Now create a client using that configuration.
let client = new e3db.Client(config)

// From this point on, the new client can be used as any other client to read
// write, delete, and query for records. See the `simple.js` documentation
// for more complete examples ...
}

main()
Loading

0 comments on commit c4368b8

Please sign in to comment.