Skip to content

Commit

Permalink
Closes rethinkdb#77; closes rethinkdb#45
Browse files Browse the repository at this point in the history
Squashed commit of the following:

commit f39e8e5bca3393d12b6dbfa5f5072d13673dd4e4
Author: Watts Martin <[email protected]>
Date:   Wed Jun 15 16:03:18 2016 -0700

    Update embed docs with new example

commit 768597121bd2dfddb10ffaff9ad693fff7ce6553
Author: Watts Martin <[email protected]>
Date:   Wed Jun 15 15:41:24 2016 -0700

    Updates based on review

commit e8d494dd895865fcf82677d62e41f0d375e31de3
Author: Watts Martin <[email protected]>
Date:   Wed Jun 15 11:36:21 2016 -0700

    Link to docs for setting up oauth endpoints in server object

commit 83c4387a68cbcb40c151c608d95f1c647be59582
Author: Watts Martin <[email protected]>
Date:   Wed Jun 15 11:35:31 2016 -0700

    Update CLI docs; remove scaling section

commit 6683d4b2f7c41167d116426b6d2384f32278395c
Author: Watts Martin <[email protected]>
Date:   Wed Jun 15 11:35:11 2016 -0700

    Rearrange examples file

commit d512033c64850bc841b0c0134e2dc5fb64108e3a
Author: Watts Martin <[email protected]>
Date:   Wed Jun 15 11:34:47 2016 -0700

    Draft frameworks integration document (and rename file)

commit 55870a6512e4273f39ccdfb8ddab35e5bf9519f2
Author: Watts Martin <[email protected]>
Date:   Tue Jun 14 14:58:33 2016 -0700

    Document hz make-token; closes rethinkdb#45

commit fba1396d7bcca627269473685c04a28b6bbc58aa
Author: Watts Martin <[email protected]>
Date:   Tue Jun 14 14:15:50 2016 -0700

    Integration document placeholder

commit 5dddbbd223278c80946ab2ae31b9e7b8d021a702
Author: Watts Martin <[email protected]>
Date:   Tue Jun 14 14:14:33 2016 -0700

    Reorg permissions docs slightly

commit b8493a58e8e59de804292366ba2a1b4326489cde
Author: Watts Martin <[email protected]>
Date:   Tue Jun 14 14:14:10 2016 -0700

    Typo fix

commit 56b8fe32057cafd59312fcb717fe69b23800f78e
Author: Watts Martin <[email protected]>
Date:   Tue Jun 14 14:13:36 2016 -0700

    Start CLI documentation
  • Loading branch information
Watts Martin committed Jun 15, 2016
1 parent 42d405d commit ddd0519
Show file tree
Hide file tree
Showing 6 changed files with 248 additions and 27 deletions.
8 changes: 6 additions & 2 deletions authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const horizon = Horizon({ authType: 'anonymous' });

In effect, this authentication type creates a "temporary user" for use with the current session. This allows user information to be saved while that session is active, but the user has no way of reauthenticating with the same account if the token is lost. (Note that the temporary user ID is stored in the Horizon database, and must be cleaned up manually.)

# Using OAuth
# Using OAuth {#oauth}

Your application will need a client ID and "secret" for each OAuth provider you want to connect with. The providers Horizon currently supports are:

Expand All @@ -55,7 +55,7 @@ Each provider will let you register your application, and will give you the clie

## Configuring the server

In order to use OAuth with Horizon, you'll need to configure a TLS certificate so you can serve assets with HTTPS, and either specify the `--key-file` and `--cert-file` options to `hz serve` or add them to the server's `.hz/config.toml` file. (See [The config.toml file][cf] for more details.) You can create a self-signed certificate with `hz create-cert`
In order to use OAuth with Horizon, you'll need to configure a TLS certificate so you can serve assets with HTTPS, and either specify the `--key-file` and `--cert-file` options to `hz serve` or add them to the server's `.hz/config.toml` file. (See [The config.toml file][cf] for more details.) You can create a self-signed certificate with `hz create-cert`.

