Customizing messages and evolutions in Play, beyond the documentation

Play has a very good forum. Every day a lot of doubts are posted and answered. As a developer who is using Play in almost every project, I follow the forum and I try to help answering as many as questions as I can. Today I bring to the blog two interesting questions that were posted there.

The first question was about how to customize the conversion error in Play. For example, if you have a int field in your class and the user submits a string, for instance, “two”, Play will use a formatter which is responsible for this conversion. If the value is not possible to be converted, a message will be returned. The default message is “Invalid value”.  In order to customize this message you have to override a key defined in Play.

    error.invalid.java.lang.Integer = Value is not a integer

But how to find this key? That is the good part!. It is not explained in the documentation and because of the question, I went to the source code and I found the file messages.default which has all pre defined errors keys in Play.

The second question was about how to run evolutions outside of the web application scope. This one was quite interesting, because I already had this wish and I was not capable to find the solution. Reading the forum, I saw a question about this subject and someone answered with the class OfflineEvolutions. So I gave a try and the code worked like a charm!

   object RunMigrations extends App{

      OfflineEvolutions.applyScript(new File("."),this.getClass().getClassLoader(), "default")
   }

Now, in case you have this necessity, you can run your evolutions in a separated task in sbt, for example. Another case is to run the evolutions every time you need to run a integration test. Again, this is not a case explained in the documentation, but based in a question posted in the forum, I had to find a answer and learned a little more.

Once more, thanks for reading!

 

Posted in java, jvm, playframework, scala | Leave a comment

Customizing the loading of provider’s configuration in Secure Social

In my last project, which I had to use a lot of features of Secure Social, I had to customize the way this plugin loads social credentials from the securesocial.conf file. Let me explain a little bit my problem. It is a multi tenant app and the tenant is defined by a subdomain. For example, client1.domain.com.br(negrito) and client2.domain.com.br(negrito) should load different configurations of facebook.

The problem is that Secure Social loads the social credentials from a configuration file. By default it is not possible to load multiple configurations, at least as far as I know :). So, in order to allow this kind of behavior, I had to specialize the provider and change this part of the plugin. Let’s see the code and the problems.

The first thing we need to is to inherit from the FacebookProvider class(italico) and override a method which name is settings(negrito)

    public class CustomFacebookProvider extends FacebookProvider{
	
    	public CustomFacebookProvider(Application application) {
    		super(application);
    	}
	
	
    	@Override
    	public OAuth2Settings settings() {
            
    	}
	
    }

This method is invoked to load the configuration. The default behavior is to load all information in the application startup, take a look in github(link para o github). Now we need to access the database and load the specific credentials of a tenant


	@Override
	public OAuth2Settings settings() {		;
		User client = Users.findByDomain(Context.current()._requestHeader().domain())
		return new OAuth2Settings(
						"https://graph.facebook.com/oauth/authorize",
						"https://graph.facebook.com/oauth/access_token",
						client.getFacebookConfig().getClientId(),
						client.getFacebookConfig().getClientSecret(),
						Option.apply("email"));
	}

There is just one problem, and it is a big one. I am using the Java version of Play and, at this point, the request was not set in the ThreadLocal(italico) used by Play to handle the execution of a client. In order to solve this problem, I had to use a little bit of bad practice of code, which is called POG here in Brazil(Programação orientada a gambiarra) . There is a method called doAuth(italico) which is responsible for authenticate a user in Secure Social and this same method receives a request as a parameter. So take a look in my solution:


        private static ThreadLocal<String> domainContext = new ThreadLocal<>();

	@Override
	public OAuth2Settings settings() {		;
		User client = Users.findByDomain(domainContext.get())
		return new OAuth2Settings(
						"https://graph.facebook.com/oauth/authorize",
						"https://graph.facebook.com/oauth/access_token",
						client.getFacebookConfig().getClientId(),
						client.getFacebookConfig().getClientSecret(),
						Option.apply("email"));
	}

	@Override
	public <A> Either<Result, SocialUser> doAuth(final Request<A> request) {
		domainContext.set(request.domain());
		Either<Result, SocialUser> doAuth = super.doAuth(request);
		domainContext.set(null);
		return doAuth;
	}

