ArangoDB v2.8 reached End of Life (EOL) and is no longer supported.

This documentation is outdated. Please see the most recent version here: Try latest

Details on Controller

Create


new Controller(applicationContext, options)
This creates a new Controller. The first argument is the controller context available in the variable applicationContext. The second one is an options array with the following attributes:

  • urlPrefix: All routes you define within will be prefixed with it.

Examples

app = new Controller(applicationContext, {
  urlPrefix: "/meadow"
});


HTTP Methods

get


Controller.get(path, callback)
Defines a new route on path that handles requests from the HTTP verb get. This route can also be ‘parameterized’ like /goose/:barn. In this case you can later get the value the user provided for barn via the params function in the request. The function defined in callback will be invoked whenever this type of request is recieved. callback get’s two arguments request and response, see below for further information about these objects.

Examples

app.get('/goose/barn', function (req, res) {
  // Take this request and deal with it!
});



Controller.head(path, callback)
Defines a new route on path that handles requests from the HTTP verb head. This route can also be ‘parameterized’ like /goose/:barn. In this case you can later get the value the user provided for barn via the params function in the request. The function defined in callback will be invoked whenever this type of request is recieved. callback get’s two arguments request and response, see below for further information about these objects.

Examples

app.head('/goose/barn', function (req, res) {
  // Take this request and deal with it!
});


post


Controller.post(path, callback)
Defines a new route on path that handles requests from the HTTP verb post. This route can also be ‘parameterized’ like /goose/:barn. In this case you can later get the value the user provided for barn via the params function in the request. The function defined in callback will be invoked whenever this type of request is recieved. callback get’s two arguments request and response, see below for further information about these objects.

Examples

app.post('/goose/barn', function (req, res) {
  // Take this request and deal with it!
});


put


Controller.put(path, callback)
Defines a new route on path that handles requests from the HTTP verb put. This route can also be ‘parameterized’ like /goose/:barn. In this case you can later get the value the user provided for barn via the params function in the request. The function defined in callback will be invoked whenever this type of request is recieved. callback get’s two arguments request and response, see below for further information about these objects.

Examples

app.put('/goose/barn', function (req, res) {
  // Take this request and deal with it!
});


patch


Controller.patch(path, callback)
Defines a new route on path that handles requests from the HTTP verb patch. This route can also be ‘parameterized’ like /goose/:barn. In this case you can later get the value the user provided for barn via the params function in the request. The function defined in callback will be invoked whenever this type of request is recieved. callback get’s two arguments request and response, see below for further information about these objects.

Examples

app.patch('/goose/barn', function (req, res) {
  // Take this request and deal with it!
});


delete


Controller.delete(path, callback)
Defines a new route on path that handles requests from the HTTP verb delete. This route can also be ‘parameterized’ like /goose/:barn. In this case you can later get the value the user provided for barn via the params function in the request. The function defined in callback will be invoked whenever this type of request is recieved. callback get’s two arguments request and response, see below for further information about these objects.

Examples

app.delete('/goose/barn', function (req, res) {
  // Take this request and deal with it!
});


Documenting and constraining a specific route

