Skip to content

Instantly share code, notes, and snippets.

@tbjers
Last active December 20, 2015 16:29
Show Gist options
  • Save tbjers/6162027 to your computer and use it in GitHub Desktop.
Save tbjers/6162027 to your computer and use it in GitHub Desktop.
Node.js: Scaffolding Modern Web Applications with Flatiron
<!DOCTYPE html>
<html>
<head>
<title>Flatiron Example</title>
</head>
<body>
<div id="body"></div>
</body>
</html>
var path = require('path')
, flatiron = require('flatiron')
, plates = require('plates')
, resourceful = require('resourceful')
, restful = require('restful')
, views = require('./app/plugins/plates.js')
, controllers = require('./app/plugins/controllers.js')
, app = module.exports = flatiron.app
, env = process.env.NODE_ENV || 'development'
// Configuration file
app.config.file({ file: path.join(__dirname, 'config.json') })
// Load HTTP plugin
app.use(flatiron.plugins.http, {
headers: {
'x-powered-by': 'flatiron-' + flatiron.version
}
})
// Use resourceful plugin, automatically loads resources
app.use(flatiron.plugins.resourceful, { root: __dirname })
// Use plates plugin to support layouts and views
app.use(views, { root: __dirname })
// Use controllers plugin to set up routes
app.use(controllers, { root: __dirname })
// Use RESTful Director
app.use(restful, app.config.get('restful') || {})
// Start application
app.start(app.config.get('port') || 4000, function (err) {
if (err) {
app.log.err(err)
throw err
}
var addr = app.server.address()
app.log.info('Server started on http://' + addr.address + ':' + addr.port + ' in ' + env)
})
{
"port": "8000"
, "restful": {
"strict": true
, "explore": true
, "prefix": "api"
}
, "resourceful": {
"engine": "couchdb"
, "uri": "couchdb://localhost:5984/<DATABASE>"
, "auth": "<USER>:<PASS>"
}
}
var path = require('path'),
fs = require('fs'),
flatiron = require('flatiron'),
common = flatiron.common,
existsSync = fs.existsSync || path.existsSync
exports.name = 'controllers'
exports.attach = function (options) {
var app = this
options = options || {}
//
// Accept string `options`.
//
if (typeof options === 'string')
options = { root: options }
app.controllers = app.controllers || {}
//
// Load the controllers directory based on a few intelligent defaults:
//
// * `options.dir`: Explicit path to controllers directory
// * `options.root`: Relative root to the controllers directory ('/app/controllers')
// * `app.root`: Relative root to the controllers directory ('/app/controllers')
//
if (options.dir || options.root || app.root) {
app._controllerDir = options.dir
|| path.join(options.root || app.root, 'app', 'controllers')
try {
existsSync(app._controllerDir)
}
catch (err) {
console.error('invalid controller path: ' + app._controllerDir)
return
}
var files = common.tryReaddirSync(app._controllerDir)
if (files.length === 0)
console.warn('no controllers found at: ' + app._controllerDir)
files.forEach(function (file) {
file = file.replace('.js', '')
delete app.controllers[common.capitalize(file)]
app.controllers[common.capitalize(file)] = require(
path.resolve(app._controllerDir, file)
)
app.controllers[common.capitalize(file)].init()
})
}
}
exports.init = function (done) {
var app = this
, options
//
// Attempt to merge defaults passed to `app.use(flatiron.plugins.controllers)`
// with any additional configuration that may have been loaded.
//
options = common.mixin(
{}
, app.options['controllers']
, app.config.get('controllers') || {}
)
app.config.set('controllers', options)
done()
}
var flatiron = require('flatiron')
, app = flatiron.app
var indexGet = function () {
var req = this.req
, res = this.res
res.writeHead(200, { 'content-type': 'text/html' })
res.end(app.view('index'))
}
module.exports.init = function () {
app.router.get('/', indexGet)
}
<h1>Aenean Nullam Tristique</h1>
<p>Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Curabitur blandit tempus porttitor. Donec id elit non mi porta gravida at eget metus. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
{
"name": "flatiron-example"
, "version": "0.0.0"
, "dependencies": {
"flatiron": "0.3.8"
, "plates": "0.4.8"
, "resourceful": "0.3.3"
, "restful": "0.4.4"
, "union": "0.3.7"
}
}
/*
* plates.js: Top-level plugin for exposing plates to flatiron app
*
* Original version here:
* https://github.com/flatiron/flatiron/blob/scaffolding/lib/flatiron/plugins/plates.js
*
* (C) 2011, Nodejitsu Inc.
* MIT LICENSE
*
* Modified by @xorcode
*/
var path = require('path')
, fs = require('fs')
, flatiron = require('flatiron')
, plates
try {
//
// Attempt to require plates
//
plates = require('plates')
}
catch (ex) {
//
// Do nothing since this is a progressive enhancement
//
console.warn('flatiron.plugins.plates requires the `plates` module from npm')
console.warn('install using `npm install plates`.')
console.trace()
process.exit(1)
}
exports.name = 'plates'
exports.attach = function (options) {
var app = this
if (!options) options = {}
exports._platesDir = options.dir || path.join(options.root, 'app', 'views')
exports._layoutsDir = options.layouts || path.join(exports._platesDir, 'layouts')
exports._defaultLayout = options.layout || 'app'
exports._extname = options.extname || '.html'
exports._cachedViews = {}
exports._cachedLayouts = {}
app.view = function (view, data, options) {
var layout
, html
if (!options) options = {}
if (process.env.NODE_ENV != 'production') {
exports._cachedViews = {}
exports._cachedLayouts = {}
}
layout = options.layout || exports._defaultLayout
if (!exports._cachedViews[view]) {
exports._cachedViews[view] = exports.readFileSync(path.join(exports._platesDir, view + exports._extname))
}
html = exports._cachedViews[view]
if (layout) {
if (!exports._cachedLayouts[layout]) {
exports._cachedLayouts[layout] = exports.readFileSync(path.join(exports._layoutsDir, layout + exports._extname))
}
html = plates.bind(exports._cachedLayouts[layout], { body: html })
}
return plates.bind(html, data)
}
}
exports.readFileSync = function (file) {
try {
return fs.readFileSync(file, 'utf8')
} catch (ex) {
return ''
}
}
/*
* User resource
*
* Create password example:
*
* app.resources.User.create({
* username: 'testuser'
* , email: 'testuser@example.org'
* , active: true
* }, function (err, user) {
* if (err || !user)
* return app.log.err(err)
* user.encryptPassword('thepassword', function (err, user) {
* if (err || !user)
* return app.log.error(err)
* user.save()
* })
* })
*/
var resourceful = require('resourceful')
, crypto = require('crypto')
, utils = require('../utils')
module.exports = resourceful.define('user', function () {
this.restful = true
this.remote = true
this.string('username')
this.string('email', { format: 'email', required: false })
this.string('salt')
this.string('key')
this.bool('active', { required: false, default: true })
this.timestamps()
var encryptPassword = function (secret, callback) {
var that = this
utils.hasher({
plaintext: secret
}, function (err, result) {
if (err) return callback(err)
that.salt = result.salt.toString('hex')
that.key = result.key.toString('hex')
callback(null, that)
})
}
this.method('encryptPassword', encryptPassword)
var verifyPassword = function (secret, callback) {
var that = this
, salt = new Buffer(that.salt, 'hex')
utils.hasher({
plaintext: secret
, salt: salt
}, function (err, result) {
if (err) return callback(err)
if (that.key === result.key.toString('hex'))
return callback(null, true)
return callback(null, false)
})
}
this.method('verifyPassword', verifyPassword)
})
var crypto = require('crypto')
module.exports = {
hasher: function (opts, callback) {
var that = this
if (!opts.plaintext) {
return crypto.randomBytes(6, function (err, buf) {
if (err) callback(err)
opts.plaintext = buf.toString('base64')
return that.hasher(opts, callback)
})
}
if (!opts.salt) {
return crypto.randomBytes(64, function (err, buf) {
if (err) return callback(err)
opts.salt = buf
return that.hasher(opts, callback)
})
}
opts.hash = 'sha1'
opts.iterations = opts.iterations || 10000
return crypto.pbkdf2(opts.plaintext, opts.salt, opts.iterations, 64, function (err, key) {
if (err) return callback(err)
opts.key = new Buffer(key)
return callback(null, opts)
})
}
}
Copy link

ghost commented Aug 29, 2014

good work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment