Skip to content

Instantly share code, notes, and snippets.

@liorkesos
Last active November 22, 2016 16:54
Show Gist options
  • Save liorkesos/6135208 to your computer and use it in GitHub Desktop.
Save liorkesos/6135208 to your computer and use it in GitHub Desktop.
MEAN.io code walkthrough
/*!
* nodejs-express-mongoose-demo
* Copyright(c) 2013 Madhusudhan Srinivasa <madhums8@gmail.com>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var express = require('express')
, fs = require('fs')
, passport = require('passport')
, logger = require('mean-logger')
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Load configurations
// if test env, load example file
var env = process.env.NODE_ENV || 'development'
, config = require('./config/config')[env]
, auth = require('./config/middlewares/authorization')
, mongoose = require('mongoose')
// Bootstrap db connection
var db = mongoose.connect(config.db)
// Bootstrap models
var models_path = __dirname + '/app/models'
fs.readdirSync(models_path).forEach(function (file) {
require(models_path+'/'+file)
})
// bootstrap passport config
require('./config/passport')(passport, config)
var app = express()
// express settings
require('./config/express')(app, config, passport)
// Bootstrap routes
require('./config/routes')(app, passport, auth)
// Start the app by listening on <port>
var port = process.env.PORT || 3000
app.listen(port)
console.log('Express app started on port '+port)
//Initializing logger
logger.init(app, passport, mongoose)
// expose app
exports = module.exports = app
var path = require('path')
, rootPath = path.normalize(__dirname + '/..')
, templatePath = path.normalize(__dirname + '/../app/mailer/templates')
, notifier = {
APN: false,
email: false, // true
actions: ['comment'],
tplPath: templatePath,
postmarkKey: 'POSTMARK_KEY',
parseAppId: 'PARSE_APP_ID',
parseApiKey: 'PARSE_MASTER_KEY'
}
module.exports = {
development: {
db: 'mongodb://localhost/mean-dev',
root: rootPath,
notifier: notifier,
app: {
name: 'MEAN - A Modern Stack - Development'
},
facebook: {
clientID: "APP_ID",
clientSecret: "APP_SECRET",
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
twitter: {
clientID: "CONSUMER_KEY",
clientSecret: "CONSUMER_SECRET",
callbackURL: "http://localhost:3000/auth/twitter/callback"
},
github: {
clientID: 'APP_ID',
clientSecret: 'APP_SECRET',
callbackURL: 'http://localhost:3000/auth/github/callback'
},
google: {
clientID: "APP_ID",
clientSecret: "APP_SECRET",
callbackURL: "http://localhost:3000/auth/google/callback"
},
},
test: {
db: 'mongodb://localhost/mean-test',
root: rootPath,
notifier: notifier,
app: {
name: 'MEAN - A Modern Stack - Test'
},
facebook: {
clientID: "APP_ID",
clientSecret: "APP_SECRET",
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
twitter: {
clientID: "CONSUMER_KEY",
clientSecret: "CONSUMER_SECRET",
callbackURL: "http://localhost:3000/auth/twitter/callback"
},
github: {
clientID: 'APP_ID',
clientSecret: 'APP_SECRET',
callbackURL: 'http://localhost:3000/auth/github/callback'
},
google: {
clientID: "APP_ID",
clientSecret: "APP_SECRET",
callbackURL: "http://localhost:3000/auth/google/callback"
}
},
production: {
db: 'mongodb://localhost/mean',
root: rootPath,
notifier: notifier,
app: {
name: 'MEAN - A Modern Stack - Production'
},
facebook: {
clientID: "APP_ID",
clientSecret: "APP_SECRET",
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
twitter: {
clientID: "CONSUMER_KEY",
clientSecret: "CONSUMER_SECRET",
callbackURL: "http://localhost:3000/auth/twitter/callback"
},
github: {
clientID: 'APP_ID',
clientSecret: 'APP_SECRET',
callbackURL: 'http://localhost:3000/auth/github/callback'
},
google: {
clientID: "APP_ID",
clientSecret: "APP_SECRET",
callbackURL: "http://localhost:3000/auth/google/callback"
}
}
}
/*
* Generic require login routing middleware
*/
exports.requiresLogin = function (req, res, next) {
if (!req.isAuthenticated()) {
return res.redirect('/login')
}
next()
};
/*
* User authorizations routing middleware
*/
exports.user = {
hasAuthorization : function (req, res, next) {
if (req.profile.id != req.user.id) {
return res.redirect('/users/'+req.profile.id)
}
next()
}
}
/*
* Article authorizations routing middleware
*/
exports.article = {
hasAuthorization : function (req, res, next) {
if (req.article.user.id != req.user.id) {
return res.redirect('/articles/'+req.article.id)
}
next()
}
}
var async = require('async')
module.exports = function (app, passport, auth) {
// user routes
var users = require('../app/controllers/users')
app.get('/signin', users.signin)
app.get('/signup', users.signup)
app.get('/signout', users.signout)
app.post('/users', users.create)
app.post('/users/session', passport.authenticate('local', {failureRedirect: '/signin', failureFlash: 'Invalid email or password.'}), users.session)
app.get('/users/me', users.me)
app.get('/users/:userId', users.show)
app.get('/auth/facebook', passport.authenticate('facebook', { scope: [ 'email', 'user_about_me'], failureRedirect: '/signin' }), users.signin)
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/signin' }), users.authCallback)
app.get('/auth/github', passport.authenticate('github', { failureRedirect: '/signin' }), users.signin)
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/signin' }), users.authCallback)
app.get('/auth/twitter', passport.authenticate('twitter', { failureRedirect: '/signin' }), users.signin)
app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/signin' }), users.authCallback)
app.get('/auth/google', passport.authenticate('google', { failureRedirect: '/signin', scope: 'https://www.google.com/m8/feeds' }), users.signin)
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/signin', scope: 'https://www.google.com/m8/feeds' }), users.authCallback)
app.param('userId', users.user)
var articles = require('../app/controllers/articles')
app.get('/articles', articles.all)
app.post('/articles', auth.requiresLogin, articles.create)
app.get('/articles/:articleId', articles.show)
app.put('/articles/:articleId', auth.requiresLogin, auth.article.hasAuthorization, articles.update)
app.del('/articles/:articleId', auth.requiresLogin, auth.article.hasAuthorization, articles.destroy)
app.param('articleId', articles.article)
// home route
var index = require('../app/controllers/index')
app.get('/', index.render)
}
extends layouts/default
block content
section(data-ng-view)
script(type="text/javascript").
window.user = !{user};
head
meta(charset='utf-8')
meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
meta(name='viewport', content='width=device-width,initial-scale=1')
title= appName+' - '+title
meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
meta(name="keywords", content="node.js, express, mongoose, mongodb, angularjs")
meta(name="description", content="MEAN - A Modern Stack: MongoDB, ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).")
link(href='/img/icons/favicon.ico', rel='shortcut icon', type='image/x-icon')
meta(property='fb:app_id', content='APP_ID')
meta(property='og:title', content='#{appName} - #{title}')
meta(property='og:description', content='MEAN - A Modern Stack: MongoDB, ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).')
meta(property='og:type', content='website')
meta(property='og:url', content='APP_URL')
meta(property='og:image', content='APP_LOGO')
meta(property='og:site_name', content='MEAN - A Modern Stack')
meta(property='fb:admins', content='APP_ADMIN')
link(rel='stylesheet', href='/lib/bootstrap/docs/assets/css/bootstrap.css')
link(rel='stylesheet', href='/lib/bootstrap/docs/assets/css/bootstrap-responsive.css')
link(rel='stylesheet', href='/css/common.css')
link(rel='stylesheet', href='/css/views/index.css')
link(rel='stylesheet', href='/css/views/articles.css')
//if lt IE 9
script(src='http://html5shim.googlecode.com/svn/trunk/html5.js')
!!! 5
html(lang='en', xmlns='http://www.w3.org/1999/xhtml', xmlns:fb='https://www.facebook.com/2008/fbml', itemscope='itemscope', itemtype='http://schema.org/Product')
include ../includes/head
body
header.navbar.navbar-fixed-top.navbar-inverse(data-ng-include="'views/header.html'")
section.content
section.container
block content
include ../includes/foot
script(type='text/javascript', src='lib/jquery/jquery.min.js')
script(type='text/javascript', src='lib/angular/angular.min.js')
script(type='text/javascript', src='lib/angular-cookies/angular-cookies.min.js')
script(type='text/javascript', src='lib/angular-resource/angular-resource.min.js')
script(type='text/javascript', src='lib/angular-bootstrap/ui-bootstrap-tpls.min.js')
script(type='text/javascript', src='js/app.js')
script(type='text/javascript', src='js/config.js')
script(type='text/javascript', src='js/directives.js')
script(type='text/javascript', src='js/filters.js')
script(type='text/javascript', src='js/services/global.js')
script(type='text/javascript', src='js/services/articles.js')
script(type='text/javascript', src='js/controllers/articles.js')
script(type='text/javascript', src='js/controllers/index.js')
script(type='text/javascript', src='js/controllers/header.js')
script(type='text/javascript', src='js/init.js')
//Setting up route
window.app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/articles', { templateUrl: 'views/articles/list.html' }).
when('/articles/create', { templateUrl: 'views/articles/create.html' }).
when('/articles/:articleId/edit', { templateUrl: 'views/articles/edit.html' }).
when('/articles/:articleId', { templateUrl: 'views/articles/view.html' }).
when('/', { templateUrl: 'views/index.html' }).
otherwise({redirectTo: '/'});
}]);
//Removing tomcat unspported headers
window.app.config(['$httpProvider', function($httpProvider, Configuration) {
//delete $httpProvider.defaults.headers.common["X-Requested-With"];
}]);
//Setting HTML5 Location Mode
window.app.config(['$locationProvider', function($locationProvider) {
//$locationProvider.html5Mode(true);
$locationProvider.hashPrefix("!");
}]);
window.app = angular.module('MEAN', ['ngCookies', 'ngResource', 'ui.bootstrap']);
function ArticlesController($scope, $routeParams, $location, Global, Articles) {
$scope.global = Global;
$scope.create = function () {
var article = new Articles({ title: this.title, content: this.content });
article.$save(function (response) {
$location.path("articles/" + response._id);
});
this.title = "";
this.content = "";
};
$scope.remove = function (article) {
article.$remove();
for (var i in $scope.articles) {
if ($scope.articles[i] == article) {
$scope.articles.splice(i, 1)
}
}
};
$scope.update = function () {
var article = $scope.article;
if (!article.updated) {
article.updated = [];
}
article.updated.push(new Date().getTime());
article.$update(function () {
$location.path('articles/' + article._id);
});
};
$scope.find = function (query) {
Articles.query(query, function (articles) {
$scope.articles = articles;
});
};
$scope.findOne = function () {
Articles.get({ articleId: $routeParams.articleId }, function (article) {
$scope.article = article;
});
};
}
<section data-ng-controller="ArticlesController" data-ng-init="find()">
<ul class="unstyled">
<li data-ng-repeat="article in articles">
<span>{{article.created | date:'medium'}}</span> /
<span>{{article.user.name}}</span>
<h2><a data-ng-href="#!/articles/{{article._id}}">{{article.title}}</a></h2>
<div>{{article.content}}</div>
</li>
</ul>
<h1 data-ng-hide="!articles || articles.length">No articles yet. <br> Why don't you <a href="/#!/articles/create">Create One</a>?</h1>
</section>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment