Sails app
This commit is contained in:
73
config/400.js
Normal file
73
config/400.js
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Default 400 (Bad Request) handler
|
||||
*
|
||||
* Sails will automatically respond using this middleware when a blueprint is requested
|
||||
* with missing or invalid parameters
|
||||
* (e.g. `POST /user` was used to create a user, but required parameters were missing)
|
||||
*
|
||||
* This middleware can also be invoked manually from a controller or policy:
|
||||
* res.badRequest( [validationErrors], [redirectTo] )
|
||||
*
|
||||
*
|
||||
* @param {Array|Object|String} validationErrors
|
||||
* optional errors
|
||||
* usually an array of validation errors from the ORM
|
||||
*
|
||||
* @param {String} redirectTo
|
||||
* optional URL
|
||||
* (absolute or relative, e.g. google.com/foo or /bar/baz)
|
||||
* of the page to redirect to. Usually only relevant for traditional HTTP requests,
|
||||
* since if this was triggered from an AJAX or socket request, JSON should be sent instead.
|
||||
*/
|
||||
|
||||
module.exports[400] = function badRequest(validationErrors, redirectTo, req, res) {
|
||||
|
||||
/*
|
||||
* NOTE: This function is Sails middleware-- that means that not only do `req` and `res`
|
||||
* work just like their Express equivalents to handle HTTP requests, they also simulate
|
||||
* the same interface for receiving socket messages.
|
||||
*/
|
||||
|
||||
var statusCode = 400;
|
||||
|
||||
var result = {
|
||||
status: statusCode
|
||||
};
|
||||
|
||||
// Optional validationErrors object
|
||||
if (validationErrors) {
|
||||
result.validationErrors = validationErrors;
|
||||
}
|
||||
|
||||
// For requesters expecting JSON, everything works like you would expect-- a simple JSON response
|
||||
// indicating the 400: Bad Request status with relevant information will be returned.
|
||||
if (req.wantsJSON) {
|
||||
return res.json(result, result.status);
|
||||
}
|
||||
|
||||
// For traditional (not-AJAX) web forms, this middleware follows best-practices
|
||||
// for when a user submits invalid form data:
|
||||
// i. First, a one-time-use flash variable is populated, probably a string message or an array
|
||||
// of semantic validation error objects.
|
||||
// ii. Then the user is redirected back to `redirectTo`, i.e. the URL where the bad request originated.
|
||||
// iii. There, the controller and/or view might use the flash `errors` to either display a message or highlight
|
||||
// the invalid HTML form fields.
|
||||
if (redirectTo) {
|
||||
|
||||
// Set flash message called `errors` (one-time-use in session)
|
||||
req.flash('errors', validationErrors);
|
||||
|
||||
// then redirect back to the `redirectTo` URL
|
||||
return res.redirect(redirectTo);
|
||||
}
|
||||
|
||||
|
||||
// Depending on your app's needs, you may choose to look at the Referer header here
|
||||
// and redirect back. Please do so at your own risk!
|
||||
// For security reasons, Sails does not provide this affordance by default.
|
||||
// It's safest to provide a 'redirectTo' URL and redirect there directly.
|
||||
|
||||
// If `redirectTo` was not specified, just respond w/ JSON
|
||||
return res.json(result, result.status);
|
||||
|
||||
};
|
||||
52
config/403.js
Normal file
52
config/403.js
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Default 403 (Forbidden) middleware
|
||||
*
|
||||
* This middleware can be invoked from a controller or policy:
|
||||
* res.forbidden( [message] )
|
||||
*
|
||||
*
|
||||
* @param {String|Object|Array} message
|
||||
* optional message to inject into view locals or JSON response
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports[403] = function badRequest(message, req, res) {
|
||||
|
||||
/*
|
||||
* NOTE: This function is Sails middleware-- that means that not only do `req` and `res`
|
||||
* work just like their Express equivalents to handle HTTP requests, they also simulate
|
||||
* the same interface for receiving socket messages.
|
||||
*/
|
||||
|
||||
var viewFilePath = '403';
|
||||
var statusCode = 403;
|
||||
|
||||
var result = {
|
||||
status: statusCode
|
||||
};
|
||||
|
||||
// Optional message
|
||||
if (message) {
|
||||
result.message = message;
|
||||
}
|
||||
|
||||
// If the user-agent wants a JSON response, send json
|
||||
if (req.wantsJSON) {
|
||||
return res.json(result, result.status);
|
||||
}
|
||||
|
||||
// Set status code and view locals
|
||||
res.status(result.status);
|
||||
for (var key in result) {
|
||||
res.locals[key] = result[key];
|
||||
}
|
||||
// And render view
|
||||
res.render(viewFilePath, result, function (err) {
|
||||
// If the view doesn't exist, or an error occured, send json
|
||||
if (err) { return res.json(result, result.status); }
|
||||
|
||||
// Otherwise, serve the `views/403.*` page
|
||||
res.render(viewFilePath);
|
||||
});
|
||||
|
||||
};
|
||||
38
config/404.js
Normal file
38
config/404.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Default 404 (Not Found) handler
|
||||
*
|
||||
* If no route matches are found for a request, Sails will respond using this handler.
|
||||
*
|
||||
* This middleware can also be invoked manually from a controller or policy:
|
||||
* Usage: res.notFound()
|
||||
*/
|
||||
|
||||
module.exports[404] = function pageNotFound(req, res) {
|
||||
|
||||
/*
|
||||
* NOTE: This function is Sails middleware-- that means that not only do `req` and `res`
|
||||
* work just like their Express equivalents to handle HTTP requests, they also simulate
|
||||
* the same interface for receiving socket messages.
|
||||
*/
|
||||
|
||||
var viewFilePath = '404';
|
||||
var statusCode = 404;
|
||||
var result = {
|
||||
status: statusCode
|
||||
};
|
||||
|
||||
// If the user-agent wants a JSON response, send json
|
||||
if (req.wantsJSON) {
|
||||
return res.json(result, result.status);
|
||||
}
|
||||
|
||||
res.status(result.status);
|
||||
res.render(viewFilePath, function (err) {
|
||||
// If the view doesn't exist, or an error occured, send json
|
||||
if (err) { return res.json(result, result.status); }
|
||||
|
||||
// Otherwise, serve the `views/404.*` page
|
||||
res.render(viewFilePath);
|
||||
});
|
||||
|
||||
};
|
||||
77
config/500.js
Normal file
77
config/500.js
Normal file
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Default 500 (Server Error) middleware
|
||||
*
|
||||
* If an error is thrown in a policy or controller,
|
||||
* Sails will respond using this default error handler
|
||||
*
|
||||
* This middleware can also be invoked manually from a controller or policy:
|
||||
* res.serverError( [errors] )
|
||||
*
|
||||
*
|
||||
* @param {Array|Object|String} errors
|
||||
* optional errors
|
||||
*/
|
||||
|
||||
module.exports[500] = function serverErrorOccurred(errors, req, res) {
|
||||
|
||||
/*
|
||||
* NOTE: This function is Sails middleware-- that means that not only do `req` and `res`
|
||||
* work just like their Express equivalents to handle HTTP requests, they also simulate
|
||||
* the same interface for receiving socket messages.
|
||||
*/
|
||||
|
||||
var viewFilePath = '500',
|
||||
statusCode = 500,
|
||||
i, errorToLog, errorToJSON;
|
||||
|
||||
var result = {
|
||||
status: statusCode
|
||||
};
|
||||
|
||||
// Normalize a {String|Object|Error} or array of {String|Object|Error}
|
||||
// into an array of proper, readable {Error}
|
||||
var errorsToDisplay = sails.util.normalizeErrors(errors);
|
||||
for (i in errorsToDisplay) {
|
||||
|
||||
// Log error(s) as clean `stack`
|
||||
// (avoids ending up with \n, etc.)
|
||||
if ( errorsToDisplay[i].original ) {
|
||||
errorToLog = sails.util.inspect(errorsToDisplay[i].original);
|
||||
}
|
||||
else {
|
||||
errorToLog = errorsToDisplay[i].stack;
|
||||
}
|
||||
sails.log.error('Server Error (500)');
|
||||
sails.log.error(errorToLog);
|
||||
|
||||
// Use original error if it exists
|
||||
errorToJSON = errorsToDisplay[i].original || errorsToDisplay[i].message;
|
||||
errorsToDisplay[i] = errorToJSON;
|
||||
}
|
||||
|
||||
// Only include errors if application environment is set to 'development'
|
||||
// In production, don't display any identifying information about the error(s)
|
||||
if (sails.config.environment === 'development') {
|
||||
result.errors = errorsToDisplay;
|
||||
}
|
||||
|
||||
// If the user-agent wants JSON, respond with JSON
|
||||
if (req.wantsJSON) {
|
||||
return res.json(result, result.status);
|
||||
}
|
||||
|
||||
// Set status code and view locals
|
||||
res.status(result.status);
|
||||
for (var key in result) {
|
||||
res.locals[key] = result[key];
|
||||
}
|
||||
// And render view
|
||||
res.render(viewFilePath, result, function (err) {
|
||||
// If the view doesn't exist, or an error occured, just send JSON
|
||||
if (err) { return res.json(result, result.status); }
|
||||
|
||||
// Otherwise, if it can be rendered, the `views/500.*` page is rendered
|
||||
res.render(viewFilePath, result);
|
||||
});
|
||||
|
||||
};
|
||||
39
config/adapters.js
Normal file
39
config/adapters.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Global adapter config
|
||||
*
|
||||
* The `adapters` configuration object lets you create different global "saved settings"
|
||||
* that you can mix and match in your models. The `default` option indicates which
|
||||
* "saved setting" should be used if a model doesn't have an adapter specified.
|
||||
*
|
||||
* Keep in mind that options you define directly in your model definitions
|
||||
* will override these settings.
|
||||
*
|
||||
* For more information on adapter configuration, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports.adapters = {
|
||||
|
||||
// If you leave the adapter config unspecified
|
||||
// in a model definition, 'default' will be used.
|
||||
'default': 'disk',
|
||||
|
||||
// Persistent adapter for DEVELOPMENT ONLY
|
||||
// (data is preserved when the server shuts down)
|
||||
disk: {
|
||||
module: 'sails-disk'
|
||||
},
|
||||
|
||||
// MySQL is the world's most popular relational database.
|
||||
// Learn more: http://en.wikipedia.org/wiki/MySQL
|
||||
myLocalMySQLDatabase: {
|
||||
|
||||
module: 'sails-mysql',
|
||||
host: 'YOUR_MYSQL_SERVER_HOSTNAME_OR_IP_ADDRESS',
|
||||
user: 'YOUR_MYSQL_USER',
|
||||
// Psst.. You can put your password in config/local.js instead
|
||||
// so you don't inadvertently push it up if you're using version control
|
||||
password: 'YOUR_MYSQL_PASSWORD',
|
||||
database: 'YOUR_MYSQL_DB'
|
||||
}
|
||||
};
|
||||
16
config/bootstrap.js
vendored
Normal file
16
config/bootstrap.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Bootstrap
|
||||
*
|
||||
* An asynchronous boostrap function that runs before your Sails app gets lifted.
|
||||
* This gives you an opportunity to set up your data model, run jobs, or perform some special logic.
|
||||
*
|
||||
* For more information on bootstrapping your app, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports.bootstrap = function (cb) {
|
||||
|
||||
// It's very important to trigger this callack method when you are finished
|
||||
// with the bootstrap! (otherwise your server will never lift, since it's waiting on the bootstrap)
|
||||
cb();
|
||||
};
|
||||
169
config/controllers.js
Normal file
169
config/controllers.js
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Controllers
|
||||
*
|
||||
* By default, Sails inspects your controllers, models, and configuration and binds
|
||||
* certain routes automatically. These dynamically generated routes are called blueprints.
|
||||
*
|
||||
* These settings are for the global configuration of controllers & blueprint routes.
|
||||
* You may also override these settings on a per-controller basis by defining a '_config'
|
||||
* key in any of your controller files, and assigning it an object, e.g.:
|
||||
* {
|
||||
* // ...
|
||||
* _config: { blueprints: { rest: false } }
|
||||
* // ...
|
||||
* }
|
||||
*
|
||||
* For more information on configuring controllers and blueprints, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports.controllers = {
|
||||
|
||||
|
||||
/**
|
||||
* NOTE:
|
||||
* A lot of the configuration options below affect so-called "CRUD methods",
|
||||
* or your controllers' `find`, `create`, `update`, and `destroy` actions.
|
||||
*
|
||||
* It's important to realize that, even if you haven't defined these yourself, as long as
|
||||
* a model exists with the same name as the controller, Sails will respond with built-in CRUD
|
||||
* logic in the form of a JSON API, including support for sort, pagination, and filtering.
|
||||
*/
|
||||
blueprints: {
|
||||
|
||||
/**
|
||||
* `actions`
|
||||
*
|
||||
* Action blueprints speed up backend development and shorten the development workflow by
|
||||
* eliminating the need to manually bind routes.
|
||||
* When enabled, GET, POST, PUT, and DELETE routes will be generated for every one of a controller's actions.
|
||||
*
|
||||
* If an `index` action exists, additional naked routes will be created for it.
|
||||
* Finally, all `actions` blueprints support an optional path parameter, `id`, for convenience.
|
||||
*
|
||||
* For example, assume we have an EmailController with actions `send` and `index`.
|
||||
* With `actions` enabled, the following blueprint routes would be bound at runtime:
|
||||
*
|
||||
* `EmailController.index`
|
||||
* :::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
* `GET /email/:id?` `GET /email/index/:id?`
|
||||
* `POST /email/:id?` `POST /email/index/:id?`
|
||||
* `PUT /email/:id?` `PUT /email/index/:id?`
|
||||
* `DELETE /email/:id?` `DELETE /email/index/:id?`
|
||||
*
|
||||
* `EmailController.send`
|
||||
* :::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
* `GET /email/send/:id?`
|
||||
* `POST /email/send/:id?`
|
||||
* `PUT /email/send/:id?`
|
||||
* `DELETE /email/send/:id?`
|
||||
*
|
||||
*
|
||||
* `actions` are enabled by default, and are OK for production-- however,
|
||||
* you must take great care not to inadvertently expose unsafe controller logic to GET requests.
|
||||
*/
|
||||
actions: true,
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* `rest`
|
||||
*
|
||||
* REST blueprints are the automatically generated routes Sails uses to expose
|
||||
* a conventional REST API on top of a controller's `find`, `create`, `update`, and `destroy`
|
||||
* actions.
|
||||
*
|
||||
* For example, a BoatController with `rest` enabled generates the following routes:
|
||||
* :::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
* GET /boat/:id? -> BoatController.find
|
||||
* POST /boat -> BoatController.create
|
||||
* PUT /boat/:id -> BoatController.update
|
||||
* DELETE /boat/:id -> BoatController.destroy
|
||||
*
|
||||
* `rest` blueprints are enabled by default, and suitable for a production scenario.
|
||||
*/
|
||||
rest: true,
|
||||
|
||||
|
||||
/**
|
||||
* `shortcuts`
|
||||
*
|
||||
* Shortcut blueprints are simple helpers to provide access to a controller's CRUD methods
|
||||
* from your browser's URL bar. When enabled, GET, POST, PUT, and DELETE routes will be generated
|
||||
* for the controller's`find`, `create`, `update`, and `destroy` actions.
|
||||
*
|
||||
* `shortcuts` are enabled by default, but SHOULD BE DISABLED IN PRODUCTION!!!!!
|
||||
*/
|
||||
shortcuts: true,
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* `prefix`
|
||||
*
|
||||
* An optional mount path for all blueprint routes on a controller, including `rest`,
|
||||
* `actions`, and `shortcuts`. This allows you to continue to use blueprints, even if you
|
||||
* need to namespace your API methods.
|
||||
*
|
||||
* For example, `prefix: '/api/v2'` would make the following REST blueprint routes
|
||||
* for a FooController:
|
||||
*
|
||||
* `GET /api/v2/foo/:id?`
|
||||
* `POST /api/v2/foo`
|
||||
* `PUT /api/v2/foo/:id`
|
||||
* `DELETE /api/v2/foo/:id`
|
||||
*
|
||||
* By default, no prefix is used.
|
||||
*/
|
||||
prefix: '',
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* `pluralize`
|
||||
*
|
||||
* Whether to pluralize controller names in generated routes
|
||||
*
|
||||
* For example, REST blueprints for `FooController` with `pluralize` enabled:
|
||||
* GET /foos/:id?
|
||||
* POST /foos
|
||||
* PUT /foos/:id?
|
||||
* DELETE /foos/:id?
|
||||
*/
|
||||
pluralize: false
|
||||
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* `jsonp`
|
||||
*
|
||||
* If enabled, allows built-in CRUD methods to support JSONP for cross-domain requests.
|
||||
*
|
||||
* Example usage (REST blueprint + UserController):
|
||||
* `GET /user?name=ciaran&limit=10&callback=receiveJSONPResponse`
|
||||
*
|
||||
* Defaults to false.
|
||||
*/
|
||||
jsonp: false,
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* `expectIntegerId`
|
||||
*
|
||||
* If enabled, built-in CRUD methods will only accept valid integers as an :id parameter.
|
||||
*
|
||||
* i.e. trigger built-in API if requests look like:
|
||||
* `GET /user/8`
|
||||
* but not like:
|
||||
* `GET /user/a8j4g9jsd9ga4ghjasdha`
|
||||
*
|
||||
* Defaults to false.
|
||||
*/
|
||||
expectIntegerId: false
|
||||
|
||||
};
|
||||
49
config/cors.js
Normal file
49
config/cors.js
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Cross-Origin Resource Sharing (CORS)
|
||||
*
|
||||
* CORS is like a more modern version of JSONP-- it allows your server/API
|
||||
* to successfully respond to requests from client-side JavaScript code
|
||||
* running on some other domain (e.g. google.com)
|
||||
* Unlike JSONP, it works with POST, PUT, and DELETE requests
|
||||
*
|
||||
* For more information on CORS, check out:
|
||||
* http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
|
||||
*
|
||||
* Note that any of these settings (besides 'allRoutes') can be changed on a per-route basis
|
||||
* by adding a "cors" object to the route configuration:
|
||||
*
|
||||
* '/get foo': {
|
||||
* controller: 'foo',
|
||||
* action: 'bar',
|
||||
* cors: {
|
||||
* origin: 'http://foobar.com,https://owlhoot.com'
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports.cors = {
|
||||
|
||||
// Allow CORS on all routes by default? If not, you must enable CORS on a
|
||||
// per-route basis by either adding a "cors" configuration object
|
||||
// to the route config, or setting "cors:true" in the route config to
|
||||
// use the default settings below.
|
||||
allRoutes: false,
|
||||
|
||||
// Which domains which are allowed CORS access?
|
||||
// This can be a comma-delimited list of hosts (beginning with http:// or https://)
|
||||
// or "*" to allow all domains CORS access.
|
||||
origin: '*',
|
||||
|
||||
// Allow cookies to be shared for CORS requests?
|
||||
credentials: true,
|
||||
|
||||
// Which methods should be allowed for CORS requests? This is only used
|
||||
// in response to preflight requests (see article linked above for more info)
|
||||
methods: 'GET, POST, PUT, DELETE, OPTIONS, HEAD',
|
||||
|
||||
// Which headers should be allowed for CORS requests? This is only used
|
||||
// in response to preflight requests.
|
||||
headers: 'content-type'
|
||||
|
||||
};
|
||||
40
config/csrf.js
Normal file
40
config/csrf.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Cross-Site Request Forgery Protection
|
||||
*
|
||||
* CSRF tokens are like a tracking chip. While a session tells the server that a user
|
||||
* "is who they say they are", a csrf token tells the server "you are where you say you are".
|
||||
*
|
||||
* When enabled, all non-GET requests to the Sails server must be accompanied by
|
||||
* a special token, identified as the '_csrf' parameter.
|
||||
*
|
||||
* This option protects your Sails app against cross-site request forgery (or CSRF) attacks.
|
||||
* A would-be attacker needs not only a user's session cookie, but also this timestamped,
|
||||
* secret CSRF token, which is refreshed/granted when the user visits a URL on your app's domain.
|
||||
*
|
||||
* This allows us to have certainty that our users' requests haven't been hijacked,
|
||||
* and that the requests they're making are intentional and legitimate.
|
||||
*
|
||||
* This token has a short-lived expiration timeline, and must be acquired by either:
|
||||
*
|
||||
* (a) For traditional view-driven web apps:
|
||||
* Fetching it from one of your views, where it may be accessed as
|
||||
* a local variable, e.g.:
|
||||
* <form>
|
||||
* <input type="hidden" name="_csrf" value="<%= _csrf %>" />
|
||||
* </form>
|
||||
*
|
||||
* or (b) For AJAX/Socket-heavy and/or single-page apps:
|
||||
* Sending a GET request to the `/csrfToken` route, where it will be returned
|
||||
* as JSON, e.g.:
|
||||
* { _csrf: 'ajg4JD(JGdajhLJALHDa' }
|
||||
*
|
||||
*
|
||||
* Enabling this option requires managing the token in your front-end app.
|
||||
* For traditional web apps, it's as easy as passing the data from a view into a form action.
|
||||
* In AJAX/Socket-heavy apps, just send a GET request to the /csrfToken route to get a valid token.
|
||||
*
|
||||
* For more information on CSRF, check out:
|
||||
* http://en.wikipedia.org/wiki/Cross-site_request_forgery
|
||||
*/
|
||||
|
||||
module.exports.csrf = false;
|
||||
17
config/i18n.js
Normal file
17
config/i18n.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Internationalization / Localization Settings
|
||||
*
|
||||
* If your app will touch people from all over the world, i18n (or internationalization)
|
||||
* may be an important part of your international strategy.
|
||||
*
|
||||
*
|
||||
* For more information, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports.i18n = {
|
||||
|
||||
// Which locales are supported?
|
||||
locales: ['en', 'es', 'fr', 'de']
|
||||
|
||||
};
|
||||
24
config/locales/_README.md
Normal file
24
config/locales/_README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Internationalization / Localization Settings
|
||||
|
||||
## Locale
|
||||
All locale files live under `config/locales`. Here is where you can add locale data as JSON key-value pairs. The name of the file should match the language that you are supporting, which allows for automatic language detection based on the user request.
|
||||
|
||||
Here is an example locale stringfile for the Spanish language (`config/locales/es.json`):
|
||||
```json
|
||||
{
|
||||
"Hello!": "Hola!",
|
||||
"Hello %s, how are you today?": "¿Hola %s, como estas?",
|
||||
}
|
||||
```
|
||||
## Usage
|
||||
Locales can be accessed in controllers/policies through `res.i18n()`, or in views through the `__(key)` or `i18n(key)` functions.
|
||||
Remember that the keys are case sensitive and require exact key matches, e.g.
|
||||
|
||||
```ejs
|
||||
<h1> <%= __('Welcome to PencilPals!') %> </h1>
|
||||
<h2> <%= i18n('Hello %s, how are you today?', 'Pencil Maven') %> </h2>
|
||||
<p> <%= i18n('That\'s right-- you can use either i18n() or __()') %> </p>
|
||||
```
|
||||
|
||||
## Configuration
|
||||
Localization/internationalization config can be found in `config/i18n.js`, from where you can set your supported locales.
|
||||
3
config/locales/de.json
Normal file
3
config/locales/de.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"Welcome": "Wilkommen"
|
||||
}
|
||||
3
config/locales/en.json
Normal file
3
config/locales/en.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"Welcome": "Welcome"
|
||||
}
|
||||
3
config/locales/es.json
Normal file
3
config/locales/es.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"Welcome": "Bienvenido"
|
||||
}
|
||||
3
config/locales/fr.json
Normal file
3
config/locales/fr.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"Welcome": "Bienvenue"
|
||||
}
|
||||
27
config/log.js
Normal file
27
config/log.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Logger configuration
|
||||
*
|
||||
* Configure the log level for your app, as well as the transport
|
||||
* (Underneath the covers, Sails uses Winston for logging, which
|
||||
* allows for some pretty neat custom transports/adapters for log messages)
|
||||
*
|
||||
* For more information on the Sails logger, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
|
||||
// Valid `level` configs:
|
||||
// i.e. the minimum log level to capture with sails.log.*()
|
||||
//
|
||||
// 'error' : Display calls to `.error()`
|
||||
// 'warn' : Display calls from `.error()` to `.warn()`
|
||||
// 'debug' : Display calls from `.error()`, `.warn()` to `.debug()`
|
||||
// 'info' : Display calls from `.error()`, `.warn()`, `.debug()` to `.info()`
|
||||
// 'verbose': Display calls from `.error()`, `.warn()`, `.debug()`, `.info()` to `.verbose()`
|
||||
//
|
||||
log: {
|
||||
level: 'info'
|
||||
}
|
||||
|
||||
};
|
||||
83
config/policies.js
Normal file
83
config/policies.js
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Policy mappings (ACL)
|
||||
*
|
||||
* Policies are simply Express middleware functions which run **before** your controllers.
|
||||
* You can apply one or more policies to a given controller, or protect just one of its actions.
|
||||
*
|
||||
* Any policy file (e.g. `authenticated.js`) can be dropped into the `/policies` folder,
|
||||
* at which point it can be accessed below by its filename, minus the extension, (e.g. `authenticated`)
|
||||
*
|
||||
* For more information on policies, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
|
||||
module.exports.policies = {
|
||||
|
||||
// Default policy for all controllers and actions
|
||||
// (`true` allows public access)
|
||||
'*': true
|
||||
|
||||
/*
|
||||
// Here's an example of adding some policies to a controller
|
||||
RabbitController: {
|
||||
|
||||
// Apply the `false` policy as the default for all of RabbitController's actions
|
||||
// (`false` prevents all access, which ensures that nothing bad happens to our rabbits)
|
||||
'*': false,
|
||||
|
||||
// For the action `nurture`, apply the 'isRabbitMother' policy
|
||||
// (this overrides `false` above)
|
||||
nurture : 'isRabbitMother',
|
||||
|
||||
// Apply the `isNiceToAnimals` AND `hasRabbitFood` policies
|
||||
// before letting any users feed our rabbits
|
||||
feed : ['isNiceToAnimals', 'hasRabbitFood']
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Here's what the `isNiceToAnimals` policy from above might look like:
|
||||
* (this file would be located at `policies/isNiceToAnimals.js`)
|
||||
*
|
||||
* We'll make some educated guesses about whether our system will
|
||||
* consider this user someone who is nice to animals.
|
||||
*
|
||||
* Besides protecting rabbits (while a noble cause, no doubt),
|
||||
* here are a few other example use cases for policies:
|
||||
*
|
||||
* + cookie-based authentication
|
||||
* + role-based access control
|
||||
* + limiting file uploads based on MB quotas
|
||||
* + OAuth
|
||||
* + BasicAuth
|
||||
* + or any other kind of authentication scheme you can imagine
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
module.exports = function isNiceToAnimals (req, res, next) {
|
||||
|
||||
// `req.session` contains a set of data specific to the user making this request.
|
||||
// It's kind of like our app's "memory" of the current user.
|
||||
|
||||
// If our user has a history of animal cruelty, not only will we
|
||||
// prevent her from going even one step further (`return`),
|
||||
// we'll go ahead and redirect her to PETA (`res.redirect`).
|
||||
if ( req.session.user.hasHistoryOfAnimalCruelty ) {
|
||||
return res.redirect('http://PETA.org');
|
||||
}
|
||||
|
||||
// If the user has been seen frowning at puppies, we have to assume that
|
||||
// they might end up being mean to them, so we'll
|
||||
if ( req.session.user.frownsAtPuppies ) {
|
||||
return res.redirect('http://www.dailypuppy.com/');
|
||||
}
|
||||
|
||||
// Finally, if the user has a clean record, we'll call the `next()` function
|
||||
// to let them through to the next policy or our controller
|
||||
next();
|
||||
};
|
||||
*/
|
||||
166
config/routes.js
Normal file
166
config/routes.js
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* Routes
|
||||
*
|
||||
* Sails uses a number of different strategies to route requests.
|
||||
* Here they are top-to-bottom, in order of precedence.
|
||||
*
|
||||
* For more information on routes, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* (1) Core middleware
|
||||
*
|
||||
* Middleware included with `app.use` is run first, before the router
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* (2) Static routes
|
||||
*
|
||||
* This object routes static URLs to handler functions--
|
||||
* In most cases, these functions are actions inside of your controllers.
|
||||
* For convenience, you can also connect routes directly to views or external URLs.
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports.routes = {
|
||||
|
||||
// By default, your root route (aka home page) points to a view
|
||||
// located at `views/home/index.ejs`
|
||||
//
|
||||
// (This would also work if you had a file at: `/views/home.ejs`)
|
||||
'/': {
|
||||
view: 'home/index'
|
||||
}
|
||||
|
||||
/*
|
||||
// But what if you want your home page to display
|
||||
// a signup form located at `views/user/signup.ejs`?
|
||||
'/': {
|
||||
view: 'user/signup'
|
||||
}
|
||||
|
||||
|
||||
// Let's say you're building an email client, like Gmail
|
||||
// You might want your home route to serve an interface using custom logic.
|
||||
// In this scenario, you have a custom controller `MessageController`
|
||||
// with an `inbox` action.
|
||||
'/': 'MessageController.inbox'
|
||||
|
||||
|
||||
// Alternatively, you can use the more verbose syntax:
|
||||
'/': {
|
||||
controller: 'MessageController',
|
||||
action: 'inbox'
|
||||
}
|
||||
|
||||
|
||||
// If you decided to call your action `index` instead of `inbox`,
|
||||
// since the `index` action is the default, you can shortcut even further to:
|
||||
'/': 'MessageController'
|
||||
|
||||
|
||||
// Up until now, we haven't specified a specific HTTP method/verb
|
||||
// The routes above will apply to ALL verbs!
|
||||
// If you want to set up a route only for one in particular
|
||||
// (GET, POST, PUT, DELETE, etc.), just specify the verb before the path.
|
||||
// For example, if you have a `UserController` with a `signup` action,
|
||||
// and somewhere else, you're serving a signup form looks like:
|
||||
//
|
||||
// <form action="/signup">
|
||||
// <input name="username" type="text"/>
|
||||
// <input name="password" type="password"/>
|
||||
// <input type="submit"/>
|
||||
// </form>
|
||||
|
||||
// You would want to define the following route to handle your form:
|
||||
'post /signup': 'UserController.signup'
|
||||
|
||||
|
||||
// What about the ever-popular "vanity URLs" aka URL slugs?
|
||||
// (you might remember doing this with `mod_rewrite` in Apache)
|
||||
//
|
||||
// This is where you want to set up root-relative dynamic routes like:
|
||||
// http://yourwebsite.com/twinkletoez
|
||||
//
|
||||
// NOTE:
|
||||
// You'll still want to allow requests through to the static assets,
|
||||
// so we need to set up this route to ignore URLs that have a trailing ".":
|
||||
// (e.g. your javascript, CSS, and image files)
|
||||
'get /*(^.*)': 'UserController.profile'
|
||||
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* (3) Action blueprints
|
||||
* These routes can be disabled by setting (in `config/controllers.js`):
|
||||
* `module.exports.controllers.blueprints.actions = false`
|
||||
*
|
||||
* All of your controllers ' actions are automatically bound to a route. For example:
|
||||
* + If you have a controller, `FooController`:
|
||||
* + its action `bar` is accessible at `/foo/bar`
|
||||
* + its action `index` is accessible at `/foo/index`, and also `/foo`
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* (4) Shortcut CRUD blueprints
|
||||
*
|
||||
* These routes can be disabled by setting (in config/controllers.js)
|
||||
* `module.exports.controllers.blueprints.shortcuts = false`
|
||||
*
|
||||
* If you have a model, `Foo`, and a controller, `FooController`,
|
||||
* you can access CRUD operations for that model at:
|
||||
* /foo/find/:id? -> search lampshades using specified criteria or with id=:id
|
||||
*
|
||||
* /foo/create -> create a lampshade using specified values
|
||||
*
|
||||
* /foo/update/:id -> update the lampshade with id=:id
|
||||
*
|
||||
* /foo/destroy/:id -> delete lampshade with id=:id
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* (5) REST blueprints
|
||||
*
|
||||
* These routes can be disabled by setting (in config/controllers.js)
|
||||
* `module.exports.controllers.blueprints.rest = false`
|
||||
*
|
||||
* If you have a model, `Foo`, and a controller, `FooController`,
|
||||
* you can access CRUD operations for that model at:
|
||||
*
|
||||
* get /foo/:id? -> search lampshades using specified criteria or with id=:id
|
||||
*
|
||||
* post /foo -> create a lampshade using specified values
|
||||
*
|
||||
* put /foo/:id -> update the lampshade with id=:id
|
||||
*
|
||||
* delete /foo/:id -> delete lampshade with id=:id
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* (6) Static assets
|
||||
*
|
||||
* Flat files in your `assets` directory- (these are sometimes referred to as 'public')
|
||||
* If you have an image file at `/assets/images/foo.jpg`, it will be made available
|
||||
* automatically via the route: `/images/foo.jpg`
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* (7) 404 (not found) handler
|
||||
*
|
||||
* Finally, if nothing else matched, the default 404 handler is triggered.
|
||||
* See `config/404.js` to adjust your app's 404 logic.
|
||||
*/
|
||||
|
||||
56
config/session.js
Normal file
56
config/session.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Session
|
||||
*
|
||||
* Sails session integration leans heavily on the great work already done by Express, but also unifies
|
||||
* Socket.io with the Connect session store. It uses Connect's cookie parser to normalize configuration
|
||||
* differences between Express and Socket.io and hooks into Sails' middleware interpreter to allow you
|
||||
* to access and auto-save to `req.session` with Socket.io the same way you would with Express.
|
||||
*
|
||||
* For more information on configuring the session, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports.session = {
|
||||
|
||||
// Session secret is automatically generated when your new app is created
|
||||
// Replace at your own risk in production-- you will invalidate the cookies of your users,
|
||||
// forcing them to log in again.
|
||||
secret: '7c4a87c5984e13546e5ee92cef884fc3'
|
||||
|
||||
|
||||
// In production, uncomment the following lines to set up a shared redis session store
|
||||
// that can be shared across multiple Sails.js servers
|
||||
// adapter: 'redis',
|
||||
//
|
||||
// The following values are optional, if no options are set a redis instance running
|
||||
// on localhost is expected.
|
||||
// Read more about options at: https://github.com/visionmedia/connect-redis
|
||||
//
|
||||
// host: 'localhost',
|
||||
// port: 6379,
|
||||
// ttl: <redis session TTL in seconds>,
|
||||
// db: 0,
|
||||
// pass: <redis auth password>
|
||||
// prefix: 'sess:'
|
||||
|
||||
|
||||
// Uncomment the following lines to use your Mongo adapter as a session store
|
||||
// adapter: 'mongo',
|
||||
//
|
||||
// host: 'localhost',
|
||||
// port: 27017,
|
||||
// db: 'sails',
|
||||
// collection: 'sessions',
|
||||
//
|
||||
// Optional Values:
|
||||
//
|
||||
// # Note: url will override other connection settings
|
||||
// url: 'mongodb://user:pass@host:port/database/collection',
|
||||
//
|
||||
// username: '',
|
||||
// password: '',
|
||||
// auto_reconnect: false,
|
||||
// ssl: false,
|
||||
// stringify: true
|
||||
|
||||
};
|
||||
223
config/sockets.js
Normal file
223
config/sockets.js
Normal file
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Socket Configuration
|
||||
*
|
||||
* These configuration options provide transparent access to Sails' encapsulated
|
||||
* pubsub/socket server for complete customizability.
|
||||
*
|
||||
* For more information on using Sails with Sockets, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports.sockets = {
|
||||
|
||||
// This custom onConnect function will be run each time AFTER a new socket connects
|
||||
// (To control whether a socket is allowed to connect, check out `authorization` config.)
|
||||
// Keep in mind that Sails' RESTful simulation for sockets
|
||||
// mixes in socket.io events for your routes and blueprints automatically.
|
||||
onConnect: function(session, socket) {
|
||||
|
||||
// By default: do nothing
|
||||
// This is a good place to subscribe a new socket to a room, inform other users that
|
||||
// someone new has come online, or any other custom socket.io logic
|
||||
},
|
||||
|
||||
// This custom onDisconnect function will be run each time a socket disconnects
|
||||
onDisconnect: function(session, socket) {
|
||||
|
||||
// By default: do nothing
|
||||
// This is a good place to broadcast a disconnect message, or any other custom socket.io logic
|
||||
},
|
||||
|
||||
|
||||
|
||||
// `transports`
|
||||
//
|
||||
// A array of allowed transport methods which the clients will try to use.
|
||||
// The flashsocket transport is disabled by default
|
||||
// You can enable flashsockets by adding 'flashsocket' to this list:
|
||||
transports: [
|
||||
'websocket',
|
||||
'htmlfile',
|
||||
'xhr-polling',
|
||||
'jsonp-polling'
|
||||
],
|
||||
|
||||
|
||||
|
||||
|
||||
// Use this option to set the datastore socket.io will use to manage rooms/sockets/subscriptions:
|
||||
// default: memory
|
||||
adapter: 'memory',
|
||||
|
||||
|
||||
// Node.js (and consequently Sails.js) apps scale horizontally.
|
||||
// It's a powerful, efficient approach, but it involves a tiny bit of planning.
|
||||
// At scale, you'll want to be able to copy your app onto multiple Sails.js servers
|
||||
// and throw them behind a load balancer.
|
||||
//
|
||||
// One of the big challenges of scaling an application is that these sorts of clustered
|
||||
// deployments cannot share memory, since they are on physically different machines.
|
||||
// On top of that, there is no guarantee that a user will "stick" with the same server between
|
||||
// requests (whether HTTP or sockets), since the load balancer will route each request to the
|
||||
// Sails server with the most available resources. However that means that all room/pubsub/socket
|
||||
// processing and shared memory has to be offloaded to a shared, remote messaging queue (usually Redis)
|
||||
//
|
||||
// Luckily, Socket.io (and consequently Sails.js) apps support Redis for sockets by default.
|
||||
// To enable a remote redis pubsub server:
|
||||
// adapter: 'redis',
|
||||
// host: '127.0.0.1',
|
||||
// port: 6379,
|
||||
// db: 'sails',
|
||||
// pass: '<redis auth password>'
|
||||
// Worth mentioning is that, if `adapter` config is `redis`,
|
||||
// but host/port is left unset, Sails will try to connect to redis
|
||||
// running on localhost via port 6379
|
||||
|
||||
|
||||
|
||||
// `authorization`
|
||||
//
|
||||
// Global authorization for Socket.IO access,
|
||||
// this is called when the initial handshake is performed with the server.
|
||||
//
|
||||
// By default (`authorization: true`), when a socket tries to connect, Sails verifies
|
||||
// that a valid cookie was sent with the upgrade request. If the cookie doesn't match
|
||||
// any known user session, a new user session is created for it.
|
||||
//
|
||||
// However, in the case of cross-domain requests, it is possible to receive a connection
|
||||
// upgrade request WITHOUT A COOKIE (for certain transports)
|
||||
// In this case, there is no way to keep track of the requesting user between requests,
|
||||
// since there is no identifying information to link him/her with a session.
|
||||
//
|
||||
// If you don't care about keeping track of your socket users between requests,
|
||||
// you can bypass this cookie check by setting `authorization: false`
|
||||
// which will disable the session for socket requests (req.session is still accessible
|
||||
// in each request, but it will be empty, and any changes to it will not be persisted)
|
||||
//
|
||||
// On the other hand, if you DO need to keep track of user sessions,
|
||||
// you can pass along a ?cookie query parameter to the upgrade url,
|
||||
// which Sails will use in the absense of a proper cookie
|
||||
// e.g. (when connection from the client):
|
||||
// io.connect('http://localhost:1337?cookie=smokeybear')
|
||||
//
|
||||
// (Un)fortunately, the user's cookie is (should!) not accessible in client-side js.
|
||||
// Using HTTP-only cookies is crucial for your app's security.
|
||||
// Primarily because of this situation, as well as a handful of other advanced
|
||||
// use cases, Sails allows you to override the authorization behavior
|
||||
// with your own custom logic by specifying a function, e.g:
|
||||
/*
|
||||
authorization: function authorizeAttemptedSocketConnection(reqObj, cb) {
|
||||
|
||||
// Any data saved in `handshake` is available in subsequent requests
|
||||
// from this as `req.socket.handshake.*`
|
||||
|
||||
//
|
||||
// to allow the connection, call `cb(null, true)`
|
||||
// to prevent the connection, call `cb(null, false)`
|
||||
// to report an error, call `cb(err)`
|
||||
}
|
||||
*/
|
||||
authorization: true,
|
||||
|
||||
// Match string representing the origins that are allowed to connect to the Socket.IO server
|
||||
origins: '*:*',
|
||||
|
||||
// Should we use heartbeats to check the health of Socket.IO connections?
|
||||
heartbeats: true,
|
||||
|
||||
// When client closes connection, the # of seconds to wait before attempting a reconnect.
|
||||
// This value is sent to the client after a successful handshake.
|
||||
'close timeout': 60,
|
||||
|
||||
// The # of seconds between heartbeats sent from the client to the server
|
||||
// This value is sent to the client after a successful handshake.
|
||||
'heartbeat timeout': 60,
|
||||
|
||||
// The max # of seconds to wait for an expcted heartbeat before declaring the pipe broken
|
||||
// This number should be less than the `heartbeat timeout`
|
||||
'heartbeat interval': 25,
|
||||
|
||||
// The maximum duration of one HTTP poll-
|
||||
// if it exceeds this limit it will be closed.
|
||||
'polling duration': 20,
|
||||
|
||||
// Enable the flash policy server if the flashsocket transport is enabled
|
||||
// 'flash policy server': true,
|
||||
|
||||
// By default the Socket.IO client will check port 10843 on your server
|
||||
// to see if flashsocket connections are allowed.
|
||||
// The Adobe Flash Player normally uses 843 as default port,
|
||||
// but Socket.io defaults to a non root port (10843) by default
|
||||
//
|
||||
// If you are using a hosting provider that doesn't allow you to start servers
|
||||
// other than on port 80 or the provided port, and you still want to support flashsockets
|
||||
// you can set the `flash policy port` to -1
|
||||
'flash policy port': 10843,
|
||||
|
||||
// Used by the HTTP transports. The Socket.IO server buffers HTTP request bodies up to this limit.
|
||||
// This limit is not applied to websocket or flashsockets.
|
||||
'destroy buffer size': '10E7',
|
||||
|
||||
// Do we need to destroy non-socket.io upgrade requests?
|
||||
'destroy upgrade': true,
|
||||
|
||||
// Should Sails/Socket.io serve the `socket.io.js` client?
|
||||
// (as well as WebSocketMain.swf for Flash sockets, etc.)
|
||||
'browser client': true,
|
||||
|
||||
// Cache the Socket.IO file generation in the memory of the process
|
||||
// to speed up the serving of the static files.
|
||||
'browser client cache': true,
|
||||
|
||||
// Does Socket.IO need to send a minified build of the static client script?
|
||||
'browser client minification': false,
|
||||
|
||||
// Does Socket.IO need to send an ETag header for the static requests?
|
||||
'browser client etag': false,
|
||||
|
||||
// Adds a Cache-Control: private, x-gzip-ok="", max-age=31536000 header to static requests,
|
||||
// but only if the file is requested with a version number like /socket.io/socket.io.v0.9.9.js.
|
||||
'browser client expires': 315360000,
|
||||
|
||||
// Does Socket.IO need to GZIP the static files?
|
||||
// This process is only done once and the computed output is stored in memory.
|
||||
// So we don't have to spawn a gzip process for each request.
|
||||
'browser client gzip': false,
|
||||
|
||||
// Optional override function to serve all static files,
|
||||
// including socket.io.js et al.
|
||||
// Of the form :: function (req, res) { /* serve files */ }
|
||||
'browser client handler': false,
|
||||
|
||||
// Meant to be used when running socket.io behind a proxy.
|
||||
// Should be set to true when you want the location handshake to match the protocol of the origin.
|
||||
// This fixes issues with terminating the SSL in front of Node
|
||||
// and forcing location to think it's wss instead of ws.
|
||||
'match origin protocol': false,
|
||||
|
||||
// Direct access to the socket.io MQ store config
|
||||
// The 'adapter' property is the preferred method
|
||||
// (`undefined` indicates that Sails should defer to the 'adapter' config)
|
||||
store: undefined,
|
||||
|
||||
// A logger instance that is used to output log information.
|
||||
// (`undefined` indicates deferment to the main Sails log config)
|
||||
logger: undefined,
|
||||
|
||||
// The amount of detail that the server should output to the logger.
|
||||
// (`undefined` indicates deferment to the main Sails log config)
|
||||
'log level': undefined,
|
||||
|
||||
// Whether to color the log type when output to the logger.
|
||||
// (`undefined` indicates deferment to the main Sails log config)
|
||||
'log colors': undefined,
|
||||
|
||||
// A Static instance that is used to serve the socket.io client and its dependencies.
|
||||
// (`undefined` indicates use default)
|
||||
'static': undefined,
|
||||
|
||||
// The entry point where Socket.IO starts looking for incoming connections.
|
||||
// This should be the same between the client and the server.
|
||||
resource: '/socket.io'
|
||||
|
||||
};
|
||||
72
config/views.js
Normal file
72
config/views.js
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Views
|
||||
*
|
||||
* Server-sent views are a classic and effective way to get your app up and running.
|
||||
* Views are normally served from controllers. Below, you can configure your
|
||||
* templating language/framework of choice and configure Sails' layout support.
|
||||
*
|
||||
* For more information on views and layouts, check out:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
module.exports.views = {
|
||||
|
||||
// View engine (aka template language)
|
||||
// to use for your app's *server-side* views
|
||||
//
|
||||
// Sails+Express supports all view engines which implement
|
||||
// TJ Holowaychuk's `consolidate.js`, including, but not limited to:
|
||||
//
|
||||
// ejs, jade, handlebars, mustache
|
||||
// underscore, hogan, haml, haml-coffee, dust
|
||||
// atpl, eco, ect, jazz, jqtpl, JUST, liquor, QEJS,
|
||||
// swig, templayed, toffee, walrus, & whiskers
|
||||
|
||||
// For more options, check out the docs:
|
||||
// https://github.com/balderdashy/sails-wiki/blob/0.9/config.views.md#engine
|
||||
|
||||
engine: 'ejs',
|
||||
|
||||
|
||||
|
||||
// Layouts are simply top-level HTML templates you can use as wrappers
|
||||
// for your server-side views. If you're using ejs or jade, you can take advantage of
|
||||
// Sails' built-in `layout` support.
|
||||
//
|
||||
// When using a layout, when one of your views is served, it is injected into
|
||||
// the `body` partial defined in the layout. This lets you reuse header
|
||||
// and footer logic between views.
|
||||
//
|
||||
// NOTE: Layout support is only implemented for the `ejs` view engine!
|
||||
// For most other engines, it is not necessary, since they implement
|
||||
// partials/layouts themselves. In those cases, this config will be silently
|
||||
// ignored.
|
||||
//
|
||||
// The `layout` setting may be set to one of:
|
||||
//
|
||||
// If `true`, Sails will look for the default, located at `views/layout.ejs`
|
||||
// If `false`, layouts will be disabled.
|
||||
// Otherwise, if a string is specified, it will be interpreted as the relative path
|
||||
// to your layout from `views/` folder.
|
||||
// (the file extension, e.g. ".ejs", should be omitted)
|
||||
//
|
||||
|
||||
layout: 'layout'
|
||||
|
||||
|
||||
|
||||
// Using Multiple Layouts with EJS
|
||||
//
|
||||
// If you're using the default engine, `ejs`, Sails supports the use of multiple
|
||||
// `layout` files. To take advantage of this, before rendering a view, override
|
||||
// the `layout` local in your controller by setting `res.locals.layout`.
|
||||
// (this is handy if you parts of your app's UI look completely different from each other)
|
||||
//
|
||||
// e.g. your default might be
|
||||
// layout: 'layouts/public'
|
||||
//
|
||||
// But you might override that in some of your controllers with:
|
||||
// layout: 'layouts/internal'
|
||||
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user