Browse Source

Merge pull request #485 from moxiegirl/radiks-add

Adding radiks to the docs
feat/clarity-updates
Moxiegirl 5 years ago
committed by GitHub
parent
commit
58370e6588
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      _data/navigation_learn.yml
  2. 1
      _develop/overview_auth.md
  3. 101
      _develop/radiks-collaborate.md
  4. 69
      _develop/radiks-intro.md
  5. 313
      _develop/radiks-models.md
  6. 119
      _develop/radiks-server-extras.md
  7. 212
      _develop/radiks-setup.md
  8. 4
      _develop/storage.md
  9. 2
      _develop/zero_to_dapp_2.md
  10. 2
      _develop/zero_to_dapp_2_win.md
  11. 2
      _develop/zero_to_dapp_3.md
  12. 2
      _develop/zero_to_dapp_3_win.md
  13. 18
      _includes/architecture.md
  14. 2
      _includes/commandline.md
  15. 2
      _includes/question.html
  16. 2
      _org/wallet-install.md
  17. 35
      _storage/overview.md

8
_data/navigation_learn.yml

@ -16,6 +16,14 @@
docs:
- develop/collections
- develop/collection-type
- title: Radiks data
docs:
- develop/radiks-intro
- develop/radiks-setup
- develop/radiks-models
- develop/radiks-collaborate
- develop/radiks-server-extras
- title: Try it! Zero to DApp
docs:

1
_develop/overview_auth.md

@ -4,7 +4,6 @@ permalink: /:collection/:path.html
---
# Understand Blockstack Auth
{:.no_toc}
Blockstack Auth provides single sign on and authentication without third parties or remote servers. On this page, you'll get an overview of authentication from a developer and user perspective. The following topics are covered:

101
_develop/radiks-collaborate.md

@ -0,0 +1,101 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Collaborate with groups
{:.no_toc}
A key feature of Radiks is support for private collaboration between multiple users. Supporting collaboration with client-side encryption and user-owned storage can be complicated, but the patterns to implement it are generally the same among most applications. Radiks supplies interfaces for collaboration, making it easy to build private, collaborative apps.
You use the <a href="https://github.com/blockstack/radiks/blob/master/src/models/user-group.ts" target="_blank"><code>UserGroup</code></a> class to build a collaborative group with Radiks. In this section, you learn about this class.
* TOC
{:toc}
## Understand the UserGroup workflow
The key model behind a collaborative group is `UserGroup`. By default, it only has one attribute, `name`, which is encrypted. You can subclass `UserGroup` with different attributes as needed.
The general workflow for creating a collaborative group that can share and edit encrypted models is as follows:
1. The admin of the group creates a new `UserGroup`.
This group acts as the 'hub' and controls the logic around inviting and removing users.
2. The admin invites one or more other users to a group:
* The admin specifies the username of the user they want to invite
* Radiks looks up the user's public key
* Radiks creates an 'invitation' that is encrypted with the user's public key, and contains information about the `UserGroup`
3. When the invited user 'activates' an invitation, they create a `GroupMembership`.
They use this membership instance to reference information (such as private keys and signing keys) related to the group.
As they participate in a group, the group's members can create and update models that are related to the group. These models **must** contain a `userGroupId` attribute used to reference the group. This allows Radiks to know which keys to use for encryption and signing.
When needed, the group admin can remove a user from a group. To remove a user from the group, the admin creates a new private key for signing and encryption. Then, the admin updates the `GroupMembership` of all users _except_ the user they just removed. This update-and-remove action is also known as rotating the key.
After a key is rotated, all new and updated models must use the new key for signing. Radiks-server validates all group-related models to ensure that they're signed with the most up-to-date key.
## Work with a UserGroup
This section details the methods on the <a href="https://github.com/blockstack/radiks/blob/master/src/models/user-group.ts" target="_blank"><code>UserGroup</code> class you can use to create, add members to, and query a group.
### Create a UserGroup
To create a `UserGroup`, you must import the class into your application from `radiks`:
```javascript
import { UserGroup } from 'radiks';
// ...
```
Calling `create` on a new `UserGroup` will create the group and activate an invitation for the group's creator.
```javascript
const group = new UserGroup({ name: 'My Group Name' });
await group.create();
```
A group's creator is also the group's admin.
### Invite users to become members
Use the `makeGroupMembership` method on a `UserGroup` instance to invite a user. The only argument passed to this method is the user's `username`.
```javascript
import { UserGroup } from 'radiks';
const group = await UserGroup.findById(myGroupId);
const usernameToInvite = 'hankstoever.id';
const invitation = await group.makeGroupMembership(usernameToInvite);
console.log(invitation._id); // the ID used to later activate an invitation
```
### Accept an invitation
Use the `activate` method on a `GroupInvitation` instance to activate an invitation on behalf of a user:
```javascript
import { GroupInvitation } from 'radiks';
const invitation = await GroupInvitation.findById(myInvitationID);
await invitation.activate();
```
## View all activated UserGroups for the current user
Call `UserGroup.myGroups` to fetch all groups that the current user is a member of:
```javascript
import { UserGroup } from 'radiks';
const groups = await UserGroup.myGroups();
```
## Find a UserGroup
Use the method `UserGroup.find(id)` when fetching a specific UserGroup. This method has extra boilerplate to handle decrypting the model, because the private keys may need to be fetched from different models.
```javascript
const group = await UserGroup.find('my-id-here');
```