[cf]: /docs/configuration

Expand Down Expand Up @@ -89,6 +89,10 @@ Verify the configuration by running `hz serve` and browsing to `https://localhos

If instead you only see empty brackets (e.g., `{ }`), ensure you've restarted the Horizon server, and that it's using the `.hz/config.toml` file you've edited.

**Note:** If your application embeds Horizon rather than using `hz serve`, you'll need to pass the OAuth endpoint to that object. Read "Configuring OAuth providers" in [Embedding Horizon][eh] for details.

[eh]: /docs/embed

## Configuring the client application

Use `authType: 'token'` when initializing Horizon in your client, and then use the `authEndpoint()` command to retrieve the endpoint for your OAuth identity provider and redirect the user to that URL.
Expand Down
63 changes: 46 additions & 17 deletions server.md → cli.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,55 @@
---
layout: documentation
title: Running the Horizon server
id: server
permalink: /docs/server/
title: The Horizon CLI
id: cli
permalink: /docs/cli/
---

The `hz` command line tool's primary function is to start a standalone Horizon server. It also provides utilities for initializing a new Horizon project, creating a self-signed SSL certificate, and other tasks.

**Commands**

* Table of Contents
{:toc}

# init

Initialize a new Horizon project. `hz init` with no argument will initialize a project in the current directory; `hz init <directory>` will initialize a project in the specified directory, creating the directory if necessary. The project will be given the name of the specified directory (the current directory if no argument is given).

# serve

The `hz serve <project path>` command starts a Horizon server for the given Horizon project. Once started, it serves HTTP(S) requests for your application on the configured port.

Every Horizon server requires a RethinkDB server to connect to. Use the `--connect <RethinkDB host>` option to connect to an existing RethinkDB server, or use `--start-rethinkdb` to automatically start a local RethinkDB server.
Every Horizon server requires a RethinkDB server to connect to. Use the `--connect <RethinkDB host>` option to connect to an existing RethinkDB server, or use `--start-rethinkdb` to automatically start a local RethinkDB server. (Note that the `--dev` option for development mode includes `--start-rethinkdb` by default.)

# Command-line options {#options}
## Command-line options {#serve-options}

`hz serve` supports the following command-line options:

## General options
* `--project-name NAME, -n NAME` Name of the Horizon project. Determines the name of the RethinkDB database that stores the project data. Default: Last component of the project path
### General options

* `--project-name NAME, -n NAME` Name of the Horizon project. Determines the name of the RethinkDB database that stores the project data.
* `--serve-static [PATH]` Enable serving static files via HTTP(S). You can additionally specify the path from which static files will be served (default: `./dist`).
* `--config PATH` Which [config file][config-file] to use. Default: `.hz/config.toml`
* `--debug [yes|no]` Print additional debug output. Default: `no`

## Network options
### Network options

* `--bind HOST, -b HOST` The host name or IP address that the Horizon server should listen on for incoming requests. Can be specified multiple times to bind to multiple addresses. Default: `localhost`
* `--port PORT, -p PORT` The port number the Horizon server should listen on for incoming requests. Default: `8181`
* `--connect HOST:PORT, -c HOST:PORT` The host and port of the RethinkDB server to connect to. Default: `localhost:28015`
* `--key-file PATH` The key file to use for the HTTPS server. Default: `./horizon-key.pem`
* `--cert-file PATH` The certificate to use for the HTTPS server. Default: `./horizon-cert.pem`

## Authentication options
### Authentication options

* `--token-secret SECRET` A key string for signing JWTs. If not specified, a new random secret is used on each server start.
* `--allow-unauthenticated [yes|no]` Allow unauthenticated users. See [Authentication][auth] for details. Default: `no`
* `--allow-anonymous [yes|no]` Allow anonymous users. See [Authentication][auth] for details. Default: `no`
* `--auth PROVIDER,ID,SECRET` Enable an auth provider with the given options. E.g. `facebook,ID,SECRET`. See [Authentication][auth] for details.
* `--auth-redirect URL` The URL to redirect to upon completing authentication. Default: `/`

## Development options
### Development options

* `--dev` Runs the server in [development mode](#development-mode).
* `--secure [yes|no]` Serve websockets and files over encrypted (HTTPS) connections. Ignores the `--key-file` and `--cert-file` options if set to `no`. Default: `yes`
Expand All @@ -47,7 +62,7 @@ Every Horizon server requires a RethinkDB server to connect to. Use the `--conne
[config-file]: /docs/configuration
[permissions]: /docs/permissions

