-
Notifications
You must be signed in to change notification settings - Fork 3
Javascript API
WARNING: preliminary specification draft, work-in-progress, subject to breaking changes.
The CryptoBox API can be conceptually split in
- an access control API, provided by the
Cryptoboxesinterface, - and a reactive I/O API, provided by the
CryptoBoxinterface.
-
cryptoboxmodule -
Cryptoboxesinterface -
CryptoBoxinterface-
CryptoBox.read()method -
CryptoBox.write()method -
CryptoBox.channel()method -
CryptoBox.info()method
-
import { Observable } from 'rxjs/Observable'
import cb from 'cryptobox'
const CRYPTOBOXES = cb({
url: 'cryptobox.mydomain.com/admin',
agent: 'user agent identifier'
})
// called when user submits signup form with verified passphrase
function onSignup (credentials) {
CRYPTOBOXES.create(credentials)
.then(cb => {
console.log('registration pending email verification')
console.log('identification string: ', CRYPTOBOXES.info().id)
})
.catch(err => console.log(err))
}
// called when user submits login form
function onLogin (credentials) {
CRYPTOBOXES.access(credentials)
.then(cb => {
if (cb.info().secret) { // first login from new agent
console.log('new agent pending authorization')
console.log('agent identification string: ', CRYPTOBOXES.info().id)
console.log('authorization secret: ', cb.info().secret)
} else { // successfully logged in
cb.read(Observable.of({})) // empty range => fetch all docs
.subscribe(docs => console.log(docs))
}
})
.catch(err => console.log(err))
}The default import of the cryptobox module is a function
that takes a global configuration object argument
and returns an object instance of the Cryptoboxes Interface.
The supplied configuration object defines the URL of the cryptobox server API
and the identification string of the calling user agent.
Other properties of the configuration object are TBD.
require('cryptobox')(config: object, deps: object): Cryptoboxesmandatory factory configuration object, with the following mandatory properties:
-
url: stringURL of the cryptobox administration server API. Protocol defaults tohttpswhich is the only accepted possibility.
the config object may also include the following optional properties:
-
agent: stringidentification string of the calling user agent. defaults to a user agent signature based on available web APIs, or to a random UUID. - TBD. eg. alternate PouchDB instance, prefix for PouchDB database names, sync options, email service, delay for automatic logout, API version string, etc.
optional object for injecting the following dependencies: TBD
An object instance that implements the Cryptoboxes interface.
-
invalid argumentwhen the config object is missing or not of type {url: string, agent: string}.
import cb from 'cryptobox'
const CRYPTOBOXES = cb({
url: 'cryptobox.mydomain.com/admin',
agent: 'user agent identifier'
})The Cryptoboxes interface provides control access methods to
- create new
CryptoBoxinstances:Cryptoboxes.create(), - retrieve existing
CryptoBoxinstances:Cryptoboxes.access().
The Cryptoboxes interface also includes an info() method
which returns a copy of the configuration data it was created with.
Implementations of the Cryptoboxes interface transparently manage
the administration server API:
- for creating a new cryptobox account,
- for accessing an existing cryptobox for the first time from a new user agent.
These procedures specifically require two successive calls to this interface:
-
Cryptoboxes.create()orCryptoboxes.access(): the first method call respectively requests a new account or authorization of a new user agent, -
Cryptoboxes.access(): the second method call eventually retrieves the requested cryptobox and should be called after successful email verification (new account) or user agent authorization.
If the user agent is already registered and authorized for access to the user account, then only the second call is required to retrieve the corresponding cryptobox.
Access control is managed exclusively through the Cryptoboxes methods,
which invariably require valid credentials
to return a CryptoBox instance.
Regardless of successful authentication with valid credentials,
returned CryptoBox instances can nonetheless eventually be locked,
i.e. their methods systematically raise an UNAUTHORIZED error:
- when the
CryptoBoxis pending email verification or user agent authorization, - when access authorization has automatically expired.
The only way to refresh authorization and unlock a CryptoBox instance
is by eventually calling the Cryptoboxes.access() method anew,
e.g. after successful user agent authorization.
Cryptoboxes instances may be considered immutable.
Signup for a new account with the administration server API for the given credentials and return a cryptobox pending email verification.
A CryptoBox pending email verification is locked,
i.e. its methods systematically raise an UNAUTHORIZED error.
It can be unlocked by calling Cryptoboxes.access()
with the same credentials once the email has been successfully verified.
This method requires network access to the cryptobox administration server API.
Cryptoboxes.create(credentials: object, options?: object): Promise<CryptoBox>The credentials object should include the following properties:
-
id: stringthe user's id, e.g. email -
secret: stringthe user's secret passphrase. the passphrase should be verified before calling this method, i.e. it would typically have to be entered twice by the user.
ignored in the current version of the API.
if the Promise resolves successfully,
the returned CryptoBox is pending email verification and locked.
-
UNAUTHORIZEDif a valid account already exists for the given email. NETWORK_ERROR
CRYPTOBOXES.create(credentials)
.then(cb => {
console.log('registration pending email verification')
console.log('identification string: ', CRYPTOBOXES.info().id)
})
.catch(err => console.log(err))return an existing CryptoBox for the given email.
- if this is the first access from the calling user agent,
i.e. the user agent has not yet been authorized,
the returned
CryptoBoxis pending authorization from an authorized user agent. - otherwise, if online, a connection is automatically set up with the corresponding couchDB instance, and replication is initiated.
When the returned CryptoBox is pending authorization, it is locked,
i.e. its methods raise an UNAUTHORIZED error.
It can be unlocked by calling Cryptoboxes.access() again
with the same credentials once the calling user agent
has been successfully authorized.
This method only requires network access to the cryptobox administration server API upon first access from a new user agent not yet authorized.
Cryptoboxes.access(credentials: object, options?: object): Promise<CryptoBox>The credentials object should include the following properties:
-
id: stringthe user's id, e.g. email -
secret: stringthe user's secret passphrase.
ignored in the current version of the API.
-
CRYPTOBOX_NOT_FOUND_ERRORif no valid cryptobox account exists for the given email, or if the given credentials are not valid. NETWORK_ERROR
CRYPTOBOXES.access(credentials)
.then(cb => {
if (cb.info().secret) { // first login from new agent
console.log('new agent pending authorization')
console.log('agent identification string: ', CRYPTOBOXES.info().id)
console.log('authorization secret: ', cb.info().secret)
} else { // successfully logged in
cb.read(Observable.of({})) // empty range => fetch all docs
.subscribe(docs => console.log(docs))
}
})
.catch(err => console.log(err))an immutable copy of the configuration data the Cryptoboxes instance was created with.
Cryptoboxes.config: { url: string, agent: string }none
a copy of the configuration data the Cryptoboxes instance was created with.
The CryptoBox interface primarily provides reactive I/O methods
to read and write data from/to implementing instances.
-
CryptoBox.read()method -
CryptoBox.write()method -
CryptoBox.channel()method // 'info', 'changes' -
CryptoBox.info()method // shorthand for channel('info').getValue()
Reactively fetch documents from the CryptoBox,
i.e. this method is a reactive operator that takes an Observable sequence
of document references as input,
and outputs a corresponding Observable sequence of documents,
similar to a through stream that maps an input stream to an output stream.
A document reference can be an individual reference or a set of references, which are any of the following:
- a document
_idstring, - a reference object with
_idand_revstrings, - a range object with
firstand/orlast_idstring,
By default, for document references that do not specify a _rev string,
_rev defaults to the current revision of the referenced document.
This method raises an UNAUTHORIZED error when the CryptoBox is locked.
CryptoBox.read(refs: Observable<Ref|Set<Ref>>, options?: object): Observable<Doc|Set<Doc>>an Observable sequence of individual Ref instances
or of collections of Ref instances.
a Ref object is either a _id string,
or a reference object with both an _id and a _rev string,
or a range object with a first and last _id string.
ignored in the current version of the API.
an Observable sequence of individual Doc instances
or of collections of Doc instances,
as referenced by the input Observable sequence.
the returned revision of each document defaults to the current revision
if not specified by the input reference.
-
INVALID_REFERENCEwhen the inputObservablesupplies an element that is not aRefinstance or a collection ofRefinstances -
UNAUTHORIZEDwhen theCryptoboxis locked
retrieve all documents
cb.read(Observable.of({})) // empty range => fetch all docs
.subscribe(docs => console.log(docs))Reactively store documents into the CryptoBox,
i.e. this method is a reactive operator that takes an Observable sequence
of documents as input,
and outputs a corresponding Observable sequence of document references
of the successfully stored documents,
similar to a through stream that maps an input stream to an output stream.
The output document references are the reference objects
with _id and _rev strings of the successfully stored documents,
and/or error objects for the documents that could not be stored.
_id UUID strings are automatically generated for Doc objects
that do not have an _id property.
This method raises an UNAUTHORIZED error when the CryptoBox is locked.
CryptoBox.write(docs: Observable<Doc|Set<Doc>>, options?: object): Observable<Res|Set<Res>>an Observable sequence of individual Doc instances
or of collections of Doc instances.
_id UUID strings are automatically generated for Doc objects
that do not have an _id property.
ignored in the current version of the API.
an Observable sequence of individual Res instances
or of collections of Res instances.
a Res object is either a reference object
with _id and _rev strings of the successfully stored document,
or an error object if the document could not be stored.
-
UNAUTHORIZEDwhen theCryptoboxis locked -
UNSUCCESSFULwhen some documents could not be successfully stored
delete all documents
cb.write(cb
.read(Observable.of({})) // empty range => fetch all docs
.map(docs => docs.map(doc => {
doc._delete = true
return doc
}))
)
.subscribe(res => console.log(res))CryptoBox.channel():CryptoBox.():Copyright 2016 Stephane M. Catala
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and Limitations under the License.