From ef9e1f3444d893e721250a952cb72e0f997e24ac Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Mon, 2 Sep 2013 01:08:28 -0400 Subject: [PATCH] rewrite: push login modal to the front page, don't allow anonymous usage. --- assets/js/controllers/authCtrl.js | 19 ++++++-- assets/js/services/authServices.js | 1 + assets/js/services/userServices.js | 8 ++-- assets/js/static.js | 6 +++ src/controllers/user.js | 2 +- src/middleware.js | 5 +-- src/routes/pages.js | 5 +++ src/server.js | 3 +- views/shared/modals/login.jade | 5 ++- views/static/front.jade | 69 +++++++++++++++++++++++++----- views/static/layout.jade | 27 +++++++++--- 11 files changed, 120 insertions(+), 30 deletions(-) create mode 100644 assets/js/static.js diff --git a/assets/js/controllers/authCtrl.js b/assets/js/controllers/authCtrl.js index 7fdd91d6cc..5f9fa82d93 100644 --- a/assets/js/controllers/authCtrl.js +++ b/assets/js/controllers/authCtrl.js @@ -4,10 +4,11 @@ The authentication controller (login & facebook) */ -habitrpg.controller("AuthCtrl", ['$scope', '$rootScope', 'Facebook', 'LocalAuth', 'User', '$http', '$location', 'API_URL', - function($scope, $rootScope, Facebook, LocalAuth, User, $http, $location, API_URL) { +habitrpg.controller("AuthCtrl", ['$scope', '$rootScope', 'User', '$http', '$location', 'API_URL', + function($scope, $rootScope, User, $http, $location, API_URL) { var runAuth; var showedFacebookMessage; + $scope.useUUID = false; $scope.toggleUUID = function() { if (showedFacebookMessage === false) { @@ -16,16 +17,19 @@ habitrpg.controller("AuthCtrl", ['$scope', '$rootScope', 'Facebook', 'LocalAuth' } $scope.useUUID = !$scope.useUUID; }; + $scope.logout = function() { localStorage.clear(); - location.reload(); + window.location.href = '/logout'; }; + runAuth = function(id, token) { User.authenticate(id, token, function(err) { window.location.href = '/'; //$rootScope.modals.login = false; }); }; + $scope.register = function() { /*TODO highlight invalid inputs we have this as a workaround for https://github.com/HabitRPG/habitrpg-mobile/issues/64 @@ -45,6 +49,7 @@ habitrpg.controller("AuthCtrl", ['$scope', '$rootScope', 'Facebook', 'LocalAuth' } }); }; + $scope.auth = function() { var data; data = { @@ -68,4 +73,12 @@ habitrpg.controller("AuthCtrl", ['$scope', '$rootScope', 'Facebook', 'LocalAuth' }); } }; + + $scope.playButtonClick = function(){ + if (User.authenticated()) { + window.location.href = '/'; + } else { + $('#login-modal').modal('show'); + } + } }]); diff --git a/assets/js/services/authServices.js b/assets/js/services/authServices.js index fad0176ecd..4efa0efd46 100644 --- a/assets/js/services/authServices.js +++ b/assets/js/services/authServices.js @@ -2,6 +2,7 @@ /** * Services that persists and retrieves user from localStorage. + * FIXME is this file ever used? */ var facebook = {} diff --git a/assets/js/services/userServices.js b/assets/js/services/userServices.js index 187b534e2a..78f847265f 100644 --- a/assets/js/services/userServices.js +++ b/assets/js/services/userServices.js @@ -5,8 +5,8 @@ */ angular.module('userServices', []). - factory('User', ['$http', '$location', 'Notification', 'API_URL', 'STORAGE_USER_ID', 'STORAGE_SETTINGS_ID', - function($http, $location, Notification, API_URL, STORAGE_USER_ID, STORAGE_SETTINGS_ID) { + factory('User', ['$http', '$location', 'API_URL', 'STORAGE_USER_ID', 'STORAGE_SETTINGS_ID', + function($http, $location, API_URL, STORAGE_USER_ID, STORAGE_SETTINGS_ID) { var authenticated = false, defaultSettings = { auth: { apiId: '', apiToken: ''}, @@ -92,7 +92,7 @@ angular.module('userServices', []). queue.push(sent.shift()) }); settings.fetching = false; - Notification.push({type:'text', text:"We're offline"}) + //Notification.push({type:'text', text:"We're offline"}) }); @@ -174,7 +174,7 @@ angular.module('userServices', []). //If user does not have ApiID that forward him to settings. if (!settings.auth.apiId || !settings.auth.apiToken) { - $location.path("/login"); + //$location.path("/login"); } else { userServices.authenticate(settings.auth.apiId, settings.auth.apiToken) } diff --git a/assets/js/static.js b/assets/js/static.js new file mode 100644 index 0000000000..4876031b17 --- /dev/null +++ b/assets/js/static.js @@ -0,0 +1,6 @@ +"use strict"; + +window.habitrpg = angular.module('habitrpg', ['userServices']) + .constant("API_URL", "") + .constant("STORAGE_USER_ID", 'habitrpg-user') + .constant("STORAGE_SETTINGS_ID", 'habit-mobile-settings') \ No newline at end of file diff --git a/src/controllers/user.js b/src/controllers/user.js index ca426e06b2..cc1c4b70f6 100644 --- a/src/controllers/user.js +++ b/src/controllers/user.js @@ -31,7 +31,6 @@ var NO_USER_FOUND = {err: "No user found."}; beforeEach auth interceptor */ - api.auth = function(req, res, next) { var token, uid; uid = req.headers['x-api-user']; @@ -53,6 +52,7 @@ api.auth = function(req, res, next) { } res.locals.wasModified = +user._v !== +req.query._v; res.locals.user = user; + req.session.userId = user._id; return next(); }); }; diff --git a/src/middleware.js b/src/middleware.js index 27274de1f8..5af9b64044 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -5,8 +5,8 @@ module.exports = function(req, res, next) { // show them the splash page if they're not logged in var isStatic = req.url.split('/')[1] == 'static'; -// if (!isStatic && !req.headers['x-api-user'] && !req.headers['x-api-key'] && req.headers.accept != 'application/json') -// return res.redirect('/static/front') + if (req.url == '/' && !req.headers['x-api-user'] && !req.headers['x-api-key'] && !(req.session && req.session.userId)) + return res.redirect('/static/front') res.locals.habitrpg = res.locals.habitrpg || {} _.defaults(res.locals.habitrpg, { @@ -20,7 +20,6 @@ module.exports = function(req, res, next) { res.header("Access-Control-Allow-Methods", "OPTIONS,GET,POST,PUT,HEAD,DELETE"); res.header("Access-Control-Allow-Headers", "Content-Type,Accept,Content-Encoding,X-Requested-With,x-api-user,x-api-key"); - //wtf is this for? if (req.method === 'OPTIONS') { return res.send(200); } diff --git a/src/routes/pages.js b/src/routes/pages.js index 8e1f7fe590..965c226fdc 100644 --- a/src/routes/pages.js +++ b/src/routes/pages.js @@ -19,6 +19,11 @@ router.get('/partials/options', function(req, res) { res.render('options'); }); +router.get('/logout', function(req, res) { + delete req.session.userId; + res.redirect('/'); +}) + // -------- Marketing -------- router.get('/splash.html', function(req, res) { diff --git a/src/server.js b/src/server.js index ce9277daff..bcaf820b95 100644 --- a/src/server.js +++ b/src/server.js @@ -34,6 +34,8 @@ app.use(express.logger("dev")); app.use(express.bodyParser()); app.use(require('connect-assets')()); app.use(express.methodOverride()); +app.use(express.cookieParser(nconf.get('SESSION_SECRET'))); +app.use(express.session()); app.use(require('./middleware')); app.use(app.router); app.use(express['static'](path.join(__dirname, "/../public"))); @@ -71,7 +73,6 @@ module.exports = server; # .use(express.methodOverride()) # # Uncomment and supply secret to add Derby session handling # # Derby session middleware creates req.session and socket.io sessions - # .use(express.cookieParser()) # .use(store.sessionMiddleware # secret: process.env.SESSION_SECRET || 'YOUR SECRET HERE' # cookie: { maxAge: TWO_WEEKS } # defaults to 2 weeks? aka, can delete this line? diff --git a/views/shared/modals/login.jade b/views/shared/modals/login.jade index e5d7e08691..9245d18535 100644 --- a/views/shared/modals/login.jade +++ b/views/shared/modals/login.jade @@ -1,4 +1,7 @@ -div(modal='modals.login') +// This file was moved to /views/static/front.jade, as we're requiring login / registration from front page now + keep this file around until we're sure of that decision + +//-div(modal='modals.login') .modal-header h3 Login / Register .modal-body diff --git a/views/static/front.jade b/views/static/front.jade index 2ca8f2c6ae..9019d7c948 100644 --- a/views/static/front.jade +++ b/views/static/front.jade @@ -4,15 +4,62 @@ block title title HabitRPG | Gamify Your Life block content - #wrap - //-include ./header - .jumbotron.masthead + div(ng-app='habitrpg') + #wrap(ng-controller='AuthCtrl') + //-include ./header + .jumbotron.masthead + .container + h1 + img(src='/bower_components/habitrpg-shared/img/logo/habitrpg_pixel.png', alt='HabitRPG') + p + | A habit building program which treats your life like a Role Playing Game. Level up as you succeed, lose HP as you fail, earn money to buy weapons and armor. + a.btn.btn-primary.btn-small(ng-click='playButtonClick()') Play .container - h1 - img(src='/bower_components/habitrpg-shared/img/logo/habitrpg_pixel.png', alt='HabitRPG') - p - | A habit building program which treats your life like a Role Playing Game. Level up as you succeed, lose HP as you fail, earn money to buy weapons and armor. - a.btn.btn-primary.btn-small(href='/?play=1') Play - .container - p(style='height:600;') - iframe(src='//player.vimeo.com/video/57639356', width='100%', height='539', frameborder='0', webkitallowfullscreen='', mozallowfullscreen='', allowfullscreen='') \ No newline at end of file + p(style='height:600;') + iframe(src='//player.vimeo.com/video/57639356', width='100%', height='539', frameborder='0', webkitallowfullscreen='', mozallowfullscreen='', allowfullscreen='') + + .modal.fade#login-modal + .modal-dialog + .modal-content + .modal-header + button.close(type='button', data-dismiss='modal', aria-hidden='true') × + h4.modal-title Login / Register + .modal-body + //a(href='/auth/facebook') + img(src='/img/facebook-login-register.jpeg', alt='Login / Register With Facebook') + //h3 Or + ul.nav.nav-tabs + li.active + a(data-toggle='tab',data-target='#login-tab') Login + li + a(data-toggle='tab',data-target='#register-tab') Register + + .tab-content + .tab-pane.active + form(ng-submit='auth()') + .control-group + input(type='text', ng-model='loginUsername', placeholder='{{useUUID ? "UUID" : "Username"}}') + .control-group + input(type='{{useUUID ? "text" : "password"}}', ng-model='loginPassword', placeholder='{{useUUID ? "API Token" : "Password"}}') + .control-group + label.checkbox + input(type='checkbox', ng-click='useUUID = !useUUID') + | Use UUID / API Token (For Facebook Users) + .control-group + input.btn.btn-primary(type='submit', value='Login') + + .tab-pane + form(ng-submit='register()', name='registrationForm') + .control-group + input(type='text', ng-model='registerVals.username', placeholder='Username', required) + .control-group + input(type='email', ng-model='registerVals.email', placeholder='Email', required) + .control-group + input(type='password', ng-model='registerVals.password', placeholder='Password', required) + .control-group + input(type='password', ng-model='registerVals.confirmPassword', placeholder='Password Confirm', required) + .control-group + input.btn.btn-primary(type='submit', value='Register') + + .modal-footer + button.btn.btn-default(type='button', data-dismiss='modal') Close \ No newline at end of file diff --git a/views/static/layout.jade b/views/static/layout.jade index 2c35eaa01f..53361e8145 100644 --- a/views/static/layout.jade +++ b/views/static/layout.jade @@ -7,16 +7,31 @@ html meta(charset='utf-8') meta(name='viewport', content='width=device-width, initial-scale=1.0') - // CDN - link(href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap.min.css', rel='stylesheet') - link(href='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/css/bootstrap-responsive.min.css', rel='stylesheet') - link(href='/css/docs.css', rel='stylesheet') + + // CSS + link(rel='stylesheet', href='/bower_components/bootstrap/docs/assets/css/bootstrap.css') + link(rel='stylesheet', href='/bower_components/bootstrap/docs/assets/css/bootstrap-responsive.css') + link(href='/bower_components/bootstrap/docs/assets/css/docs.css', rel='stylesheet') link(href='/css/static-pages.css', rel='stylesheet') link(href='/css/footer.css', rel='stylesheet') - script(src='//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js') - script(src='//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.1/js/bootstrap.min.js') + + // FIXME we gotta get rid of all these requirements in userServices. we don't need habitrpg-shared, lodash, moment, etc here + // and habitrpg-shared alone is ~700kb + + // JS + script(type='text/javascript', src='/bower_components/jquery/jquery.min.js') + script(type='text/javascript', src='/bower_components/lodash/dist/lodash.min.js') + script(type='text/javascript', src='/bower_components/habitrpg-shared/dist/habitrpg-shared.js') + script(type='text/javascript', src='/bower_components/moment/min/moment.min.js') + script(type='text/javascript', src='/bower_components/angular/angular.min.js') + script(type='text/javascript', src='/bower_components/bootstrap/docs/assets/js/bootstrap.min.js') script(type='text/javascript'). $.getScript("//s7.addthis.com/js/250/addthis_widget.js#pubid=lefnire"); + + != js('static') + != js('services/userServices') + != js('controllers/authCtrl') + body block content