# Development mode {#development-mode}
## Development mode {#development-mode}

In development mode (`hz serve --dev`), the following flags are enabled by default:

Expand All @@ -64,14 +79,28 @@ Development mode makes it easy to run a local Horizon instance during applicatio

Development mode should never be enabled on a production server that is publicly accessible. An attacker can exploit a development server by sending unintended requests. These requests can be used to read and/or modify arbitrary data stored for your Horizon application, or can be used to exhaust the resources of your server.

# Scaling Horizon {#scaling}
# create-cert

Create a private and public TLS certificate pair for development. Running this will create two files, `horizon-cert.pem` and `horizon-key.pem`. These can be specified as options to `hz serve` or placed in the [configuration file][config-file].

Note that the certificate created by `create-cert` uses no local identity information; the data is completely random. If you need to use an existing certificate or credentials, you'll have to create the certificate on your own using `openssl` or a similar tool.

# get-schema

Extract the currently defined Horizon schema, including validation rules, collection and index specifications, as a TOML file. For an example of this command in practice, read the section on "Configuring rules" in [Permissions and schema enforcement][perm].

[perm]: /permissions/#configuring

Run `hz get-schema -h` for details on options.

# set-schema

Horizon supports horizontal scalability. You can serve the same application from multiple Horizon servers across different machines or even data centers.
Load a previously-extracted schema into a Horizon cluster. Run `hz set-schema -h` for details on options.

Servers in a Horizon cluster access a common RethinkDB cluster in order to synchronize the state of your application's state and any internal metadata.
# make-token

To serve your application from multiple machines, simply copy the static application files to each machine. Then start one Horizon server per machine, using the `--connect <RethinkDB host>` option to connect to a common RethinkDB cluster. Make sure that the `--project-name` option is identical among all servers, or they will be unable to synchronize the application state.
Manually create a JSON Web Token for a user, allowing user bootstrapping. This is necessary to log in as the Horizon admin user the first time.

See the [RethinkDB documentation][rethinkdb-scaling] on information on how to horizontally scale a RethinkDB cluster.
For more details, read "Making an admin auth token" in [Permissions and schema enforcement][admin].

[rethinkdb-scaling]: http://www.rethinkdb.com/docs/sharding-and-replication/
[admin]: /permissions/#admin
127 changes: 127 additions & 0 deletions embed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
layout: documentation
title: Embedding Horizon
id: embed
permalink: /docs/embed/
---

While you can start the Horizon server from the `hz` [command line tool][cli], it's also possible to embed it into a Node web app by importing `@horizon/server` and passing a server connection to the Horizon constructor.

[cli]: /docs/cli

For instance, using the [Express][] framework, the steps are:

[express]: http://expressjs.com

```js
#!/usr/bin/env node
'use strict'

const express = require('express');
const horizon = require('@horizon/server');

const app = express();
const http_server = app.listen(8181);
const options = { auth: { token_secret: 'my_super_secret_secret' } };
const horizon_server = horizon(http_server, options);

console.log('Listening on port 8181.');
```

