Sails app
This commit is contained in:
45
.gitignore
vendored
Normal file
45
.gitignore
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
########################
|
||||
# sails
|
||||
########################
|
||||
.sails
|
||||
.waterline
|
||||
.rigging
|
||||
.tmp
|
||||
|
||||
|
||||
########################
|
||||
# node.js / npm
|
||||
########################
|
||||
lib-cov
|
||||
*.seed
|
||||
*.log
|
||||
*.csv
|
||||
*.dat
|
||||
*.out
|
||||
*.pid
|
||||
*.gz
|
||||
|
||||
pids
|
||||
logs
|
||||
results
|
||||
|
||||
node_modules
|
||||
|
||||
npm-debug.log
|
||||
|
||||
|
||||
########################
|
||||
# misc / editors
|
||||
########################
|
||||
*~
|
||||
*#
|
||||
.DS_STORE
|
||||
.netbeans
|
||||
nbproject
|
||||
.idea
|
||||
|
||||
|
||||
########################
|
||||
# local config
|
||||
########################
|
||||
config/local.js
|
||||
484
Gruntfile.js
Normal file
484
Gruntfile.js
Normal file
@@ -0,0 +1,484 @@
|
||||
/**
|
||||
* Gruntfile
|
||||
*
|
||||
* If you created your Sails app with `sails new foo --linker`,
|
||||
* the following files will be automatically injected (in order)
|
||||
* into the EJS and HTML files in your `views` and `assets` folders.
|
||||
*
|
||||
* At the top part of this file, you'll find a few of the most commonly
|
||||
* configured options, but Sails' integration with Grunt is also fully
|
||||
* customizable. If you'd like to work with your assets differently
|
||||
* you can change this file to do anything you like!
|
||||
*
|
||||
* More information on using Grunt to work with static assets:
|
||||
* http://gruntjs.com/configuring-tasks
|
||||
*/
|
||||
|
||||
module.exports = function (grunt) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* CSS files to inject in order
|
||||
* (uses Grunt-style wildcard/glob/splat expressions)
|
||||
*
|
||||
* By default, Sails also supports LESS in development and production.
|
||||
* To use SASS/SCSS, Stylus, etc., edit the `sails-linker:devStyles` task
|
||||
* below for more options. For this to work, you may need to install new
|
||||
* dependencies, e.g. `npm install grunt-contrib-sass`
|
||||
*/
|
||||
|
||||
var cssFilesToInject = [
|
||||
'linker/**/*.css'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Javascript files to inject in order
|
||||
* (uses Grunt-style wildcard/glob/splat expressions)
|
||||
*
|
||||
* To use client-side CoffeeScript, TypeScript, etc., edit the
|
||||
* `sails-linker:devJs` task below for more options.
|
||||
*/
|
||||
|
||||
var jsFilesToInject = [
|
||||
|
||||
// Below, as a demonstration, you'll see the built-in dependencies
|
||||
// linked in the proper order order
|
||||
|
||||
// Bring in the socket.io client
|
||||
'linker/js/socket.io.js',
|
||||
|
||||
// then beef it up with some convenience logic for talking to Sails.js
|
||||
'linker/js/sails.io.js',
|
||||
|
||||
// A simpler boilerplate library for getting you up and running w/ an
|
||||
// automatic listener for incoming messages from Socket.io.
|
||||
'linker/js/app.js',
|
||||
|
||||
// *-> put other dependencies here <-*
|
||||
|
||||
// All of the rest of your app scripts imported here
|
||||
'linker/**/*.js'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Client-side HTML templates are injected using the sources below
|
||||
* The ordering of these templates shouldn't matter.
|
||||
* (uses Grunt-style wildcard/glob/splat expressions)
|
||||
*
|
||||
* By default, Sails uses JST templates and precompiles them into
|
||||
* functions for you. If you want to use jade, handlebars, dust, etc.,
|
||||
* edit the relevant sections below.
|
||||
*/
|
||||
|
||||
var templateFilesToInject = [
|
||||
'linker/**/*.html'
|
||||
];
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DANGER:
|
||||
//
|
||||
// With great power comes great responsibility.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
// Modify css file injection paths to use
|
||||
cssFilesToInject = cssFilesToInject.map(function (path) {
|
||||
return '.tmp/public/' + path;
|
||||
});
|
||||
|
||||
// Modify js file injection paths to use
|
||||
jsFilesToInject = jsFilesToInject.map(function (path) {
|
||||
return '.tmp/public/' + path;
|
||||
});
|
||||
|
||||
|
||||
templateFilesToInject = templateFilesToInject.map(function (path) {
|
||||
return 'assets/' + path;
|
||||
});
|
||||
|
||||
|
||||
// Get path to core grunt dependencies from Sails
|
||||
var depsPath = grunt.option('gdsrc') || 'node_modules/sails/node_modules';
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-clean/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-copy/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-concat/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-sails-linker/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-jst/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-watch/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-uglify/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-cssmin/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-less/tasks');
|
||||
grunt.loadTasks(depsPath + '/grunt-contrib-coffee/tasks');
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
|
||||
copy: {
|
||||
dev: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
cwd: './assets',
|
||||
src: ['**/*.!(coffee)'],
|
||||
dest: '.tmp/public'
|
||||
}
|
||||
]
|
||||
},
|
||||
build: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
cwd: '.tmp/public',
|
||||
src: ['**/*'],
|
||||
dest: 'www'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
clean: {
|
||||
dev: ['.tmp/public/**'],
|
||||
build: ['www']
|
||||
},
|
||||
|
||||
jst: {
|
||||
dev: {
|
||||
|
||||
// To use other sorts of templates, specify the regexp below:
|
||||
// options: {
|
||||
// templateSettings: {
|
||||
// interpolate: /\{\{(.+?)\}\}/g
|
||||
// }
|
||||
// },
|
||||
|
||||
files: {
|
||||
'.tmp/public/jst.js': templateFilesToInject
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
less: {
|
||||
dev: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'assets/styles/',
|
||||
src: ['*.less'],
|
||||
dest: '.tmp/public/styles/',
|
||||
ext: '.css'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'assets/linker/styles/',
|
||||
src: ['*.less'],
|
||||
dest: '.tmp/public/linker/styles/',
|
||||
ext: '.css'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
coffee: {
|
||||
dev: {
|
||||
options:{
|
||||
bare:true
|
||||
},
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
cwd: 'assets/js/',
|
||||
src: ['**/*.coffee'],
|
||||
dest: '.tmp/public/js/',
|
||||
ext: '.js'
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: 'assets/linker/js/',
|
||||
src: ['**/*.coffee'],
|
||||
dest: '.tmp/public/linker/js/',
|
||||
ext: '.js'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
concat: {
|
||||
js: {
|
||||
src: jsFilesToInject,
|
||||
dest: '.tmp/public/concat/production.js'
|
||||
},
|
||||
css: {
|
||||
src: cssFilesToInject,
|
||||
dest: '.tmp/public/concat/production.css'
|
||||
}
|
||||
},
|
||||
|
||||
uglify: {
|
||||
dist: {
|
||||
src: ['.tmp/public/concat/production.js'],
|
||||
dest: '.tmp/public/min/production.js'
|
||||
}
|
||||
},
|
||||
|
||||
cssmin: {
|
||||
dist: {
|
||||
src: ['.tmp/public/concat/production.css'],
|
||||
dest: '.tmp/public/min/production.css'
|
||||
}
|
||||
},
|
||||
|
||||
'sails-linker': {
|
||||
|
||||
devJs: {
|
||||
options: {
|
||||
startTag: '<!--SCRIPTS-->',
|
||||
endTag: '<!--SCRIPTS END-->',
|
||||
fileTmpl: '<script src="%s"></script>',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'.tmp/public/**/*.html': jsFilesToInject,
|
||||
'views/**/*.html': jsFilesToInject,
|
||||
'views/**/*.ejs': jsFilesToInject
|
||||
}
|
||||
},
|
||||
|
||||
prodJs: {
|
||||
options: {
|
||||
startTag: '<!--SCRIPTS-->',
|
||||
endTag: '<!--SCRIPTS END-->',
|
||||
fileTmpl: '<script src="%s"></script>',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'.tmp/public/**/*.html': ['.tmp/public/min/production.js'],
|
||||
'views/**/*.html': ['.tmp/public/min/production.js'],
|
||||
'views/**/*.ejs': ['.tmp/public/min/production.js']
|
||||
}
|
||||
},
|
||||
|
||||
devStyles: {
|
||||
options: {
|
||||
startTag: '<!--STYLES-->',
|
||||
endTag: '<!--STYLES END-->',
|
||||
fileTmpl: '<link rel="stylesheet" href="%s">',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
|
||||
// cssFilesToInject defined up top
|
||||
files: {
|
||||
'.tmp/public/**/*.html': cssFilesToInject,
|
||||
'views/**/*.html': cssFilesToInject,
|
||||
'views/**/*.ejs': cssFilesToInject
|
||||
}
|
||||
},
|
||||
|
||||
prodStyles: {
|
||||
options: {
|
||||
startTag: '<!--STYLES-->',
|
||||
endTag: '<!--STYLES END-->',
|
||||
fileTmpl: '<link rel="stylesheet" href="%s">',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'.tmp/public/index.html': ['.tmp/public/min/production.css'],
|
||||
'views/**/*.html': ['.tmp/public/min/production.css'],
|
||||
'views/**/*.ejs': ['.tmp/public/min/production.css']
|
||||
}
|
||||
},
|
||||
|
||||
// Bring in JST template object
|
||||
devTpl: {
|
||||
options: {
|
||||
startTag: '<!--TEMPLATES-->',
|
||||
endTag: '<!--TEMPLATES END-->',
|
||||
fileTmpl: '<script type="text/javascript" src="%s"></script>',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'.tmp/public/index.html': ['.tmp/public/jst.js'],
|
||||
'views/**/*.html': ['.tmp/public/jst.js'],
|
||||
'views/**/*.ejs': ['.tmp/public/jst.js']
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/*******************************************
|
||||
* Jade linkers (TODO: clean this up)
|
||||
*******************************************/
|
||||
|
||||
devJsJADE: {
|
||||
options: {
|
||||
startTag: '// SCRIPTS',
|
||||
endTag: '// SCRIPTS END',
|
||||
fileTmpl: 'script(type="text/javascript", src="%s")',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'views/**/*.jade': jsFilesToInject
|
||||
}
|
||||
},
|
||||
|
||||
prodJsJADE: {
|
||||
options: {
|
||||
startTag: '// SCRIPTS',
|
||||
endTag: '// SCRIPTS END',
|
||||
fileTmpl: 'script(type="text/javascript", src="%s")',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'views/**/*.jade': ['.tmp/public/min/production.js']
|
||||
}
|
||||
},
|
||||
|
||||
devStylesJADE: {
|
||||
options: {
|
||||
startTag: '// STYLES',
|
||||
endTag: '// STYLES END',
|
||||
fileTmpl: 'link(rel="stylesheet", href="%s")',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'views/**/*.jade': cssFilesToInject
|
||||
}
|
||||
},
|
||||
|
||||
prodStylesJADE: {
|
||||
options: {
|
||||
startTag: '// STYLES',
|
||||
endTag: '// STYLES END',
|
||||
fileTmpl: 'link(rel="stylesheet", href="%s")',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'views/**/*.jade': ['.tmp/public/min/production.css']
|
||||
}
|
||||
},
|
||||
|
||||
// Bring in JST template object
|
||||
devTplJADE: {
|
||||
options: {
|
||||
startTag: '// TEMPLATES',
|
||||
endTag: '// TEMPLATES END',
|
||||
fileTmpl: 'script(type="text/javascript", src="%s")',
|
||||
appRoot: '.tmp/public'
|
||||
},
|
||||
files: {
|
||||
'views/**/*.jade': ['.tmp/public/jst.js']
|
||||
}
|
||||
}
|
||||
/************************************
|
||||
* Jade linker end
|
||||
************************************/
|
||||
},
|
||||
|
||||
watch: {
|
||||
api: {
|
||||
|
||||
// API files to watch:
|
||||
files: ['api/**/*']
|
||||
},
|
||||
assets: {
|
||||
|
||||
// Assets to watch:
|
||||
files: ['assets/**/*'],
|
||||
|
||||
// When assets are changed:
|
||||
tasks: ['compileAssets', 'linkAssets']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// When Sails is lifted:
|
||||
grunt.registerTask('default', [
|
||||
'compileAssets',
|
||||
'linkAssets',
|
||||
'watch'
|
||||
]);
|
||||
|
||||
grunt.registerTask('compileAssets', [
|
||||
'clean:dev',
|
||||
'jst:dev',
|
||||
'less:dev',
|
||||
'copy:dev',
|
||||
'coffee:dev'
|
||||
]);
|
||||
|
||||
grunt.registerTask('linkAssets', [
|
||||
|
||||
// Update link/script/template references in `assets` index.html
|
||||
'sails-linker:devJs',
|
||||
'sails-linker:devStyles',
|
||||
'sails-linker:devTpl',
|
||||
'sails-linker:devJsJADE',
|
||||
'sails-linker:devStylesJADE',
|
||||
'sails-linker:devTplJADE'
|
||||
]);
|
||||
|
||||
|
||||
// Build the assets into a web accessible folder.
|
||||
// (handy for phone gap apps, chrome extensions, etc.)
|
||||
grunt.registerTask('build', [
|
||||
'compileAssets',
|
||||
'linkAssets',
|
||||
'clean:build',
|
||||
'copy:build'
|
||||
]);
|
||||
|
||||
// When sails is lifted in production
|
||||
grunt.registerTask('prod', [
|
||||
'clean:dev',
|
||||
'jst:dev',
|
||||
'less:dev',
|
||||
'copy:dev',
|
||||
'coffee:dev',
|
||||
'concat',
|
||||
'uglify',
|
||||
'cssmin',
|
||||
'sails-linker:prodJs',
|
||||
'sails-linker:prodStyles',
|
||||
'sails-linker:devTpl',
|
||||
'sails-linker:prodJsJADE',
|
||||
'sails-linker:prodStylesJADE',
|
||||
'sails-linker:devTplJADE'
|
||||
]);
|
||||
|
||||
// When API files are changed:
|
||||
// grunt.event.on('watch', function(action, filepath) {
|
||||
// grunt.log.writeln(filepath + ' has ' + action);
|
||||
|
||||
// // Send a request to a development-only endpoint on the server
|
||||
// // which will reuptake the file that was changed.
|
||||
// var baseurl = grunt.option('baseurl');
|
||||
// var gruntSignalRoute = grunt.option('signalpath');
|
||||
// var url = baseurl + gruntSignalRoute + '?action=' + action + '&filepath=' + filepath;
|
||||
|
||||
// require('http').get(url)
|
||||
// .on('error', function(e) {
|
||||
// console.error(filepath + ' has ' + action + ', but could not signal the Sails.js server: ' + e.message);
|
||||
// });
|
||||
// });
|
||||
};
|
||||
2
README.bak.md
Normal file
2
README.bak.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# lunch
|
||||
### a Sails application
|
||||
0
api/adapters/.gitkeep
Normal file
0
api/adapters/.gitkeep
Normal file
0
api/controllers/.gitkeep
Normal file
0
api/controllers/.gitkeep
Normal file
0
api/models/.gitkeep
Normal file
0
api/models/.gitkeep
Normal file
21
api/policies/isAuthenticated.js
Normal file
21
api/policies/isAuthenticated.js
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* isAuthenticated
|
||||
*
|
||||
* @module :: Policy
|
||||
* @description :: Simple policy to allow any authenticated user
|
||||
* Assumes that your login action in one of your controllers sets `req.session.authenticated = true;`
|
||||
* @docs :: http://sailsjs.org/#!documentation/policies
|
||||
*
|
||||
*/
|
||||
module.exports = function(req, res, next) {
|
||||
|
||||
// User is allowed, proceed to the next policy,
|
||||
// or if this is the last policy, the controller
|
||||
if (req.session.authenticated) {
|
||||
return next();
|
||||
}
|
||||
|
||||
// User is not allowed
|
||||
// (default res.forbidden() behavior can be overridden in `config/403.js`)
|
||||
return res.forbidden('You are not permitted to perform this action.');
|
||||
};
|
||||
0
api/services/.gitkeep
Normal file
0
api/services/.gitkeep
Normal file
2
app.js
Normal file
2
app.js
Normal file
@@ -0,0 +1,2 @@
|
||||
// Start sails and pass it command line arguments
|
||||
require('sails').lift(require('optimist').argv);
|
||||
BIN
assets/favicon.ico
Normal file
BIN
assets/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 920 B |
0
assets/images/.gitkeep
Normal file
0
assets/images/.gitkeep
Normal file
0
assets/js/.gitkeep
Normal file
0
assets/js/.gitkeep
Normal file
71
assets/js/app.js
Normal file
71
assets/js/app.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* app.js
|
||||
*
|
||||
* This file contains some conventional defaults for working with Socket.io + Sails.
|
||||
* It is designed to get you up and running fast, but is by no means anything special.
|
||||
*
|
||||
* Feel free to change none, some, or ALL of this file to fit your needs!
|
||||
*/
|
||||
|
||||
|
||||
(function (io) {
|
||||
|
||||
// as soon as this file is loaded, connect automatically,
|
||||
var socket = io.connect();
|
||||
if (typeof console !== 'undefined') {
|
||||
log('Connecting to Sails.js...');
|
||||
}
|
||||
|
||||
socket.on('connect', function socketConnected() {
|
||||
|
||||
// Listen for Comet messages from Sails
|
||||
socket.on('message', function messageReceived(message) {
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Replace the following with your own custom logic
|
||||
// to run when a new message arrives from the Sails.js
|
||||
// server.
|
||||
///////////////////////////////////////////////////////////
|
||||
log('New comet message received :: ', message);
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
});
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Here's where you'll want to add any custom logic for
|
||||
// when the browser establishes its socket connection to
|
||||
// the Sails.js server.
|
||||
///////////////////////////////////////////////////////////
|
||||
log(
|
||||
'Socket is now connected and globally accessible as `socket`.\n' +
|
||||
'e.g. to send a GET request to Sails, try \n' +
|
||||
'`socket.get("/", function (response) ' +
|
||||
'{ console.log(response); })`'
|
||||
);
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Expose connected `socket` instance globally so that it's easy
|
||||
// to experiment with from the browser console while prototyping.
|
||||
window.socket = socket;
|
||||
|
||||
|
||||
// Simple log function to keep the example simple
|
||||
function log () {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
})(
|
||||
|
||||
// In case you're wrapping socket.io to prevent pollution of the global namespace,
|
||||
// you can replace `window.io` with your own `io` here:
|
||||
window.io
|
||||
|
||||
);
|
||||
166
assets/js/sails.io.js
Normal file
166
assets/js/sails.io.js
Normal file
@@ -0,0 +1,166 @@
|
||||
/**
|
||||
* sails.io.js
|
||||
*
|
||||
* This file allows you to send and receive socket.io messages to & from Sails
|
||||
* by simulating a REST client interface on top of socket.io.
|
||||
*
|
||||
* It models its API after the $.ajax pattern from jQuery you might be familiar with.
|
||||
*
|
||||
* So to switch from using AJAX to Socket.io, instead of:
|
||||
* `$.post( url, [data], [cb] )`
|
||||
*
|
||||
* You would use:
|
||||
* `socket.post( url, [data], [cb] )`
|
||||
*
|
||||
* For more information, visit:
|
||||
* http://sailsjs.org/#documentation
|
||||
*/
|
||||
|
||||
(function (io) {
|
||||
|
||||
|
||||
// We'll be adding methods to `io.SocketNamespace.prototype`, the prototype for the
|
||||
// Socket instance returned when the browser connects with `io.connect()`
|
||||
var Socket = io.SocketNamespace;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simulate a GET request to sails
|
||||
* e.g.
|
||||
* `socket.get('/user/3', Stats.populate)`
|
||||
*
|
||||
* @param {String} url :: destination URL
|
||||
* @param {Object} params :: parameters to send with the request [optional]
|
||||
* @param {Function} cb :: callback function to call when finished [optional]
|
||||
*/
|
||||
|
||||
Socket.prototype.get = function (url, data, cb) {
|
||||
return this.request(url, data, cb, 'get');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simulate a POST request to sails
|
||||
* e.g.
|
||||
* `socket.post('/event', newMeeting, $spinner.hide)`
|
||||
*
|
||||
* @param {String} url :: destination URL
|
||||
* @param {Object} params :: parameters to send with the request [optional]
|
||||
* @param {Function} cb :: callback function to call when finished [optional]
|
||||
*/
|
||||
|
||||
Socket.prototype.post = function (url, data, cb) {
|
||||
return this.request(url, data, cb, 'post');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simulate a PUT request to sails
|
||||
* e.g.
|
||||
* `socket.post('/event/3', changedFields, $spinner.hide)`
|
||||
*
|
||||
* @param {String} url :: destination URL
|
||||
* @param {Object} params :: parameters to send with the request [optional]
|
||||
* @param {Function} cb :: callback function to call when finished [optional]
|
||||
*/
|
||||
|
||||
Socket.prototype.put = function (url, data, cb) {
|
||||
return this.request(url, data, cb, 'put');
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simulate a DELETE request to sails
|
||||
* e.g.
|
||||
* `socket.delete('/event', $spinner.hide)`
|
||||
*
|
||||
* @param {String} url :: destination URL
|
||||
* @param {Object} params :: parameters to send with the request [optional]
|
||||
* @param {Function} cb :: callback function to call when finished [optional]
|
||||
*/
|
||||
|
||||
Socket.prototype['delete'] = function (url, data, cb) {
|
||||
return this.request(url, data, cb, 'delete');
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simulate HTTP over Socket.io
|
||||
* @api private :: but exposed for backwards compatibility w/ <= sails@~0.8
|
||||
*/
|
||||
|
||||
Socket.prototype.request = request;
|
||||
function request (url, data, cb, method) {
|
||||
|
||||
var socket = this;
|
||||
|
||||
var usage = 'Usage:\n socket.' +
|
||||
(method || 'request') +
|
||||
'( destinationURL, dataToSend, fnToCallWhenComplete )';
|
||||
|
||||
// Remove trailing slashes and spaces
|
||||
url = url.replace(/^(.+)\/*\s*$/, '$1');
|
||||
|
||||
// If method is undefined, use 'get'
|
||||
method = method || 'get';
|
||||
|
||||
|
||||
if ( typeof url !== 'string' ) {
|
||||
throw new Error('Invalid or missing URL!\n' + usage);
|
||||
}
|
||||
|
||||
// Allow data arg to be optional
|
||||
if ( typeof data === 'function' ) {
|
||||
cb = data;
|
||||
data = {};
|
||||
}
|
||||
|
||||
// Build to request
|
||||
var json = io.JSON.stringify({
|
||||
url: url,
|
||||
data: data
|
||||
});
|
||||
|
||||
|
||||
// Send the message over the socket
|
||||
socket.emit(method, json, function afterEmitted (result) {
|
||||
|
||||
var parsedResult = result;
|
||||
|
||||
if (result && typeof result === 'string') {
|
||||
try {
|
||||
parsedResult = io.JSON.parse(result);
|
||||
} catch (e) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.warn("Could not parse:", result, e);
|
||||
}
|
||||
throw new Error("Server response could not be parsed!\n" + result);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Handle errors more effectively
|
||||
if (parsedResult === 404) throw new Error("404: Not found");
|
||||
if (parsedResult === 403) throw new Error("403: Forbidden");
|
||||
if (parsedResult === 500) throw new Error("500: Server error");
|
||||
|
||||
cb && cb(parsedResult);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}) (
|
||||
|
||||
// In case you're wrapping socket.io to prevent pollution of the global namespace,
|
||||
// you can replace `window.io` with your own `io` here:
|
||||
window.io
|
||||
|
||||
);
|
||||
3328
assets/js/socket.io.js
Normal file
3328
assets/js/socket.io.js
Normal file
File diff suppressed because it is too large
Load Diff
6
assets/robots.txt
Normal file
6
assets/robots.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# The robots.txt file is used to control how search engines index your live URLs.
|
||||
# See http://www.robotstxt.org/wc/norobots.html for more information.
|
||||
#
|
||||
# To prevent search engines from seeing the site altogether, uncomment the next two lines:
|
||||
# User-Agent: *
|
||||
# Disallow: /
|
||||
0
assets/styles/.gitkeep
Normal file
0
assets/styles/.gitkeep
Normal file
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'
|
||||
|
||||
|
||||
};
|
||||
21
package.json
Normal file
21
package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "lunch",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"description": "a Sails application",
|
||||
"dependencies": {
|
||||
"sails": "0.9.9",
|
||||
"grunt": "0.4.1",
|
||||
"sails-disk": "~0.9.0",
|
||||
"ejs": "0.8.4",
|
||||
"optimist": "0.3.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app.js",
|
||||
"debug": "node debug app.js"
|
||||
},
|
||||
"main": "app.js",
|
||||
"repository": "",
|
||||
"author": "",
|
||||
"license": ""
|
||||
}
|
||||
76
views/403.ejs
Normal file
76
views/403.ejs
Normal file
@@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
|
||||
|
||||
444444444 000000000 333333333333333
|
||||
4::::::::4 00:::::::::00 3:::::::::::::::33
|
||||
4:::::::::4 00:::::::::::::00 3::::::33333::::::3
|
||||
4::::44::::4 0:::::::000:::::::03333333 3:::::3
|
||||
4::::4 4::::4 0::::::0 0::::::0 3:::::3
|
||||
4::::4 4::::4 0:::::0 0:::::0 3:::::3
|
||||
4::::4 4::::4 0:::::0 0:::::0 33333333:::::3
|
||||
4::::444444::::4440:::::0 000 0:::::0 3:::::::::::3
|
||||
4::::::::::::::::40:::::0 000 0:::::0 33333333:::::3
|
||||
4444444444:::::4440:::::0 0:::::0 3:::::3
|
||||
4::::4 0:::::0 0:::::0 3:::::3
|
||||
4::::4 0::::::0 0::::::0 3:::::3
|
||||
4::::4 0:::::::000:::::::03333333 3:::::3
|
||||
44::::::44 00:::::::::::::00 3::::::33333::::::3
|
||||
4::::::::4 00:::::::::00 3:::::::::::::::33
|
||||
4444444444 000000000 333333333333333
|
||||
|
||||
|
||||
|
||||
This is the default "403: Forbidden" page.
|
||||
User agents that don't "Accept" HTML will see a JSON version instead.
|
||||
You can customize the control logic for your needs in `config/403.js`
|
||||
|
||||
You can trigger this response from one of your controllers or policies with:
|
||||
`return res.forbidden( msg );`
|
||||
(where `msg` is an optional error message to include in the response)
|
||||
|
||||
|
||||
|
||||
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Forbidden</title>
|
||||
<link href='http://sailsjs.org/styles/fonts.css' rel='stylesheet'/>
|
||||
<style>
|
||||
/* Styles included inline since you'll probably be deleting or replacing this page anyway */
|
||||
html,body{text-align:left;font-size:1em}html,body,img,form,textarea,input,fieldset,div,p,div,ul,li,ol,dl,dt,dd,h1,h2,h3,h4,h5,h6,pre,code{margin:0;padding:0}ul,li{list-style:none}img{display:block}a img{border:0}a{text-decoration:none;font-weight:normal;font-family:inherit}*:active,*:focus{outline:0;-moz-outline-style:none}h1,h2,h3,h4,h5,h6,h7{font-weight:normal;font-size:1em}.clearfix:after{clear:both;content:".";display:block;font-size:0;height:0;line-height:0;visibility:hidden}.page .ocean{background:url('http://sailsjs.com/images/waves.png') #0c8da0 no-repeat center 0;height:315px}.page .ocean img{margin-right:auto;margin-left:auto}.page .waves{display:block;padding-top:25px;margin-right:auto;margin-left:auto}.page .main{display:block;margin-top:90px}.page .logo{width:150px;margin-top:3.5em;margin-left:auto;margin-right:auto}.page .fishy{display:block;padding-top:100px}.page .help{padding-top:2em}.page h1{font-family:"Open Sans","Myriad Pro",Arial,sans-serif;font-weight:bold;font-size:1.7em;color:#001c20;text-align:center}.page h2{font-family:"Open Sans","Myriad Pro",Arial,sans-serif;font-weight:300;font-size:1.5em;color:#001c20;text-align:center}.page p{font-family:"Open Sans","Myriad Pro",Arial,sans-serif;font-size:1.25em;color:#001c20;text-align:center}.page a{color:#118798}.page a:hover{color:#b1eef7}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="page">
|
||||
<div class="ocean">
|
||||
<img class="fishy" src="http://sailsjs.com/images/image_devInTub.png">
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<h1>
|
||||
Forbidden
|
||||
</h1>
|
||||
<h2>
|
||||
<% if (typeof message !== 'undefined') { %>
|
||||
<%= message %>
|
||||
<% } else { %>
|
||||
You don't have permission to see the page you're trying to reach.
|
||||
<% } %>
|
||||
</h2>
|
||||
<p class="help">
|
||||
<a href="http://en.wikipedia.org/wiki/HTTP_403">Why</a> might this be happening?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="logo">
|
||||
<a href="http://sailsjs.org">
|
||||
<img src="http://sailsjs.org/images/logo.png">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
72
views/404.ejs
Normal file
72
views/404.ejs
Normal file
@@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
|
||||
|
||||
444444444 000000000 444444444
|
||||
4::::::::4 00:::::::::00 4::::::::4
|
||||
4:::::::::4 00:::::::::::::00 4:::::::::4
|
||||
4::::44::::4 0:::::::000:::::::0 4::::44::::4
|
||||
4::::4 4::::4 0::::::0 0::::::0 4::::4 4::::4
|
||||
4::::4 4::::4 0:::::0 0:::::0 4::::4 4::::4
|
||||
4::::4 4::::4 0:::::0 0:::::0 4::::4 4::::4
|
||||
4::::444444::::4440:::::0 000 0:::::04::::444444::::444
|
||||
4::::::::::::::::40:::::0 000 0:::::04::::::::::::::::4
|
||||
4444444444:::::4440:::::0 0:::::04444444444:::::444
|
||||
4::::4 0:::::0 0:::::0 4::::4
|
||||
4::::4 0::::::0 0::::::0 4::::4
|
||||
4::::4 0:::::::000:::::::0 4::::4
|
||||
44::::::44 00:::::::::::::00 44::::::44
|
||||
4::::::::4 00:::::::::00 4::::::::4
|
||||
4444444444 000000000 4444444444
|
||||
|
||||
|
||||
|
||||
This is the default "404: Not Found" page.
|
||||
User agents that don't "Accept" HTML will see a JSON version instead.
|
||||
You can customize the control logic for your needs in `config/404.js`
|
||||
|
||||
Sails considers a request to be in a "404: Not Found" state when a user
|
||||
requests a URL which doesn't match any of your app's routes or blueprints.
|
||||
|
||||
You can also trigger this response from one of your controllers or policies with:
|
||||
`return res.notFound();`
|
||||
|
||||
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Page Not Found</title>
|
||||
<link href='http://sailsjs.org/styles/fonts.css' rel='stylesheet'/>
|
||||
<style>
|
||||
/* Styles included inline since you'll probably be deleting this page anyway */
|
||||
html,body{text-align:left;font-size:1em}html,body,img,form,textarea,input,fieldset,div,p,div,ul,li,ol,dl,dt,dd,h1,h2,h3,h4,h5,h6,pre,code{margin:0;padding:0}ul,li{list-style:none}img{display:block}a img{border:0}a{text-decoration:none;font-weight:normal;font-family:inherit}*:active,*:focus{outline:0;-moz-outline-style:none}h1,h2,h3,h4,h5,h6,h7{font-weight:normal;font-size:1em}.clearfix:after{clear:both;content:".";display:block;font-size:0;height:0;line-height:0;visibility:hidden}.fourohfour .ocean{background:url('http://sailsjs.com/images/waves.png') #0c8da0 no-repeat center 0;height:315px}.fourohfour .ocean img{margin-right:auto;margin-left:auto}.fourohfour .waves{display:block;padding-top:25px;margin-right:auto;margin-left:auto}.fourohfour .main{display:block;margin-top:90px}.fourohfour .logo{width:150px;margin-top:3.5em;margin-left:auto;margin-right:auto}.fourohfour .fishy{display:block;padding-top:27px}.fourohfour .help{padding-top:2em}.fourohfour h1{font-family:"Open Sans","Myriad Pro",Arial,sans-serif;font-weight:bold;font-size:1.7em;color:#001c20;text-align:center}.fourohfour h2{font-family:"Open Sans","Myriad Pro",Arial,sans-serif;font-weight:300;font-size:1.5em;color:#001c20;text-align:center}.fourohfour p{font-family:"Open Sans","Myriad Pro",Arial,sans-serif;font-size:1.25em;color:#001c20;text-align:center}.fourohfour a{color:#118798}.fourohfour a:hover{color:#b1eef7}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="fourohfour">
|
||||
<div class="ocean">
|
||||
<img class="fishy" src="http://sailsjs.org/images/fishy4.png">
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<h1>
|
||||
Something's fishy here.
|
||||
</h1>
|
||||
<h2>
|
||||
The page you were trying to reach doesn't exist.
|
||||
</h2>
|
||||
<p class="help">
|
||||
<a href="http://en.wikipedia.org/wiki/HTTP_404">Why</a> might this be happening?
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="logo">
|
||||
<a href="http://sailsjs.org">
|
||||
<img src="http://sailsjs.org/images/logo.png">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
86
views/500.ejs
Normal file
86
views/500.ejs
Normal file
File diff suppressed because one or more lines are too long
93
views/home/index.ejs
Normal file
93
views/home/index.ejs
Normal file
@@ -0,0 +1,93 @@
|
||||
<!-- Default home page -->
|
||||
<link type="text/css" href='http://sailsjs.org/styles/fonts.css' rel='stylesheet'/>
|
||||
<style>
|
||||
/* Styles included inline since you'll probably be deleting this page anyway */
|
||||
html,body{text-align:left;font-size:1em}html,body,img,form,textarea,input,fieldset,div,p,div,ul,li,ol,dl,dt,dd,h1,h2,h3,h4,h5,h6,pre,code{margin:0;padding:0}ul,li{list-style:none}img{display:block}a img{border:0}a{text-decoration:none;font-weight:normal;font-family:inherit}*:active,*:focus{outline:0;-moz-outline-style:none}h1,h2,h3,h4,h5,h6{font-weight:normal}div.clear{clear:both}.clearfix:after{clear:both;content:".";display:block;font-size:0;height:0;line-height:0;visibility:hidden}body{font-family:"Open Sans",Arial,sans-serif;font-weight:300;font-size:15px}h1{color:#0c8da0;font-size:2em;font-weight:300}h2{font-size:1.5em;font-weight:300;margin-top:4%}h3{font-size:1.25em;font-weight:300;font-style:italic;margin-bottom:5px}h4{color:#0c8da0;font-weight:300;font-size:1.5em}span{font-weight:700}ul{margin-top:5%;margin-bottom:5%}a{text-decoration:none;color:inherit}p{margin-bottom:7px;font-size:.9em}.container{max-width:997px;margin:0 auto;padding:0 4%}.sprite{font-weight:normal;background:url(http://sailsjs.org/images/newapp.sprite.png) no-repeat}.top-bar{position:relative;padding-top:10px;background-color:#001c20;height:55px}.main{float:left;max-width:610px;height:555px;margin-top:50px}.steps{height:250px}.getting-started p{ margin-bottom: 30px; line-height: 26px; }.getting-started div{float:left;width:540px}.getting-started li{clear:both;height:60px;margin-top:20px;margin-bottom:20px}.getting-started .sprite{margin-left:10px;padding-left:60px;height:42px;width:0}.getting-started .one{background-position:0 0}.getting-started .two{background-position:0 -42px}.getting-started .three{background-position:0 -83px}.delete{margin-top:5%;height:52px;background:#e3f0f1;border:1px solid #118798;color:#118798;clear:both}.delete .sprite{margin-top:10px;margin-bottom:10px;margin-left:9%;padding-left:42px;padding-top:7px;height:25px;background-position:0 -126px}.delete a{color:#0c8da0;font-weight:bold;padding-left:1%}.side-bar{max-width:327px;height:555px;float:left;border-left:1px solid #0c8da0;margin-left:25px;margin-top:50px;padding-left:25px}.side-bar ul{margin-bottom:10%}.side-bar ul li{margin-top:5px;margin-bottom:.25em}.side-bar ul li a{margin-bottom:.25em}.side-bar .sprite{padding-left:25px}.side-bar .single_page{background-position:0 -199px}.side-bar .traditional{background-position:0 -219px}.side-bar .realtime{background-position:0 -179px}.side-bar .api{background-position:0 -158px}.boxy{font-family:Courier,"Courier New",sans-serif;background-color:#e4edec;border:1px solid #d0d6d6;padding-left:5px;padding-right:5px;padding-top:2px;padding-bottom:2px;font-weight:100}.sixteen{margin-right:10px}.nineteen{margin-right:7px}
|
||||
.main { width: 100%; }
|
||||
body { min-width: 925px; }
|
||||
</style>
|
||||
<!--[if IE 7]>
|
||||
<style>
|
||||
.getting-started li{overflow:visible;clear:both}.delete{width:690px}
|
||||
</style>
|
||||
<![endif]-->
|
||||
|
||||
<div class="top-bar">
|
||||
<div class="container clearfix">
|
||||
<img class="logo" src="http://sailsjs.org/images/sails-logo.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container clearfix">
|
||||
<div class="main">
|
||||
<h1 id="main-title"><%= __('Welcome') %></h1>
|
||||
<h2>Getting started</h2>
|
||||
<p>Don't worry, we've got your back.</p>
|
||||
<div class="steps">
|
||||
<ul class="getting-started">
|
||||
<li>
|
||||
<div class="sprite one"></div>
|
||||
<div>
|
||||
<h3>Get your API going.</h3>
|
||||
<p>
|
||||
Run <span class="boxy">sails generate foo</span>. This will create a model <span class="boxy">Foo</span> and controller <span class="boxy">FooController</span>
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="sprite two"></div>
|
||||
<div>
|
||||
<h3>
|
||||
Lift your app.
|
||||
</h3>
|
||||
<p>
|
||||
Run <span class="boxy">sails lift</span> to start up your app. If you visit <span class="boxy">http://localhost:1337/foo</span> in your browser, you'll see a socket.io-compatible REST API was generated for your 'Foo' model.
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="sprite three"></div>
|
||||
<div>
|
||||
<h3>
|
||||
Dive in and start building.
|
||||
</h3>
|
||||
<p>From here, you can modify your models, create custom controller methods as Express middleware, and create custom routes (routes are set up in <span class="boxy">config/routes.js</span>). Visit <a href="http://sailsjs.org">the Sails website</a> for more information on next steps.</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="delete">
|
||||
<div class="sprite">You're looking at: <span class="boxy">views/home/index.ejs</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="side-bar">
|
||||
<h4 id="new">
|
||||
New to Sails?
|
||||
</h4>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://sailsjs.org">Visit sailsjs.org</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://sailsjs.org/#!documentation">Documentation</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h4>
|
||||
Next Steps
|
||||
</h4>
|
||||
<ul>
|
||||
<li class="sprite single_page">
|
||||
<a target="_blank" href="http://sailsjs.org">Build a single page app</a>
|
||||
</li>
|
||||
<li class="sprite traditional">
|
||||
<a target="_blank" href="http://sailsjs.org">Build a traditional webapp</a>
|
||||
</li>
|
||||
<li class="sprite realtime">
|
||||
<a target="_blank" href="http://sailsjs.org">Build a realtime app</a>
|
||||
</li>
|
||||
<li class="sprite api">
|
||||
<a target="_blank" href="http://sailsjs.org">Build an API</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
96
views/layout.ejs
Normal file
96
views/layout.ejs
Normal file
@@ -0,0 +1,96 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
For demonstration purposes, the `title` is dynamically set here based on
|
||||
your `sails.config.appName` to show that you can inject data into layouts
|
||||
exactly the same way as with your other view templates.
|
||||
-->
|
||||
<title><%- title %></title>
|
||||
|
||||
<!-- Viewport mobile tag for sensible mobile support -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
||||
|
||||
<!--
|
||||
|
||||
Stylesheets
|
||||
========================
|
||||
|
||||
You can link any CSS, LESS, or image files in your `assets` directory
|
||||
as you would normally: using <link/> tags.
|
||||
|
||||
-->
|
||||
|
||||
<!--
|
||||
|
||||
Support for LESS included by default
|
||||
================================================
|
||||
|
||||
LESS files are automatically compiled when they change using the Gruntfile
|
||||
located in the top-level of this Sails app. If you run into issues with styles
|
||||
not reloading, check the Sails log output in your console for LESS compilation errors.
|
||||
If necessary, shut down and then lift your app again.
|
||||
|
||||
-->
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- Include the view file for the current controller/route -->
|
||||
<%- body %>
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Client-side Javascript
|
||||
========================
|
||||
|
||||
You can import any js files in your `assets` directory as you would
|
||||
normally: using <script></script> tags.
|
||||
|
||||
Here's an example of importing a few dependencies, in order:
|
||||
-->
|
||||
<!-- Bring in the socket.io client -->
|
||||
<script type="text/javascript" src="/js/socket.io.js"></script>
|
||||
<!-- then beef it up with some convenience logic for talking to Sails.js -->
|
||||
<script type="text/javascript" src="/js/sails.io.js"></script>
|
||||
<!-- listen on socket.io for incoming messages -->
|
||||
<script type="text/javascript" src="/js/app.js"></script>
|
||||
|
||||
<!-- Your scripts here? -->
|
||||
<!-- Your scripts here? -->
|
||||
<!-- Your scripts here? -->
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Looking for client-side CoffeeScript or TypeScript?
|
||||
================================================
|
||||
|
||||
CoffeeScript and TypeScript precompilation are not installed by default,
|
||||
but if you'd like to mix those features in, it is straightforward to
|
||||
`npm install` the relevant grunt community modules and modify your Gruntfile
|
||||
to use them.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Another way: The Asset Linker
|
||||
========================
|
||||
|
||||
Sails supports a Grunt-based asset linker, to automatically inject
|
||||
<link> and <script> tags, as well any client-side templates you're using
|
||||
into your HTML layouts and views, respecting dependencies.
|
||||
|
||||
You created this Sails app with the asset linker disabled.
|
||||
If you change your mind, check out the docs on the subject:
|
||||
http://sailsjs.org/#!documentation/asset-management
|
||||
|
||||
-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user