diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..8c48f35 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "resources/assets/bower" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index ea6dc57..b8a6a38 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ -.idea/* -node_modules/* -public/dist/* -bower_components/* -/config.js -/config/* +.idea +node_modules +!node_modules/app +!node_modules/config +!node_modules/modules +!node_modules/resources +public +resources/assets/bower +config/config-*.js diff --git a/License b/License index cb0c611..2e6e64b 100644 --- a/License +++ b/License @@ -1,4 +1,4 @@ -MEANStack bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js +MEANStack.io bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js The purpose of the application is to facilitate the development offering the best of MEAN with a stack of packages, frameworks, libraries and strategies. The MIT License (MIT) diff --git a/README.md b/README.md index 4005e24..07c1929 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# MEANStack +# MEANStack.io *bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js* Is a solution full-stack JavaScript, based on MongoDB, Express, AngularJS, Node.js and another stack of packages. @@ -17,12 +17,114 @@ Is a solution full-stack JavaScript, based on MongoDB, Express, AngularJS, Node. Are some of the packages that we use to make this dream come true. -## Getting Started -Getting started ? go to the official page [meanstack.developscript.com](http://meanstack.developscript.com/getting-started) +## Prerequisites +Install Node.js e MongoDB. + +### Install Node.js +Installing Node.js via package manager access https://nodejs.org/en/download/package-manager/ + +#### Notes +if you use Debian and Ubuntu based Linux distributions be sure to install **build-essential**. +```bash +$ sudo apt-get install -y build-essential +``` + +if you use Enterprise Linux and Fedora be sure to install **gcc-c++ make**. +```bash +$ yum install gcc-c++ make +``` + +### Install MongoDB +Installing MongoDB access https://docs.mongodb.org/manual/installation/ + +#### Note +If you've never worked with a MongoDB read in your documentation before you install it, official documentation access, https://docs.mongodb.org/manual/ + +## Installation + +Before you begin installing MEANStack we will update the NPM and soon after installing Gulp, Bower and nodemon in the global scope. + +### Updating NPM +```bash +$ npm update -g npm +``` + +### Install Gulp +```bash +$ npm install -g gulp +``` + +### Install Bower +```bash +$ npm install -g bower +``` + +### Install Nodemon +Nodemon is a utility that will monitor for any changes in your source and automatically restart your server. Perfect for development. Install it using npm. +```bash +$ npm install -g nodemon +``` + +#### Note +If you already have the Gulp and Bower recommend updates them. +```bash +$ npm update -g gulp bower +``` + +### The first step +Clone the repository GitHub. +```bash +$ git clone git@github.com:developscript/meanstack.io.git +``` + +### The second step +Install the back-end dependencies. +```bash +$ npm install +``` + +### The third step +Install the front-end dependencies. +```bash +$ bower install +``` + +### The fourth step +Configure the application. For this we have a sample file "config/config.example.js" copy and rename it to "config/config-development.js". +```bash +$ cp config/config.example.js config/config-development.js +``` + +#### Configuration file. +The file "config/config-development.js" represents the configuration of your environment. What ? within package.json we have: +```js +"start": "NODE_ENV=development nodemon ./bin/www" +``` +The "NODE_ENV" property sets which environment setting will be used. Example: +```js +"start": "NODE_ENV=production nodemon ./bin/www" // Its configuration file is "config/config-production.js". +``` + +### The fifth step +Run Gulp. +```bash +$ gulp +``` + +### The sixth step +Start the application. +```bash +$ npm start +``` + +If you want to use the Gulp with Browsersync +```bash +$ gulp watch +``` ## Documentation -Documentation can be found on the [meanstack.developscript.com](http://meanstack.developscript.com/documentation) +Documentation can be found on the [meanstack.io](http://meanstack.io/documentation) ## Copyright & License -Copyright © 2016 Developscript - Licensed under [MIT](https://github.com/developscript/meanstack/blob/master/License). +Copyright © 2016 Developscript - Licensed under [MIT](https://github.com/developscript/meanstack.io/blob/master/License). diff --git a/app.js b/app.js index 78da6bf..cdbc8ee 100644 --- a/app.js +++ b/app.js @@ -3,29 +3,32 @@ var express = require('express'), app = express(), path = require('path'), + compression = require('compression'), favicon = require('serve-favicon'), logger = require('morgan'), cookieParser = require('cookie-parser'), bodyParser = require('body-parser'), session = require('express-session'), store = new session.MemoryStore(), - passport = require('passport'), - response = require('./modules/response'), - passportStrategies = require('./passport'), - policies = require('./routes/policies'), - routes = require('./routes'), - settings = require('./config'), - hbs = require('express-handlebars').create( + middleware = require('app/http/middleware'), + routes = require('app/http/routes'), + settings = require('config'), + hbs = require('express-hbs'), + hbsEngine = hbs.express4( { extname: ".hbs", - partialsDir: path.join(__dirname, 'views/partials/') + layoutsDir: path.join(__dirname, 'resources/views/layouts/'), + partialsDir: path.join(__dirname, 'resources/views/partials/') } - ); + ), + hbsHelpers = require('app/helpers'); -app.engine('hbs', hbs.engine); +app.engine('hbs', hbsEngine); app.set('view engine', 'hbs'); -app.set('views', path.join(__dirname, 'views')); -app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); +hbsHelpers(); +app.use(compression()); +app.set('views', path.join(__dirname, 'resources/views')); +app.use(favicon(path.join(__dirname, 'public', 'favicon.png'))); app.use(express.static(path.join(__dirname, 'public'))); app.use(logger('dev')); app.use(bodyParser.json()); @@ -38,36 +41,26 @@ app.use(session( saveUninitialized: false, store: store, cookie: { - httpOnly: true, maxAge: 2419200000 + httpOnly: true, + maxAge: (typeof settings.cookie.maxAge !== 'undefined')? settings.cookie.maxAge : 2419200000 } } ) ); /** - * Module Response + * Init Middleware. */ -app.use(response()); +middleware(app); -/** - * Init Passaport - */ -app.use(passport.initialize()); -app.use(passport.session()); -passportStrategies(passport); - -/** - * Module Auth - */ -policies(app); /** - * Initialize Routes + * Initialize Routes. */ routes(app); /** - * error handler + * Error handler. */ app.use(function (err, req, res, next) { res.status(err.status || 500); diff --git a/app/helpers/index.js b/app/helpers/index.js new file mode 100644 index 0000000..7971d4a --- /dev/null +++ b/app/helpers/index.js @@ -0,0 +1,21 @@ +'use strict'; + +/** + * Helpers for Handlebars. + * + * Example: + * {{ foo }} or {{ ucfirst variable }} + * + * More documentation: + * http://handlebarsjs.com/expressions.html#helpers, + * https://github.com/barc/express-hbs + */ +var hbs = require('express-hbs'), + ucfirst = require('./ucfirst'); + +module.exports = function () { + + // Make a string's first character uppercase. + ucfirst(); + +}; diff --git a/app/helpers/ucfirst.js b/app/helpers/ucfirst.js new file mode 100644 index 0000000..f72935b --- /dev/null +++ b/app/helpers/ucfirst.js @@ -0,0 +1,17 @@ +'use strict'; + +var hbs = require('express-hbs'); + +module.exports = function () { + /** + * Make a string's first character uppercase. + * + * @param str + * @returns {string} + */ + hbs.registerHelper('ucfirst', function (str) { + var f = str.charAt(0) + .toUpperCase(); + return f + str.substr(1); + }); +}; diff --git a/app/http/controllers/account/forgot.js b/app/http/controllers/account/forgot.js new file mode 100644 index 0000000..8d794e1 --- /dev/null +++ b/app/http/controllers/account/forgot.js @@ -0,0 +1,152 @@ +'use strict'; + +var express = require('express'), + router = express.Router(), + User = require('app/models/user').User, + settings = require('config'), + mailer = require('app/mail'), + mailerSmtp = mailer.smtp(settings.mail), + mailerSendMail = mailer.sendMail, + crypto = require('crypto'), + login = require('modules/account/login'); + + +/** + * Forgot password. + * If user logged with application OAuth send email with application logged. + * If logged with application local send email with token for reset password. + */ +router.post('/', function (req, res, next) { + + var data = req.body, + validaEmail = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i; + + if (!validaEmail.test(data.email)) { + req.response.setMsg('Please enter a valid email address !'); + return res.json(req.response.return()); + } + + User.findOne({email: new RegExp('^' + data.email + '$', "i")}, function (err, user) { + if (err) { + return next(err); + } + + if (!user) { + req.response.setMsg('E-mail "' + data.email + '" not registered.'); + return res.json(req.response.return()); + } + + var paramsTemplate = { + user: user, + settings: settings + }, + paramsSendMail = { + from: '"' + settings.name + '" <' + settings.mail.smtp.auth.user + '>', + to: data.email + }, + errorSendMail = 'Error sending email, try again, if still does not work please contact support !', + successSendMail = 'Message has been sent to the e-mail ' + user.email; + + if (typeof user.oauth.provider !== 'undefined') { + mailerSendMail( + mailerSmtp, + 'forgot-account/logged-with-application', + paramsTemplate, + paramsSendMail, + function (success) { + if (!success) { + req.response.setMsg(errorSendMail); + return res.json(req.response.return()); + } + + req.response.setSuccess(); + req.response.setMsg(successSendMail); + return res.json(req.response.return()); + } + ); + + } else { + crypto.randomBytes(20, function (err, buf) { + user.resetPassword.token = buf.toString('hex'); + // 1 hour expires token + user.resetPassword.expires = Date.now() + 3600000; + // Get IP address client. + user.resetPassword.ip = req.header('x-forwarded-for') || req.connection.remoteAddress; + user.save(function (err) { + if (err) { + return next(err); + } + + paramsTemplate.user = user; + + mailerSendMail( + mailerSmtp, + 'forgot-account/link-reset-password', + paramsTemplate, + paramsSendMail, + function (success) { + if (!success) { + req.response.setMsg(errorSendMail); + return res.json(req.response.return()); + } + + req.response.setSuccess(); + req.response.setMsg(successSendMail); + return res.json(req.response.return()); + } + ); + }); + }); + } + }); +}); + +/** + * Reset Password. + */ +router.post('/reset', function (req, res, next) { + + var data = req.body, + remoteAddress = req.header('x-forwarded-for') || req.connection.remoteAddress; + + if (!data.token || (data.token).length < 20) { + req.response.setMsg('Token invalid !'); + } + if (!data.password || (data.password).length < 6) { + req.response.setMsg('Your password must have more than 6 characters !'); + } + if (data.password != data.repassword) { + req.response.setMsg('Make sure your passwords are the same !'); + } + if (req.response.hasMsg()) { + return res.json(req.response.return()); + } + + User.findOne( + { + 'resetPassword.token': data.token, + 'resetPassword.expires': {$gt: Date.now()}, + 'resetPassword.ip': remoteAddress + }, + function (err, user) { + if (err) { + return next(err); + } + if (!user) { + req.response.setMsg('Token is invalid or has expired.'); + return res.json(req.response.return()); + } + + user.password = user.generateHash(data.password); + user.resetPassword.token = null; + user.resetPassword.expires = null; + user.resetPassword.ip = null; + user.save(function (err) { + req.response.setSuccess(); + login(req, res, next, err, user); + }); + } + ); +}); + +module.exports = router; diff --git a/app/http/controllers/account/logoff.js b/app/http/controllers/account/logoff.js new file mode 100644 index 0000000..23abbc3 --- /dev/null +++ b/app/http/controllers/account/logoff.js @@ -0,0 +1,19 @@ +'use strict'; + +var express = require('express'), + router = express.Router(); + +/** + * Logoff. + */ +router.post('/', function (req, res) { + req.setCookie(false, + function () { + req.logout(); + req.response.setSuccess(); + res.json(req.response.return()); + } + ); +}); + +module.exports = router; diff --git a/routes/routers/account/signin.js b/app/http/controllers/account/signin.js similarity index 56% rename from routes/routers/account/signin.js rename to app/http/controllers/account/signin.js index 45e2d8b..3f7f8b1 100644 --- a/routes/routers/account/signin.js +++ b/app/http/controllers/account/signin.js @@ -3,40 +3,12 @@ var express = require('express'), router = express.Router(), passport = require('passport'), - login = require('./_login'), - - /** - * Function login OAuth - * @param req - * @param res - * @param next - * @param err - * @param user - * @returns {*} - */ - loginOAuth = function (req, res, next, err, user) { - if (err) { - return next(err); - } - if (!user || !req.response.getSuccess()) { - var error = req.response.getMsg(); - return res.redirect('/signin?error=' + error.join()); - } - req.logIn(user, function (err) { - if (err) { - return next(err); - } - req.setCookie(true, - function () { - res.redirect('/user'); - } - ); - }); - }; + login = require('modules/account/login'), + loginOAuth = require('modules/account/login/oauth'); /** - * Strategy local sign in + * Strategy local sign in. */ router.post('/', function (req, res, next) { passport.authenticate('local-signin', function (err, user) { @@ -45,12 +17,12 @@ router.post('/', function (req, res, next) { }); /** - * Strategy Signin Facebook + * Strategy Signin Facebook. */ -router.get('/facebook', passport.authenticate('facebook')); +router.get('/facebook', passport.authenticate('facebook', {scope: ['email']})); /** - * Handle the callback after facebook has authenticated the user + * Handle the callback after Facebook has authenticated the user. */ router.get('/facebook/callback', function (req, res, next) { passport.authenticate('facebook', function (err, user) { @@ -59,12 +31,12 @@ router.get('/facebook/callback', function (req, res, next) { }); /** - * Strategy Signin Google + * Strategy Signin Google. */ -router.get('/google', passport.authenticate('google')); +router.get('/google', passport.authenticate('google', {scope: ['profile', 'email']})); /** - * Handle the callback after Google has authenticated the user + * Handle the callback after Google has authenticated the user. */ router.get('/google/callback', function (req, res, next) { passport.authenticate('google', function (err, user) { @@ -73,12 +45,12 @@ router.get('/google/callback', function (req, res, next) { }); /** - * Strategy Signin Linkedin + * Strategy Signin Linkedin. */ router.get('/linkedin', passport.authenticate('linkedin')); /** - * Handle the callback after Linkedin has authenticated the user + * Handle the callback after Linkedin has authenticated the user. */ router.get('/linkedin/callback', function (req, res, next) { passport.authenticate('linkedin', function (err, user) { @@ -87,12 +59,12 @@ router.get('/linkedin/callback', function (req, res, next) { }); /** - * Strategy Signin Twitter + * Strategy Signin Twitter. */ router.get('/twitter', passport.authenticate('twitter')); /** - * Handle the callback after Twitter has authenticated the user + * Handle the callback after Twitter has authenticated the user. */ router.get('/twitter/callback', function (req, res, next) { passport.authenticate('twitter', function (err, user) { @@ -101,12 +73,12 @@ router.get('/twitter/callback', function (req, res, next) { }); /** - * Strategy Signin Google + * Strategy Signin Github. */ router.get('/github', passport.authenticate('github')); /** - * Handle the callback after Google has authenticated the user + * Handle the callback after Github has authenticated the user. */ router.get('/github/callback', function (req, res, next) { passport.authenticate('github', function (err, user) { diff --git a/app/http/controllers/account/signup.js b/app/http/controllers/account/signup.js new file mode 100644 index 0000000..1b5f664 --- /dev/null +++ b/app/http/controllers/account/signup.js @@ -0,0 +1,17 @@ +'use strict'; + +var express = require('express'), + router = express.Router(), + passport = require('passport'), + login = require('modules/account/login'); + +/** + * Strategy local sign up. + */ +router.post('/', function (req, res, next) { + passport.authenticate('local-signup', function (err, user) { + login(req, res, next, err, user); + })(req, res, next); +}); + +module.exports = router; diff --git a/app/http/controllers/home.js b/app/http/controllers/home.js new file mode 100644 index 0000000..b7fbd36 --- /dev/null +++ b/app/http/controllers/home.js @@ -0,0 +1,13 @@ +'use strict'; + +var express = require('express'), + router = express.Router(); + +/** + * Router for page index AngularJS. + */ +router.get('/:ever*?', function (req, res) { + res.render('index'); +}); + +module.exports = router; diff --git a/routes/routers/view.js b/app/http/controllers/views/auto-load.js similarity index 88% rename from routes/routers/view.js rename to app/http/controllers/views/auto-load.js index 2bea14b..79143ef 100644 --- a/routes/routers/view.js +++ b/app/http/controllers/views/auto-load.js @@ -4,7 +4,7 @@ var express = require('express'), router = express.Router(); /** - * Load views AngularJS + * Auto load views AngularJS. */ router.get('*', function (req, res) { diff --git a/app/http/controllers/views/myaccount.js b/app/http/controllers/views/myaccount.js new file mode 100644 index 0000000..34ba9fb --- /dev/null +++ b/app/http/controllers/views/myaccount.js @@ -0,0 +1,21 @@ +'use strict'; + +var express = require('express'), + router = express.Router(), + moment = require('moment'), + settings = require('config'); + +/** + * Custom route index My Account. + * Sending object to the front end. + */ +router.get('/index', function (req, res) { + res.render('myaccount/index', + { + 'welcome': 'Welcome Thank you for using ' + settings.name + ' ', + 'date': moment().format('LLLL') + } + ); +}); + +module.exports = router; diff --git a/app/http/middleware/index.js b/app/http/middleware/index.js new file mode 100644 index 0000000..7ec79e2 --- /dev/null +++ b/app/http/middleware/index.js @@ -0,0 +1,34 @@ +'use strict'; + +var policies = require('app/policies'), + viewComposer = require('./view-composer'), + response = require('modules/response'), + passport = require('modules/account/passport'); + +/** + * Initialize middleware. + * + * @param app + */ +module.exports = function (app) { + + /** + * Init Passaport. + */ + passport(app); + + /** + * Module Auth. + */ + policies(app); + + /** + * View Composer. + */ + app.use(viewComposer); + + /** + * Module Response. + */ + app.use(response()); +}; diff --git a/app/http/middleware/view-composer.js b/app/http/middleware/view-composer.js new file mode 100644 index 0000000..ffc2e15 --- /dev/null +++ b/app/http/middleware/view-composer.js @@ -0,0 +1,66 @@ +'use strict'; + +var settings = require('config'); + +/** + * View Composer. + * More documentation: http://expressjs.com/en/api.html#res.locals + * + * @param req + * @param res + * @param next + */ +var viewComposer = function (req, res, next) { + /** + * Auxiliary function. + * Returns the User or false. + * + * @param req + * @returns {*} + */ + var user = function (req) { + return (req.isAuthenticated()) ? req.user : false; + }; + + /** + * Locals settings. + * + * @type {{name: string, version: string}} + */ + res.locals.settings = { + name: settings.name, + version: settings.version + }; + + /** + * Locals user. + * + * Example: + * {{#if user}} + * {{ user.username }} + * {{/if}} + * + * @type {Object|Boolean} + */ + res.locals.user = user(req); + + /** + * Locals isAuthenticated + * Return true if the User is logged. + * + * @type {Boolean} + */ + res.locals.isAuthenticated = req.isAuthenticated(); + + /** + * Locals isUnauthenticated + * Return true if the User not logged. + * + * @type {Boolean} + */ + res.locals.isAuthenticated = req.isUnauthenticated(); + + next(); +}; + +module.exports = viewComposer; diff --git a/app/http/routes.js b/app/http/routes.js new file mode 100644 index 0000000..fc57809 --- /dev/null +++ b/app/http/routes.js @@ -0,0 +1,33 @@ +'use strict'; + +/** + * Initialize routes + * + * @param app + */ +module.exports = function (app) { + + /** + * Route account + */ + app.use('/account/signin', require('./controllers/account/signin')); + app.use('/account/signup', require('./controllers/account/signup')); + app.use('/account/forgot', require('./controllers/account/forgot')); + app.use('/account/logoff', require('./controllers/account/logoff')); + + /** + * Custom routes view + */ + app.use('/view/myaccount', require('./controllers/views/myaccount')); + + /** + * Auto Load views + */ + app.use('/view', require('./controllers/views/auto-load')); + + /** + * Index. + */ + app.all('*', require('./controllers/home')); + +}; diff --git a/app/mail/index.js b/app/mail/index.js new file mode 100644 index 0000000..491a5fd --- /dev/null +++ b/app/mail/index.js @@ -0,0 +1,79 @@ +'use strict'; + +var nodemailer = require('nodemailer'), + EmailTemplate = require('email-templates').EmailTemplate, + path = require('path'), + + /** + * Create transport SMTP. + * + * @param mail + */ + smtp = function (mail, callback) { + var nodemailerSmtp = nodemailer.createTransport({ + host: mail.smtp.host, + secure: mail.smtp.secure, + port: mail.smtp.port, + auth: { + user: mail.smtp.auth.user, + pass: mail.smtp.auth.pass + }, + logger: mail.smtp.logger, + debug: mail.smtp.debug + }); + + if (typeof callback === 'undefined') { + return nodemailerSmtp; + } else { + return callback(nodemailerSmtp); + } + }, + + /** + * Load template. + * + * @param templatePath + * @param params + * @param callback + */ + template = function (templatePath, params, callback) { + var template = new EmailTemplate(path.join(__dirname, 'templates', templatePath)), + templateParams = (typeof params === 'undefined') ? {} : params; + + template.render(templateParams, function (err, result) { + return callback(err, result); + }); + }, + + /** + * Send e-mail with template. + * + * @param mailerSmtp + * @param templatePath + * @param templateParams + * @param mailParams + * @param callback + */ + sendMail = function (mailerSmtp, templatePath, templateParams, mailParams, callback) { + template(templatePath, templateParams, function (err, template) { + if (err) { + return callback(false); + } + + mailParams.html = template.html; + mailParams.subject = template.subject; + + mailerSmtp.sendMail(mailParams, function (err) { + if (err) { + return callback(false); + } + + return callback(true); + }); + }); + }; + +// Export modules. +module.exports.smtp = smtp; +module.exports.template = template; +module.exports.sendMail = sendMail; diff --git a/app/mail/templates/forgot-account/link-reset-password/html.hbs b/app/mail/templates/forgot-account/link-reset-password/html.hbs new file mode 100644 index 0000000..7dd1957 --- /dev/null +++ b/app/mail/templates/forgot-account/link-reset-password/html.hbs @@ -0,0 +1,62 @@ + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ {{ settings.name }} +
+ {{ settings.description }} +
+ Hello, {{ user.username }} +
+ Reset password access click here! . +
+ Or copy and paste this link into your browser. {{ settings.server.url }}forgot/{{ user.resetPassword.token }} +
+
+ + + + +
+ + + + + + + + + +
+ {{ settings.name }} +
+ {{ settings.description }} +
+
+
diff --git a/app/mail/templates/forgot-account/link-reset-password/subject.hbs b/app/mail/templates/forgot-account/link-reset-password/subject.hbs new file mode 100644 index 0000000..bd546dc --- /dev/null +++ b/app/mail/templates/forgot-account/link-reset-password/subject.hbs @@ -0,0 +1 @@ +{{ settings.name }} - Password Reset ! \ No newline at end of file diff --git a/app/mail/templates/forgot-account/logged-with-application/html.hbs b/app/mail/templates/forgot-account/logged-with-application/html.hbs new file mode 100644 index 0000000..ed605f0 --- /dev/null +++ b/app/mail/templates/forgot-account/logged-with-application/html.hbs @@ -0,0 +1,63 @@ + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ {{ settings.name }} +
+ {{ settings.description }} +
+ Hello, {{ user.username }} +
+ You logged with application {{ user.oauth.provider }}. +
+ Go to the page {{ settings.server.url }}signin + and click login with {{ user.oauth.provider }}. +
+
+ + + + +
+ + + + + + + + + +
+ {{ settings.name }} +
+ {{ settings.description }} +
+
+
diff --git a/app/mail/templates/forgot-account/logged-with-application/subject.hbs b/app/mail/templates/forgot-account/logged-with-application/subject.hbs new file mode 100644 index 0000000..bd546dc --- /dev/null +++ b/app/mail/templates/forgot-account/logged-with-application/subject.hbs @@ -0,0 +1 @@ +{{ settings.name }} - Password Reset ! \ No newline at end of file diff --git a/models/index.js b/app/models/index.js similarity index 80% rename from models/index.js rename to app/models/index.js index ebfbf60..8400447 100644 --- a/models/index.js +++ b/app/models/index.js @@ -1,9 +1,9 @@ 'use strict'; /** - * Connection MongoDB + * Connection MongoDB. */ -var settings = require('../config'), +var settings = require('config'), mongoose = require('mongoose'); mongoose.connect("mongodb://" + settings.dbconnect.user + ":" + settings.dbconnect.password + "@" + settings.dbconnect.host + ":" + settings.dbconnect.port + "/" + settings.dbconnect.base); @@ -15,7 +15,7 @@ db.on("error", function (err) { }); db.once("open", function () { - console.log("connection established."); + console.log("Connection established MongoDB."); }); module.exports.mongoose = mongoose; diff --git a/models/users.js b/app/models/user.js similarity index 68% rename from models/users.js rename to app/models/user.js index ce4fbdf..1e31e20 100644 --- a/models/users.js +++ b/app/models/user.js @@ -6,7 +6,8 @@ var connection = require("./index"), bcrypt = require('bcrypt'), /** - * Schema User + * Schema User. + * * @type {*|Schema} */ UsersSchema = new Schema( @@ -28,17 +29,19 @@ var connection = require("./index"), minLength: 6, required: false }, - resetPasswordToken: { - type: String, - required: false - }, - resetPasswordExpires: { - type: String, - required: false - }, - resetPasswordIp: { - type: String, - required: false + resetPassword:{ + token: { + type: String, + required: false + }, + expires: { + type: String, + required: false + }, + ip: { + type: String, + required: false + } }, oauth: { id: { @@ -58,7 +61,8 @@ var connection = require("./index"), ); /** - * Generating a hash Password + * Generating a hash Password. + * * @param password */ UsersSchema.methods.generateHash = function (password) { @@ -67,10 +71,11 @@ UsersSchema.methods.generateHash = function (password) { /** * Checking Password. + * * @param password */ UsersSchema.methods.validPassword = function (password) { - return (typeof this.password !== 'undefined') ? bcrypt.compareSync(password, this.password) : false; + return (typeof this.password !== 'undefined' && password.length >= 6) ? bcrypt.compareSync(password, this.password) : false; }; /** @@ -81,11 +86,11 @@ UsersSchema.methods.newObjectId = function () { }; /** - * Create model User + * Create model User. */ -var Users = mongoose.model("usersaccount", UsersSchema); +var User = mongoose.model("useraccounts", UsersSchema); /** - * Export model User + * Export model User. */ -module.exports.Users = Users; +module.exports.User = User; diff --git a/app/package.json b/app/package.json new file mode 100644 index 0000000..b9b0c8b --- /dev/null +++ b/app/package.json @@ -0,0 +1,3 @@ +{ + "name": "meanstack.io-app" +} \ No newline at end of file diff --git a/app/policies/index.js b/app/policies/index.js new file mode 100644 index 0000000..122f87f --- /dev/null +++ b/app/policies/index.js @@ -0,0 +1,24 @@ +'use strict'; + +var routes = require('./routes'), + auth = require('modules/auth'), + settings = require('config'); + +/** + * Policies + * + * @param app + */ +module.exports = function (app) { + + /** + * Validate Routes. + */ + app.use(auth.routes(routes)); + + /** + * Create cookie for control angular. + */ + app.use(auth.cookie(settings.cookie)); + +}; diff --git a/routes/policies/routes.js b/app/policies/routes.js similarity index 56% rename from routes/policies/routes.js rename to app/policies/routes.js index ba50fd6..7feddc4 100644 --- a/routes/policies/routes.js +++ b/app/policies/routes.js @@ -1,19 +1,20 @@ 'use strict'; /** - * Set routes for authentication + * Set routes for authentication. * [ * { - * route: '/sign/up', //Required, route for valid - * method: ['post','get',...], //Optional, Method for valid, if not exist valid all method - * auth: true, //if route is authenticated true for false - * }, + * route: '/sign/up', //Required, route for valid + * method: ['post','get',...], //Optional, Method for valid, if not exist valid all method + * auth: true, //if route is authenticated true or false + * }, * ] + * * @type {*[]} */ module.exports = [ { - route: '/view/user', + route: '/view/myaccount', auth: true }, { diff --git a/bin/www b/bin/www index d82d11e..3b1814d 100755 --- a/bin/www +++ b/bin/www @@ -1,27 +1,24 @@ #!/usr/bin/env node var app = require('../app'), - settings = require('../config'), + settings = require('config'), debug = require('debug')(settings.server.hostname), http = require('http'); /** * Get port from environment and store in Express. */ - var port = normalizePort(process.env.PORT || settings.server.port); app.set('port', port); /** * Create HTTP server. */ - var server = http.createServer(app); /** * Listen on provided port, on all network interfaces. */ - server.listen(port, settings.server.hostname); server.on('error', onError); server.on('listening', onListening); @@ -29,7 +26,6 @@ server.on('listening', onListening); /** * Normalize a port into a number, string, or false. */ - function normalizePort(val) { var port = parseInt(val, 10); @@ -49,7 +45,6 @@ function normalizePort(val) { /** * Event listener for HTTP server "error" event. */ - function onError(error) { if (error.syscall !== 'listen') { throw error; @@ -77,7 +72,6 @@ function onError(error) { /** * Event listener for HTTP server "listening" event. */ - function onListening() { var addr = server.address(), bind = typeof addr === 'string' diff --git a/bower.json b/bower.json index 0da47ae..5de9bcf 100644 --- a/bower.json +++ b/bower.json @@ -1,9 +1,9 @@ { - "name": "meanstack", - "description": "MEANStack bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js", + "name": "MEANStack.io", + "description": "MEANStack.io bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js", "main": "", "authors": [ - "Rafael Pegorari " + "Rafael Pegorari " ], "license": "MIT", "moduleType": [ @@ -28,6 +28,7 @@ "angular-resource": "~1.5.0", "oclazyload": "~1.0.9", "AngularJS-Toaster": "~1.2.0", - "bootstrap-sass": "^3.3.6" + "bootstrap-sass": "^3.3.6", + "font-awesome": "fontawesome#^4.6.2" } } diff --git a/config.example.js b/config/config.example.js similarity index 69% rename from config.example.js rename to config/config.example.js index 886f074..c27482d 100644 --- a/config.example.js +++ b/config/config.example.js @@ -1,9 +1,12 @@ /** * Config Application + * + * @type {{name: string, description: string, version: string, server: {hostname: string, port: string, url: string}, dbconnect: {host: string, port: string, user: string, password: string, base: string}, session: {secret: string}, cookie: {flagAngularLogged: string, maxAge: number}, mail: {smtp: {host: string, secure: boolean, port: string, auth: {user: string, pass: string}, logger: boolean, debug: boolean}}}} */ var settings = { - name: 'MEANStack', - version: "0.1.0", + name: 'MEANStack.io', + description: 'bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js', + version: "0.2.0-dev", server: { hostname: 'localhost', port: '8000', @@ -20,7 +23,8 @@ var settings = { secret: '##########' }, cookie: { - flagAngularLogged: 'login' + flagAngularLogged: 'login', + maxAge: 2419200000 }, mail: { smtp: { @@ -40,22 +44,26 @@ var settings = { /** * Config auth Facebook * URL for create application: "https://developers.facebook.com/quickstarts" + * + * @type {{clientID: string, clientSecret: string, callbackURL: string}} */ settings.facebookStrategy = { - clientID: '####################', // your App ID - clientSecret: '####################', // your App Secret - callbackURL: settings.server.url + 'account/signin/facebook/callback' //callback return facebook + clientID: '####################', + clientSecret: '####################', + callbackURL: settings.server.url + 'account/signin/facebook/callback' }; /** * Config auth Google * URL for create application: "https://console.developers.google.com/projectselector/apis/library" * More documentation: "https://developers.google.com/+/web/signin/", "https://developers.google.com/identity/sign-in/web/devconsole-project" + * + * @type {{clientID: string, clientSecret: string, callbackURL: string}} */ settings.googleStrategy = { - clientID: '####################.apps.googleusercontent.com', // your App ID - clientSecret: '####################', // your App Secret - callbackURL: settings.server.url + 'account/signin/google/callback' //callback return google + clientID: '####################.apps.googleusercontent.com', + clientSecret: '####################', + callbackURL: settings.server.url + 'account/signin/google/callback' }; /** @@ -63,11 +71,13 @@ settings.googleStrategy = { * URL for create application and more documentation "https://developer.linkedin.com/docs/oauth2" * After creating the application set in "Default Application Permissions" r_basicprofile r_emailaddress * for return profile datas + * + * @type {{clientID: string, clientSecret: string, callbackURL: string}} */ settings.linkedinStrategy = { - clientID: '####################', // your App ID - clientSecret: '####################', // your App Secret - callbackURL: settings.server.url + 'account/signin/linkedin/callback' //callback return linkedin + clientID: '####################', + clientSecret: '####################', + callbackURL: settings.server.url + 'account/signin/linkedin/callback' }; /** @@ -84,21 +94,22 @@ settings.linkedinStrategy = { * @type {{consumerKey: string, consumerSecret: string, callbackURL: string}} */ settings.twitterStrategy = { - consumerKey: '####################', // your App ID - consumerSecret: '####################', // your App Secret - callbackURL: settings.server.url + 'account/signin/twitter/callback' //callback return twitter + consumerKey: '####################', + consumerSecret: '####################', + callbackURL: settings.server.url + 'account/signin/twitter/callback' }; /** * Config auth GitHub * Create application: Go on GitHub("https://github.com/"), create or access your organization, go to settings, click on the "OAuth applications" and register your new application. * More documentation: "https://developer.github.com/v3/oauth/" + * * @type {{clientID: string, clientSecret: string, callbackURL: string}} */ settings.githubStrategy = { - clientID: '####################', // your App ID - clientSecret: '####################', // your App Secret - callbackURL: settings.server.url + 'account/signin/github/callback' //callback return linkedin + clientID: '####################', + clientSecret: '####################', + callbackURL: settings.server.url + 'account/signin/github/callback' }; module.exports = settings; diff --git a/config/index.js b/config/index.js new file mode 100644 index 0000000..1fb0e4a --- /dev/null +++ b/config/index.js @@ -0,0 +1,13 @@ +'use strict'; + +/** + * Load configuration from the "process.env.NODE_ENV". + * Example: + * process.env.NODE_ENV = 'production' + * config file = 'config-production.js' + */ +var path = require('path'), + env = (process.env.NODE_ENV) ? process.env.NODE_ENV : 'development', + pathConfig = path.join(__dirname, 'config-' + env + '.js'); + +module.exports = require(pathConfig); diff --git a/config/package.json b/config/package.json new file mode 100644 index 0000000..8d92d57 --- /dev/null +++ b/config/package.json @@ -0,0 +1,3 @@ +{ + "name": "meanstack.io-config" +} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 9892dec..999d468 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -26,10 +26,10 @@ var argv = require('minimist')(process.argv.slice(2)), browserSync = require('browser-sync'), runSequence = require('run-sequence'), path = { - bower: __dirname + '/bower_components/', - dist: __dirname + '/public/dist/', - src: __dirname + '/public/src/', - angular: __dirname + '/public/src/javascripts/angular/' + bower: __dirname + '/resources/assets/bower/', + dist: __dirname + '/public/', + src: __dirname + '/resources/assets/', + angular: __dirname + '/resources/assets/javascripts/angular/' }, files = { js: [ @@ -54,25 +54,31 @@ var argv = require('minimist')(process.argv.slice(2)), path.angular + 'controllers/app/*.js' ], js_modules: [ - path.angular + 'controllers/modules/*.js', - path.angular + 'controllers/modules/login/*.js' + path.angular + 'controllers/partials/*.js', + path.angular + 'controllers/partials/login/*.js' ], css: [ path.bower + 'AngularJS-Toaster/toaster.scss', + path.bower + 'font-awesome/scss/font-awesome.scss', path.src + 'stylesheets/sass/main.scss', - path.src + 'stylesheets/styles/*.{scss,css}' + path.src + 'stylesheets/styles/**/*.{scss,css}' ], fonts: [ - path.bower + 'bootstrap-sass/assets/fonts/bootstrap/*.{eot,svg,ttf,woff,woff2}', - path.src + 'fonts/*.{eot,svg,ttf,woff,woff2}' + path.bower + 'bootstrap-sass/assets/fonts/bootstrap/*.{otf,eot,svg,ttf,woff,woff2}', + path.bower + 'font-awesome/fonts/*.{otf,eot,svg,ttf,woff,woff2}', + path.src + 'fonts/**/*.{otf,eot,svg,ttf,woff,woff2}' ], images: [ - path.src + 'images/*.{png,jpg,jpeg}' + path.src + 'images/**/*.{png,jpg,jpeg}' + ], + icons: [ + path.src + 'icons/*' ] }, /** * Ignore files bower * Used - Not validation in jshint + * * @param file * @returns {boolean} */ @@ -82,6 +88,7 @@ var argv = require('minimist')(process.argv.slice(2)), /** * Ignore files js_modules * Used - Not concat with main script + * * @param file * @returns {boolean} */ @@ -94,24 +101,42 @@ var argv = require('minimist')(process.argv.slice(2)), } } return true; + }, + /** + * Compress images files. + * + * @param files + * @param dist + */ + compressImages = function (files, dist, level) { + var optimizationLevel = (typeof level === 'undefined') ? 3 : level; + + gulp.src(files) + .pipe(cache( + imagemin( + { + optimizationLevel: optimizationLevel, + progressive: true, + interlaced: true + } + ) + )) + .pipe(gulp.dest(dist)) + .pipe(browserSync.reload({stream: true})) }; /** * Compress Images */ gulp.task('images', function () { - gulp.src(files.images) - .pipe(cache( - imagemin( - { - optimizationLevel: 3, - progressive: true, - interlaced: true - } - ) - )) - .pipe(gulp.dest(path.dist + 'images/')) - .pipe(browserSync.reload({stream: true})) + compressImages(files.images, path.dist + 'images/'); +}); + +/** + * Compress Icons + */ +gulp.task('icons', function () { + compressImages(files.icons, path.dist + '/'); }); /** @@ -125,8 +150,8 @@ gulp.task('styles', function () { this.emit('end'); } })) - .pipe(concat('main.css')) .pipe(sass()) + .pipe(concat('main.css')) .pipe(autoprefixer('last 2 versions')) .pipe(gulpif(!argv.production, gulp.dest(path.dist + 'stylesheets/'))) .pipe(rename({suffix: '.min'})) @@ -180,7 +205,7 @@ gulp.task('build', function (callback) { runSequence( 'scripts', 'styles', - ['fonts', 'images'], + ['fonts', 'images', 'icons'], callback); }); @@ -203,11 +228,11 @@ gulp.task('bs-reload', function () { */ gulp.task('watch', ['default'], function () { browserSync.init({ - proxy: settings.server.hostname+":"+settings.server.port + proxy: settings.server.hostname + ":" + settings.server.port }); - gulp.watch("public/src/stylesheets/**/*.scss", ['styles']); - gulp.watch("public/src/javascripts/**/*.js", ['scripts']); - gulp.watch("public/src/images/**/*", ['images']); - gulp.watch("public/src/fonts/*", ['fonts']); - gulp.watch("*.hbs", ['bs-reload']); + gulp.watch(path.src + "/stylesheets/**/**.{css,scss}", ['styles']); + gulp.watch(path.src + "/javascripts/**/**.js", ['scripts']); + gulp.watch(path.src + "/images/**/**", ['images']); + gulp.watch(path.src + "/fonts/**/**", ['fonts']); + gulp.watch("**.hbs", ['bs-reload']); }); diff --git a/routes/routers/account/_login.js b/modules/account/login/index.js similarity index 82% rename from routes/routers/account/_login.js rename to modules/account/login/index.js index 842e5a7..808dd0d 100644 --- a/routes/routers/account/_login.js +++ b/modules/account/login/index.js @@ -1,7 +1,8 @@ 'use strict'; /** - * Login + * Login. + * * @param req * @param res * @param next @@ -22,6 +23,9 @@ module.exports = function (req, res, next, err, user) { } req.setCookie(true, function () { + req.response.setData({ + username: user.username + }); return res.json(req.response.return()); } ); diff --git a/modules/account/login/oauth.js b/modules/account/login/oauth.js new file mode 100644 index 0000000..97d79ea --- /dev/null +++ b/modules/account/login/oauth.js @@ -0,0 +1,31 @@ +'use strict'; + +/** + * Login OAuth. + * + * @param req + * @param res + * @param next + * @param err + * @param user + * @returns {*} + */ +module.exports = function (req, res, next, err, user) { + if (err) { + return next(err); + } + if (!user || !req.response.getSuccess()) { + var error = req.response.getMsg(); + return res.redirect('/signin?error=' + error.join()); + } + req.logIn(user, function (err) { + if (err) { + return next(err); + } + req.setCookie(true, + function () { + res.redirect('/myaccount'); + } + ); + }); +}; diff --git a/passport/strategies/facebookStrategy.js b/modules/account/passport/facebook-strategy.js similarity index 85% rename from passport/strategies/facebookStrategy.js rename to modules/account/passport/facebook-strategy.js index d988dbe..ad08836 100644 --- a/passport/strategies/facebookStrategy.js +++ b/modules/account/passport/facebook-strategy.js @@ -1,10 +1,10 @@ 'use strict'; var facebookStrategy = require('passport-facebook').Strategy, - settings = require('../../config'), - findOrCreateOAuth = require('./_findOrCreateOAuth'); + settings = require('config'), + findOrCreateOAuth = require('./find-or-create-oauth'); /** - * Strategy Facebook + * Strategy Facebook. */ module.exports = function (passport) { passport.use('facebook', diff --git a/passport/strategies/_findOrCreateOAuth.js b/modules/account/passport/find-or-create-oauth.js similarity index 77% rename from passport/strategies/_findOrCreateOAuth.js rename to modules/account/passport/find-or-create-oauth.js index a819cbc..9b998bf 100644 --- a/passport/strategies/_findOrCreateOAuth.js +++ b/modules/account/passport/find-or-create-oauth.js @@ -1,9 +1,10 @@ 'use strict'; -var modelUser = require('../../models/users').Users; +var User = require('app/models/user').User; /** - * Find or Create user for strategies OAuth + * Find or Create user for strategies OAuth. + * * @param req * @param token * @param refreshToken @@ -12,7 +13,7 @@ var modelUser = require('../../models/users').Users; */ module.exports = function (req, token, refreshToken, profile, done) { - modelUser.findOne({'oauth.provider': profile.provider, 'oauth.id': profile.id}, function (err, user) { + User.findOne({'oauth.provider': profile.provider, 'oauth.id': profile.id}, function (err, user) { if (err) { return done(err); } @@ -22,7 +23,7 @@ module.exports = function (req, token, refreshToken, profile, done) { } var email = profile.emails[0].value; - modelUser.findOne({email: new RegExp('^' + email + '$', "i")}, function (err, user) { + User.findOne({email: new RegExp('^' + email + '$', "i")}, function (err, user) { if (err) { return done(err); } @@ -31,7 +32,7 @@ module.exports = function (req, token, refreshToken, profile, done) { return done(null, false); } - var newUser = new modelUser(); + var newUser = new User(); newUser._id = newUser.newObjectId(); newUser.oauth.provider = profile.provider; newUser.oauth.id = profile.id; diff --git a/passport/strategies/githubStrategy.js b/modules/account/passport/github-strategy.js similarity index 74% rename from passport/strategies/githubStrategy.js rename to modules/account/passport/github-strategy.js index c53a725..c6ec180 100644 --- a/passport/strategies/githubStrategy.js +++ b/modules/account/passport/github-strategy.js @@ -1,11 +1,11 @@ 'use strict'; var githubStrategy = require('passport-github').Strategy, - settings = require('../../config'), - findOrCreateOAuth = require('./_findOrCreateOAuth'); + settings = require('config'), + findOrCreateOAuth = require('./find-or-create-oauth'); /** - * Strategy GitHub + * Strategy GitHub. */ module.exports = function (passport) { passport.use('github', @@ -14,8 +14,8 @@ module.exports = function (passport) { clientID: settings.githubStrategy.clientID, clientSecret: settings.githubStrategy.clientSecret, callbackURL: settings.githubStrategy.callbackURL, - scope: ['user:email'], - passReqToCallback: true + passReqToCallback: true, + scope: ['user:email'] }, function (req, token, refreshToken, profile, done) { findOrCreateOAuth(req, token, refreshToken, profile, done); diff --git a/passport/strategies/googleStrategy.js b/modules/account/passport/google-strategy.js similarity index 79% rename from passport/strategies/googleStrategy.js rename to modules/account/passport/google-strategy.js index 1159e19..946fce3 100644 --- a/passport/strategies/googleStrategy.js +++ b/modules/account/passport/google-strategy.js @@ -1,11 +1,11 @@ 'use strict'; var googleStrategy = require('passport-google-oauth').OAuth2Strategy, - settings = require('../../config'), - findOrCreateOAuth = require('./_findOrCreateOAuth'); + settings = require('config'), + findOrCreateOAuth = require('./find-or-create-oauth'); /** - * Strategy Google + * Strategy Google. */ module.exports = function (passport) { passport.use('google', @@ -14,7 +14,6 @@ module.exports = function (passport) { clientID: settings.googleStrategy.clientID, clientSecret: settings.googleStrategy.clientSecret, callbackURL: settings.googleStrategy.callbackURL, - scope: ['profile', 'email'], passReqToCallback: true }, function (req, token, refreshToken, profile, done) { diff --git a/modules/account/passport/index.js b/modules/account/passport/index.js new file mode 100644 index 0000000..827fdc4 --- /dev/null +++ b/modules/account/passport/index.js @@ -0,0 +1,71 @@ +'use strict'; + +var passport = require('passport'), + User = require('app/models/user').User, + localStrategy = require('./local-strategy'), + facebookStrategy = require('./facebook-strategy'), + googleStrategy = require('./google-strategy'), + twitterStrategy = require('./twitter-strategy'), + linkedinStrategy = require('./linkedin-strategy'), + githubStrategy = require('./github-strategy'); + +/** + * Create strategies to login. + * + * @param app + */ +module.exports = function (app) { + + /** + * Init Passaport. + */ + app.use(passport.initialize()); + app.use(passport.session()); + + /** + * Serialize id user for session. + */ + passport.serializeUser(function (user, done) { + done(null, user.id); + }); + + /** + * Find user by deserialize id. + */ + passport.deserializeUser(function (id, done) { + User.findById(id, function (err, user) { + done(err, user); + }); + }); + + /** + * Strategy Local. + * Sign In, Sign Up + */ + localStrategy(passport); + + /** + * Strategy Facebook. + */ + facebookStrategy(passport); + + /** + * Strategy Google. + */ + googleStrategy(passport); + + /** + * Strategy Twitter. + */ + twitterStrategy(passport); + + /** + * Strategy Linkedin. + */ + linkedinStrategy(passport); + + /** + * Strategy GitHub. + */ + githubStrategy(passport); +}; diff --git a/passport/strategies/linkedinStrategy.js b/modules/account/passport/linkedin-strategy.js similarity index 82% rename from passport/strategies/linkedinStrategy.js rename to modules/account/passport/linkedin-strategy.js index 8348ac6..08eafbb 100644 --- a/passport/strategies/linkedinStrategy.js +++ b/modules/account/passport/linkedin-strategy.js @@ -1,11 +1,11 @@ 'use strict'; var linkedinStrategy = require('passport-linkedin-oauth2').Strategy, - settings = require('../../config'), - findOrCreateOAuth = require('./_findOrCreateOAuth'); + settings = require('config'), + findOrCreateOAuth = require('./find-or-create-oauth'); /** - * Strategy Linkedin + * Strategy Linkedin. */ module.exports = function (passport) { passport.use('linkedin', @@ -19,6 +19,7 @@ module.exports = function (passport) { state: true }, function (req, token, refreshToken, profile, done) { + console.log(profile); findOrCreateOAuth(req, token, refreshToken, profile, done); } ) diff --git a/passport/strategies/localStrategy.js b/modules/account/passport/local-strategy.js similarity index 87% rename from passport/strategies/localStrategy.js rename to modules/account/passport/local-strategy.js index 9f63ca3..4895fdf 100644 --- a/passport/strategies/localStrategy.js +++ b/modules/account/passport/local-strategy.js @@ -1,15 +1,15 @@ 'use strict'; var localStrategy = require('passport-local').Strategy, - modelUser = require('../../models/users').Users; + User = require('app/models/user').User; /** - * Strategy local + * Strategy local. */ module.exports = function (passport) { /** - * Strategy local singin + * Strategy local singin. */ passport.use('local-signin', new localStrategy( @@ -19,7 +19,7 @@ module.exports = function (passport) { passReqToCallback: true }, function (req, email, password, done) { - modelUser.findOne({email: new RegExp('^' + email + '$', "i")}, function (err, user) { + User.findOne({email: new RegExp('^' + email + '$', "i")}, function (err, user) { if (err) { return done(err); } @@ -40,7 +40,7 @@ module.exports = function (passport) { ); /** - * Strategy local singup + * Strategy local singup. */ passport.use('local-signup', new localStrategy( @@ -66,18 +66,18 @@ module.exports = function (passport) { req.response.setMsg('Make sure your passwords are the same !'); } - modelUser.findOne({email: new RegExp('^' + email + '$', "i")}, function (err, findUser) { + User.findOne({email: new RegExp('^' + email + '$', "i")}, function (err, user) { if (err) { return done(err); } - if (findUser) { + if (user) { req.response.setMsg('E-mail already registered.'); } if (req.response.hasMsg()) { return done(null, false); } - var newUser = new modelUser(); + var newUser = new User(); newUser._id = newUser.newObjectId(); newUser.username = data.username; newUser.email = email; diff --git a/passport/strategies/twitterStrategy.js b/modules/account/passport/twitter-strategy.js similarity index 85% rename from passport/strategies/twitterStrategy.js rename to modules/account/passport/twitter-strategy.js index 2527d00..50aef2d 100644 --- a/passport/strategies/twitterStrategy.js +++ b/modules/account/passport/twitter-strategy.js @@ -1,11 +1,11 @@ 'use strict'; var twitterStrategy = require('passport-twitter').Strategy, - settings = require('../../config'), - findOrCreateOAuth = require('./_findOrCreateOAuth'); + settings = require('config'), + findOrCreateOAuth = require('./find-or-create-oauth'); /** - * Strategy Twitter + * Strategy Twitter. */ module.exports = function (passport) { passport.use('twitter', diff --git a/modules/auth.js b/modules/auth/index.js similarity index 78% rename from modules/auth.js rename to modules/auth/index.js index 4aa034e..4e5789f 100644 --- a/modules/auth.js +++ b/modules/auth/index.js @@ -1,9 +1,8 @@ 'use strict'; -var settings = require('../config'); - /** * Controls access to routes. + * * @param routes * @returns {Function} */ @@ -40,13 +39,13 @@ module.exports.routes = function (routes) { if (filtredRoute.length === 1) { var route = filtredRoute[0]; if (typeof route.auth !== 'undefined' && route.auth === true) { - if (req.user) { + if (req.isAuthenticated()) { return next(); } return res.render('error/403'); } else if (typeof route.auth !== 'undefined' && route.auth === false) { - if (!req.user) { + if (req.isUnauthenticated()) { return next(); } return res.render('error/403'); @@ -61,14 +60,16 @@ module.exports.routes = function (routes) { /** * Create cookie for login control AngularJS + * + * @param cookie * @private */ -function _cookie() { +module.exports.cookie = function(cookie) { - this.initialize = function (req, res, next) { + return function (req, res, next) { function setCookie(val, callback) { - res.cookie(settings.cookie.flagAngularLogged, val, {path: '/', httpOnly: false, maxAge: 3600000}); + res.cookie(cookie.flagAngularLogged, val, {path: '/', httpOnly: false, maxAge: cookie.maxAge}); if (callback) { callback(); } @@ -78,13 +79,17 @@ function _cookie() { req.setCookie = setCookie; } - if (req.user) { - res.cookie('login', true, {path: '/', httpOnly: false, maxAge: 3600000}); - return next(); + if (req.isAuthenticated()) { + return req.setCookie(true, + function () { + return next(); + } + ); } - res.cookie('login', false, {path: '/', httpOnly: false, maxAge: 3600000}); - return next(); + return req.setCookie(false, + function () { + return next(); + } + ); }; -} - -module.exports.cookie = new _cookie(); +}; diff --git a/modules/mail.js b/modules/mail.js deleted file mode 100644 index 9d74b04..0000000 --- a/modules/mail.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -var nodemailer = require('nodemailer'), - settings = require('../config'); - -module.exports.smtp = nodemailer.createTransport({ - host: settings.mail.smtp.host, - secure: settings.mail.smtp.secure, - port: settings.mail.smtp.port, - auth: { - user: settings.mail.smtp.auth.user, - pass: settings.mail.smtp.auth.pass - }, - logger: settings.mail.smtp.logger, - debug: settings.mail.smtp.debug -}); diff --git a/modules/package.json b/modules/package.json new file mode 100644 index 0000000..a61b1a7 --- /dev/null +++ b/modules/package.json @@ -0,0 +1,3 @@ +{ + "name": "meanstack.io-modules" +} \ No newline at end of file diff --git a/modules/response.js b/modules/response/index.js similarity index 74% rename from modules/response.js rename to modules/response/index.js index 8aac70e..d957cf0 100644 --- a/modules/response.js +++ b/modules/response/index.js @@ -1,7 +1,8 @@ 'use strict'; /** - * Export module Response for "req.response" + * Export module Response for "req.response". + * * @returns {Function} */ module.exports = function () { @@ -15,21 +16,22 @@ module.exports = function () { }; /** - * Default return response + * Default return response. + * * @private */ function response() { var val = { success: false, msg: [], - data: {}, - privateDate: {} + data: {} }; this.setSuccess = function (boolean) { val.success = (typeof boolean === 'undefined') ? true : boolean; return true; }; + this.getSuccess = function () { return val.success; }; @@ -38,28 +40,25 @@ function response() { val.msg.push(msg); return true; }; + this.getMsg = function () { return val.msg; }; + this.setData = function (data) { val.data = data; return true; }; + this.getData = function () { return val.data; }; - this.setPrivateData = function (privateData) { - val.privateData = privateData; - return true; - }; - this.getPrivateData = function () { - return val.privateData; - }; + this.hasMsg = function () { return ((val.msg).length); }; + this.return = function () { - delete val.privateData; return val; } } diff --git a/node_modules/app b/node_modules/app new file mode 120000 index 0000000..5df94d9 --- /dev/null +++ b/node_modules/app @@ -0,0 +1 @@ +../app \ No newline at end of file diff --git a/node_modules/config b/node_modules/config new file mode 120000 index 0000000..3ca249e --- /dev/null +++ b/node_modules/config @@ -0,0 +1 @@ +../config \ No newline at end of file diff --git a/node_modules/modules b/node_modules/modules new file mode 120000 index 0000000..464b823 --- /dev/null +++ b/node_modules/modules @@ -0,0 +1 @@ +../modules \ No newline at end of file diff --git a/node_modules/resources b/node_modules/resources new file mode 120000 index 0000000..35a4f7a --- /dev/null +++ b/node_modules/resources @@ -0,0 +1 @@ +../resources \ No newline at end of file diff --git a/package.json b/package.json index 787b678..609b7e0 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,34 @@ { - "name": "meanstack", - "description": "MEANStack bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js", - "version": "0.1.0", + "name": "MEANStack.io", + "version": "0.2.0-dev", + "description": "MEANStack.io bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js", + "scripts": { + "start": "NODE_ENV=development nodemon ./bin/www" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/developscript/meanstack.io.git" + }, "author": "Rafael Pegorari ", "license": "MIT", - "repository": "developscript/meanstack", - "scripts": { - "start": "nodemon ./bin/www" + "bugs": { + "url": "https://github.com/developscript/meanstack.io/issues" }, + "homepage": "http://meanstack.io", "dependencies": { "bcrypt": "^0.8.5", "body-parser": "~1.13.2", "bower": "^1.7.2", + "compression": "^1.6.1", "cookie-parser": "~1.3.5", "debug": "~2.2.0", + "email-templates": "^2.3.0", "express": "~4.13.1", - "express-handlebars": "^2.0.1", + "express-hbs": "^1.0.1", "express-session": "^1.13.0", "handlebars": "^4.0.5", "kerberos": "0.0.18", + "moment": "^2.13.0", "mongoose": "^4.3.6", "morgan": "~1.6.1", "nodemailer": "^2.2.1", diff --git a/passport/index.js b/passport/index.js deleted file mode 100644 index 336c0f0..0000000 --- a/passport/index.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -var modelUser = require('../models/users').Users, - localStrategy = require('./strategies/localStrategy'), - facebookStrategy = require('./strategies/facebookStrategy'), - googleStrategy = require('./strategies/googleStrategy'), - twitterStrategy = require('./strategies/twitterStrategy'), - linkedinStrategy = require('./strategies/linkedinStrategy'), - githubStrategy = require('./strategies/githubStrategy'); - -/** - * Create strategy to login - * @param passport - */ -module.exports = function (passport) { - - /** - * Serialize id user for session. - */ - passport.serializeUser(function (user, done) { - done(null, user.id); - }); - - /** - * Find user by deserialize id. - */ - passport.deserializeUser(function (id, done) { - modelUser.findById(id, function (err, user) { - done(err, user); - }); - }); - - /** - * Strategy Local - * Sign In, Sign Up - */ - localStrategy(passport); - - /** - * Strategy Facebook - */ - facebookStrategy(passport); - - /** - * Strategy Google - */ - googleStrategy(passport); - - /** - * Strategy Twitter - */ - twitterStrategy(passport); - - /** - * Strategy Linkedin - */ - linkedinStrategy(passport); - - /** - * Strategy GitHub - */ - githubStrategy(passport); -}; diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index c7699ee..0000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/src/javascripts/angular/controllers/modules/gettingstartedController.js b/public/src/javascripts/angular/controllers/modules/gettingstartedController.js deleted file mode 100644 index 39304c7..0000000 --- a/public/src/javascripts/angular/controllers/modules/gettingstartedController.js +++ /dev/null @@ -1,4 +0,0 @@ -angular.module("App") - .controller("gettingstartedController", ['$rootScope', '$scope', function ($rootScope, $scope) { - //Documentation Controller - }]); diff --git a/public/src/javascripts/angular/controllers/modules/userController.js b/public/src/javascripts/angular/controllers/modules/userController.js deleted file mode 100644 index c26fd5e..0000000 --- a/public/src/javascripts/angular/controllers/modules/userController.js +++ /dev/null @@ -1,8 +0,0 @@ -angular.module("App") - .controller("userController", ['$rootScope', '$scope', '$location', function ($rootScope, $scope, $location) { - //Facebook login add hash #_=_ in URL - var hash = $location.hash(); - if(hash === '_=_'){ - $location.hash(); - } - }]); diff --git a/public/src/javascripts/angular/modules/path.js b/public/src/javascripts/angular/modules/path.js deleted file mode 100644 index bcac6c3..0000000 --- a/public/src/javascripts/angular/modules/path.js +++ /dev/null @@ -1,38 +0,0 @@ -var AppPath = angular.module('AppPath', []); - -AppPath.provider("path", [function () { - var settings_default = { - "path": { - "min": true, - "controller": "/dist/javascripts/", - "image": "/dist/images/", - "style": "/dist/stylesheets/" - } - }, - settings = {}; - - this.setSettings = function (op_settings) { - settings = angular.extend(settings_default, op_settings); - }; - - this.$get = ['settings', - function (settings) { - var service = {}, - min = (typeof settings.path.min === true); - extension = function (type) { - return ((min) ? '.min' : '') + '.' + type; - }; - - /** - * Return controller path according destination and minification. - * @param nameController - * @returns {*} - */ - service.controller = function (nameController) { - return settings.path.controller + nameController + extension('js'); - }; - - return service; - } - ]; -}]); diff --git a/public/src/stylesheets/sass/components/_blocks.scss b/public/src/stylesheets/sass/components/_blocks.scss deleted file mode 100644 index e69de29..0000000 diff --git a/public/src/stylesheets/sass/components/_forms.scss b/public/src/stylesheets/sass/components/_forms.scss deleted file mode 100644 index e69de29..0000000 diff --git a/public/src/stylesheets/sass/pages/_signinup.scss b/public/src/stylesheets/sass/pages/_signinup.scss deleted file mode 100644 index 93a0c9b..0000000 --- a/public/src/stylesheets/sass/pages/_signinup.scss +++ /dev/null @@ -1,11 +0,0 @@ -.forgot-link{ - padding-bottom: 10px; - font-size: 12px; - text-align: right; -} - -.nav-singinup{ - border-top: 1px solid#888; - padding-top:15px; - font-size:12px -} diff --git a/resources/assets/fonts/.gitignore b/resources/assets/fonts/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/resources/assets/fonts/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/resources/assets/icons/favicon.png b/resources/assets/icons/favicon.png new file mode 100644 index 0000000..c0058e2 Binary files /dev/null and b/resources/assets/icons/favicon.png differ diff --git a/resources/assets/images/.gitignore b/resources/assets/images/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/resources/assets/images/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/public/src/javascripts/angular/app.js b/resources/assets/javascripts/angular/app.js similarity index 80% rename from public/src/javascripts/angular/app.js rename to resources/assets/javascripts/angular/app.js index af1408e..4a1eb75 100644 --- a/public/src/javascripts/angular/app.js +++ b/resources/assets/javascripts/angular/app.js @@ -1,7 +1,8 @@ /** * Modules for APP AngularJS */ -var App = angular.module("App", [ +var App; +App = angular.module("App", [ "ui.router", "oc.lazyLoad", "ngResource", diff --git a/public/src/javascripts/angular/config.js b/resources/assets/javascripts/angular/config.js similarity index 67% rename from public/src/javascripts/angular/config.js rename to resources/assets/javascripts/angular/config.js index 29f559b..3934122 100644 --- a/public/src/javascripts/angular/config.js +++ b/resources/assets/javascripts/angular/config.js @@ -10,18 +10,18 @@ App.config(['$interpolateProvider', function ($interpolateProvider) { * Config application */ App.constant('settings', { - "path": { - "min": true, - "controller": "/dist/javascripts/", - "image": "/dist/images/", - "style": "/dist/stylesheets/" + path: { + min: true, + controller: "/javascripts/", + image: "/images/", + style: "/stylesheets/" }, - "auth": { + auth: { redirect: { notLogged: "/signin", - logged: "/user" + logged: "/myaccount" }, - "cookie": { + cookie: { flagAngularLogged: "login" } } diff --git a/public/src/javascripts/angular/configs/auth.js b/resources/assets/javascripts/angular/configs/auth.js similarity index 100% rename from public/src/javascripts/angular/configs/auth.js rename to resources/assets/javascripts/angular/configs/auth.js diff --git a/public/src/javascripts/angular/configs/oclazyload.js b/resources/assets/javascripts/angular/configs/oclazyload.js similarity index 100% rename from public/src/javascripts/angular/configs/oclazyload.js rename to resources/assets/javascripts/angular/configs/oclazyload.js diff --git a/public/src/javascripts/angular/configs/path.js b/resources/assets/javascripts/angular/configs/path.js similarity index 100% rename from public/src/javascripts/angular/configs/path.js rename to resources/assets/javascripts/angular/configs/path.js diff --git a/public/src/javascripts/angular/controllers/app/headerController.js b/resources/assets/javascripts/angular/controllers/app/headerController.js similarity index 83% rename from public/src/javascripts/angular/controllers/app/headerController.js rename to resources/assets/javascripts/angular/controllers/app/headerController.js index cd3e173..667eb66 100644 --- a/public/src/javascripts/angular/controllers/app/headerController.js +++ b/resources/assets/javascripts/angular/controllers/app/headerController.js @@ -1,6 +1,7 @@ App.controller('headerController', ['$scope', '$rootScope', '$location', 'request', '$templateCache', function ($scope, $rootScope, $location, request, $templateCache) { /** * Active navegation + * * @param viewLocation * @returns {boolean} */ @@ -8,6 +9,13 @@ App.controller('headerController', ['$scope', '$rootScope', '$location', 'reques return viewLocation === $location.path(); }; + /** + * Alter username navbar. + */ + $rootScope.$on('username', function(event, name) { + $scope.username = name; + }); + /** * Logoff */ diff --git a/resources/assets/javascripts/angular/controllers/partials/aboutController.js b/resources/assets/javascripts/angular/controllers/partials/aboutController.js new file mode 100644 index 0000000..e416d19 --- /dev/null +++ b/resources/assets/javascripts/angular/controllers/partials/aboutController.js @@ -0,0 +1,4 @@ +angular.module("App") + .controller("aboutController", ['$rootScope', '$scope', function ($rootScope, $scope) { + //aboutController + }]); diff --git a/public/src/javascripts/angular/controllers/modules/homeController.js b/resources/assets/javascripts/angular/controllers/partials/homeController.js similarity index 82% rename from public/src/javascripts/angular/controllers/modules/homeController.js rename to resources/assets/javascripts/angular/controllers/partials/homeController.js index 9252864..3cd7e5e 100644 --- a/public/src/javascripts/angular/controllers/modules/homeController.js +++ b/resources/assets/javascripts/angular/controllers/partials/homeController.js @@ -1,4 +1,4 @@ angular.module("App") .controller("homeController", ['$rootScope', '$scope', function ($rootScope, $scope) { - //Home Controller + //HomeController }]); diff --git a/public/src/javascripts/angular/controllers/modules/login/forgotController.js b/resources/assets/javascripts/angular/controllers/partials/login/forgotController.js similarity index 99% rename from public/src/javascripts/angular/controllers/modules/login/forgotController.js rename to resources/assets/javascripts/angular/controllers/partials/login/forgotController.js index 576b6a6..33e25c6 100644 --- a/public/src/javascripts/angular/controllers/modules/login/forgotController.js +++ b/resources/assets/javascripts/angular/controllers/partials/login/forgotController.js @@ -17,5 +17,4 @@ angular.module("App") } ); }; - }]); diff --git a/public/src/javascripts/angular/controllers/modules/login/forgotResetPasswordController.js b/resources/assets/javascripts/angular/controllers/partials/login/forgotResetPasswordController.js similarity index 82% rename from public/src/javascripts/angular/controllers/modules/login/forgotResetPasswordController.js rename to resources/assets/javascripts/angular/controllers/partials/login/forgotResetPasswordController.js index b7f3c3b..b01e6e0 100644 --- a/public/src/javascripts/angular/controllers/modules/login/forgotResetPasswordController.js +++ b/resources/assets/javascripts/angular/controllers/partials/login/forgotResetPasswordController.js @@ -13,12 +13,15 @@ angular.module("App") }, function (response) { if (response.success) { $templateCache.removeAll(); - $location.path('/user'); + + // Alter username navbar. + $rootScope.$emit('username', response.data.username); + + $location.path('/myaccount'); } else { toaster.error("Error", response.msg.join('
')); } } ); }; - }]); diff --git a/public/src/javascripts/angular/controllers/modules/login/signinController.js b/resources/assets/javascripts/angular/controllers/partials/login/signinController.js similarity index 81% rename from public/src/javascripts/angular/controllers/modules/login/signinController.js rename to resources/assets/javascripts/angular/controllers/partials/login/signinController.js index 632fa0e..225c856 100644 --- a/public/src/javascripts/angular/controllers/modules/login/signinController.js +++ b/resources/assets/javascripts/angular/controllers/partials/login/signinController.js @@ -8,7 +8,7 @@ angular.module("App") } /** - * Signin strategy local + * Sign in strategy local */ $scope.signIn = function () { request('/account/signin').post( @@ -18,7 +18,11 @@ angular.module("App") }, function (response) { if (response.success) { $templateCache.removeAll(); - $location.path('/user'); + + // Alter username navbar. + $rootScope.$emit('username', response.data.username); + + $location.path('/myaccount'); } else { toaster.error("Error", response.msg.join('
')); } diff --git a/public/src/javascripts/angular/controllers/modules/login/signupController.js b/resources/assets/javascripts/angular/controllers/partials/login/signupController.js similarity index 79% rename from public/src/javascripts/angular/controllers/modules/login/signupController.js rename to resources/assets/javascripts/angular/controllers/partials/login/signupController.js index 23e8e4b..72d519b 100644 --- a/public/src/javascripts/angular/controllers/modules/login/signupController.js +++ b/resources/assets/javascripts/angular/controllers/partials/login/signupController.js @@ -2,7 +2,7 @@ angular.module("App") .controller("signupController", ['$rootScope', '$scope', 'request', '$location', 'toaster', '$templateCache', function ($rootScope, $scope, request, $location, toaster, $templateCache) { /** - * Signup strategy local + * Sign up strategy local */ $scope.signUp = function () { request('/account/signup').post( @@ -14,12 +14,15 @@ angular.module("App") }, function (response) { if (response.success) { $templateCache.removeAll(); - $location.path('/user'); + + // Alter username navbar. + $rootScope.$emit('username', response.data.username); + + $location.path('/myaccount'); } else { toaster.error("Error", response.msg.join('
')); } } ); }; - }]); diff --git a/resources/assets/javascripts/angular/controllers/partials/myAccountController.js b/resources/assets/javascripts/angular/controllers/partials/myAccountController.js new file mode 100644 index 0000000..b6e97e2 --- /dev/null +++ b/resources/assets/javascripts/angular/controllers/partials/myAccountController.js @@ -0,0 +1,4 @@ +angular.module("App") + .controller("myAccountController", ['$rootScope', '$scope', '$location', function ($rootScope, $scope, $location) { + //myAccountController + }]); diff --git a/resources/assets/javascripts/angular/directives/compile.js b/resources/assets/javascripts/angular/directives/compile.js new file mode 100644 index 0000000..16bd6a8 --- /dev/null +++ b/resources/assets/javascripts/angular/directives/compile.js @@ -0,0 +1,21 @@ +/** + * Listening the directive and add value on the front end. + * Used to change the user's name on the front end. + * + * Example: + * Value + */ +App.directive('compile', ['$compile', function ($compile) { + return function(scope, element, attrs) { + scope.$watch( + function(scope) { + return scope.$eval(attrs.compile); + }, + function(value) { + element.html(value); + + $compile(element.contents())(scope); + } + ); + }; +}]); diff --git a/public/src/javascripts/angular/factory/request.js b/resources/assets/javascripts/angular/factory/request.js similarity index 100% rename from public/src/javascripts/angular/factory/request.js rename to resources/assets/javascripts/angular/factory/request.js diff --git a/public/src/javascripts/angular/modules/auth.js b/resources/assets/javascripts/angular/modules/auth.js similarity index 70% rename from public/src/javascripts/angular/modules/auth.js rename to resources/assets/javascripts/angular/modules/auth.js index 20d4f6c..111dba6 100644 --- a/public/src/javascripts/angular/modules/auth.js +++ b/resources/assets/javascripts/angular/modules/auth.js @@ -1,3 +1,54 @@ +/** + * Module authentication for AngularJS. + * + * Example: + * + * // Auth false + * .state('signup', { + * url: "/signup", + * templateUrl: "/view/login/signup", + * ... + * // Control access + * access: { + * // Only access page if not login. + * auth: false, + * // Optional redirect: URL + * redirect: '/myaccount', + * } + * ... + * + * // Auth true + * .state('myaccount', { + * url: "/myaccount", + * ... + * // Control access + * access: { + * // Only access page if logged. + * auth: true, + * // Optional setting -> redirect: URL + * redirect: '/signin' + * // redirect result, domain.com/signin?r=/myaccount + * } + * ... + * + * === Config redirect default in file ../config.js === + * + * ... + * "auth": { + * redirect: { + * notLogged: "/signin", + * logged: "/myaccount" + * } + * } + * ... + * + * + * === Check user is logged === + * + * return {boolean} + * service.check() + * + */ var AppPath = angular.module('AppAuth', []); AppPath.provider("auth", [function () { @@ -5,7 +56,7 @@ AppPath.provider("auth", [function () { "auth": { redirect: { notLogged: "/signin", - logged: "/user" + logged: "/myaccount" }, "cookie": { flagAngularLogged: "login" @@ -24,6 +75,7 @@ AppPath.provider("auth", [function () { /** * Check user is logged + * * @returns {boolean} */ service.check = function () { @@ -44,6 +96,7 @@ AppPath.provider("auth", [function () { /** * Route control access + * * @param toState */ service.routeAuth = function (toState) { diff --git a/resources/assets/javascripts/angular/modules/path.js b/resources/assets/javascripts/angular/modules/path.js new file mode 100644 index 0000000..4f4be65 --- /dev/null +++ b/resources/assets/javascripts/angular/modules/path.js @@ -0,0 +1,83 @@ +/** + * Module load file path. + * controller, + * image, + * style, + * + * Example: + * + * ... + * controller: "homeController", //Controller page + * resolve: { + * //Load dependencies + * deps: ['$ocLazyLoad', 'path', function ($ocLazyLoad, path) { + * return $ocLazyLoad.load({ + * //Insert controller before id + * insertBefore: '#load_controllers', + * files: [ + * //Return controller path according destination and minify. + * path.controller('homeController') + * ] + * }, + * ... + * + * === Config path directories in file ../config.js === + * + * ... + * path: { + * min: true, + * controller: "/javascripts/", + * image: "/images/", + * style: "/stylesheets/" + * }, + * ... + * + */ + +var AppPath = angular.module('AppPath', []); + +AppPath.provider("path", [function () { + var settings_default = { + "path": { + "min": true, + "controller": "/javascripts/", + "image": "/images/", + "style": "/stylesheets/" + } + }, + settings = {}; + + this.setSettings = function (op_settings) { + settings = angular.extend(settings_default, op_settings); + }; + + this.$get = ['settings', + function (settings) { + var service = {}, + min = (typeof settings.path.min === 'undefined' || settings.path.min === true); + extension = function (type) { + return ((min) ? '.min' : '') + '.' + type; + }; + + /** + * Return controller path according destination and minify. + * + * @param controllerName + * @returns {*} + */ + service.controller = function (controllerName) { + return settings.path.controller + controllerName + extension('js'); + }; + + service.image = function (image) { + return settings.path.image + image; + }; + + service.style = function (style) { + return settings.path.style + style; + }; + + return service; + } + ]; +}]); diff --git a/public/src/javascripts/angular/routers.js b/resources/assets/javascripts/angular/routers.js similarity index 89% rename from public/src/javascripts/angular/routers.js rename to resources/assets/javascripts/angular/routers.js index a7f8543..def0fac 100644 --- a/public/src/javascripts/angular/routers.js +++ b/resources/assets/javascripts/angular/routers.js @@ -11,7 +11,7 @@ App.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', functio templateUrl: "/view/home/index", //Route view data: { title: 'Home', //Title page - description: 'MEANStack bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js' //Description Page + description: 'MEANStack.io bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js' //Description Page }, controller: "homeController", //Controller page resolve: { @@ -21,7 +21,7 @@ App.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', functio //Insert controller before id insertBefore: '#load_controllers', files: [ - //Return controller path according destination and minification. + //Return controller path according destination and minify. path.controller('homeController') ] } @@ -30,17 +30,17 @@ App.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', functio } }) - .state('getting-started', { - url: "/getting-started", - templateUrl: "/view/gettingstarted/index", - data: {title: 'Getting Started'}, - controller: "gettingstartedController", + .state('about', { + url: "/about", + templateUrl: "/view/about/index", + data: {title: 'About'}, + controller: "aboutController", resolve: { deps: ['$ocLazyLoad', 'path', function ($ocLazyLoad, path) { return $ocLazyLoad.load({ insertBefore: '#load_controllers', files: [ - path.controller('gettingstartedController') + path.controller('aboutController') ] } ); @@ -156,17 +156,17 @@ App.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', functio } }) - .state('user', { - url: "/user", - templateUrl: "/view/user/index", - data: {title: 'User'}, - controller: "userController", + .state('myaccount', { + url: "/myaccount", + templateUrl: "/view/myaccount/index", + data: {title: 'My Account'}, + controller: "myAccountController", resolve: { deps: ['$ocLazyLoad', 'path', function ($ocLazyLoad, path) { return $ocLazyLoad.load({ insertBefore: '#load_controllers', files: [ - path.controller('userController') + path.controller('myAccountController') ] } ); @@ -180,7 +180,7 @@ App.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', functio * Optional setting -> redirect: URL * Default config settings.auth.redirect.(logged for auth true || notLogged for auth false) * ex: redirect: '/signin' - * result url: domain.com/signin?r=/user + * result url: domain.com/signin?r=/myaccount */ } }) diff --git a/public/src/javascripts/angular/run.js b/resources/assets/javascripts/angular/run.js similarity index 91% rename from public/src/javascripts/angular/run.js rename to resources/assets/javascripts/angular/run.js index fe2c1b3..ed21d85 100644 --- a/public/src/javascripts/angular/run.js +++ b/resources/assets/javascripts/angular/run.js @@ -1,4 +1,6 @@ -/* Init global settings and run the app */ +/** + * Init global settings and run the app + */ App.run(["$rootScope", "settings", "$state", "auth", function ($rootScope, settings, $state, auth) { // state to be accessed from view $rootScope.$state = $state; diff --git a/public/src/stylesheets/sass/common/_global.scss b/resources/assets/stylesheets/sass/common/_global.scss similarity index 58% rename from public/src/stylesheets/sass/common/_global.scss rename to resources/assets/stylesheets/sass/common/_global.scss index 728cc7b..9f39853 100644 --- a/public/src/stylesheets/sass/common/_global.scss +++ b/resources/assets/stylesheets/sass/common/_global.scss @@ -1,5 +1,5 @@ body { - font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; + font: 14px Arial, Helvetica, sans-serif; } .small-label{ diff --git a/public/src/stylesheets/sass/common/_variables.scss b/resources/assets/stylesheets/sass/common/_variables.scss similarity index 100% rename from public/src/stylesheets/sass/common/_variables.scss rename to resources/assets/stylesheets/sass/common/_variables.scss diff --git a/resources/assets/stylesheets/sass/components/_blocks.scss b/resources/assets/stylesheets/sass/components/_blocks.scss new file mode 100644 index 0000000..213937c --- /dev/null +++ b/resources/assets/stylesheets/sass/components/_blocks.scss @@ -0,0 +1,11 @@ +.jumbotron{ + background: transparent; + border-bottom: 1px solid #E7E7E7; + text-align: center; +} + +.alert { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} diff --git a/public/src/stylesheets/sass/components/_buttons.scss b/resources/assets/stylesheets/sass/components/_buttons.scss similarity index 59% rename from public/src/stylesheets/sass/components/_buttons.scss rename to resources/assets/stylesheets/sass/components/_buttons.scss index 2074082..59158bd 100644 --- a/public/src/stylesheets/sass/components/_buttons.scss +++ b/resources/assets/stylesheets/sass/components/_buttons.scss @@ -1,34 +1,29 @@ -.buttons-social{ - margin-bottom: 10px; - a{ - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - } - a:hover, a:focus, a:active{ - opacity: .88; - } - .color-linkedin{ +.btn { + &.linkedin { color: #fff; background-color: #1B86BC; border-color: #1B86BC; } - .color-facebook{ + + &.facebook { color: #fff; background-color: #44619D; border-color: #44619D; } - .color-twitter{ + + &.twitter { color: #fff; background-color: #339CC3; border-color: #339CC3; } - .color-googleplus{ + + &.googleplus { color: #fff; background-color: #D73D32; border-color: #D73D32; } - .color-github{ + + &.github { color: #fff; background-color: #202021; border-color: #202021; diff --git a/resources/assets/stylesheets/sass/components/_forms.scss b/resources/assets/stylesheets/sass/components/_forms.scss new file mode 100644 index 0000000..51e1fac --- /dev/null +++ b/resources/assets/stylesheets/sass/components/_forms.scss @@ -0,0 +1,5 @@ +.form-control, .btn { + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} diff --git a/public/src/stylesheets/sass/layouts/_footer.scss b/resources/assets/stylesheets/sass/layouts/_footer.scss similarity index 100% rename from public/src/stylesheets/sass/layouts/_footer.scss rename to resources/assets/stylesheets/sass/layouts/_footer.scss diff --git a/public/src/stylesheets/sass/layouts/_header.scss b/resources/assets/stylesheets/sass/layouts/_header.scss similarity index 100% rename from public/src/stylesheets/sass/layouts/_header.scss rename to resources/assets/stylesheets/sass/layouts/_header.scss diff --git a/public/src/stylesheets/sass/main.scss b/resources/assets/stylesheets/sass/main.scss similarity index 64% rename from public/src/stylesheets/sass/main.scss rename to resources/assets/stylesheets/sass/main.scss index 1d098ac..d677c09 100644 --- a/public/src/stylesheets/sass/main.scss +++ b/resources/assets/stylesheets/sass/main.scss @@ -1,7 +1,6 @@ - @import "common/variables"; -@import "../../../../bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss"; +@import "../../bower/bootstrap-sass/assets/stylesheets/_bootstrap.scss"; @import "common/global"; @import "components/blocks"; @@ -11,4 +10,3 @@ @import "layouts/footer"; @import "pages/home"; -@import "pages/signinup"; diff --git a/public/src/stylesheets/sass/pages/_home.scss b/resources/assets/stylesheets/sass/pages/_home.scss similarity index 100% rename from public/src/stylesheets/sass/pages/_home.scss rename to resources/assets/stylesheets/sass/pages/_home.scss diff --git a/public/src/stylesheets/styles/main.css b/resources/assets/stylesheets/styles/main.css similarity index 100% rename from public/src/stylesheets/styles/main.css rename to resources/assets/stylesheets/styles/main.css diff --git a/public/src/stylesheets/styles/main.scss b/resources/assets/stylesheets/styles/main.scss similarity index 100% rename from public/src/stylesheets/styles/main.scss rename to resources/assets/stylesheets/styles/main.scss diff --git a/resources/package.json b/resources/package.json new file mode 100644 index 0000000..2d4a493 --- /dev/null +++ b/resources/package.json @@ -0,0 +1,3 @@ +{ + "name": "meanstack.io-resources" +} \ No newline at end of file diff --git a/resources/views/about/index.hbs b/resources/views/about/index.hbs new file mode 100644 index 0000000..48ff30c --- /dev/null +++ b/resources/views/about/index.hbs @@ -0,0 +1,91 @@ +
+

+ MEANStack.io + About +

+ +

+ bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js +

+
+ + +

+ MEANStack.io Is a solution full-stack JavaScript, based on MongoDB, Express, AngularJS, Node.js and another + stack of packages. +

+ +
    +
  • + Stack of packages + +
      +
    • + Gulp gulp-sass, gulp-minify-css, gulp-imagemin, gulp-uglify, gulp-jshint, browser-sync and more... +
    • + +
    • + Bower package manager. Used to manage front-end packages. +
    • + +
    • + Handlebars template manager. +
    • + +
    • + Mongoose MongoDB object modeling tool. +
    • + +
    • + Nodemailer module to send e-mails with Node.js. +
    • + +
    • + Passporte authentication middleware for Node.js. With passport-facebook, passport-github, + passport-google-oauth, passport-linkedin-oauth2, passport-twitter and passport-local form to login + strategy. +
    • + +
    • + jQuery JavaScript Library. +
    • + +
    • + AngularUI Router Routing framework for AngularJS. +
    • + +
    • + ocLazyLoad Lazy load modules & components in AngularJS. +
    • + +
    • + Bootstrap for Sass is Bootstrap... +
    • +
    +
  • +
+ +

+ Are some of the packages that we use to make this dream come true. +

+ + + +

+ Documentation can be found on the meanstack.io/documentation +

+ + + +

+ Copyright © 2016 Developscript - Licensed under MIT. +

diff --git a/resources/views/error/403.hbs b/resources/views/error/403.hbs new file mode 100644 index 0000000..3254c64 --- /dev/null +++ b/resources/views/error/403.hbs @@ -0,0 +1,9 @@ +
+

+ Doh !!! You are not authorized to access this page. +

+ +

+ What do you look not here... Go to home page ! +

+
diff --git a/resources/views/error/404.hbs b/resources/views/error/404.hbs new file mode 100644 index 0000000..d630fe0 --- /dev/null +++ b/resources/views/error/404.hbs @@ -0,0 +1,9 @@ +
+

+ Doh !!! Page not found. +

+ +

+ What do you look not here... Go to home page ! +

+
diff --git a/views/home/index.hbs b/resources/views/home/index.hbs similarity index 63% rename from views/home/index.hbs rename to resources/views/home/index.hbs index 989fc87..9ef6576 100644 --- a/views/home/index.hbs +++ b/resources/views/home/index.hbs @@ -1,6 +1,6 @@ -
+

- MEANStack + MEANStack.io

diff --git a/resources/views/index.hbs b/resources/views/index.hbs new file mode 100644 index 0000000..6a4759a --- /dev/null +++ b/resources/views/index.hbs @@ -0,0 +1,5 @@ +{{!< app}} + +

+
+
diff --git a/resources/views/layouts/app.hbs b/resources/views/layouts/app.hbs new file mode 100644 index 0000000..afb1aa0 --- /dev/null +++ b/resources/views/layouts/app.hbs @@ -0,0 +1,42 @@ + + + + + + + + + + + + +{{>nav}} + +
+ + {{{body}}} + +
+ + + +{{>toaster}} + + + + + +{{{block "scripts"}}} + + + \ No newline at end of file diff --git a/views/login/forgot/index.hbs b/resources/views/login/forgot/index.hbs similarity index 86% rename from views/login/forgot/index.hbs rename to resources/views/login/forgot/index.hbs index 2edc757..cf6b78a 100644 --- a/views/login/forgot/index.hbs +++ b/resources/views/login/forgot/index.hbs @@ -1,14 +1,12 @@
-
-

Reset your password

- - +
diff --git a/resources/views/myaccount/index.hbs b/resources/views/myaccount/index.hbs new file mode 100644 index 0000000..6f27d2d --- /dev/null +++ b/resources/views/myaccount/index.hbs @@ -0,0 +1,41 @@ +
+

+ {{ settings.name }} + My Account +

+ +

+ bringing together the best of MEAN MongoDB, Express, AngularJS and Node.js +

+
+ + + +

+ Logged with: + {{#if user.oauth.provider}} + - {{ ucfirst user.oauth.provider }} + {{^}} + Local strategy + {{/if}} +

+ +

+ Username: {{ user.username }} +

+ +

+ E-Mail: {{ user.email }} +

diff --git a/resources/views/partials/login-social.hbs b/resources/views/partials/login-social.hbs new file mode 100644 index 0000000..1946e0e --- /dev/null +++ b/resources/views/partials/login-social.hbs @@ -0,0 +1,26 @@ + diff --git a/views/partials/nav.hbs b/resources/views/partials/nav.hbs similarity index 78% rename from views/partials/nav.hbs rename to resources/views/partials/nav.hbs index dcc4eaa..aea5cf1 100644 --- a/views/partials/nav.hbs +++ b/resources/views/partials/nav.hbs @@ -1,43 +1,51 @@ -
+