Express and Horizon are required, and Express is instantiated with `app.listen()`. Then the resulting `http_server` object is passed to `horizon` along with an option object. Options that can be passed to the Horizon server constructor are identical to the similarly-named options that can be defined in the [configuration file][cf], with the same defaults:

* `project_name`
* `rdb_host`: `'localhost'`
* `rdb_port`: `28015`
* `auto_create_collection`: `false`
* `auto_create_index`: `false`
* `permissions`: `true`
* `path`: `'/horizon;`
* `auth`:
* `success_redirect`: `'/'`
* `failure_redirect`: `'/'`
* `duration`: `'1d'`
* `create_new_users`: `true`
* `new_user_group`: `'authenticated'`
* `token_secret`: `null`
* `allow_anonymous`: `false`
* `allow_unauthenticated`: `false`

**Note:** Passing options to the constructor is the only way to configure the Horizon server when it's embedded. The `.hz/config.toml` configuration file will not be read.

[cf]: /docs/configuration

For some examples with other frameworks, including Koa and Hapi, consult the Horizon [examples page][ex].

[ex]: /docs/examples

## Configuring OAuth providers

OAuth endpoints cannot be set up through the options passed to the Horizon server constructor. Instead, you'll need to use the `add_auth_provider` method on the instantiated Horizon server object.

```js
// ... initialization code as above for Express
const horizon_server = horizon(http_server, options);

horizon_server.add_auth_provider(
horizon_instance.auth.github,
{ id: 'id', secret: 'secret', path: 'github' }
);
```

For more details on setting up Oauth, read the section in [Authentication][a].

[a]: /docs/auth/#oauth

## Attaching Horizon to multiple HTTP servers

It's possible to pass a list of HTTP servers to the Horizon constructor rather than just one. Here's an example script that attaches Horizon to a public HTTPS server on port 8181 and a local HTTP server on port 8282:

```js
'use strict';
const horizon = require('@horizon/server');

const fs = require('fs');
const http = require('http');
const https = require('https');

// Attach the horizon server to two http servers
// one on [::]:8181 over HTTPS and one on 127.0.0.1:8282 over HTTP
const on_http_request = (req, res) => {
res.writeHead(404);
res.end('File not found.');
};

const public_server = https.createServer({
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
}, on_http_request);

const loopback_server = http.createServer(on_http_request);

public_server.listen(8181);
loopback_server.listen(8282, '127.0.0.1');

const horizon_server = horizon([public_server, loopback_server], {
project_name: 'foo',
auth: {
token_secret: 'bar',
allow_anonymous: true,
allow_unauthenticated: true,
},
});

// Add Twitch authentication
horizon_server.add_auth_provider(horizon.auth.twitch, {
path: 'twitch',
id: '0000000000000000000000000000000',
secret: '0000000000000000000000000000000',
});

// Shut down the server after 60 seconds
setTimeout(() => {
horizon_server.close();
public_server.close();
loopback_server.close();
}, 60000);
```
32 changes: 25 additions & 7 deletions examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,28 @@ example applications to help you get started.

<img src="https://i.imgur.com/XFostB8.gif" align="right" width="450px">