If you now want to document your route, you can use JSDoc style comments (a multi-line comment block where the first line starts with /** instead of /*) above your routes to do that:

/** Get all foxxes
  *
  * If you want to get all foxxes, please use this
  * method to do that.
  */
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 API by chaining the following methods onto your path definition:

pathParam


Route.pathParam(id, options)
If you defined a route “/foxx/:name”, containing a parameter called name you can constrain which format this parameter is allowed to have. This format is defined using joi in the options parameter. Using this function will at first allow you to access this parameter in your route handler using req.params(id), will reject any request having a paramter that does not match the joi definition and creates a documentation for this parameter in ArangoDBs WebInterface.
For more information on joi see the official Joi documentation.
Parameter

  • id: name of the param.
  • options: a joi schema or an object with the following properties:
    • type: a joi schema.
    • description: documentation description for the parameter.
    • required (optional): whether the parameter is required. Default: determined by type.
      Examples
      app.get("/foxx/:name", function {
      // Do something
      }).pathParam("name", joi.string().required().description("Name of the Foxx"));
      


      You can also pass in a configuration object instead:

      app.get("/foxx/:name", function {
      // Do something
      }).pathParam("name", {
      type: joi.string(),
      required: true,
      description: "Name of the Foxx"
      });
      

queryParam


Route.queryParam(id, options)
Describe a query parameter:
If you defined a route “/foxx”, you can allow a query paramter with the name id on it and constrain the format of this parameter by giving it a joi type in the options parameter. Using this function will at first allow you to access this parameter in your route handler using req.params(id), will reject any request having a paramter that does not match the joi definition and creates a documentation for this parameter in ArangoDBs WebInterface.
For more information on joi see the official Joi documentation.
You can also provide a description of this parameter and whether you can provide the parameter multiple times.
Parameter

  • id: name of the parameter
  • options: a joi schema or an object with the following properties:
    • type: a joi schema
    • description: documentation description for this param.
    • required (optional): whether the param is required. Default: determined by type.
    • allowMultiple (optional): whether the param can be specified more than once. Default: false.
      Examples
      app.get("/foxx", function {
      // Do something
      }).queryParam("id",
      joi.string()
      .required()
      .description("Id of the Foxx")
      .meta({allowMultiple: false})
      });
      


      You can also pass in a configuration object instead:

      app.get("/foxx", function {
      // Do something
      }).queryParam("id", {
      type: joi.string().required().description("Id of the Foxx"),
      allowMultiple: false
      });
      

bodyParam


Route.bodyParam(paramName, options)
Defines that this route expects a JSON body when requested and binds it to a pseudo parameter with the name paramName. The body can than be read in the the handler using req.params(paramName) on the request object. In the options parameter you can define how a valid request body should look like. This definition can be done in two ways, either using joi directly. Accessing the body in this case will give you a JSON object. The other way is to use a Foxx Model. Accessing the body in this case will give you an instance of this Model. For both ways an entry for the body will be added in the Documentation in ArangoDBs WebInterface. For information about how to annotate your models, see the Model section. All requests sending a body that does not match the validation given this way will automatically be rejected.
You can also wrap the definition into an array, in this case this route expects a body of type array containing arbitrary many valid objects. Accessing the body parameter will then of course return an array of objects.
Note: The behavior of bodyParam changes depending on the rootElement option set in the manifest. If it is set to true, it is expected that the body is an object with a key of the same name as the paramName argument. The value of this object is either a single object or in the case of a multi element an array of objects.
Parameter

  • paramName: name of the body parameter in req.parameters.
  • options: a joi schema or an object with the following properties:
  • description: the documentation description of the request body.
  • type: the Foxx model or joi schema to use.
  • allowInvalid (optional): true if validation should be skipped. (Default: false)
    Examples
    app.post("/foxx", function (req, res) {
      var foxxBody = req.parameters.foxxBody;
      // Do something with foxxBody
    }).bodyParam("foxxBody", {
      description: "Body of the Foxx",
      type: FoxxBodyModel
    });
    


    Using a joi schema:

    app.post("/foxx", function (req, res) {
      var joiBody = req.parameters.joiBody;
      // Do something with the number
    }).bodyParam("joiBody", {
      type: joi.number().integer().min(5),
      description: "A number greater than five",
      allowInvalid: false // default
    });
    


    Shorthand version:

    app.post("/foxx", function (req, res) {
      var joiBody = req.parameters.joiBody;
      // Do something with the number
    }).bodyParam(
      "joiBody",
      joi.number().integer().min(5)
      .description("A number greater than five")
      .meta({allowInvalid: false}) // default
    );
    

errorResponse