I used a ThreadLocal to store the current request and use it in the method settings(italico). I know it is not the best, but I could not store this request in a instance variable because the provider is loaded as a plugin, and plugins are singletons. Using this technique I can retrieve the domain and pass it to the method responsible for loading the tenant information.

The last part is that you have to change the configuration in your play.plugins(negrito) file.

   10001:security.securesocial.CustomFacebookProvider

That is it folks! Every week I try to write something that was useful for me in one my projects. If you have any topic that is interesting for you, comment here and I will be glad in writing about!

 

Posted in Uncategorized | Leave a comment

Plugins as extension points for your apps!

Normally, we use plugins to help us in a daily tasks, for example: send emails, secure our actions, upload files to amazon etc.  Play itself has a lot of parts built on top of plugins, more examples: evolutions, ebean and web service client. Another usage of plugins is as extension points of our apps.

In one of my current projects, the application needs to process a lot of data and provide a visualization for the client. This is a multi tenant app. So there is a core which is responsible for processing the information and there are specialized apps which are responsible for build its own visualization. Let’s take a look in the piece of code in the core:

    public class AllocationResult {

    	public String getBrokenConstraintsAsString(){
           //need the Html object with the visualization
           return html;
    	}

    }

As you can see, after processing we need to generate the visualization part. Here is where the plugin can be used.

        public abstract class BrokenConstraintsViewPlugin implements Plugin{

        	private Application application;

        	public BrokenConstraintsViewPlugin(Application application) {
        		this.application = application;
        	}

        	public abstract Html getView(Collection<ConstraintMatchTotal> constraints);

        	@Override
        	public boolean enabled() {
        		return true;
        	}

        	@Override
        	public void onStart() {
        		// TODO Auto-generated method stub

        	}

        	@Override
        	public void onStop() {
        		// TODO Auto-generated method stub

        	}
        }    }

We created the plugin as an abstract class, in order to force the client apps to inherit this class and build the visualization. Now we can use Play to load the specialized plugin!

    public class AllocationResult {

    	private static BrokenConstraintsViewPlugin constraintsPlugin = Play
    			.application().plugin(BrokenConstraintsViewPlugin.class);

    	public String getBrokenConstraintsAsString(){
    		Html html = constraintsPlugin.getView(constraints);
    		return html.body();
    	}

    }

We can pass the abstract class as argument and the Application(negrito) class will load the specialization. Of course, you need to register your plugin in the play.plugins file.

This feature is very important in order to provide extension points in your apps.  If you are building an API using Play, maybe this feature will be helpful for you :). Thanks for reading!

Posted in Uncategorized | Leave a comment

Changing the registration process in SecureSocial

This is a quick post about a customization that I had to write for a use case with Secure Social. Secure Social, at least in its 2.1.x version, has a very fixed flow in order to register a new user. First you need to register a new email, after that, an email is sent to the user with a generated token embedded in a link. The user has to follow this link in order to finish the registration process, filling the form with a few fields.

