Repository: incubator-ignite Updated Branches: refs/heads/ignite-843 8406e7c0d -> edb80e605
IGNITE-843 Reworked password reset from token to link. Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/edb80e60 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/edb80e60 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/edb80e60 Branch: refs/heads/ignite-843 Commit: edb80e605db4e7e031b3d719d75c4ffee3dd4e71 Parents: 8406e7c Author: AKuznetsov <akuznet...@gridgain.com> Authored: Fri Aug 7 08:28:25 2015 +0700 Committer: AKuznetsov <akuznet...@gridgain.com> Committed: Fri Aug 7 08:28:25 2015 +0700 ---------------------------------------------------------------------- modules/control-center-web/src/main/js/app.js | 2 +- .../src/main/js/controllers/common-module.js | 38 +++++--------- .../control-center-web/src/main/js/package.json | 22 ++++---- .../src/main/js/routes/public.js | 39 ++++++++------ .../src/main/js/views/login.jade | 55 ++++++++++++++++++++ .../src/main/js/views/loginModal.jade | 55 -------------------- .../src/main/js/views/reset.jade | 21 ++++++-- .../src/main/js/views/resetModal.jade | 38 -------------- .../src/main/js/views/templates/layout.jade | 2 +- 9 files changed, 123 insertions(+), 149 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/app.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/app.js b/modules/control-center-web/src/main/js/app.js index 413d92c..5b7d9c2 100644 --- a/modules/control-center-web/src/main/js/app.js +++ b/modules/control-center-web/src/main/js/app.js @@ -100,7 +100,7 @@ app.all('/configuration/*', mustAuthenticated); app.all('*', function(req, res, next) { var becomeUsed = req.session.viewedUser && req.user.admin; - if (req.url == '/reset') { + if (req.url.lastIndexOf('/reset', 0) === 0) { res.locals.user = null; res.locals.becomeUsed = false; } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/controllers/common-module.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/controllers/common-module.js b/modules/control-center-web/src/main/js/controllers/common-module.js index 60e02fc..ef3f5ba 100644 --- a/modules/control-center-web/src/main/js/controllers/common-module.js +++ b/modules/control-center-web/src/main/js/controllers/common-module.js @@ -595,10 +595,8 @@ controlCenterModule.controller('activeLink', [ }]); // Login popup controller. -controlCenterModule.controller('auth', [ - '$scope', '$modal', '$http', '$window', '$timeout', '$common', '$focus', - function ($scope, $modal, $http, $window, $timeout, $common, $focus) { - $scope.showResetModal = false; +controlCenterModule.controller('auth', ['$scope', '$modal', '$http', '$window', '$common', '$focus', + function ($scope, $modal, $http, $window, $common, $focus) { $scope.action = 'login'; $scope.userDropdown = [{text: 'Profile', href: '/profile'}]; @@ -610,15 +608,11 @@ controlCenterModule.controller('auth', [ $scope.userDropdown.push({text: 'Log Out', href: '/logout'}); } - // Pre-fetch modal dialogs. - var loginModal = $modal({scope: $scope, templateUrl: '/loginModal', show: false}); - var resetModal = $modal({scope: $scope, templateUrl: '/resetModal', show: false}); + if ($scope.token && !$scope.error) + $focus('user_password'); - // Show reset modal if needed. - $timeout(function () { - if ($scope.showResetModal) - $scope.reset() - }); + // Pre-fetch modal dialogs. + var loginModal = $modal({scope: $scope, templateUrl: '/login', show: false}); // Show login modal. $scope.login = function () { @@ -629,15 +623,6 @@ controlCenterModule.controller('auth', [ }); }; - // Show reset password modal. - $scope.reset = function () { - resetModal.$promise.then(function () { - resetModal.show(); - - $focus('user_token'); - }); - }; - // Try to authorize user with provided credentials. $scope.auth = function (action, user_info) { $http.post('/' + action, user_info) @@ -661,13 +646,16 @@ controlCenterModule.controller('auth', [ $scope.resetPassword = function (user_info) { $http.post('/reset_password', user_info) .success(function (data) { - resetModal.hide(); - $scope.user_info = {email: data}; $scope.login(); }) - .error(function (data) { - $common.showError(data, 'top', '#errors-container'); + .error(function (data, state) { + $common.showError(data); + + if (state == 503) { + $scope.user_info = {}; + $scope.login(); + } }); } }]); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/package.json ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/package.json b/modules/control-center-web/src/main/js/package.json index 72a0497..f9a1425 100644 --- a/modules/control-center-web/src/main/js/package.json +++ b/modules/control-center-web/src/main/js/package.json @@ -21,30 +21,30 @@ }, "dependencies": { "archiver": "^0.14.4", - "body-parser": "~1.12.0", + "body-parser": "~1.13.3", "connect-flash": "^0.1.1", "connect-mongo": "^0.8.1", "cookie-parser": "~1.3.4", - "debug": "~2.1.1", - "express": "~4.12.2", + "debug": "~2.2.0", + "express": "~4.13.3", "express-session": "^1.11.1", - "jade": "~1.9.2", - "lodash": "3.10.0", - "mongoose": "^4.0.2", + "jade": "~1.11.0", + "lodash": "3.10.1", + "mongoose": "^4.1.1", "mongoose-deep-populate": "1.1.0", - "nconf": "^0.7.1", + "nconf": "^0.7.2", "node-sass-middleware": "^0.9.0", "passport": "^0.2.1", "passport-local": "^1.0.0", "passport-local-mongoose": "^1.0.0", "nodemailer": "1.4.0", - "serve-favicon": "~2.2.0", + "serve-favicon": "~2.3.0", "ws": "~0.7.2" }, "devDependencies": { - "morgan": "~1.5.1", + "morgan": "~1.6.1", "supertest": "^1.0.1", - "mocha": "~2.0.1", - "should": "~3.1.3" + "mocha": "~2.2.5", + "should": "~7.0.2" } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/routes/public.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/public.js b/modules/control-center-web/src/main/js/routes/public.js index 3f770a1..483baa9 100644 --- a/modules/control-center-web/src/main/js/routes/public.js +++ b/modules/control-center-web/src/main/js/routes/public.js @@ -42,18 +42,8 @@ router.get('/copy', function (req, res) { }); /* GET login dialog. */ -router.get('/loginModal', function (req, res) { - res.render('loginModal'); -}); - -/* GET reset password page. */ -router.get('/reset', function (req, res) { - res.render('reset'); -}); - -/* GET reset password page. */ -router.get('/resetModal', function (req, res) { - res.render('resetModal'); +router.get('/login', function (req, res) { + res.render('login'); }); /** @@ -146,8 +136,7 @@ router.post('/request_password_reset', function(req, res) { subject: 'Password Reset', text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' + 'Please click on the following link, or paste this into your browser to complete the process:\n\n' + - 'http://' + req.headers.host + '/reset\n' + - 'And enter this reset token: ' + token + '\n\n' + + 'http://' + req.headers.host + '/reset/' + token + '\n\n' + 'If you did not request this, please ignore this email and your password will remain unchanged.\n\n' + '--------------\n' + 'Apache Ignite Web Control Center\n' @@ -163,6 +152,26 @@ router.post('/request_password_reset', function(req, res) { }); }); +router.get('/reset', function (req, res) { + res.render('reset', {}); +}); + +/* GET reset password page. */ +router.get('/reset/:token', function (req, res) { + var token = req.params.token; + + var data = {token: token}; + + db.Account.findOne({resetPasswordToken: token}, function (err, user) { + if (!user) + data.error = 'Invalid token for password reset!'; + else if (err) + data.error = err; + + res.render('reset', data); + }); +}); + /** * Reset password with given token. */ @@ -205,7 +214,7 @@ router.post('/reset_password', function(req, res) { transporter.sendMail(mailOptions, function(err){ if (err) - return res.status(401).send('Failed to send password reset confirmation e-mail!'); + return res.status(503).send('Password was changed, but failed to send confirmation e-mail!<br />' + err); return res.status(200).send(user.email); }); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/views/login.jade ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/views/login.jade b/modules/control-center-web/src/main/js/views/login.jade new file mode 100644 index 0000000..8b32aa1 --- /dev/null +++ b/modules/control-center-web/src/main/js/views/login.jade @@ -0,0 +1,55 @@ +//- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +mixin lbl(txt) + label.col-sm-3.required #{txt} + +.modal.center(role='dialog') + .modal-dialog + .modal-content + #errors-container.modal-header.header + button.close(type='button' ng-click='$hide()' aria-hidden='true') × + h1.navbar-brand + a(href='/') Apache Ignite Web Configurator + h4.modal-title(style='padding-right: 55px') Authentication + p(style='padding-right: 55px') Log in or register in order to collaborate + form.form-horizontal(name='loginForm' ng-init='action == "login"') + .modal-body.row + .col-sm-9.col-sm-offset-1 + .details-row(ng-show='action == "register"') + +lbl('Full Name:') + .col-sm-9 + input#user_name.form-control(enter-focus-next enter-focus-next-id='user_email' type='text' ng-model='user_info.username' placeholder='John Smith' ng-required='action=="register"') + .details-row + +lbl('Email:') + .col-sm-9 + input#user_email.form-control(enter-focus-next enter-focus-next-id='user_password' type='email' ng-model='user_info.email' placeholder='y...@domain.com' required on-enter='action == "request_password_reset" && loginForm.$valid && auth(action, user_info)') + .details-row(ng-show='action != "request_password_reset"') + +lbl('Password:') + .col-sm-9 + input#user_password.form-control(enter-focus-next enter-focus-next-id='user_confirm' type='password' ng-model='user_info.password' placeholder='Password' ng-required='action != "request_password_reset"' on-enter='action == "login" && loginForm.$valid && auth(action, user_info)') + .details-row(ng-if='action == "register"') + +lbl('Confirm:') + .col-sm-9 + input#user_confirm.form-control(type='password' ng-model='user_info.confirm' match='user_info.password' placeholder='Confirm password' ng-required='action == "register"' on-enter='loginForm.$valid && auth(action, user_info)') + .modal-footer + a.labelField(ng-show='action != "request_password_reset"' ng-click='action = "request_password_reset"' event-focus='click' event-focus-id='user_email') Forgot password? + a.labelField(ng-show='action == "request_password_reset"' ng-click='action = "login"' event-focus='click' event-focus-id='user_email') Log In + a.labelLogin(ng-show='action == "register"' event-focus='click' event-focus-id='user_email' ng-click='action = "login";') Log In + a.labelLogin(ng-show='action == "login"' event-focus='click' event-focus-id='user_name' ng-click='action = "register"') Sign Up + button.btn.btn-primary(ng-show='action == "login"' ng-disabled='loginForm.$invalid' ng-click='auth(action, user_info)') Log In + button.btn.btn-primary(ng-show='action == "register"' ng-disabled='loginForm.$invalid' ng-click='auth(action, user_info)') Sign Up + button.btn.btn-primary(ng-show='action == "request_password_reset"' ng-disabled='loginForm.$invalid' ng-click='auth(action, user_info)') Reset Password http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/views/loginModal.jade ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/views/loginModal.jade b/modules/control-center-web/src/main/js/views/loginModal.jade deleted file mode 100644 index 8b32aa1..0000000 --- a/modules/control-center-web/src/main/js/views/loginModal.jade +++ /dev/null @@ -1,55 +0,0 @@ -//- - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -mixin lbl(txt) - label.col-sm-3.required #{txt} - -.modal.center(role='dialog') - .modal-dialog - .modal-content - #errors-container.modal-header.header - button.close(type='button' ng-click='$hide()' aria-hidden='true') × - h1.navbar-brand - a(href='/') Apache Ignite Web Configurator - h4.modal-title(style='padding-right: 55px') Authentication - p(style='padding-right: 55px') Log in or register in order to collaborate - form.form-horizontal(name='loginForm' ng-init='action == "login"') - .modal-body.row - .col-sm-9.col-sm-offset-1 - .details-row(ng-show='action == "register"') - +lbl('Full Name:') - .col-sm-9 - input#user_name.form-control(enter-focus-next enter-focus-next-id='user_email' type='text' ng-model='user_info.username' placeholder='John Smith' ng-required='action=="register"') - .details-row - +lbl('Email:') - .col-sm-9 - input#user_email.form-control(enter-focus-next enter-focus-next-id='user_password' type='email' ng-model='user_info.email' placeholder='y...@domain.com' required on-enter='action == "request_password_reset" && loginForm.$valid && auth(action, user_info)') - .details-row(ng-show='action != "request_password_reset"') - +lbl('Password:') - .col-sm-9 - input#user_password.form-control(enter-focus-next enter-focus-next-id='user_confirm' type='password' ng-model='user_info.password' placeholder='Password' ng-required='action != "request_password_reset"' on-enter='action == "login" && loginForm.$valid && auth(action, user_info)') - .details-row(ng-if='action == "register"') - +lbl('Confirm:') - .col-sm-9 - input#user_confirm.form-control(type='password' ng-model='user_info.confirm' match='user_info.password' placeholder='Confirm password' ng-required='action == "register"' on-enter='loginForm.$valid && auth(action, user_info)') - .modal-footer - a.labelField(ng-show='action != "request_password_reset"' ng-click='action = "request_password_reset"' event-focus='click' event-focus-id='user_email') Forgot password? - a.labelField(ng-show='action == "request_password_reset"' ng-click='action = "login"' event-focus='click' event-focus-id='user_email') Log In - a.labelLogin(ng-show='action == "register"' event-focus='click' event-focus-id='user_email' ng-click='action = "login";') Log In - a.labelLogin(ng-show='action == "login"' event-focus='click' event-focus-id='user_name' ng-click='action = "register"') Sign Up - button.btn.btn-primary(ng-show='action == "login"' ng-disabled='loginForm.$invalid' ng-click='auth(action, user_info)') Log In - button.btn.btn-primary(ng-show='action == "register"' ng-disabled='loginForm.$invalid' ng-click='auth(action, user_info)') Sign Up - button.btn.btn-primary(ng-show='action == "request_password_reset"' ng-disabled='loginForm.$invalid' ng-click='auth(action, user_info)') Reset Password http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/views/reset.jade ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/views/reset.jade b/modules/control-center-web/src/main/js/views/reset.jade index 950f1a7..778c5e3 100644 --- a/modules/control-center-web/src/main/js/views/reset.jade +++ b/modules/control-center-web/src/main/js/views/reset.jade @@ -17,7 +17,22 @@ extends templates/layout block container - .row - .text-center(ng-controller='auth' ng-init='showResetModal=true') + .row(ng-init='token = #{JSON.stringify(token)}; error=#{JSON.stringify(error)}') + .text-center(ng-if='!token') p Further instructions for password reset have been sent to your e-mail address. - button.btn.btn-primary(ng-click='reset()' href='#') Reset Password + .text-center(ng-if='error') + p {{::error}} + div(ng-controller='auth' ng-if='token && !error') + form.form-horizontal(name='resetForm' ng-init='user_info.token = token') + .settings-row + label.col-sm-1 Token: + label {{::token}} + .settings-row + label.col-sm-1.required Password: + .col-sm-3 + input#user_password.form-control(enter-focus-next enter-focus-next-id='user_confirm' type='password' ng-model='user_info.password' placeholder='New password' required) + .settings-row + label.col-sm-1.required Confirm: + .col-sm-3 + input#user_confirm.form-control(type='password' ng-model='user_info.confirm' match='user_info.password' placeholder='Confirm new password' required on-enter='resetForm.$valid && resetPassword(user_info)') + button.btn.btn-primary(ng-disabled='resetForm.$invalid' ng-click='resetPassword(user_info)') Reset Password http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/views/resetModal.jade ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/views/resetModal.jade b/modules/control-center-web/src/main/js/views/resetModal.jade deleted file mode 100644 index df3dec8..0000000 --- a/modules/control-center-web/src/main/js/views/resetModal.jade +++ /dev/null @@ -1,38 +0,0 @@ -//- - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -.modal.center(role='dialog') - .modal-dialog - #errors-container.modal-content - .modal-header.header - button.close(type='button' ng-click='$hide()' aria-hidden='true') × - h4.modal-title(style='padding-right: 55px') Reset password - form.form-horizontal(name='resetForm' ng-init='action == "login"') - .modal-body.row - .col-sm-9.col-sm-offset-1 - .details-row - label.col-sm-4.required Token: - .col-sm-8 - input#user_token.form-control(enter-focus-next enter-focus-next-id='user_password' type='text' ng-model='user_info.token' placeholder='Reset token' required) - .details-row - label.col-sm-4.required New password: - .col-sm-8 - input#user_password.form-control(enter-focus-next enter-focus-next-id='user_confirm' type='password' ng-model='user_info.password' placeholder='New password' required) - .details-row - label.col-sm-4.required Confirm: - .col-sm-8 - input#user_confirm.form-control(type='password' ng-model='user_info.confirm' match='user_info.password' placeholder='Confirm new password' required on-enter='resetPassword(user_info)') - .modal-footer - button.btn.btn-primary(ng-disabled='resetForm.$invalid' ng-click='resetPassword(user_info)') Reset Password - http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/edb80e60/modules/control-center-web/src/main/js/views/templates/layout.jade ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/views/templates/layout.jade b/modules/control-center-web/src/main/js/views/templates/layout.jade index 10aaa75..91062ba 100644 --- a/modules/control-center-web/src/main/js/views/templates/layout.jade +++ b/modules/control-center-web/src/main/js/views/templates/layout.jade @@ -34,7 +34,7 @@ html(ng-app='ignite-web-control-center' ng-init='user = #{JSON.stringify(user)}; block scripts script(src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js') - script(src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.min.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js') script(src='//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js') script(src='//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular-sanitize.js')