Route.errorResponse(errorClassOrName, code, description, [callback])
Define a reaction to a thrown error for this route: If your handler throws an error of the errorClass defined in errorClassOrName or the error has an attribute name equal to errorClassOrName, it will be caught and the response object will be filled with the given status code and a JSON with error set to your description as the body.
If you want more control over the returned JSON, you can give an optional fourth parameter in form of a function. It gets the error as an argument, the return value will be transformed into JSON and then be used as the body. The status code will be used as described above. The description will be used for the documentation.
It also adds documentation for this error response to the generated documentation.
Examples

/* define our own error type, FoxxyError */
var FoxxyError = function (message) {
  this.name = "FError";
  this.message = "the following FoxxyError occurred: " + message;
};
FoxxyError.prototype = new Error();
<br />
app.get("/foxx", function {
  /* throws a FoxxyError */
  throw new FoxxyError();
}).errorResponse(FoxxyError, 303, "This went completely wrong. Sorry!");
<br />
app.get("/foxx", function {
  throw new FoxxyError("oops!");
}).errorResponse("FError", 303, "This went completely wrong. Sorry!", function (e) {
  return {
    code: 123,
    desc: e.message
  };
});

onlyif


Route.onlyIf(check)
This functionality is used to secure a route by applying a checking function on the request beforehand, for example the check authorization. It expects check to be a function that takes the request object as first parameter. This function is executed before the actual handler is invoked. If check throws an error the actual handler will not be invoked. Remember to provide an errorResponse on the route as well to define the behavior in this case.
Examples

app.get("/foxx", function {
  // Do something
}).onlyIf(aFunction).errorResponse(ErrorClass, 303, "This went completely wrong. Sorry!");

onlyIfAuthenticated


FoxxController#onlyIfAuthenticated(code, reason)
Please activate sessions for this app if you want to use this function. Or activate authentication (deprecated). If the user is logged in, it will do nothing. Otherwise it will respond with the status code and the reason you provided (the route handler won’t be called). This will also add the according documentation for this route.
Examples

app.get("/foxx", function {
  // Do something
}).onlyIfAuthenticated(401, "You need to be authenticated");

summary


Route.summary(description)
Set the summary for this route in the documentation. Can’t be longer than 8192 characters. This is equal to using JavaDoc style comments right above your function. If you provide both comment and summary() the call to summary() wins and will be used.
Examples
Version with comment:

/** Short description
  * 
  * Longer description
  * with multiple lines
  */
app.get("/foxx", function() {
});


is identical to:

app.get("/foxx", function() {
})
.summary("Short description")
.notes(["Longer description", "with multiple lines"]); 


notes


Route.notes(...description)
Set the long description for this route in the documentation // Examples
Version with comment:

/** Short description
  * 
  * Longer description
  * with multiple lines
  */
app.get("/foxx", function() {
});


is identical to:

app.get("/foxx", function() {
})
.summary("Short description")
.notes(["Longer description", "with multiple lines"]); 


extend

In many use-cases several of the functions are always used in a certain combination (e.g.: onlyIf with errorResponse). In order to avoid duplicating this equal usage for several routes in your application you can extend the controller with your own functions. These functions can simply combine several of the above on a single name, so you only have to invoke your self defined single function on all routes using these extensions.


Controller.extend(extensions)
Extends all functions to define routes in this controller. This allows to combine several route extensions with the invocation of a single function. This is especially useful if you use the same input parameter in several routes of your controller and want to apply the same validation, documentation and error handling for it.
The extensions parameter is a JSON object with arbitrary keys. Each key is used as the name of the function you want to define (you cannot overwrite internal functions like pathParam) and the value is a function that will be invoked. This function can get arbitrary many arguments and the this of the function is bound to the route definition object (e.g. you can use this.pathParam()). Your newly defined function is chainable similar to the internal functions.
Examples
Define a validator for a queryParameter, including documentation and errorResponses in a single command:

controller.extend({
  myParam: function (maxValue) {
    this.queryParam("value", {type: joi.number().required()});
    this.onlyIf(function(req) {
      var v = req.param("value");
      if (v > maxValue) {
        throw new NumberTooLargeError();
      }
    });
    this.errorResponse(NumberTooLargeError, 400, "The given value is too large");
  }
});
<br />
controller.get("/goose/barn", function(req, res) {
  // Will only be invoked if the request has parameter value and it is less or equal 5.
}).myParam(5);