At one of my current projects, I don’t have the necessity to send the email with the generated token, the only need is to redirect the user to the registration form. To accomplish this task, we have to create a controller with a custom handleStartSignup. Basically, we need to copy the method from the Registration controller of Secure Social and delete the line which sends the email.

    import _root_.java.util.UUID
    import play.api.mvc.{RequestHeader, Result, Action, Controller}
    import play.api.data._
    import play.api.data.Forms._
    import play.api.data.validation.Constraints._
    import play.api.Play
    import securesocial.core.providers.UsernamePasswordProvider
    import securesocial.core._
    import com.typesafe.plugin._
    import Play.current
    import securesocial.core.providers.utils._
    import org.joda.time.DateTime
    import play.api.i18n.Messages
    import securesocial.core.providers.Token
    import scala.Some
    import securesocial.core.IdentityId
    import scala.language.reflectiveCalls
    import securesocial.controllers.Registration

    object CustomRegistration extends Controller {

      def handleStartSignUp = Action { implicit request =>
        if (Registration.registrationEnabled) {
          Registration.startForm.bindFromRequest.fold(
            implicit errors => {
              BadRequest(use[securesocial.controllers.TemplatesPlugin].getStartSignUpPage)
            },
            email => {
              // check if there is already an account for this email address
              UserService.findByEmailAndProvider(email, UsernamePasswordProvider.UsernamePassword) match {
                case Some(user) => {
                  // user signed up already, send an email offering to login/recover password
                  Mailer.sendAlreadyRegisteredEmail(user)
                  Redirect(Registration.onHandleStartSignUpGoTo).flashing(Registration.Success -> Messages(Registration.ThankYouCheckEmail), Registration.Email -> email)
                }
                case None => {
                  val token = createToken(email, isSignUp = true)
                  //original line
                  //Mailer.sendSignUpEmail(email, token._1)
                  Redirect(s"/signup/${token._1}")
                }
              }
            })
        } else NotFound(views.html.defaultpages.notFound.render(request, None))
      }

      private def createToken(email: String, isSignUp: Boolean): (String, Token) = {
        val uuid = UUID.randomUUID().toString
        val now = DateTime.now

        val token = Token(
          uuid, email,
          now,
          now.plusMinutes(Registration.TokenDuration),
          isSignUp = isSignUp)
        UserService.save(token)
        (uuid, token)
      }

    }

The better approach would be to write a custom plugin which could handle these steps of the registration process, but Secure Social does not provide this customization. Now, you need to change your file of routes to use the new method.

   //rest of your file
   POST  /signup br.com.celerate.security.CustomRegistration.handleStartSignUp

If you try this code, you will notice that was generated a new problem in your project. The default startSignupView page of SecureSocial uses the old method Registration.handleStartSignUp, we need to customize this view as well. It is not hard, just follow the steps described in the original site. You have to implement all methods from the TemplatesPlugin trait, but we only need to customize the startSignUp,  so let's keep the others. In order to make this job easier, use as an example the DefaultTemplatesPlugin class.  To do not create the view from scratch, just copy the code from the original, again.

As you can see, it was little bit hard to customize this behavior. Remember that you always can use the source code of the lib as a path to discover something. Of course, it's easier to start for the documentation and forums but, if you don't find, don't stop and try to take a look in the source code. Secure Social has a code that is not hard to understand. See you!.

Posted in java, jvm, playframework, scala | Tagged , , | Leave a comment

Login/Password authentication in Secure Social

In another post I wrote about how to configure secure social to log in using a
social network. In this one, I am gonna walk through another common scenario,
setup a login/password based authentication. You need to understand a few things to put
everything in order. Let’s go!

If you don’t know anything about secure social, click in the link above and
spend a few minutes to read the other post about how to setup secure social :).
The first thing you have to change is the provider used in the configuration file,
usually called securesocial.conf. You need to use the userpass
entry in order to configure some aspects of your authentication.

    userpass {
    	withUserNameSupport=false
    	sendWelcomeEmail=false
    	enableGravatarSupport=true
    	signupSkipLogin=true
    	tokenDuration=60
    	tokenDeleteInterval=5
    	minimumPasswordLength=8
    	enableTokenJob=true
    	hasher=bcrypt
    }

The most strange key, at least for me, is the first one. The withUserNameSupport tells to Secure Social to use the user name instead of the email as the login for the
application. Maybe the keys about tokens are not clear right now, but wait a little and everything will be solved.

Another part that must be changed is the plugin's file. We need to change the provider
to use the UserPass provider instead of some social provider.

    1500:com.typesafe.plugin.CommonsMailerPlugin
    9994:securesocial.core.DefaultAuthenticatorStore
    9995:securesocial.core.DefaultIdGenerator
    9996:securesocial.core.providers.utils.DefaultPasswordValidator
    9997:securesocial.controllers.DefaultTemplatesPlugin
    9998:br.com.celerate.security.CelerateUserService
    9999:securesocial.core.providers.utils.BCryptPasswordHasher
    10001:securesocial.core.providers.UsernamePasswordProvider

