1
0
Fork 0

Added req.cookie and res.cookie helper methods to Foxx.

This commit is contained in:
Alan Plum 2014-09-04 21:27:09 +02:00
parent 39ba358cd8
commit 251e046929
2 changed files with 149 additions and 41 deletions

View File

@ -32,13 +32,13 @@
!SECTION Documenting and constraining a specific route
If you now want to document your route, you can use JSDoc style comments (a
multiline comment block with the first line starting with */*** instead
If you now want to document your route, you can use JSDoc style comments (a
multiline comment block with the first line starting with */*** instead
of */**) above your routes to do that:
```js
/** Get all foxxes
*
*
* If you want to get all foxxes, please use this
* method to do that.
*/
@ -47,11 +47,11 @@ app.get("/foxxes", function () {
});
```
The first line will be treated as a summary (For optical reasons in the
produced documentation, the summary is restricted to 60 characters). All
following lines will be treated as additional notes shown in the detailed
view of the route documentation. With the provided information, Foxx will
generate a nice documentation for you. Furthermore you can describe your
The first line will be treated as a summary (For optical reasons in the
produced documentation, the summary is restricted to 60 characters). All
following lines will be treated as additional notes shown in the detailed
view of the route documentation. With the provided information, Foxx will
generate a nice documentation for you. Furthermore you can describe your
API by chaining the following methods onto your path definition:
!SUBSECTION Path Param
@ -77,7 +77,7 @@ API by chaining the following methods onto your path definition:
!SUBSECTION onlyIfAuthenticated
<!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContext_onlyIfAuthenticated
!SECTION Documenting and constraining all routes
In addition to documenting a specific route, you can also
@ -97,12 +97,12 @@ The following methods are available.
<!-- js/server/modules/org/arangodb/foxx/request_context.js -->
@startDocuBlock JSF_foxx_RequestContextBuffer_onlyIfAuthenticated
!SECTION Before and After Hooks
You can use the following two functions to do something before or respectively
after the normal routing process is happening. You could use that for logging
or to manipulate the request or response (translate it to a certain format for
You can use the following two functions to do something before or respectively
after the normal routing process is happening. You could use that for logging
or to manipulate the request or response (translate it to a certain format for
example).
!SUBSECTION Before
@ -120,14 +120,14 @@ example).
!SECTION The Request and Response Objects
When you have created your FoxxController you can now define routes on it.
You provide each with a function that will handle the request. It gets two
When you have created your FoxxController you can now define routes on it.
You provide each with a function that will handle the request. It gets two
arguments (four, to be honest. But the other two are not relevant for now):
* The *request* object
* The *response* object
These objects are provided by the underlying ArangoDB actions and enhanced
These objects are provided by the underlying ArangoDB actions and enhanced
by the *BaseMiddleware* provided by Foxx.
!SUBSECTION The Request Object
@ -136,7 +136,7 @@ The *request* object inherits several attributes from the underlying Actions:
* *compatibility*: an integer specifying the compatibility version sent by the
client (in request header *x-arango-version*). If the client does not send this
header, ArangoDB will set this to the minimum compatible version number. The
header, ArangoDB will set this to the minimum compatible version number. The
value is 10000 * major + 100 * minor (e.g. *10400* for ArangoDB version 1.4).
* *user*: the name of the current ArangoDB user. This will be populated only
@ -145,17 +145,17 @@ The *request* object inherits several attributes from the underlying Actions:
* *database*: the name of the current database (e.g. *_system*)
* *protocol*: *http* or *https*
* *server*: a JSON object with sub-attributes *address* (containing server
* *server*: a JSON object with sub-attributes *address* (containing server
host name or IP address) and *port* (server port).
* *path*: request URI path, with potential [database name](../Glossary/README.html#database_name) stripped off.
* *url*: request URI path + query string, with potential database name
* *url*: request URI path + query string, with potential database name
stripped off
* *headers*: a JSON object with the request headers as key/value pairs
* *cookies*: a JSON object with the request cookies as key/value pairs
* *requestType*: the request method (e.g. "GET", "POST", "PUT", ...)
@ -183,6 +183,10 @@ convenience methods:
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_params
!SUBSECTION Cookie
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_request_cookie
!SECTION The Response Object
@ -202,41 +206,45 @@ You provide your response body as a string here.
!SUBSECTION Response Json
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_response_json
!SUBSECTION Response Cookie
<!-- js/server/modules/org/arangodb/foxx/base_middleware.js -->
@startDocuBlock JSF_foxx_BaseMiddleware_response_cookie
!SECTION Controlling Access to Foxx Applications
Access to Foxx applications is controlled by the regular authentication mechanisms
Access to Foxx applications is controlled by the regular authentication mechanisms
present in ArangoDB. The server can be run with or without HTTP authentication.
If authentication is turned on,
then every access to the server is authenticated via HTTP authentication. This
includes Foxx applications. The global authentication can be toggled
If authentication is turned on,
then every access to the server is authenticated via HTTP authentication. This
includes Foxx applications. The global authentication can be toggled
via the configuration option.
If global HTTP authentication is turned on, requests to Foxx applications will
If global HTTP authentication is turned on, requests to Foxx applications will
require HTTP authentication too, and only valid users present in the *_users*
system collection are allowed to use the applications.
Since ArangoDB 1.4, there is an extra option to restrict the authentication to
just system API calls, such as */_api/...* and */_admin/...*. This option can be
turned on using the
"server.authenticate-system-only" configuration option. If it is turned on,
then only system API requests need authentication whereas all requests to Foxx
applications and routes will not require authentication.
Since ArangoDB 1.4, there is an extra option to restrict the authentication to
just system API calls, such as */_api/...* and */_admin/...*. This option can be
turned on using the
"server.authenticate-system-only" configuration option. If it is turned on,
then only system API requests need authentication whereas all requests to Foxx
applications and routes will not require authentication.
This is recommended if you want to disable HTTP authentication for Foxx applications
but still want the general database APIs to be protected with HTTP authentication.
If you need more fine grained control over the access to your Foxx application,
we built an authentication system you can use. Currently we only support cookie-based
authentication, but we will add the possibility to use Auth Tokens and external OAuth
we built an authentication system you can use. Currently we only support cookie-based
authentication, but we will add the possibility to use Auth Tokens and external OAuth
providers in the near future. Of course you can roll your own authentication mechanism
if you want to, and you can do it in an application-specific way if required.
To use the per-application authentication, you should first turn off the global
HTTP authentication (or at least restrict it to system API calls as mentioned above).
HTTP authentication (or at least restrict it to system API calls as mentioned above).
Otherwise clients will need HTTP authentication and need additional authentication by
your Foxx application.
your Foxx application.
To have global HTTP authentication turned on for system APIs but turned off for Foxx,
your server startup parameters should look like this:
@ -246,13 +254,13 @@ your server startup parameters should look like this:
**Note**: During development, you may even turn off HTTP authentication completely:
--server.disable-authentication true --server.authenticate-system-only true
Please keep in mind that turning HTTP authentication off completely will allow
Please keep in mind that turning HTTP authentication off completely will allow
unauthenticated access by anyone to all API functions, so do not use this is production.
Now it's time to configure the application-specific authentication. We built a small
Now it's time to configure the application-specific authentication. We built a small
[demo application](https://github.com/arangodb/foxx-authentication) to demonstrate how
this works.
this works.
To use the application-specific authentication in your own app, first activate it in your controller.

View File

@ -45,10 +45,61 @@ BaseMiddleware = function () {
trace,
_ = require("underscore"),
console = require("console"),
crypto = require("org/arangodb/crypto"),
actions = require("org/arangodb/actions");
requestFunctions = {
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_BaseMiddleware_request_cookie
///
/// `request.cookie(name, cfg)`
///
/// Read a cookie from the request. Optionally the cookie's signature can be verified.
///
/// *Parameter*
///
/// * *name*: the name of the cookie to read from the request.
/// * *cfg* (optional): an object with any of the following properties:
/// * *signed* (optional): an object with any of the following properties:
/// * *secret*: a secret string that was used to sign the cookie.
/// * *algorithm*: hashing algorithm that was used to sign the cookie. Default: *"sha256"*.
///
/// If *signed* is a string, it will be used as the *secret* instead.
///
/// If a *secret* is provided, a second cookie with the name *name + ".sig"* will
/// be read and its value will be verified as the cookie value's signature.
///
/// If the cookie is not set or its signature is invalid, "undefined" will be returned instead.
///
/// @EXAMPLES
///
/// ```
/// var sid = request.cookie("sid", {signed: "keyboardcat"});
/// ```
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
cookie: function (name, cfg) {
if (!cfg || typeof cfg !== 'object') {
cfg = {};
}
var value = this.cookies[name] || undefined;
if (value && cfg.signed) {
if (typeof cfg.signed === 'string') {
cfg.signed = {secret: cfg.signed};
}
var valid = crypto.constantEquals(
this.cookies[name + '.sig'] || '',
crypto.hmac(cfg.signed.secret, value, cfg.signed.algorithm)
);
if (!valid) {
value = undefined;
}
}
return value;
},
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_BaseMiddleware_request_body
///
@ -102,6 +153,55 @@ BaseMiddleware = function () {
responseFunctions = {
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_BaseMiddleware_response_cookie
///
/// `response.cookie(name, value, cfg)`
///
/// Add a cookie to the response. Optionally the cookie can be signed.
///
/// *Parameter*
///
/// * *name*: the name of the cookie to add to the response.
/// * *value*: the value of the cookie to add to the response.
/// * *cfg* (optional): an object with any of the following properties:
/// * *ttl* (optional): the number of seconds until this cookie expires.
/// * *path* (optional): the cookie path.
/// * *domain* (optional): the cookie domain.
/// * *secure* (optional): mark the cookie as safe transport (HTTPS) only.
/// * *httpOnly* (optional): mark the cookie as HTTP(S) only.
/// * *signed* (optional): an object with any of the following properties:
/// * *secret*: a secret string to sign the cookie with.
/// * *algorithm*: hashing algorithm to sign the cookie with. Default: *"sha256"*.
///
/// If *signed* is a string, it will be used as the *secret* instead.
///
/// If a *secret* is provided, a second cookie with the name *name + ".sig"* will
/// be added to the response, containing the cookie's HMAC signature.
///
/// @EXAMPLES
///
/// ```
/// response.cookie("sid", "abcdef", {signed: "keyboardcat"});
/// ```
/// @endDocuBlock
////////////////////////////////////////////////////////////////////////////////
cookie: function (name, value, cfg) {
if (!cfg || typeof cfg !== 'object') {
cfg = {ttl: cfg};
}
var ttl = (typeof cfg.ttl === 'number' && cfg.ttl !== Infinity) ? cfg.ttl : undefined;
actions.addCookie(this, name, value, ttl, cfg.path, cfg.domain, cfg.secure, cfg.httpOnly);
if (cfg.signed) {
if (typeof cfg.signed === 'string') {
cfg.signed = {secret: cfg.signed};
}
var sig = crypto.hmac(cfg.signed.secret, value, cfg.signed.algorithm);
actions.addCookie(this, name + '.sig', sig, ttl, cfg.path, cfg.domain, cfg.secure, cfg.httpOnly);
}
},
////////////////////////////////////////////////////////////////////////////////
/// @startDocuBlock JSF_foxx_BaseMiddleware_response_status
///