Documenting and constraining all routes

In addition to documenting a specific route, you can also do the same for all routes of a controller. For this purpose use the allRoutes object of the according controller. The following methods are available.

Examples

Provide an error response for all routes handled by this controller:

ctrl.allRoutes
.errorResponse(Unauthorized, 401, 'Not authenticated.')
.errorResponse(NotFound, 404, 'Document not found.')
.errorResponse(ImATeapot, 418, 'I\'m a teapot.');

ctrl.get('/some/route', function (req, res) {
  // ...
  throw new NotFound('The document does not exist');
  // ...
}); // no errorResponse needed here

ctrl.get('/another/route', function (req, res) {
  // ...
  throw new NotFound('I made you a cookie but I ated it');
  // ...
}); // no errorResponse needed here either

errorResponse


Controller.allRoutes.errorResponse(errorClass, code, description)
This is equal to invoking Route.errorResponse on all routes bound to this controller.
Examples

app.allRoutes.errorResponse(FoxxyError, 303, "This went completely wrong. Sorry!");
<br />
app.get("/foxx", function {
  // Do something
});

onlyIf


Controller.allRoutes.onlyIf(code, reason)
This is equal to invoking Route.onlyIf on all routes bound to this controller.
Examples

app.allRoutes.onlyIf(myPersonalCheck);
<br />
app.get("/foxx", function {
  // Do something
});

onlyIfAuthenticated


Controller.allRoutes.onlyIfAuthenticated(code, description)
This is equal to invoking Route.onlyIfAuthenticated on all routes bound to this controller.
Examples

app.allRoutes.onlyIfAuthenticated(401, "You need to be authenticated");
<br />
app.get("/foxx", function {
  // Do something
});

pathParam


Controller.allRoutes.pathParam(id, options)
This is equal to invoking Route.pathParam on all routes bound to this controller.
Examples

app.allRoutes.pathParam("id", joi.string().required().description("Id of the Foxx"));
<br />
app.get("/foxx/:id", function {
  // Secured by pathParam
});


You can also pass in a configuration object instead:

app.allRoutes.pathParam("id", {
  type: joi.string(),
  required: true,
  description: "Id of the Foxx"
});
<br />
app.get("/foxx/:id", function {
  // Secured by pathParam
});

bodyParam


Controller.allRoutes.queryParam(id, options)
This is equal to invoking Route.queryParam on all routes bound to this controller.
Examples

app.allroutes.queryParam("id",
  joi.string()
  .required()
  .description("Id of the Foxx")
  .meta({allowMultiple: false})
});
<br />
app.get("/foxx", function {
  // Do something
});


You can also pass in a configuration object instead:

app.allroutes.queryParam("id", {
  type: joi.string().required().description("Id of the Foxx"),
  allowMultiple: false
});
<br />
app.get("/foxx", function {
  // Do something
});

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 example).

before


Controller.before(path, callback)
Defines an additional function on the route path which will be executed before the callback defined for a specific HTTP verb is executed. The callback function has the same signature as the callback in the specific route. You can also omit the path, in this case callback will be executed before handleing any request in this Controller.
If callback returns the Boolean value false, the route handling will not proceed. You can use this to intercept invalid or unauthorized requests and prevent them from being passed to the matching routes.

Examples

app.before('/high/way', function(req, res) {
  //Do some crazy request logging
});


after


Controller.after(path, callback)
Similar to Controller.before(path, callback) but callback will be invoked after the request is handled in the specific route.

Examples

app.after('/high/way', function(req, res) {
  //Do some crazy response logging
});


around


Controller.around(path, callback)
Similar to Controller.before(path, callback) callback will be invoked instead of the specific handler. callback takes two additional paramaters opts and next where opts contains options assigned to the route and next is a function. Whenever you call next in callback the specific handler is invoked, if you do not call next the specific handler will not be invoked at all. So using around you can execute code before and after a specific handler and even call the handler only under certain circumstances. If you omit path callback will be called on every request.