We used the UsernamePasswordProvider class to handle the authentication
part for us and we had to configure other plugins which do other things. For example,
we need to hash the password(BCryptPasswordHasher), maybe send a email(CommonsMailerPlugin) and validate the password sent by the user(DefaultPasswordValidator). These plugins are not necessary when you are dealing with social authentication.

Maybe you have noticed that there is a plugin which is not from SecureSocial. It is
the CelerateUserService. You need to create a class to handle the process
of create a new user in the system, verify the existence of a user in your system, etc.
We created this same class in the other post, but now it will be a little bit different.

    public class CelerateUserService extends BaseUserService {

    	public CelerateUserService(Application application) {
    		super(application);
    		// TODO Auto-generated constructor stub
    	}

    	@Override
    	public Identity doSave(Identity user) {
    		final SystemUser systemUser = new SystemUser();
    		newSystemUser(user, systemUser);
    		Identity foundUser = doFind(user.identityId());
    		if (foundUser == null) {
    			return TransactionHelper.run(new Function0<WrapIdentity>() {

    				@Override
    				public WrapIdentity apply() throws Throwable {
    					JPA.em().persist(systemUser);
    					return new WrapIdentity(systemUser);
    				}
    			});
    		}
    		return foundUser;
    	}

    	private void newSystemUser(Identity user, final SystemUser systemUser) {
    		systemUser.setEmail(user.email().get());
    		systemUser.setLastName(user.lastName());
    		systemUser.setPassword(user.passwordInfo().get().password());
    		systemUser.setFirstName(user.firstName());
    		systemUser.setProvider(user.identityId().providerId());
    		PasswordInfo passwordInfo = user.passwordInfo().get();
    		String salt = passwordInfo.salt().isDefined() ? passwordInfo
    				.salt().get() : null;
    		systemUser.setPasswordInfo(new SystemPasswordInfo(passwordInfo
    				.hasher(), salt));
    	}

    	@Override
    	public void doSave(Token token) {
    		final SignupToken newToken = SignupToken.from(token);
    		TransactionHelper.run(new Runnable() {

    			@Override
    			public void run() {
    				JPA.em().persist(newToken);
    			}
    		});
    	}

    	@Override
    	public Identity doFind(final IdentityId identityId) {
    		return TransactionHelper.run(new Function0<WrapIdentity>() {

    			@Override
    			public WrapIdentity apply() throws Throwable {
    				Option<SystemUser> user = SystemUsers
    						.findByEmail(identityId.userId());
    				return user.isDefined() ? new WrapIdentity(user.get())
    						: null;
    			}
    		});
    	}

    	@Override
    	public Token doFindToken(final String tokenId) {
    		return TransactionHelper.run(new Function0<Token>() {

    			@Override
    			public Token apply() throws Throwable {
    				return JPA.em().find(SignupToken.class, tokenId)
    						.toSecureSocialToken();
    			}
    		});
    	}

    	@Override
    	public Identity doFindByEmailAndProvider(String email,
    			String providerId) {
    		return doFind(new IdentityId(email, providerId));
    	}

    	@Override
    	public void doDeleteToken(String uuid) {
    		// TODO Auto-generated method stub

    	}

    	@Override
    	public void doDeleteExpiredTokens() {
    		// TODO Auto-generated method stub

    	}

    }

There is a lot going on in this class. Let's start with all methods that have
token as part of the name or receive a Token as a parameter. When you
want to save a new user, Secure Social uses a two step registration process.
First the new user need to register a email. After that Secure Social will send
an email with the generated token, that is why you need to use the Typesafe
mailer plugin. Here is an example of url:(exemplo aqui) When a user tries to
follow this url, Secure Social will try to validate this token and that is why
you need to override the methods doFindToken and doSave(Token token).
You have to find a way to store this information and query it later. I opted for
save the token in my database.

