Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Registration & Reset password #68

Open
wants to merge 46 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
52a306a
Merge pull request #1 from ordavidil/update-gitignore
ordavidil Jun 16, 2015
bce2ec0
Adding "Reset Password" message.
Jun 18, 2015
d8be92d
Adding "Reset Password" endpoint.
Jun 18, 2015
feb0c2d
Adding "Forgot Password" flow on the client.
Jun 18, 2015
7236eb4
Adding "Save new password" flow to the client.
Jun 18, 2015
309cb12
WIP - Adding an endpoint to update a user entity.
Jun 18, 2015
8da77cf
Changing resource name to prevent a clash with the 'users' resource.
Jun 22, 2015
70595ce
WIP - Adding sign up page.
Jun 23, 2015
2f3c7eb
WIP - Adding email availability endpoint.
Jun 23, 2015
70b62d9
WIP - Adding username availability endpoint.
Jun 23, 2015
701a538
Adding "Verify Email" message.
Jun 24, 2015
ed95f95
Fixing email & username availability endpoints
Jun 24, 2015
c081b8c
Adding the option of creating new user through endpoint.
Jun 24, 2015
40ce87c
Adding the "sign up" function to the client.
Jun 24, 2015
48f8f68
Resetting the flags before each request.
Jun 25, 2015
285b6e9
Adding email verification mechanism.
Jun 25, 2015
3673dcc
Prevent from drupal to notify users about activated account.
Jun 25, 2015
a03bfa0
Changing to camelCase.
Jul 5, 2015
70b5b56
Improved the error msg.
Jul 5, 2015
cb081e4
Adding a setter for the access token.
Jul 5, 2015
6a38f14
Adding comment.
Jul 5, 2015
a5d061c
Removing unnecessary variable.
Jul 5, 2015
3a094b9
Cleanup files.
Jul 5, 2015
7174bd6
Adding RESTful empty response.
Jul 6, 2015
bf0b5f8
Fixing err msgs on "Forgot Password" page.
Jul 6, 2015
fe3cf58
Deny access to password field on GET request.
Jul 7, 2015
9337802
Adding "Users Availability".
Jul 7, 2015
942507a
Sending verification mail via "hook_user_insert".
Jul 9, 2015
e811c6d
Changing back the class to extend from.
Jul 9, 2015
d52578c
Removing "SkeletonTokenNotifierResource" class.
Jul 9, 2015
245e436
Checking the site settings before sending a verification mail.
Jul 9, 2015
21dc4a7
Checking the site settings before allowing a user to register.
Jul 9, 2015
90a7201
Removing unnecessary name/mail setters.
Jul 12, 2015
1afa24f
Cleanup.
Jul 12, 2015
b51a293
Cleanup.
Jul 14, 2015
b3af456
Cleanup.
Jul 15, 2015
a5883a1
Verify the email on the state resolve.
Aug 18, 2015
ae513bc
Cleaning up the "Reset Password" controller.
Aug 19, 2015
159671d
Fixing .travis.tml
Aug 20, 2015
237c8a7
Fixing .travis.yml round #2
Aug 20, 2015
2377d6f
Fixing .travis.yml round #3
Aug 20, 2015
b2804c1
Updating angular version.
Aug 20, 2015
32ea7af
Fixing .travis.yml round #4
Aug 20, 2015
d4969d7
Fixing travis.yml round #5
Sep 1, 2015
d9c2023
Update angular minor version.
Sep 1, 2015
5292ce9
Fixing travis.yml round #6
Sep 1, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
language: php
sudo: false

php:
- 5.5
Expand All @@ -8,26 +9,28 @@ mysql:
username: root
encoding: utf8

# install php packages required for running a web server from drush on php 5.3
addons:
apt:
packages:
- php5-cgi
- php5-mysql

before_install:
- sudo apt-get update > /dev/null
- composer self-update

# Install Grunt and Bower.
- npm install -g grunt-cli bower
- npm install -g yo bower grunt-cli casperjs

# Install Sass and Compass for Grunt to work.
- gem install compass

install:
# install php packages required for running a web server from drush on php 5.3
- sudo apt-get install -y --force-yes php5-cgi php5-mysql

# Install Drush.
- export PATH="$HOME/.composer/vendor/bin:$PATH"
- composer global require drush/drush:6.*
- phpenv rehash

- npm install -g yo bower grunt-cli casperjs
- npm install

# Test the Yeoman generator.
Expand All @@ -37,12 +40,6 @@ install:
- npm link

before_script:
# Create display.
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start

# Run PhantomJs.
- phantomjs --webdriver=4444 > ~/phantomjs.log 2>&1 &