Examples

app.around('/high/way', function(req, res, opts, next) {
  //Do some crazy request logging
  next();
  //Do some more crazy request logging
});

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 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 by the BaseMiddleware provided by Foxx.

The Request Object

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 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 if authentication is turned on, and will be null otherwise.

  • database: the name of the current database (e.g. _system)

  • protocol: http or https

  • 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 stripped off.

  • url: request URI path + query string, with potential database name stripped off

  • headers: a JSON object with the request headers as key/value pairs. Note: All header field names are lower-cased

  • cookies: a JSON object with the request cookies as key/value pairs

  • requestType: the request method (e.g. “GET”, “POST”, “PUT”, …)

  • requestBody: the complete body of the request as a string

  • parameters: a JSON object with all parameters set in the URL as key/value pairs

  • urlParameters: a JSON object with all named parameters defined for the route as key/value pairs.

In addition to these attributes, a Foxx request objects provides the following convenience methods:

body


request.body()
Get the JSON parsed body of the request. If you need the raw version, please refer to the rawBody function.

rawBody


request.rawBody()
The raw request body, not parsed. The body is returned as a UTF-8 string. Note that this can only be used sensibly if the request body contains valid UTF-8. If the request body is known to contain non-UTF-8 data, the request body can be accessed by using request.rawBodyBuffer.

rawBodyBuffer


request.rawBodyBuffer()
The raw request body, returned as a Buffer object.

params


request.params(key)
Get the parameters of the request. This process is two-fold:

  • If you have defined an URL like /test/:id and the user requested /test/1, the call params(“id”) will return 1.
  • If you have defined an URL like /test and the user gives a query component, the query parameters will also be returned. So for example if the user requested /test?a=2, the call params(“a”) will return 2.


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"});

requestParts

Only useful for multi-part requests.


request.requestParts()
Returns an array containing the individual parts of a multi-part request. Each part contains a headers attribute with all headers of the part, and a data attribute with the content of the part in a Buffer object. If the request is not a multi-part request, this function will throw an error.

The Response Object

Every response object has the body attribute from the underlying Actions to set the raw body by hand.

You provide your response body as a string here.

Response status


response.status(code)
Set the status code of your response, for example:

Examples

response.status(404);

Response set


response.set(key, value)
Set a header attribute, for example:

Examples

response.set("Content-Length", 123);
response.set("Content-Type", "text/plain");


or alternatively:

response.set({
  "Content-Length": "123",
  "Content-Type": "text/plain"
});

Response json


response.json(object)
Set the content type to JSON and the body to the JSON encoded object you provided.

Examples

response.json({'born': 'December 12, 1915'});


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"});

Response send


response.send(value)
Sets the response body to the specified value. If value is a Buffer object, the content type will be set to application/octet-stream if not yet set. If value is a string, the content type will be set to text/html if not yet set. If value is an object, it will be treated as in res.json.

Examples

response.send({"born": "December 12, 1915"});
response.send(new Buffer("some binary data"));
response.send("<html><head><title>Hello World</title></head><body></body></html>");

Response sendFile


response.sendFile(filename, options)
Sets the content of the specified file as the response body. The filename must be absolute. If no content type is yet set for the response, the response’s content type will be determined automatically based on the filename extension. If no content type is known for the extension, the content type will default to application/octet-stream.
The options array can be used to control the behavior of sendFile. Currently only the following option exists:

  • lastModified: if set to true, the last modification date and time of the file will be returned in the Last-Modified HTTP header

Examples

response.sendFile('/tmp/results.json');
response.sendFile(applicationContext.fileName('image.png'), { lastModified: true });

Controlling Access to Foxx Applications

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 via the configuration option.

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.

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 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). Otherwise clients will need HTTP authentication and need additional authentication by 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:

--server.disable-authentication false --server.authenticate-system-only true

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 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 demo application to demonstrate how this works.

To use the application-specific authentication in your own app, first activate it in your controller.

Active Authentication


Controller.activateAuthentication(opts)
To activate authentication for this controller, call this function before defining any routes. In the opts object you can set the following keys:

  • type: Currently we only support cookie, but this will change in the future
  • cookieLifetime: An integer. Lifetime of cookies in seconds
  • cookieName: A string used as the name of the cookie
  • sessionLifetime: An integer. Lifetime of sessions in seconds

Examples

app.activateAuthentication({
  type: "cookie",
  cookieLifetime: 360000,
  cookieName: "my_cookie",
  sessionLifetime: 400,
});


Login


FoxxController#login(path, opts)
Add a route for the login. You can provide further customizations via the the options:

  • usernameField and passwordField can be used to adjust the expected attributes in the post request. They default to username and password.
  • onSuccess is a function that you can define to do something if the login was successful. This includes sending a response to the user. This defaults to a function that returns a JSON with user set to the identifier of the user and
  • key set to the session key.
  • onError is a function that you can define to do something if the login did not work. This includes sending a response to the user. This defaults to a function that sets the response to 401 and returns a JSON with error set to “Username or Password was wrong”.
    Both onSuccess and onError should take request and result as arguments.

Examples

app.login('/login', {
  onSuccess(req, res) {
    res.json({"success": true});
  }
});


Logout


FoxxController#logout(path, opts)
This works pretty similar to the logout function and adds a path to your app for the logout functionality. You can customize it with a custom onSuccess and onError function:

  • onSuccess is a function that you can define to do something if the logout was successful. This includes sending a response to the user. This defaults to a function that returns a JSON with message set to “logged out”.
  • onError is a function that you can define to do something if the logout did not work. This includes sending a response to the user. This defaults to a function that sets the response to 401 and returns a JSON with error set to “No session was found”.
    Both onSuccess and onError should take request and result as arguments.

Examples

app.logout('/logout', {
  onSuccess(req, res) {
    res.json({"message": "Bye, Bye"});
  }
});


Register


FoxxController#register(path, opts)
This works pretty similar to the logout function and adds a path to your app for the register functionality. You can customize it with a custom onSuccess and onError function:

  • onSuccess is a function that you can define to do something if the registration was successful. This includes sending a response to the user. This defaults to a function that returns a JSON with user set to the created user document.
  • onError is a function that you can define to do something if the registration did not work. This includes sending a response to the user. This defaults to a function that sets the response to 401 and returns a JSON with error set to “Registration failed”.
    Both onSuccess and onError should take request and result as arguments.
    You can also set the fields containing the username and password via usernameField (defaults to username) and passwordField (defaults to password). If you want to accept additional attributes for the user document, use the option acceptedAttributes and set it to an array containing strings with the names of the additional attributes you want to accept. All other attributes in the request will be ignored.
    If you want default attributes for the accepted attributes or set additional fields (for example admin) use the option defaultAttributes which should be a hash mapping attribute names to default values.

Examples

app.register('/logout', {
  acceptedAttributes: ['name'],
  defaultAttributes: {
    admin: false
  }
});


Change Password


FoxxController#changePassword(route, opts)`
Add a route for the logged in user to change the password. You can provide further customizations via the the options:

  • passwordField can be used to adjust the expected attribute in the post request. It defaults to password.
  • onSuccess is a function that you can define to do something if the change was successful. This includes sending a response to the user. This defaults to a function that returns a JSON with notice set to “Changed password!”.
  • onError is a function that you can define to do something if the login did not work. This includes sending a response to the user. This defaults to a function that sets the response to 401 and returns a JSON with error set to “No session was found”.
    Both onSuccess and onError should take request and result as arguments.

Examples

app.changePassword('/changePassword', {
  onSuccess(req, res) {
    res.json({"success": true});
  }
});


Restricting routes

To restrict routes, see the documentation for Documenting and Restraining the routes.