Other very important method is the doFindByEmailAndProvider(String email,String providerId) method. Every time a user tries to log in your application, this method will be invoked. Now you are probably asking to yourself: where is the password? You
don't need to worry about. Instead of leave the responsibility of checking the
hashed password in your hands, Secure Social just asks for you to load a user
based on his email. With this user loaded(Identity interface), Secure Social will
use the method passwordInfo to compare the password passed as argument
with the password loaded from the database.

It is a little bit boring, I know, but we need to configure an extra file, the router.
There we need to put all actions that are needed to handle the login/password
based authentication.

    #secure social
    GET     /login                      securesocial.controllers.LoginPage.login
    GET     /logout                     securesocial.controllers.LoginPage.logout

    # User Registration and password handling
    GET     /signup                     securesocial.controllers.Registration.startSignUp
    POST    /signup                    securesocial.controllers.Registration.handleStartSignUp
    GET     /signup/:token              securesocial.controllers.Registration.signUp(token)
    POST    /signup/:token              securesocial.controllers.Registration.handleSignUp(token)

    GET     /authenticate/:provider     securesocial.controllers.ProviderController.authenticate(provider)
    POST    /authenticate/:provider     securesocial.controllers.ProviderController.authenticateByPost(provider)
    GET     /not-authorized             securesocial.controllers.ProviderController.notAuthorized

Notice that all routes are provided by Secure Social. For example, all signup process can be handle out of the box by the framework. Secure social comes with a few predefined templates that you  can start using as your login and signup views. Even if you do not want to use these templates,  you will still want to use all controllers to handle the process.

That is it! Now you can use this Secure Social to handle both social or login/password
authentication process. In another post, I will back showing how to customize the templates and how to override the defaut behavior of the controller. Thanks for reading!

 

Posted in java, jvm, plataforma java, playframework, scala | Tagged , , , | Leave a comment

Play, Server Sent Events and AngularJS

I am currently involved in a project that uses a lot of server push notification. I could use Web Sockets but, as I only need of one-way of communication is being used SSE to implement all features that need push notifications. In its Scala version, Play has a nice support to SSE, let’s see an example:

	object UpdateCurrentAllocationController extends Controller {

	  val (chatOut, chatChannel) = Concurrent.broadcast[JsValue]

	  def attempts = Action {
	    implicit req =>
	      {
	        Ok.feed(chatOut &>  EventSource()).as("text/event-stream")
	      }
	  }
	}

In the view layer, it is easy to use the SSE support offered by all browsers. Let's see one more example of code:

	var feed = new EventSource('@br.com.celerate.controllers.routes.UpdateCurrentAllocationController.attempts');
	var handler = function(event){
		//code to update the view
	};
	feed.addEventListener('message', handler, false);

After each notification, we need to update our view with the new data. A common way to accomplish this task is, for example, use JQuery to manipulate the DOM elements from your template. In a Javascript centric application, update all parts of the page becomes really annoying. Take a look in this example:

	var feed = new EventSource('@controllers.routes.UpdateCurrentAllocationController.attempts');
	var handler = function(event){
		var tbody = $("#solution").empty();;
		var solution = JSON.parse(event.data);

		var classes = solution.data.classRooms;
		$.each(classes,function(index,room){
			var tr = $("<tr>").append(
					$("<td>").text(room.course.code),
					$("<td>").text(room.number),
					$("<td>").text(room.interval.begin),
					$("<td>").text(room.interval.end),
					$("<td>").text(room.formatedIntervalOfDay),
					$("<td>").text(room.instructor.name)
					);

			tr.hide().appendTo(tbody).fadeIn(1000);
		});

	};
	feed.addEventListener('message', handler, false);

You end with a javascript code highly coupled with the page elements! Every change you make in a page element, you have to update your javascript code.  This is the scenario where AngularJS better fits. You leave the code necessary to update the elements in your page directly in the html and the code necessary to retrieve the data in other part. Let's see how it works.  Let's pick the same table that was updated using JQuery and change to use the AngularJS syntax.

	<tbody id="solution" ng-app="celerateApp" ng-controller="InstructorsController">
		<tr ng-repeat="room in rooms">
	    	<td>{{room.course.code}}</td>
	        <td>{{room.number}}</td>
	        <td>{{room.interval.begin}}</td>
	        <td>{{room.interval.end}}</td>
	        <td>{{room.formatedIntervalOfDay}}</td>
	    	<td>{{room.instructor.name}}</td>
		</tr>
	</tbody>