* [Horizon Repo Examples Directory](https://github.com/rethinkdb/horizon/tree/next/examples)
* [CycleJS Chat App](https://github.com/rethinkdb/horizon/tree/next/examples/cyclejs-chat-app)
* [RiotJS Chat App](https://github.com/rethinkdb/horizon/tree/next/examples/riotjs-chat-app)
* [React Chat App](https://github.com/rethinkdb/horizon/tree/next/examples/react-chat-app)
* [React TodoMVC App](https://github.com/rethinkdb/horizon/tree/next/examples/react-todo-app)
* [Vue Chat App](https://github.com/rethinkdb/horizon/tree/next/examples/vue-chat-app)
* [Vue TodoMVC App](https://github.com/rethinkdb/horizon/tree/next/examples/vue-todo-app)
* Server-side frameworks:
* [Express][e]
* [Koa][k]
* [Hapi][h]
* React:
* [Chat app][4]
* [Todo MVC app][5]
* Vue:
* [Chat app][6]
* [Todo MVC app][7]
* CycleJS:
* [Chat app][2]
* RiotJS:
* [Chat app][3]


[e]: https://github.com/rethinkdb/horizon/tree/next/examples/express-server
[k]: https://github.com/rethinkdb/horizon/tree/next/examples/koa-server
[h]: https://github.com/rethinkdb/horizon/tree/next/examples/hapi-server
[2]: https://github.com/rethinkdb/horizon/tree/next/examples/cyclejs-chat-app
[3]: https://github.com/rethinkdb/horizon/tree/next/examples/riotjs-chat-app
[4]: https://github.com/rethinkdb/horizon/tree/next/examples/react-chat-app
[5]: https://github.com/rethinkdb/horizon/tree/next/examples/react-todo-app
[6]: https://github.com/rethinkdb/horizon/tree/next/examples/vue-chat-app
[7]: https://github.com/rethinkdb/horizon/tree/next/examples/vue-todo-app
3 changes: 3 additions & 0 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ Horizon consists of three components:
* [Permissions](/docs/permissions): how Horizon's permissions and schema enforcement system works.
* [Users and groups](/docs/users/): an overview of Horizon's user management system.
* [Authentication](/docs/auth): integrating Horizon apps with Github, Twitter and other OAuth providers.
* Running the Horizon server:
* [CLI](/docs/cli): running the `hz` command line tool.
* [Embedding](/docs/embed): using Horizon with web frameworks like Express and Koa.
* [Configuration](/docs/configuration): all about the Horizon configuration file, `.hz/config.toml`.
42 changes: 41 additions & 1 deletion permissions.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ id: permissions
permalink: /docs/permissions/
---

* Table of Contents
{:toc}

# The whitelist

Horizon's permission system is based on a query whitelist. Any operation on a Horizon collection is disallowed by default, unless there is a rule that allows the operation.

A whitelist rule has three properties that define which operations it covers:
Expand All @@ -31,7 +36,6 @@ template = "collection('messages').anyWrite()"
These rules would allow users in the `authenticated` group complete read and write access to the "messages" collection. Much finer-grained control is possible; read on for more information.
</div>


For example the following rule allows authenticated users to read their own messages from the `messages` collection:

```toml
Expand Down Expand Up @@ -350,3 +354,39 @@ validator = """
```

While there is no single rule that validates all results of the query, for each result there now is a matching rule for which the validator function passes.

# Making an admin auth token {#admin}

To log in as the admin user initially, your application will need to be bootstrapped using the [hz make-token](/cli/#make-token) command.

From the directory of your Horizon application, stop the server if it's running. (If you haven't run it yet, you'll need to initialize the database; the easiest way to do that is to start in development mode with `hz serve --dev`, then stop the server.) Then run:

```sh
hz make-token admin
```

A JSON Web Token will be printed to the console. Copy that token, and create a Horizon object with it:

```js
var horizon = Horizon({
authType: {
token: "<token>",
storeLocally: false
}
});
horizon.connect();
```

(The `storeLocally` option controls whether the token should be preserved in the browser's local storage area; if you set it to `true`, you'll remain logged in as the admin from this browser.)

The `make-token` command can be used to create a token for any user that exists in Horizon's user database. If you wished to manually create a token for a user with the ID value of '4C720BD1-2729-46BA-9213-ED84DEDE3120`, you can create the user first:

```js
horizon('users').store({id: '4C720BD1-2729-46BA-9213-ED84DEDE3120'});
```

And then get the token from the command line:

```sh
hz make-token 4C720BD1-2729-46BA-9213-ED84DEDE3120
```

0 comments on commit ddd0519

Please sign in to comment.