69
_develop/radiks-intro.md

@ -0,0 +1,69 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Radiks the data indexer
The Blockstack Radiks feature enables Blockstack decentralized applications (DApps) to index and store across data belonging to multiple users. Radiks works with Blockstack's Gaia Storage System. Using Radiks, you can build multi-player DApps that:
- index, store, and query application data
- query a user's publicly saved data
- display real-time updates that reflect in progress changes
- support collaboration among sets of users
## Why use Radiks?
Many applications server data that users create to share publicly with others, Facebook, Twitter, and Instagram are examples of such applications. Decentralized applications that want to create comparable multi-user experiences must ensure that anything a user creates for public sharing is likewise still under control of the creator in the user's Gaia storage.
For example, if Twitter were a decentralized application where many different users creating their own tweets and those tweets are stored in each user's own Gaia storage. In such a situation,a developer needs a way to track of everyone's tweets, display tweets in user timelines, and perform searches across tweets. Radiks exists to support these kinds of scenarios in that it allows applications to query across multiple user data, using complicated queries like text search, joins, and filters.
Radiks allows applications to query data in a performant and flexible way. Each application that wishes to index and query in this way requires its own Radiks server.
## How Radiks works with application data
Radiks consists of a database, a pre-built server, and a client. Each application adds Radiks client library to their application. With this library a developer models their application data. The model defines an application data schema for the Radiks server. Then, you can use calls to this model to write and query data that use that schema. Whenever an application saves or updates data on behalf of a user, Radiks follows this flow:
1. Encrypts private user data on the client-side.
2. Saves a raw JSON of this encrypted data in the user's Gaia storage.
3. Stores the encrypted data on the Radiks server.
Radiks stores public data and sensitive, non-private data. Radiks encrypts sensitive data by default before the data leaves the client. Your application can query Radiks for public data and then decrypt the sensitive information on the client. This means that the Radiks server is only able to return queries for unencrypted data.
## How Radiks authorizes writes
Radiks must ensure that user's own any data they are writing. To ensure this, Radiks creates and manages *signing keys*. These keys sign all writes that a user performs. Radiks-server validates all signatures before performing a write. This guarantees that a user is not able to overwrite another user's data.
Radiks-server also is built to support writes in a collaborative but private situation. For example, consider a collaborative document editing application, where users can create organizations and invite users to that organization. All users in that organization have read and write privileges to the organization data. These organizations have a single shared key that is used to sign and encrypt data.
When an organization administrator needs to remove a user from the group, they'll revoke a previous key and create a new one. Radiks is aware of these relationships, and will only support writes that are signed with the currently active key related to an organization.
## Is Radiks decentralized
Although Radiks applications rely on a centrally-hosted database, an application using Radiks remains fundamentally decentralized. A DApp that uses Radiks has these characteristics.
<table class="uk-table">
<tr>
<td>Built on decentralized authentication</td>
<td> Radiks is deeply tied to Blockstack authentication, which uses a blockchain and Gaia to give you full control over your user data.
</tr>
<tr>
<td>No data lock-in</td>
<td><p>All user data is first stored in Gaia before encrypted with the user's keys and stored in Radiks. This process means the user still controls their data for as long as they need to. If the application's Radiks server shuts down, the user can still access their data. And, without application to the user's signing keys, the application cannot decrypt the data. Users may also backup or migrate their application data from Gaia.
</p></td>
</tr>
<tr>
<td>Censorship resistance</td>
<td><p>All data is also stored in Gaia; no third-party can revoke access to this data.
</p></td>
</tr>
<tr>
<td>Maximum privacy</td>
<td><p>All data is encrypted on the client-side before being stored anywhere using Blockstack authorization. The application host cannot inspect, sell, or use user data in any way that a user doesn't explicitly authorize.
</p></td>
</tr>
</table>
If you are not familiar with Gaia or Blockstack authentication, see
[read the Gaia documentation](({{site.baseurl}}/storage/overview.html) and [start with the overview of Blockstack auth](overview_auth.html).

313
_develop/radiks-models.md

@ -0,0 +1,313 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Create and use models
{:.no_toc}
Radiks allows you to model your client data. You can then query this data and display it for a user in multi-player applications. A social application where users want to see the comments of other users is an example of a multi-player application. This page explains how to create a model in your distributed application using Radiks.
* TOC
{:toc}
## Overview of Model class extension
Blockstack provides a `Model` class you should extend to easily create, save, and fetch models. To create a model class, import the `Model` class from `radiks` into your application.
```javascript
import { Model, User } from 'radiks';
```
Then, create a class that extends this model, and provide a schema. Refer to <a href="https://github.com/blockstack/radiks/blob/master/src/model.ts" target="_blank">the <code>Model</code> class</a> in the `radiks` repo to get an overview of the class functionality.
Your new class must define a static `className` property. This property is used when storing and querying information. If you fail to add a `className`, Radiks defaults to the actual model's class name (`foobar.ts`) and your application will behave unpredictably.
The example class code extends `Model` to create a class named `Todo`:
```javascript
import { Model, User } from 'radiks';
class Todo extends Model {
static className = 'Todo';
static schema = { // all fields are encrypted by default
title: String,
completed: Boolean,
}
};
// after authentication:
const todo = new Todo({ title: 'Use Radiks in an app' });
await todo.save();
todo.update({
completed: true,
});
await todo.save();
const incompleteTodos = await Todo.fetchOwnList({ // fetch todos that this user created
completed: false
});
console.log(incompleteTodos.length); // 0
```
## How to create your own Model
The following sections guide you through the steps in defining your own class.
### Define a class schema
Every class must have a static `schema` property which defines the attributes of a model using field/value pairs, for example:
```javascript
class Todo extends Model {
static className = 'Todo';
static schema = { // all fields are encrypted by default
title: String,
completed: Boolean,
}
};
```
The `key` in this object is the field name and the value, for example, `String`, `Boolean`, or `Number`. In this case, the `title` is a `String` field. Alternatively, you can pass options instead of a type.
To define options, pass an object, with a mandatory `type` field. The only supported option right now is `decrypted`. This defaults to `false`, meaning the field is encrypted before the data is stored publicly. If you specify `true`, then the field is not encrypted.
Storing unencrypted fields is useful if you want to be able to query the field when fetching data. A good use-case for storing decrypted fields is to store a `foreignId` that references a different model, for a "belongs-to" type of relationship.
**Never add the `decrypted` option to fields that contain sensitive user data.** Blockstack data is stored in a decentralized Gaia storage and anyone can read the user's data. That's why encrypting it is so important. If you want to filter sensitive data, then you should do it on the client-side, after decrypting it.
### Include defaults
You may want to include an optional `defaults` static property for some field values. For example, in the class below, the `likesDogs` field is a `Boolean`, and the default is `true`.
```javascript
import { Model } from 'radiks';
class Person extends Model {
static className = 'Person';
static schema = {
name: String,
age: Number,
isHuman: Boolean,
likesDogs: {
type: Boolean,
decrypted: true // all users will know if this record likes dogs!
}
}
static defaults = {
likesDogs: true
}
}
```
If you wanted to add a default for `isHuman`, you would simply add it to the `defaults` as well. Separate each field with a comma.
### Extend the User model
Radiks also supplies <a href="https://github.com/blockstack/radiks/blob/master/src/models/user.ts" target="_blank">a default <code>User</code> model</a>. You can also extend this model to add your own attributes.
```javascript
import { User } from 'radiks';
// For example I want to add a public name on my user model
class MyAppUserModel extends User {
static schema = {
...User.schema,
displayName: {
type: String,
decrypted: true,
},
};
}
```
The default `User` model defines a `username`, but you can add a `displayName` to allow the user to set unique name in your app.
## Use a model you have defined
In this section, you learn how to use a model you have defined.
### About the _id attribute
All model instances have an `_id` attribute. An `_id` is used as a primary key when storing data and is used for fetching a model. Radiks also creates a `createdAt` and `updatedAt` property when creating and saving models.
If, when constructing a model's instance, you don't pass an `_id`, Radiks creates an `_id` for you automatically. This automatically created id uses the [`uuid/v4`](https://github.com/kelektiv/node-uuid) format. This automatic `_id` is returned by the constructor.
### Construct a model instance
To create an instance, pass some attributes to the constructor of that class:
```javascript
const person = new Person({
name: 'Hank',
isHuman: false,
likesDogs: false // just an example, I love dogs!
})
```
### Fetch an instance
To fetch an existing instance of an instance, you need the instance's `id` property. Then, call the `findById()` method or the `fetch()` method, which returns a promise.
```javascript
const person = await Person.findById('404eab3a-6ddc-4ba6-afe8-1c3fff464d44');
```
After calling these methods, Radiks automatically decrypts all encrypted fields.
### Access attributes
Other than `id`, all attributes are stored in an `attrs` property on the instance.
```javascript
const { name, likesDogs } = person.attrs;
console.log(`Does ${name} like dogs?`, likesDogs);
```
### Update attributes
To quickly update multiple attributes of an instance, pass those attributes to the `update` method.
```javascript
const newAttributes = {
likesDogs: false,
age: 30
}
person.update(newAttributes)
```
Important, calling `update` does **not** save the instance.
### Save changes
To save an instance to Gaia and MongoDB, call the `save()` method, which returns a promise. This method encrypts all attributes that do not have the `decrypted` option in their schema. Then, it saves a JSON representation of the model in Gaia, as well as in the MongoDB.
```javascript
await person.save();
```
### Delete an instance
To delete an instance, just call the `destroy` method on it.
```javascript
await person.destroy();
```
## Query a model
To fetch multiple records that match a certain query, use the class's `fetchList()` function. This method creates an HTTP query to Radiks-server, which then queries the underlying database. Radiks-server uses the `query-to-mongo` package to turn an HTTP query into a MongoDB query.
Here are some examples:
```javascript
const dogHaters = await Person.fetchList({ likesDogs: false });
```
Or, imagine a `Task` model with a `name`, a boolean for `completed`, and an `order` attribute.
```javascript
class Task extends Model {
static className = 'Task';
static schema = {
name: String,
completed: {
type: Boolean,
decrypted: true,
},
order: {
type: Number,
decrypted: true,
}
}
}
const tasks = await Task.fetchList({
completed: false,
sort: '-order'
})
```
You can read the [`query-to-mongo`](https://github.com/pbatey/query-to-mongo) package documentation to learn how to do complex querying, sorting, limiting, and so forth.
## Count models
You can also get a model's `count` record directly.
```javascript
const dogHaters = await Person.count({ likesDogs: false });
// dogHaters is the count number
```
## Fetch models created by the current user
Use the `fetchOwnList` method to find instances that were created by the current user. By using this method, you can preserve privacy, because Radiks uses a `signingKey` that only the current user knows.
```javascript
const tasks = await Task.fetchOwnList({
completed: false
});
```
## Manage relational data
It is common for applications to have multiple different models, where some reference another. For example, imagine a task-tracking application where a user has multiple projects, and each project has multiple tasks. Here's what those models might look like:
```javascript
class Project extends Model {
static className = 'Project';
static schema = { name: String }
}
class Task extends Model {
static className = 'Task';
static schema = {
name: String,
projectId: {
type: String,
decrypted: true,
}
completed: Boolean
}
}
```
Whenever you save a task, you should save a reference to the project it's in:
```javascript
const task = new Task({
name: 'Improve radiks documentation',
projectId: project._id
})
await task.save();
```
Then, later you'll want to fetch all tasks for a certain project:
```javascript
const tasks = await Task.fetchList({
projectId: project._id,
})
```
Radiks lets you define an `afterFetch` method. Use this method to automatically fetch child records when you fetch the parent instance.
```javascript
class Project extends Model {
static className = 'Project';
static schema = { name: String }
async afterFetch() {
this.tasks = await Task.fetchList({
projectId: this.id,
})
}
}
const project = await Project.findById('some-id-here');
console.log(project.tasks); // will already have fetched and decrypted all related tasks
```

119
_develop/radiks-server-extras.md

@ -0,0 +1,119 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Radiks server tips and tricks
In this section, you'll find some tips and tricks you can use to work with a Radiks server.
## Access the MongoDB collection
Radiks-server keeps all models inside of a collection. You can use the `getDB` function to access this collection from inside your application.
```js
const { getDB } = require('radiks-server');
const mongo = await getDB(MONGODB_URL);
```
[See the MongoDB Collection reference](https://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html) for documentation about how you can interact with this collection.
## Run a custom Radiks-server
If you're using an [express.js](https://expressjs.com/) server to run your application, it's probably easiest to use the Radiks-server middleware. This way, you won't have to run a separate application server and Radiks server.
Radiks-server includes an easy-to-use middleware that you can include in your application:
```javascript
const express = require('express');
const { setup } = require('radiks-server');
const app = express();
setup().then(RadiksController => {
app.use('/radiks', RadiksController);
});
```
The `setup` method returns a promise, and that promise resolves to the actual middleware that your server can use. This is because it first connects to MongoDB, and then sets up the middleware with that database connection.
The `setup` function accepts an `options` object as the first argument. If you aren't using environment variables, you can explicitly pass in a MongoDB URL here:
```javascript
setup({
mongoDBUrl: 'mongodb://localhost:27017/my-custom-database',
}).then(RadiksController => {
app.use('/radiks', RadiksController);
});
```
Currently, only the `mongoDBUrl` option is supported.
## Migrate from Firebase (or anywhere else)
Migrating data from Firebase to Radiks-server is simple and painless. You can create a script file to fetch all the Firebase data using their API. Then, you can use your `MONGOD_URI` config to use the `mongodb` npm package.
```js
// Script for transfering users from Firebase to Radiks-server
const { getDB } = require('radiks-server');
const { mongoURI } = require('......'); // How you import/require your mongoURI is up to you
const migrate = async () => {
// `mongo` is a reference to the MongoDB collection that radiks-server uses.
// You can add or edit or update data as necessary.
const mongo = await getDB(mongoURI);
/**
* Call code to get your users from firebase
* const users = await getUsersFromFirebase();
* OR grab the Firebase JSON file and set users to that value
* How you saved your user data will probably be different than the example below
*/
const users = {
'-LV1HAQToANRvhysSClr': {
blockstackId: '1N1DzKgizU4rCEaxAU21EgMaHGB5hprcBM',
username: 'kkomaz.id',
},
};
const usersToInsert = Object.values(users).map(user => {
const { username } = user;
const doc = {
username,
_id: username,
radiksType: 'BlockstackUser',
};
const op = {
updateOne: {
filter: {
_id: username,
},
update: {
$setOnInsert: doc,
},
upsert: true,
},
};
return op;
});
await mongo.bulkWrite(usersToInsert);
};
migrate()
.then(() => {
console.log('Done!');
process.exit();
})
.catch(error => {
console.error(error);
process.exit();
});
```

212
_develop/radiks-setup.md

@ -0,0 +1,212 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Set-up Radiks for your DApp
{:.no_toc}
Using Radiks with your application requires a Radiks server and a client application constructed to use the server. In this article, you learn how to install, setup, and run a pre-packaged Radiks server that connects to MongoDB. You also learn how to establish your DApp application as a client for that server.
* TOC
{:toc}
## Task 1. Set up your Radiks server
Radiks-server is a `node.js` application that uses [MongoDB](https://www.mongodb.com/) as an underlying database.
### Install and configure MongoDB
In the future, Radiks-server will support various different databases, but right now, only MongoDB 3.6 or higher is supported. MongoDB 3.6 and higher contains fixes required for naming patterns in keys.
{% include note.html content="The steps assume you want to install and run the MongoDB software locally on your workstation for testing and development. If you are deploying for a production application, you will install MongoDB on your application server or on a server connected to it. " %}
1. <a href="https://docs.mongodb.com/manual/administration/install-community/" target="_blank">Download and install MongoDB 3.6 or higher</a> on your workstation.
You can also install MongoDB using your favorite package manager; for example, Homebrew is recommended for macOS. If you are testing on a local workstation, you can use a `docker` image instead of installing locally.
2. Start the MongoDB service and verify it is running.
3. On your MongoDB instance, create a database for your application data.
You can use the <a href="https://docs.mongodb.com/manual/mongo/" target="_blank">Mongo shell</a> to do this, or you can <a href="https://www.mongodb.com/download-center/compass" target="_blank">install the MongoDB Compass</a> software to explore and work with MongoDB data.
4. Create a username/password combination with `root` privileges on your new database.
### Install and start the Radiks server
The easiest way to run `radiks-server` is to use the pre-packaged `node.js` server.
1. Install the `radiks-server` on a workstation or server.
```bash
npm install -g radiks-server
```
Or, if you prefer `yarn`:
```bash
yarn global add radiks-server
```
The default port for Mongodb is `27017`; your instance may be configured differently. By default, Radiks-server will use `'MongoDB://localhost:27017/radiks-server'` as the `MongoDB_URI` value. This is suitable for local testing, but in production, you'll want to change the hostname and possibly the database name.
3. Start the `radiks-server` in the command line to confirm your installation.
```
$ radiks-server
(node:37750) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
radiks-server is ready on http://localhost:1260
```
The `radiks-server` defaults to running on port `1260`. To change the default port, specify the `PORT` environment variable in your environment.
4. By default, the server is running at `http://localhost:1260`
4. Stop the `radiks` server process after you confirm it runs, and your installation was a success.
## Task 2. Set up your application
You must set up your application to use Radiks. This requires installing the `radiks` client package and then configuring your application to connect to your Radiks server.
### Install the radiks client software
If you are using `blockstack.js` version 18 or earlier, you must use the Radiks version 0.1.\*, otherwise if you're using `blockstack.js` version 19 or higher, use Radiks 0.2.\* .
1. Change directory to the root of you application code.
2. Install the `radiks` client package.
<table class="uk-table uk-table-small">
<thead>
<tr>
<td><strong>Use npm</strong></td>
<td><strong>Use yarn</strong></td>
</tr>
</thead>
<tbody>
<tr>
<td><code class="highlighter-rouge">npm install --save radiks</code></td>
<td><code class="highlighter-rouge">yarn add radiks</code></td>
</tr>
</tbody>
</table>
### Configure the MongoDB for your application
1. Start the mongo shell application.
```
$ mongo
MongoDB shell version v4.2.0
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("8d43cf80-490d-4cac-8bd6-40eec5c128de") }
MongoDB server version: 4.2.0
....
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
>
```
2. Create a new database for your application.
```
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> use test1
switched to db test1
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> db.createUser({user: "admin", pwd:"foobar1",roles: ["readWrite","dbAdmin"]});
Successfully added user: { "user" : "admin", "roles" : [ "readWrite", "dbAdmin" ] }
```
3. Add a user with administrative rights to the database.
```
> db.createUser({user: "admin", pwd:"foobar1",roles: ["readWrite","dbAdmin"]});
Successfully added user: { "user" : "admin", "roles" : [ "readWrite", "dbAdmin" ] }
```
4. Create an `MONGODB_URI` environment variable on the same machine where you are running the `radiks-server`.
Use the `mongodb://username:password@host:port/db_name` format for your variable. For example, to set this variable in a `bash` shell:
```bash
export MONGODB_URI="mongodb://admin:foobar1@localhost:27017/test1"
```
## Task 3. Add startup code and build your application
To set up radiks.js, you only need to configure the URL that your Radiks-server instance is running on. If you're using the pre-built Radiks server, this will be `http://localhost:1260`. If you're in production or are using a custom Radiks server, you'll need to specify the exact URL where it's available.
Radiks also is compatible with version 19 of blockstack.js, which requires you to configure a `UserSession` object to handle all user-data-related methods. You'll need to define this and pass it to your Radiks configuration so that Radiks can know how to fetch information about the current logged in user.
### Configure your application to use your `radiks-server`.
To configure your application as a `radiks` client, do the following:
1. Start your application so that a `UserSession` allows the app to both write and publish data:
```js
import { UserSession, AppConfig } from 'blockstack';
import { configure } from 'radiks';
const userSession = new UserSession({
appConfig: new AppConfig(['store_write', 'publish_data'])
})
configure({
apiServer: 'http://localhost:1260',
userSession
});
```
2. Add authentication to your application
After your user logs in with Blockstack, you'll have some code to save the user's data in your applications `localStorage`. You'll want to use the same `UserSession` you configured with Radiks, which can be fetched from the `getConfig` method.
```js
import { User, getConfig } from 'radiks';
const handleSignIn = () => {
const { userSession } = getConfig();
if (userSession.isSignInPending()) {
await userSession.handlePendingSignIn();
await User.createWithCurrentUser();
}
}
```
Calling `User.createWithCurrentUser` does the following:
* Fetch user data that Blockstack.js stores in `localStorage`
* Save the user's public data (including their public key) in Radiks-server
* Find or create a signing key that is used to authorize writes on behalf of this user
* Cache the user's signing key (and any group-related signing keys) to make signatures and decryption happen quickly later on
### Build and run your application
After you have added Radiks to your application, build and run the application. Test the application by logging in with your Blockstack ID. Create some data using the application. If you inspect the MongoDB database, you should see the encrypted data stored in the database.
You can specify the `mongoDBUrl` or the `maxLimit` option when initiating the Radiks server in your application.
```javascript
const { setup } = require('radiks-server');
setup({
...myOptions,
});
```
The `mongoDBUrl` option is the MongoDB URL for the Radiks server
The `maxLimit` option is the maximum `limit` field used inside the mongo queries. The default is 1000.
## Where to go next
Creating models for your application's data is where radiks truly becomes helpful. To learn how to use models, see the [Create and use models](radiks-models.html) section.

4
_develop/storage.md

@ -14,6 +14,10 @@ The Blockstack Platform stores application data in the Gaia Storage System. Tran
{% include note.html content="<ul> <li>Blockstack Gaia Storage APIs and on-disk format will change in upcoming pre-releases breaking backward compatibility. File encryption is currently opt-in on a file by file basis.</li> <li>Certain storage features such as collections are not implemented in the current version. These features will be rolled out in future updates.</li> </ul>" %}
## How data is stored
Gaia storage is a key-value store.
## Creating a file

2
_develop/zero_to_dapp_2.md

@ -7,7 +7,7 @@ image: /assets/img/zero-to-dapp.png
# 2 - Learn about the platform
{:.no_toc}
**Zero-to-DApp 2 of 4 for MacOS/Linux (or [Windows](zero_to_dapp_2_win.html))**
**Zero-to-DApp 2 of 4 for macOS/Linux (or [Windows](zero_to_dapp_2_win.html))**
In this part, you learn how the Blockstack platform lowers the barriers to
building with blockchain technology. You'll set up all the prerequisites you

2
_develop/zero_to_dapp_2_win.md

@ -7,7 +7,7 @@ image: /assets/img/zero-to-dapp.png
# 2 - Learn about the platform (Windows)
{:.no_toc}
**Zero-to-DApp 2 of 4 for Windows (or [MacOS/Linux](zero_to_dapp_2.html))**
**Zero-to-DApp 2 of 4 for Windows (or [macOS/Linux](zero_to_dapp_2.html))**
In this part, you learn how the Blockstack platform lowers the barriers to
building with blockchain technology. You'll set up all the prerequisites you

2
_develop/zero_to_dapp_3.md

@ -7,7 +7,7 @@ image: /assets/img/zero-to-dapp.png
# 3 - Customize your kingdom
{:.no_toc}
**Zero to DAPP 3 of 4 for MacOS/Linux (or [Windows](zero_to_dapp_3_win.html))**
**Zero to DAPP 3 of 4 for macOS/Linux (or [Windows](zero_to_dapp_3_win.html))**
In this page, you examine and modify the Animal Kingdom DApp [you built in part
2](zero_to_dapp_2.html). You'll review the underlying code and locate the

2
_develop/zero_to_dapp_3_win.md

@ -7,7 +7,7 @@ image: /assets/img/zero-to-dapp.png
# 3 - Customize your kingdom (Windows)
{:.no_toc}
**Zero to DAPP 3 of 4 for Windows (or [MacOS/Linux](zero_to_dapp_3.html))**
**Zero to DAPP 3 of 4 for Windows (or [macOS/Linux](zero_to_dapp_3.html))**
In this page, you examine and modify the Animal Kingdom DApp [you built in part
2](zero_to_dapp_2.html). You'll review the underlying code and locate the

18
_includes/architecture.md

@ -3,20 +3,14 @@
Blockchains require consensus among large numbers of people, so they can be slow. Additionally, a blockchain is not designed to hold a lot of data. This means using a blockchain for every bit of data a user might write and store is expensive. For example, imagine if an application were storing every tweet in the chain.
Blockstack addresses blockchain performance problems using a layered approach. At the base of the system is a blockchain and the Blockstack Naming System (BNS). The blockchain governs ownership of names (identities) in the system, names such as domain names, usernames, and application names.
Blockstack addresses blockchain performance problems using a layered approach. The base layer consists of the Stacks blockchain and the Blockstack Naming System (BNS). The blockchain governs ownership of identities in the Blockstack network. Identities can be names such as domain names, usernames, or application names.
Names in Blockstack correspond to routing data in the OSI stack. The routing data is stored in the Atlas Peer Network, the second layer. Every core node that joins the Blockstack Network is able to obtain an entire copy of this routing data. Blockstack uses the routing data to associate names (usernames, domains, and application names) with a particular storage location.
When an identity is created, its creation is recorded in the Stacks blockchain. Identities make up the primary data stored into the Stacks blockchain. These identities correspond to routing data in the OSI stack. The routing data is stored in the Atlas Peer Network, the second layer. Every core node that joins the Blockstack Network is able to obtain an entire copy of this routing data. Blockstack uses the routing data to associate identities (domain names, user names, and application names) with a particular storage location in the final layer, the Gaia Storage System.
The final layer is the Gaia Storage System. A Gaia system consists of a _hub
service_ and storage resource on a cloud software provider such as Azure,
DigitalOcean, Amazon EC2, and so forth. Typically the compute resource and the
storage resource belong to same cloud vendor. Gaia currently has
driver support for S3 and Azure Blob Storage, but the driver model allows for
other backend support as well.
A Gaia Storage System consists of a _hub service_ and storage resource on a cloud software provider. The storage provider can be any commercial provider such as Azure, DigitalOcean, Amazon EC2, and so forth. Typically the compute resource and the storage resource reside same cloud vendor, though this is not a requirement. Gaia currently has driver support for S3 and Azure Blob Storage, but the driver model allows for other backend support as well.
Because Gaia stores application and user data off the blockchain, a Blockstack
DApp is typically more performant than DApps created on other blockchains.
Moreover, users choose where their data lives, and Gaia enables applications
to access that user data via a uniform API. When the user logs in,
Gaia stores data as a simple key-value store. When an identity is created, a corresponding data store is associated with that identity on Gaia. When a user logs into a dApp,
the authentication process gives the application the URL of a Gaia hub, which
then writes to storage on behalf of that user.
Within Blockstack, then, the Stacks blockchain stores only identity data. Data created by the actions of an identity is stored in a Gaia Storage System. Each user has profile data. When a user interacts with a decentralized dApp that application stores application data on behalf of the user. Because Gaia stores user and application data off the blockchain, a Blockstack DApp is typically more performant than DApps created on other blockchains.

2
_includes/commandline.md

@ -60,7 +60,7 @@ To see the usage and options for the command in general, enter `blockstack-cli`
## How to install the command line
{:.no_toc}
You must have [Node.js](https://nodejs.org/en/download/) v8 or higher (v10 recommended). MacOS and Linux users can avoid `sudo` or [permissions problems](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally) or by using [`nvm`](https://github.com/nvm-sh/nvm). These instructions assume you are using a macOS or Linux system.
You must have [Node.js](https://nodejs.org/en/download/) v8 or higher (v10 recommended). macOS and Linux users can avoid `sudo` or [permissions problems](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally) or by using [`nvm`](https://github.com/nvm-sh/nvm). These instructions assume you are using a macOS or Linux system.
To install the command line, do the following:

2
_includes/question.html

@ -1 +1 @@
<div class="uk-alert-danger uk-card" uk-alert><b>QUESTION FOR REVIEWERS:</b> {{include.content}}</div>
<div class="uk-alert-danger uk-card" uk-alert><b>QUESTION FOR REVIEWERS:</b> {{include.content}}</div>

2
_org/wallet-install.md

@ -21,7 +21,7 @@ by Blockstack PBC." %}
## Mac Installation
1. <a href="https://wallet.blockstack.org" target="\_blank">Go to the wallet download page</a> in your browser.
2. Select the **MacOS Download** button.
2. Select the **macOS Download** button.
This button downloads the software to your computer.

35
_storage/overview.md

@ -23,18 +23,14 @@ The following diagram depicts the Blockstack architecture and Gaia's place in it
## User control or how is Gaia decentralized?
A Gaia hub runs as a service which writes to data storage. The hub service
A Gaia hub runs as a service which writes to data storage. The storage itself is a simple key-value store. The hub service
writes to data storage by requiring a valid authentication token from a requestor. Typically, the hub service runs on a compute resource and the storage itself on separate, dedicated storage resource. Typically, both resources belong to the same cloud computing provider.
![Gaiastorage](/storage/images/gaia-storage.png)
Gaia's approach to decentralization focuses on user control of data and its
storage. If a user can choose which Gaia hub provider to use, then that choice
is all the decentralization required to enable user-controlled applications.
Gaia's approach to decentralization focuses on user control of data and its storage. Users can choose a Gaia hub provider. If a user can choose which Gaia hub provider to use, then that choice is all the decentralization required to enable user-controlled applications. Moreover, Gaia a uniform API to access for applications to access that data.
The control of user data lies in the way that user data is accessed.
When an application fetches a file `data.txt` for a given user `alice.id`, the
lookup will follow these steps:
The control of user data lies in the way that user data is accessed. When an application fetches a file `data.txt` for a given user `alice.id`, the lookup will follow these steps:
1. Fetch the `zonefile` for `alice.id`.
2. Read her profile URL from her `zonefile`.
@ -43,35 +39,18 @@ lookup will follow these steps:
5. Read the `gaiaHubUrl` (e.g. `https://gaia.alice.org/`) out of the profile
6. Fetch the file from `https://gaia.alice.org/data.txt`.
Because `alice.id` has access to her zonefile, she can change where her profile
is stored. For example, she may do this if the current profile's service or
storage is compromised. To change where her profile is stored, she changes her
Gaia hub URL to another Gaia hub URL from another hub provider. If Alice has
sufficient compute and storage resources herself, she may run her own Gaia
Storage System and bypass a commercial Gaia hub provider all together.
Because `alice.id` has access to her zonefile, she can change where her profile is stored. For example, she may do this if the current profile's service provider or storage is compromised. To change where her profile is stored, she changes her Gaia hub URL to another Gaia hub URL. If a user has sufficient compute and storage resources, a user may run their own Gaia Storage System and bypass a commercial Gaia hub provider all together.
{% include note.html content="Users with existing identities cannot yet migrate
their data from one hub to another." %}
Applications writing directly on behalf of Alice do not need to perform a
lookup. Instead, the Blockstack <a
href="http://blockstack.github.io/blockstack.js/index.html"
target="\_blank">authentication flow</a> provides Alice's chosen application
root URL to the application. This authentication flow _is also_ within Alice's
control because Alice's browser _must_ generate the authentication response.
Applications writing directly on behalf of `alice.id` do not need to perform a lookup. Instead, the Blockstack <a href="http://blockstack.github.io/blockstack.js/index.html" target="\_blank">authentication flow</a> provides Alice's chosen application root URL to the application. This authentication flow _is also_ within Alice's control because Alice's browser _must_ generate the authentication response.
## Understand data storage
A Gaia hub stores the written data _exactly_ as given. It offers minimal
guarantees about the data. It does not ensure that data is validly formatted,
contains valid signatures, or is encrypted. Rather, the design philosophy is
that these concerns are client-side concerns.
Client libraries (such as `blockstack.js`) are capable of providing these
guarantees. Blockstack used a liberal definition of the <a href="https://en.wikipedia.org/wiki/End-to-end_principle" target="\_blank">end-to-end principle</a> to
guide this design decision.
A Gaia hub stores the written data _exactly_ as given. It offers minimal guarantees about the data. It does not ensure that data is validly formatted, contains valid signatures, or is encrypted. Rather, the design philosophy is that these concerns are client-side concerns.
Client libraries (such as `blockstack.js`) are capable of providing these guarantees. Blockstack used a liberal definition of the <a href="https://en.wikipedia.org/wiki/End-to-end_principle" target="\_blank">end-to-end principle</a> to guide this design decision.
## Gaia versus other storage systems

Loading…
Cancel
Save