The ng directives is the way you bind your elements with AngularJS. For example, room in rooms is a Angular syntax to repeat a element in your page. And the {{variable}} is the syntax to use some variables that were defined elsewhere. Now you should be asking yourself, where these variables were created? That is why we are using the ng-controller. The controller class is responsible for updating all variables bound with the elements and this is the biggest difference with the older approach, your js code is bound with variables and not with html elements. Let's see the controller code:

	var celerateApp = angular.module('celerateApp', []);

	celerateApp.controller('InstructorsController', function($scope) {

	  var feed = new EventSource('/newSolutionListener');
	  var handler = function(event){
			var solution = JSON.parse(event.data);
			$scope.$apply(function () {
				$scope.rooms = solution.data.classRooms;
			});

	  }
	  feed.addEventListener('message', handler, false);
	});

Here we have a lot of things happening. The first thing you have to do is to declare a module. The number of modules will depend on the size of your app. After that, we can configure ours controllers. You need to provide a name and a function that will be executed when the element bound with this controller is found. Now, every time that a new notification is sent from the server, we update the room variable inside the controller scope. We had to use the $apply function to notify Angular listeners which are responsible to update all variables bound with page elements. This method is needed, only if you are trying to update a scope outside from AngularJS callback, which is our case here.

So, if you are planning to build a app that has a lot of ajax or push notifications, I advise you to take a look in Angular.  You can combine the power of this framework with features like REST and push notifications provided by Play.  Enjoy it!

Posted in java, jvm, playframework, scala | Tagged , , | Leave a comment

Secure social login and Play authenticator together

It is quite common use facebook, twitter and other social networks as a login provider for application. In Play world, Secure Social is one of the most used! Here in the blog there is a tutorial that guides you to configure this extension in your project. But, it is also important that your web app provides a formal way to register new users, using a common registration form.

For this last case, the normal way to control user access is using the Play plugin, provided by the framework “out of the box”. The problem here is the integration between these two plugins. When your user authenticates through a social network, Secure Social is the one responsible for checking the access control, it already has annotations for this case. While that when the user authenticates, for instance, through your database, you will probably want to use the plugin annotation provided by Play to control the user access.

In order to use both together, you have to change the Play’s session with information that came from the social login. The good news is that Secure Social has this exactly feature! You can create a listener that can be notified when new social login is done :). Let’s see the code.

    class SocialLoginEventListener(app: play.Application) extends EventListener {
      override def id: String = "my_event_listener"

      def onEvent(event: Event, request: RequestHeader, session: Session): Option[Session] = {
        event match {
          case e: LoginEvent => {
            val loggedUser = event.user.asInstanceOf[WrapIdentity].getUser()
            Some(session.+(("email",loggedUser.getEmail())))
          }

          case e:LogoutEvent => Option(Session.deserialize(Map[String,String]()))
          case _ => None
        }
      }
    }

You just have to change the session. I put the email information here because this is the key being used for my Play Authenticator, fell free to change and use what is better for you. Another point is that Secure Social provides only a Scala version of this feature. Remember, it is not a problem, your Play project is Java and Scala! You can combine both languages to take advantage of both worlds.

Now you have to configure Secure Social to use your listener. You have to add an entry in your play.plugins file.

  9994:securesocial.core.DefaultAuthenticatorStore
  9995:securesocial.core.DefaultIdGenerator
  9997:securesocial.controllers.DefaultTemplatesPlugin
  #my implementation of a service
  9998:security.SocialUserService
  10001:securesocial.core.providers.FacebookProvider
  10009:securesocial.core.providers.InstagramProvider
  #listener
  10006:security.SocialLoginEventListener

That is it, now you are able to use both login ways together without a problem! As last week I did not write,  I am gonna write twice in this one.

Posted in Uncategorized | Leave a comment