As you probably already know we at Mono have just released AngularJS SDK which is an essential tool for all javascript developers working with Baasic. If you are one of those who aren’t yet familiar with Baasic, I strongly encourage you to read the articles which will briefly introduce you to a world of Baasic capabilites and its corresponding features. To get a broader view of our AngularJS SDK and how it fits into Baasic don’t forget to go through this announcement.
Before we go any deeper into the topic, I suggest checking out our complete Angular SDK documentation in which you’ll be able to find membership services and their methods explained in detail, along with accompanying usage examples.
This blog post will be divided in two parts. The first part will be focused on user registration, account activation and login itself. On the other hand, the second part will dig into the more complex features like:
- handling users,
- handling users’ roles,
- user extension with a custom model and
- password recovery mechanism.
Most membership systems, and this one is no exception, consists of user and role services that share a lot of common functionality between different applications. This opens up a lot of space for reusing this functionality across projects, leading to faster application development. Just think about it - you won’t need to do any custom development to handle user login, registration, account activation, and a bunch of other things like handling authorization tokens, handling recaptcha responses and so on. Your main concern will be to use them in the right places and for the right purpose.
In this blog post I will show you when, where and how you should use those services and their methods, so you can jump start your application development with a membership system being already set up. I guarantee you, by the end of a post you won’t believe how easy and fast it is to have login, registration and corresponding features in place. After all, the main purpose of Baasic itself and AngularJS SDK is to significantly speed up both application development and application publishing.
I assume you already have AngularJS installed, so in order to completely set up the working environment, you need to install only one Baasic AngularJS SDK module. Baasic AngularJS SDK is fully modular and every module is available as a Bower package. Examples in this blog won’t need all available features in the SDK, however they will need Membership module and its dependencies. In order to install it into your application, type the following into the shell and Bower will do the rest (i.e. install dependencies):
>bower install baasic-angularjs-membership
Now, that you have everything you need, you can start working on a demo application.
First of all, you need to specify a Baasic app inside your demo application - for more information on how to use Baasic dashboard and open a new application there, please visit this introduction. If you omit this step, the SDK won’t be able to make a request to the Baasic API. A suitable place to do that is inside your module’s config block.
angular.module('your-module-name', ['ui.router', 'baasic.security', 'baasic.membership'])
.config(function(baasicAppProvider){
'use strict';
//application specific code ommited on purpose
//define Baasic app
baasicAppProvider.create('your-application-name', {
apiRootUrl: 'api.baasic.com',
apiVersion: 'beta'
});
User Registration
User registration is the first thing you should think about when you start to work on a new application. Do you want to open the application content only to authorized users, or should anonymous users have access to it? Do you want to introduce some constraints or exceptions? There are a plenty of different scenarios, and Baasic can cover almost all of them.
For the demonstration purposes, I’ve built an application which requires a user to log in. In order to be able to login, user must create an account. To handle the registration logic, I have created the register-controller.js file and its template called register.html. An AngularJS controller is created inside the file, and appropriate SDK services are injected. Those services are called baasicRegisterService and baasicRecaptchaService. In a code snippet below you can see an example of a typical user object - of course, you need to fill its properties with appropriate values.
$scope.user = {
email: '',
userName: '',
password: '',
//isApproved: true,
activationUrl: $state.href('account-activation', {}, { absolute: true }) + '?activationToken={activationToken}',
creationDate: new Date(),
challengeIdentifier: '',
challengeResponse: ''
};
If you go through each property, you’ll see that there’s nothing extraordinary in the object itself. However, there is an activationUrl property which could be strange at the first glance. Since Baasic simply isn’t (and can’t be) aware of your application structure, you will need to provide an activationUrl which leads to the application’s account activation page. That url must be templated so it contains the {activationToken} expression because Baasic will replace it with a generated token, which will be used to activate the user later on.
A method which is called upon registration has a part in which reCaptcha is checked (please revisit documentation for the reCaptcha setup instructions) and a part in which a call to baasicRegisterService create() method is made. As you can see below, after some user’s input logic validation, you only have to pass that user object to the create() metod, and the user will be registered:
$scope.register = function(){
if($scope.registrationForm.$valid){
$scope.user.challengeIdentifier = baasicRecaptchaService.challenge();
$scope.user.challengeResponse = baasicRecaptchaService.response();
if ($scope.user.challengeResponse === '') {
$scope.message = 'Captcha code is required.';
return;
}
baasicRegisterService.create($scope.user)
.success(function(){
//At this point, you can redirect user to pages such as Login, etc..., or simply show an appropriate message.
})
.error(function(data, status){
//You can format your error messages based on status codes or specific error messages
baasicRecaptchaService.reload();
});
}
};
Account Activation
After everything related to user’s registration is done, an activation page can be implemented. In a similar way as a registration page, activation page is implemented via an AngularJS controller and its template. An activation url, which is sent to the Baasic API, gets the user to this activation page. In other words, the logic behind user activation is done inside of the activation-controller.js file.
There is one optional property in the user object you should pay attention to. As you can see, property is commented in the first example and it’s called isApproved. The property is responsible for the approved “state” of the user. If an application passes user object without that property, that user won’t be approved (note that unapproved users won’t be able to login into the application) and user will get an email with a link to the activation page. Property could be set to true as well. In that case, a user would be approved immediately and Baasic wouldn’t send any messages to the user - therefore, a user would be able to login immediately after the registration is finished.
Please take a look at the code below to see how you may use the SDK to activate a user:
if($stateParams.activationToken) {
baasicRegisterService.activate({activationToken: $stateParams.activationToken})
.success(function () {
$scope.message = 'You have successfully activated your account!';
})
.error(function (data, status) {
$scope.message = status + ': ' + data;
});
}
else{
$scope.message = 'Activation token is required';
}
With a help of angular-ui-router, it will be really easy to implement this small but important piece of general membership functionality.
User Login
Last thing which is covered here is, of course, the login system. After you establish both user registration and account activation, login functionality will be straightforward to implement. Like all of the examples in this blog post, login functionality is also implemented via login-controller.js file and its template. Since the examples are implemented in the same way, you may wonder if Baasic requires a “controller-template” approach. The answer is no, because you are able to implement this functionality in a way which suits your needs and your practices the best. For example, you can wrap up the functionality in directives and make them fully customizable or/and reusable application components.
An object which has to be passed to the login() method of the baasicLoginService in order to successfully log in a specified user looks like this:
$scope.user = {
userName: '',
password: '',
options: ['session', 'sliding']
};
In the code snippet below, you can see how the method call looks like. Please don’t forget to visit Baasic Rest API documentation to see all of the HTTP status codes you can get from the Baasic methods. With those HTTP status codes, you are able to build an application with appropriate user messages, which in the end leads to the good user experience:
$scope.login = function(){
baasicLoginService.login($scope.user)
.success(function(data){
//At this point, you can redirect user to the pages such as Home or Dashboard
$scope.message = 'Successful login, user token is stored into local storage';
})
.error(function(data, status){
//You can format your error messages based on http status codes
$scope.message = status === 401 ? 'Invalid username or password': 'Unable to login';
});
};
One thing you should pay attention to is that Baasic will send an access token in its response upon the successful login. An access token must be used in every Baasic API call which requires authorization. In previous SDK’s versions you had to manually save the token into the browser’s local storage. From the latest version you don’t need to do it anymore, SDK will automatically manage token storage. As a result, token is stored inside browser’s local storage under the baasic-auth-token-{your-baasic-application-name} key. Despite of that, you’ll still get the token in the response and you will be able to manage it on your own.
An implementation of the logout functionality is also straightforward. First of all, you need to get an access token from the local storage, after which you may logout a current user from the application. A code to achieve that is rather simple:
$scope.logout = function(){
var token = baasicAuthorizationService.getAccessToken();
baasicLoginService.logout(token.access_token, token.token_type)
.success(function(){
//At this point, you can redirect user to some public page
$scope.message = 'You have successfully logout yourself from baasic';
})
.error(function(data, status){
//You can format your error messages based on status codes or specific error messages
$scope.message = status + ': ' + data;
});
};
Having the user login and logout implemented, you have everything you need to jump start your application development. This functionality is at the core of each web application, and with that in place you will be able to dig into more complex Baasic features. Finally, in the Part 2 of this blog post I’ll cover more complex SDK membership features.
To conclude, I hope I’ve covered and clarified a big portion of the Baasic AngularJS SDK and its usage. Please, feel free to try it yourself. I’m happy to answer all of your questions regarding the membership SDK and Baasic overall.
Fully functional code examples can be found at an official Baasic Github page. Additionally, feel free to try out examples in action at official Baasic demo pages.
Feel free to leave a comment
comments powered by Disqus