- mkdir $TRAVIS_BUILD_DIR/../build
- cd $TRAVIS_BUILD_DIR/../build
Expand All @@ -53,6 +50,7 @@ before_script:

# Configure client.
- cd client
- bower install
- cp config.travis.json config.json
- grunt serve > ~/grunt.log 2>&1 &
- cd ..
Expand All @@ -63,12 +61,19 @@ before_script:
# Start a web server on port 8080, run in the background; wait for
# initialization.
- drush @site runserver 127.0.0.1:8080 &
- until netstat -an 2>/dev/null | grep '8080.*LISTEN'; do true; done
- until netstat -an 2>/dev/null | grep '8080.*LISTEN'; sleep 1; curl -I http://127.0.0.1:8080 ; do true; done

script:
# Create display.
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sleep 3 # give xvfb some time to start

# Wait for Grunt to finish loading.
- until $(curl --output /dev/null --silent --head --fail http://localhost:9000); do sleep 1; echo '.'; done

script:
# Run PhantomJs.
- phantomjs --webdriver=4444 > ~/phantomjs.log 2>&1 &

# Run Behat tests.
- cd ./behat
Expand Down
3 changes: 3 additions & 0 deletions app/templates/client/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ <h3>Login with demo / 1234</h3>
<script src="scripts/controllers/companies.js"></script>
<script src="scripts/controllers/events.js"></script>
<script src="scripts/controllers/login.js"></script>
<script src="scripts/controllers/signup.js"></script>
<script src="scripts/controllers/forgot-password.js"></script>
<script src="scripts/controllers/reset-password.js"></script>
<script src="scripts/services/auth.js"></script>
<script src="scripts/services/utils.js"></script>
<script src="scripts/services/events.js"></script>
Expand Down
41 changes: 39 additions & 2 deletions app/templates/client/app/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,44 @@ angular
.state('login', {
url: '/login',
templateUrl: 'views/login.html',
controller: 'LoginCtrl'
controller: 'LoginCtrl',
resolve: {
emailVerified: function() {
return false;
}
}
})
.state('signup', {
url: '/signup',
templateUrl: 'views/signup.html',
controller: 'SignUpCtrl'
})
.state('verifyEmail', {
url: '/verify-email/{accessToken:string}',
templateUrl: 'views/login.html',
controller: 'LoginCtrl',
resolve: {
emailVerified: function($stateParams, Auth, Account) {
Auth.setAccessToken($stateParams.accessToken);
return Account.verifyEmail();
}
}
})
.state('forgotPassword', {
url: '/forgot-password',
templateUrl: 'views/forgot-password.html',
controller: 'ForgotPasswordCtrl'
})
.state('resetPassword', {
url: '/reset-password/{accessToken:string}',
templateUrl: 'views/reset-password.html',
controller: 'ResetPasswordCtrl',
onEnter: page403,
resolve: {
accessToken: function($stateParams, Auth) {
Auth.setAccessToken($stateParams.accessToken);
}
}
})
.state('dashboard', {
abstract: true,
Expand Down Expand Up @@ -172,7 +209,7 @@ angular

'response': function(result) {
if (result.data.access_token) {
localStorageService.set('access_token', result.data.access_token);
Auth.setAccessToken(result.data.access_token);
}
return result;
},
Expand Down
33 changes: 33 additions & 0 deletions app/templates/client/app/scripts/controllers/forgot-password.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

/**
* @ngdoc function
* @name clientApp.controller:ForgotPasswordCtrl
* @description
* # ForgotPasswordCtrl
* Controller of the clientApp
*/
angular.module('clientApp')
.controller('ForgotPasswordCtrl', function ($scope, Auth) {

/**
* Send a password reset link.
*/
$scope.forgotPassword = function() {
// Reset the error message for each request.
$scope.ErrorMsg = false;

Auth.resetPassword($scope.email).then(function () {
$scope.passwordResetSent = true;
},
function(response) {
$scope.ErrorMsg = response.data.title;

// Too many requests.
if (response.status == 429) {
$scope.ErrorMsg = response.statusText;
$scope.TooManyRequests = true;
}
});
};
});
4 changes: 3 additions & 1 deletion app/templates/client/app/scripts/controllers/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
* Controller of the clientApp
*/
angular.module('clientApp')
.controller('LoginCtrl', function ($scope, Auth, $state) {
.controller('LoginCtrl', function ($scope, Auth, $state, emailVerified) {

$scope.emailVerified = emailVerified;

// Will be FALSE during login GET period - will cause the login button to be
// disabled.
Expand Down
30 changes: 30 additions & 0 deletions app/templates/client/app/scripts/controllers/reset-password.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

/**
* @ngdoc function
* @name clientApp.controller:ResetPasswordCtrl
* @description
* # ResetPasswordCtrl
* Controller of the clientApp
*/
angular.module('clientApp')
.controller('ResetPasswordCtrl', function ($scope, Auth, Account) {

// Determine if password was reset successfully.
$scope.passwordSaved = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Determine if password was reset successfully.


/**
* Setting the access token in the localStorage so we can get the account
* information and pull out the user ID from it to PATCH the user entity.
*
* @param password
* The new password.
*/
$scope.saveNewPassword = function(password) {
Account.get().then(function(user) {
Auth.savePassword(user.id, password).then(function() {
$scope.passwordSaved = true;
});
});
};
});
39 changes: 39 additions & 0 deletions app/templates/client/app/scripts/controllers/signup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

/**
* @ngdoc function
* @name clientApp.controller:SignUpCtrl
* @description
* # SignUpCtrl
* Controller of the clientApp
*/
angular.module('clientApp')
.controller('SignUpCtrl', function ($scope, Auth) {

// Reset the flags.
$scope.emailAvailable = true;
$scope.usernameAvailable = true;

/**
* Send a password reset link.
*/
$scope.signUp = function(user) {
// Clear the error before each request.
$scope.signupError = undefined;

Auth.usersAvailability(user).then(function(response) {
$scope.usernameAvailable = response.data.data.available.name;
$scope.emailAvailable = response.data.data.available.mail;

if ($scope.emailAvailable && $scope.usernameAvailable) {
Auth.signUp(user).then(function() {
// User registered successfully.
$scope.signedUp = true;
}, function (response) {
// Error trying to register the user.
$scope.signupError = response.data.detail;
});
}
});
};
});
20 changes: 19 additions & 1 deletion app/templates/client/app/scripts/services/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Service in the clientApp.
*/
angular.module('clientApp')
.service('Account', function ($q, $http, $timeout, Config, $rootScope, $log) {
.service('Account', function ($q, $http, $timeout, Config, $rootScope, Auth) {

// A private cache key.
var cache = {};
Expand Down Expand Up @@ -43,6 +43,24 @@ angular.module('clientApp')
return deferred.promise;
}

/**
* Verify a user.
*
* @returns {*}
*/
this.verifyEmail = function() {
// After setting the access token in the local storage (in the state
// resolve), try to get the user account from the data, if succeed then
// change its status.
return getDataFromBackend().then(function(user) {
return $http({
method: 'PATCH',
url: Config.backend + '/api/v1.1/users/' + user.id,
data: {status: 1}
});
});
};

/**
* Save meters in cache, and broadcast en event to inform that the meters data changed.
*
Expand Down
72 changes: 72 additions & 0 deletions app/templates/client/app/scripts/services/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
angular.module('clientApp')
.service('Auth', function ($injector, $rootScope, Utils, localStorageService, Config) {

/**
* An access token setter.
*
* @param accessToken
*/
this.setAccessToken = function(accessToken) {
localStorageService.set('access_token', accessToken);
};

/**
* Login by calling the Drupal REST server.
*
Expand All @@ -29,6 +38,69 @@ angular.module('clientApp')
});
};

/**
* Trigger a `reset password` action on the server for this email.
*
* @param email
* The email of the user.
*
* @returns {*}
*/
this.resetPassword = function(email) {
return $injector.get('$http')({
method: 'POST',
url: Config.backend + '/api/reset-password',
data: {email: email}
});
};

/**
* Save new password for a user.
*
* @param uid
* User id.
* @param password
* A new password to set.
*
* @returns {*}
*/
this.savePassword = function(uid, password) {
return $injector.get('$http')({
method: 'PATCH',
url: Config.backend + '/api/v1.1/users/' + uid,
data: {password: password}
});
};

/**
* Checks users availability.
*
* @param user
* @returns {*}
*/
this.usersAvailability = function(user) {
var params = 'name=' + user.name + '&mail=' + user.mail;

return $injector.get('$http')({
method: 'GET',
url: Config.backend + '/api/users-availability?' + params
});
};

/**
* Sign Up new user.
*
* @param data
* @returns {*}
*/
this.signUp = function(data) {
return $injector.get('$http')({
method: 'POST',
url: Config.backend + '/api/v1.1/users',
data: data
});
};

/**
* Logout current user.
*
Expand Down
4 changes: 4 additions & 0 deletions app/templates/client/app/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@
min-height: 500px;
}

.vertical-space {
margin-top: 15px;
margin-bottom: 15px;
}
Loading