Mark inline code as code, not italics

This commit is contained in:
Joe Nelson
2016-12-04 13:59:24 -08:00
parent 564c51fe79
commit 6b255e9806
4 changed files with 40 additions and 36 deletions
+8 -8
View File
@@ -50,7 +50,7 @@ db-schema
db-anon-role
The database role to use when executing commands on behalf of unauthenticated clients.
db-pool
Number of connections to keep open in PostgREST's database pool. Having enough here for the maximum expected simultaneous client connections can improve performance. Note it's pointless to set this higher than the `max_connections` GUC in your database.
Number of connections to keep open in PostgREST's database pool. Having enough here for the maximum expected simultaneous client connections can improve performance. Note it's pointless to set this higher than the :code:`max_connections` GUC in your database.
server-host
Where to bind the PostgREST web server.
server-port
@@ -58,7 +58,7 @@ server-port
server-proxy-url
Overrides the base URL used within the OpenAPI self-documentation hosted at the API root path.
jwt-secret
The secret used to decode JWT tokens clients provide for authentication. If this parameter is not specified then PostgREST refuses authentication requests. Choosing a value for this parameter beginning with the at sign such as `@filename` loads the secret out of an external file which is useful for non-UTF-8 binary secrets.
The secret used to decode JWT tokens clients provide for authentication. If this parameter is not specified then PostgREST refuses authentication requests. Choosing a value for this parameter beginning with the at sign such as :code:`@filename` loads the secret out of an external file which is useful for non-UTF-8 binary secrets.
max-rows
A hard limit to the number of rows PostgREST will fetch from a view, table, or stored procedure. Limits payload size for accidental or malicious requests.
pre-request
@@ -118,7 +118,7 @@ This does not protect against malicious actions, since someone can add a url par
Count-Header DoS
----------------
For convenience to client-side pagination controls PostgREST supports counting and reporting total table size in its response. As described in :ref:`Limits and Pagination`_, responses ordinarily include a range and unspecified total like
For convenience to client-side pagination controls PostgREST supports counting and reporting total table size in its response. As described in :ref:`Limits and Pagination`_, responses ordinarily include a range but leave the total unspecified like
.. code-block:: http
@@ -126,7 +126,7 @@ For convenience to client-side pagination controls PostgREST supports counting a
Range-Unit: items
Content-Range: 0-14/*
However including the request header `Prefer: count=exact` calculates and includes the full count:
However including the request header :code:`Prefer: count=exact` calculates and includes the full count:
.. code-block:: http
@@ -142,7 +142,7 @@ This is fine in small tables, but count performance degrades in big tables due t
.. note::
In future versions we will support `Prefer: count=estimated` to leverage the PostgreSQL statistics tables for a fast (and fairly accurate) result.
In future versions we will support :code:`Prefer: count=estimated` to leverage the PostgreSQL statistics tables for a fast (and fairly accurate) result.
.. _hardening_https:
@@ -168,9 +168,9 @@ A great way to inspect incoming HTTP requests including headers and query params
# sudo access is necessary for watching the network
sudo ngrep -d lo0 port 3000
The options to ngrep vary depending on the address and host on which you've bound the server. The binding is described in the `Configuration`_ section. The ngrep output isn't particularly pretty, but it's legible. Note the `Server` response header as well which identifies the version of server. This is important when submitting bug reports.
The options to ngrep vary depending on the address and host on which you've bound the server. The binding is described in the `Configuration`_ section. The ngrep output isn't particularly pretty, but it's legible. Note the :code:`Server` response header as well which identifies the version of server. This is important when submitting bug reports.
Once you've verified that requests are as you expect, you can get more information about the server operations by watching the database logs. By default PostgreSQL does not keep these logs, so you'll need to make the configuration changes below. Find `postgresql.conf` inside your PostgreSQL data directory (to find that, issue the command `show data_directory;`). Either find the settings scattered throughout the file and change them to the following values, or append this block of code to the end of the configuration file.
Once you've verified that requests are as you expect, you can get more information about the server operations by watching the database logs. By default PostgreSQL does not keep these logs, so you'll need to make the configuration changes below. Find :code:`postgresql.conf` inside your PostgreSQL data directory (to find that, issue the command :code:`show data_directory;`). Either find the settings scattered throughout the file and change them to the following values, or append this block of code to the end of the configuration file.
.. code:: sql
@@ -207,7 +207,7 @@ In the future we're investigating ways to keep the cache updated without manual
Alternate URL Structure
=======================
As discussed in `Singular or Plural`_, there are no special URL forms for singular resources in PostgREST, only operators for filtering. Thus there are no URLs like `/people/1`. It would be specified instead as
As discussed in `Singular or Plural`_, there are no special URL forms for singular resources in PostgREST, only operators for filtering. Thus there are no URLs like :code:`/people/1`. It would be specified instead as
.. code:: http
+12 -8
View File
@@ -1,3 +1,6 @@
.. role:: sql(code)
:language: sql
Tables and Views
================
@@ -57,13 +60,13 @@ For more complicated filters (such as those involving condition 1 OR condition 2
Vertical Filtering (Columns)
----------------------------
When certain columns are wide (such as those holding binary data), it is more efficient for the server to withold them in a response. The client can specify which columns are required using the `select` parameter.
When certain columns are wide (such as those holding binary data), it is more efficient for the server to withold them in a response. The client can specify which columns are required using the :sql:`select` parameter.
.. code-block:: http
GET /people?select=fname,age
GET /people?select=fname,age HTTP/1.1
The default is `*`, meaning all columns. This value will become more important below in :ref:`Resource Embedding`_.
The default is :sql:`*`, meaning all columns. This value will become more important below in :ref:`Resource Embedding`_.
.. _computed_cols:
@@ -96,7 +99,7 @@ A full-text search on the computed column:
Ordering
--------
The reserved word :code:`order` reorders the response rows. It uses a comma-separated list of columns and directions:
The reserved word :sql:`order` reorders the response rows. It uses a comma-separated list of columns and directions:
.. code-block:: http
@@ -201,7 +204,7 @@ The server will default to JSON for API endpoints and OpenAPI on the root.
Singular or Plural
------------------
By default PostgREST returns all JSON results in an array, even when there is only one item. For example, requesting `/items?id=eq.1` returns
By default PostgREST returns all JSON results in an array, even when there is only one item. For example, requesting :code:`/items?id=eq.1` returns
.. code:: json
@@ -312,12 +315,12 @@ The PostgREST url grammar limits the kinds of queries clients can perform. It pr
* Table unions and OR-conditions in the where clause
* More complicated joins than those provided by `Resource Embedding`_
* Geospatial queries that require an argument, like "points near (lat,lon)"
* More sophisticated full-text search than a simple use of the `@@` filter
* More sophisticated full-text search than a simple use of the :sql:`@@` filter
Stored Procedures
=================
Every stored procedure in the API-exposed database schema is accessible under the `/rpc` prefix. The API endpoint supports only POST which executes the function.
Every stored procedure in the API-exposed database schema is accessible under the :code:`/rpc` prefix. The API endpoint supports only POST which executes the function.
.. code:: http
@@ -339,9 +342,10 @@ The client can call it by posting an object like
.. code:: http
POST /rpc/add_them HTTP/1.1
{ "a": 1, "b": 2}
The keys of the object match the parameter names. Note that PostgreSQL converts parameter names to lowercase unless you quote them like `CREATE FUNCTION foo("mixedCase" text) ...`.
The keys of the object match the parameter names. Note that PostgreSQL converts parameter names to lowercase unless you quote them like :sql:`CREATE FUNCTION foo("mixedCase" text) ...`.
.. note::
+9 -9
View File
@@ -12,7 +12,7 @@ There are three types of roles used by PostgREST, the **authenticator**, **anony
.. image:: _static/security-roles.png
The authenticator should be created `NOINHERIT` and configured in the database to have very limited access. It is a chameleon whose job is to "become" other users to service authenticated HTTP requests. The picture below shows how the server handles authentication. If auth succeeds, it switches into the user role specified by the request, otherwise it switches into the anonymous role.
The authenticator should be created :code:`NOINHERIT` and configured in the database to have very limited access. It is a chameleon whose job is to "become" other users to service authenticated HTTP requests. The picture below shows how the server handles authentication. If auth succeeds, it switches into the user role specified by the request, otherwise it switches into the anonymous role.
.. image:: _static/security-anon-choice.png
@@ -46,7 +46,7 @@ PostgreSQL manages database access permissions using the concept of roles. A rol
Roles for Each Web User
~~~~~~~~~~~~~~~~~~~~~~~
PostgREST can accommodate either viewpoint. If you treat a role as a single user then the the JWT-based role switching described above does most of what you need. When an authenticated user makes a request PostgREST will switch into the role for that user, which in addition to restricting queries, is available to SQL through the `current_user` variable.
PostgREST can accommodate either viewpoint. If you treat a role as a single user then the the JWT-based role switching described above does most of what you need. When an authenticated user makes a request PostgREST will switch into the role for that user, which in addition to restricting queries, is available to SQL through the :code:`current_user` variable.
You can use row-level security to flexibly restrict visibility and access for the current user. Here is an `example <http://blog.2ndquadrant.com/application-users-vs-row-level-security/>`_ from Tomas Vondra, a chat table storing messages sent between users. Users can insert rows into it to send messages to other users, and query it to see messages sent to them by other users.
@@ -146,7 +146,7 @@ There is no performance penalty for having many database roles, although roles a
Custom Validation
-----------------
PostgREST honors the `exp` claim for token expiration, rejecting expired tokens. However it does not enforce any extra constraints. An example of an extra constraint would be to immediately revoke access for a certain user. The configuration file paramter `pre-request` specifies a stored procedure to call immediately after the authenticator switches into a new role and before the main query itself runs.
PostgREST honors the :code:`exp` claim for token expiration, rejecting expired tokens. However it does not enforce any extra constraints. An example of an extra constraint would be to immediately revoke access for a certain user. The configuration file paramter :code:`pre-request` specifies a stored procedure to call immediately after the authenticator switches into a new role and before the main query itself runs.
Here's an example. In the config file specify a stored procedure:
@@ -172,7 +172,7 @@ In the function you can run arbitrary code to check the request and raise an exc
Client Auth
===========
To make an authenticated request the client must include an `Authorization` HTTP header with the value `Bearer <jwt>`. For instance:
To make an authenticated request the client must include an :code:`Authorization` HTTP header with the value :code:`Bearer <jwt>`. For instance:
.. code:: http
@@ -241,7 +241,7 @@ Storing Users and Passwords
As mentioned, an external service can provide user management and coordinate with the PostgREST server using JWT. It's also possible to support logins entirely through SQL. It's a fair bit of work, so get ready.
The following table, functions, and triggers will live in a `basic_auth` schema that you shouldn't expose publicly in the API. The public views and functions will live in a different schema which internally references this internal information.
The following table, functions, and triggers will live in a :code:`basic_auth` schema that you shouldn't expose publicly in the API. The public views and functions will live in a different schema which internally references this internal information.
First we'll need a table to keep track of our users:
@@ -259,7 +259,7 @@ First we'll need a table to keep track of our users:
role name not null check (length(role) < 512),
);
We would like the role to be a foreign key to actual database roles, however PostgreSQL does not support these constraints against the `pg_roles` table. We'll use a trigger to manually enforce it.
We would like the role to be a foreign key to actual database roles, however PostgreSQL does not support these constraints against the :code:`pg_roles` table. We'll use a trigger to manually enforce it.
.. code:: plpgsql
@@ -283,7 +283,7 @@ We would like the role to be a foreign key to actual database roles, however Pos
for each row
execute procedure basic_auth.check_role_exists();
Next we'll use the pgcrypto extension and a trigger to keep passwords safe in the `users` table.
Next we'll use the pgcrypto extension and a trigger to keep passwords safe in the :code:`users` table.
.. code:: plpgsql
@@ -370,7 +370,7 @@ An API request to call this function would look like:
{ "email": "foo@bar.com", "pass": "foobar" }
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of `mysecret` as specified in the SQL code above. You'll want to change this secret in your app!)
The response would look like the snippet below. Try decoding the token at `jwt.io <https://jwt.io/>`_. (It was encoded with a secret of :code:`mysecret` as specified in the SQL code above. You'll want to change this secret in your app!)
.. code:: json
@@ -395,4 +395,4 @@ Your database roles need access to the schema, tables, views and functions in or
grant select on table pg_authid, basic_auth.users to anon;
grant execute on function login(text,text) to anon;
You may be worried from the above that anonymous users can read everything from the `basic_auth.users` table. However this table is not available for direct queries because it lives in a separate schema. The anonymous role needs access because the public `users` view reads the underlying table with the permissions of the calling user. But we have made sure the view properly restricts access to sensitive information.
You may be worried from the above that anonymous users can read everything from the :code:`basic_auth.users` table. However this table is not available for direct queries because it lives in a separate schema. The anonymous role needs access because the public :code:`users` view reads the underlying table with the permissions of the calling user. But we have made sure the view properly restricts access to sensitive information.
+11 -11
View File
@@ -84,7 +84,7 @@ PostgREST Test Suite
Creating the Test Database
~~~~~~~~~~~~~~~~~~~~~~~~~~
To properly run postgrest tests one needs to create a database. To do so, use the test creation script `create_test_database` in the `test/` folder.
To properly run postgrest tests one needs to create a database. To do so, use the test creation script :code:`create_test_database` in the :code:`test/` folder.
The script expects the following parameters:
@@ -94,22 +94,22 @@ The script expects the following parameters:
Use the `connection URI <https://www.postgresql.org/docs/current/static/libpq-connect.html#AEN45347>`_ to specify the user, password, host, and port. Do not provide the database in the connection URI. The Postgres role you are using to connect must be capable of creating new databases.
The `database_name` is the name of the database that `stack test` will connect to. If the database of the same name already exists on the server, the script will first drop it and then re-create it.
The :code:`database_name` is the name of the database that :code:`stack test` will connect to. If the database of the same name already exists on the server, the script will first drop it and then re-create it.
Optionally, specify the database user `stack test` will use. The user will be given necessary permissions to reset the database after every test run.
Optionally, specify the database user :code:`stack test` will use. The user will be given necessary permissions to reset the database after every test run.
If the user is not specified, the script will generate the role name `postgrest_test_` suffixed by the chosen database name, and will generate a random password for it.
If the user is not specified, the script will generate the role name :code:`postgrest_test_` suffixed by the chosen database name, and will generate a random password for it.
Optionally, if specifying an existing user to be used for the test connection, one can specify the password the user has.
The script will return the db uri to use in the tests--this uri corresponds to the `db-uri` parameter in the configuration file that one would use in production.
The script will return the db uri to use in the tests--this uri corresponds to the :code:`db-uri` parameter in the configuration file that one would use in production.
Generating the user and the password allows one to create the database and run the tests against any postgres server without any modifications to the server. (Such as allowing accounts without a passoword or setting up trust authentication, or requiring the server to be on the same localhost the tests are run from).
Running the Tests
~~~~~~~~~~~~~~~~~
To run the tests, one must supply the database uri in the environment variable `POSTGREST_TEST_CONNECTION`.
To run the tests, one must supply the database uri in the environment variable :code:`POSTGREST_TEST_CONNECTION`.
Typically, one would create the database and run the test in the same command line, using the `postgres` superuser:
@@ -132,12 +132,12 @@ If the environment variable is empty or not specified, then the test runner will
postgres://postgrest_test@localhost/postgrest_test
This connection assumes the test server on the `localhost` with the user `postgrest_test` without the password and the database of the same name.
This connection assumes the test server on the :code:`localhost:code:` with the user `postgrest_test` without the password and the database of the same name.
Destroying the Database
~~~~~~~~~~~~~~~~~~~~~~~
The test database will remain after the test, together with four new roles created on the postgres server. To permanently erase the created database and the roles, run the script `test/delete_test_database`, using the same superuser role used for creating the database:
The test database will remain after the test, together with four new roles created on the postgres server. To permanently erase the created database and the roles, run the script :code:`test/delete_test_database`, using the same superuser role used for creating the database:
.. code:: bash
@@ -155,16 +155,16 @@ For example, if local development is on a mac with Docker for Mac installed:
$ docker run --name db-scripting-test -e POSTGRES_PASSWORD=pwd -p 5434:5432 -d postgres
$ POSTGREST_TEST_CONNECTION=$(test/create_test_db "postgres://postgres:pwd@localhost:5434" test_db) stack test
Additionally, if one creates a docker container to run stack test (this is necessary on MacOS Sierra with GHC below 8.0.1, where `stack test` fails), one can run PostgreSQL in a separate linked container, or use the locally installed Postgres.app.
Additionally, if one creates a docker container to run stack test (this is necessary on MacOS Sierra with GHC below 8.0.1, where :code:`stack test` fails), one can run PostgreSQL in a separate linked container, or use the locally installed Postgres.app.
Build the test container with `test/Dockerfile.test`:
Build the test container with :code:`test/Dockerfile.test`:
.. code:: bash
$ docker build -t pgst-test - < text/Dockerfile.test
$ mkdir .stack-work-docker ~/.stack-linux
The first run of the test container will take a long time while the dependencies get cached. Creating the `~/.stack-linux` folder and mapping it as a volume into the container ensures that we can run the container in disposable mode and not worry about subsequent runs being slow. `.stack-work-docker` is also mapped into the container and must be specified when using stack from Linux, not to interfere with the `.stack-work` for local development. (On Sierra, `stack build` works, while `stack test` fails with GHC 8.0.1).
The first run of the test container will take a long time while the dependencies get cached. Creating the :code:`~/.stack-linux` folder and mapping it as a volume into the container ensures that we can run the container in disposable mode and not worry about subsequent runs being slow. :code:`.stack-work-docker` is also mapped into the container and must be specified when using stack from Linux, not to interfere with the :code:`.stack-work` for local development. (On Sierra, :code:`stack build` works, while :code:`stack test` fails with GHC 8.0.1).
Linked containers: