!CHAPTER Details on Controller !SUBSECTION 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** ```js app = new Controller(applicationContext, { urlPrefix: "/meadow" }); ``` !SECTION HTTP Methods !SUBSECTION 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** ```js app.get('/goose/barn', function (req, res) { // Take this request and deal with it! }); ``` !SUBSECTION head `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** ```js app.head('/goose/barn', function (req, res) { // Take this request and deal with it! }); ``` !SUBSECTION 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** ```js app.post('/goose/barn', function (req, res) { // Take this request and deal with it! }); ``` !SUBSECTION 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** ```js app.put('/goose/barn', function (req, res) { // Take this request and deal with it! }); ``` !SUBSECTION 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** ```js app.patch('/goose/barn', function (req, res) { // Take this request and deal with it! }); ``` !SUBSECTION 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** ```js app.delete('/goose/barn', function (req, res) { // Take this request and deal with it! }); ``` !SECTION 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: ```js /** 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: !SUBSECTION 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](https://github.com/spumko/joi). *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* ```js 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: ```js app.get("/foxx/:name", function { // Do something }).pathParam("name", { type: joi.string(), required: true, description: "Name of the Foxx" }); ``` !SUBSECTION 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](https://github.com/spumko/joi). 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* ```js 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: ```js app.get("/foxx", function { // Do something }).queryParam("id", { type: joi.string().required().description("Id of the Foxx"), allowMultiple: false }); ``` !SUBSECTION 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](../Develop/Manifest.md). 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* ```js 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: ```js 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: ```js 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 ); ``` !SUBSECTION 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* ```js /* define our own error type, FoxxyError */ var FoxxyError = function (message) { this.name = "FError"; this.message = "the following FoxxyError occurred: " + message; }; FoxxyError.prototype = new Error(); app.get("/foxx", function { /* throws a FoxxyError */ throw new FoxxyError(); }).errorResponse(FoxxyError, 303, "This went completely wrong. Sorry!"); app.get("/foxx", function { throw new FoxxyError("oops!"); }).errorResponse("FError", 303, "This went completely wrong. Sorry!", function (e) { return { code: 123, desc: e.message }; }); ``` !SUBSECTION 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* ```js app.get("/foxx", function { // Do something }).onlyIf(aFunction).errorResponse(ErrorClass, 303, "This went completely wrong. Sorry!"); ``` !SUBSECTION 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* ```js app.get("/foxx", function { // Do something }).onlyIfAuthenticated(401, "You need to be authenticated"); ``` !SUBSECTION 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: ```js /** Short description * * Longer description * with multiple lines */ app.get("/foxx", function() { }); ``` is identical to: ```js app.get("/foxx", function() { }) .summary("Short description") .notes(["Longer description", "with multiple lines"]); ``` !SUBSECTION notes `Route.notes(...description)` Set the long description for this route in the documentation *Examples* Version with comment: ```js /** Short description * * Longer description * with multiple lines */ app.get("/foxx", function() { }); ``` is identical to: ```js app.get("/foxx", function() { }) .summary("Short description") .notes(["Longer description", "with multiple lines"]); ``` !SUBSECTION 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: ```js 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"); } }); 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); ``` !SECTION 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: ```js 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 ``` !SUBSECTION errorResponse `Controller.allRoutes.errorResponse(errorClass, code, description)` This is equal to invoking `Route.errorResponse` on all routes bound to this controller. *Examples* ```js app.allRoutes.errorResponse(FoxxyError, 303, "This went completely wrong. Sorry!"); app.get("/foxx", function { // Do something }); ``` !SUBSECTION onlyIf `Controller.allRoutes.onlyIf(code, reason)` This is equal to invoking `Route.onlyIf` on all routes bound to this controller. *Examples* ```js app.allRoutes.onlyIf(myPersonalCheck); app.get("/foxx", function { // Do something }); ``` !SUBSECTION onlyIfAuthenticated `Controller.allRoutes.onlyIfAuthenticated(code, description)` This is equal to invoking `Route.onlyIfAuthenticated` on all routes bound to this controller. *Examples* ```js app.allRoutes.onlyIfAuthenticated(401, "You need to be authenticated"); app.get("/foxx", function { // Do something }); ``` !SUBSECTION pathParam `Controller.allRoutes.pathParam(id, options)` This is equal to invoking `Route.pathParam` on all routes bound to this controller. *Examples* ```js app.allRoutes.pathParam("id", joi.string().required().description("Id of the Foxx")); app.get("/foxx/:id", function { // Secured by pathParam }); ``` You can also pass in a configuration object instead: ```js app.allRoutes.pathParam("id", { type: joi.string(), required: true, description: "Id of the Foxx" }); app.get("/foxx/:id", function { // Secured by pathParam }); ``` !SUBSECTION bodyParam `Controller.allRoutes.queryParam(id, options)` This is equal to invoking `Route.queryParam` on all routes bound to this controller. *Examples* ```js app.allroutes.queryParam("id", joi.string() .required() .description("Id of the Foxx") .meta({allowMultiple: false}) }); app.get("/foxx", function { // Do something }); ``` You can also pass in a configuration object instead: ```js app.allroutes.queryParam("id", { type: joi.string().required().description("Id of the Foxx"), allowMultiple: false }); app.get("/foxx", function { // Do something }); ``` !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 example). !SUBSECTION 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** ```js app.before('/high/way', function(req, res) { //Do some crazy request logging }); ``` !SUBSECTION 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** ```js app.after('/high/way', function(req, res) { //Do some crazy response logging }); ``` !SUBSECTION 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** ```js app.around('/high/way', function(req, res, opts, next) { //Do some crazy request logging next(); //Do some more crazy request logging }); ``` !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 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. !SUBSECTION 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](../../Glossary/README.md#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: !SUBSECTION body `request.body()` Get the JSON parsed body of the request. If you need the raw version, please refer to the *rawBody* function. !SUBSECTION 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`. !SUBSECTION rawBodyBuffer `request.rawBodyBuffer()` The raw request body, returned as a Buffer object. !SUBSECTION 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*. !SUBSECTION 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"}); ``` !SUBSECTION 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. !SECTION 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. !SUBSECTION Response status `response.status(code)` Set the status *code* of your response, for example: **Examples** ``` response.status(404); ``` !SUBSECTION Response set `response.set(key, value)` Set a header attribute, for example: **Examples** ```js response.set("Content-Length", 123); response.set("Content-Type", "text/plain"); ``` or alternatively: ```js response.set({ "Content-Length": "123", "Content-Type": "text/plain" }); ``` !SUBSECTION Response json `response.json(object)` Set the content type to JSON and the body to the JSON encoded *object* you provided. **Examples** ```js response.json({'born': 'December 12, 1915'}); ``` !SUBSECTION 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"}); ``` !SUBSECTION 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** ```js response.send({"born": "December 12, 1915"}); response.send(new Buffer("some binary data")); response.send("Hello World"); ``` !SUBSECTION 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** ```js response.sendFile('/tmp/results.json'); response.sendFile(applicationContext.fileName('image.png'), { lastModified: true }); ``` !SECTION 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](https://github.com/arangodb/foxx-authentication) to demonstrate how this works. To use the application-specific authentication in your own app, first activate it in your controller. !SUBSECTION 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** ```js app.activateAuthentication({ type: "cookie", cookieLifetime: 360000, cookieName: "my_cookie", sessionLifetime: 400, }); ``` !SUBSECTION 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** ```js app.login('/login', { onSuccess(req, res) { res.json({"success": true}); } }); ``` !SUBSECTION 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** ```js app.logout('/logout', { onSuccess(req, res) { res.json({"message": "Bye, Bye"}); } }); ``` !SUBSECTION 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** ```js app.register('/logout', { acceptedAttributes: ['name'], defaultAttributes: { admin: false } }); ``` !SUBSECTION 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** ```js app.changePassword('/changePassword', { onSuccess(req, res) { res.json({"success": true}); } }); ``` !SUBSUBSECTION Restricting routes To restrict routes, see the documentation for Documenting and Restraining the routes.