h1. Adding authentication

Now that we have an administration area we need to plug in some authentication. Fortunately, Play has a module for that. It’s called the **Secure** module.

h2. <a>Enabling the Secure module</a>

Enable the **Secure** module in the @yabe/conf/dependencies.yml@ file and restart the application.

bc. # Import the secure module
    - secure

After restarting, Play should say that the module is loaded.

The **Secure** module comes with a set of default routes that you can easily enable in the @yabe/conf/routes@ file (or we could define our own routes as well):

bc. # Import Secure routes
*       /                                       module:secure

h2. <a>Protecting the admin controllers</a>

The module provides a @controllers.Secure@ controller that declares all needed interceptors. Of course we could just inherit from this controller but because Java is limited to simple inheritance it would be problematic.

Instead of directly inheriting from the @Secure@ controller, we can annotate the admin controllers using the <code>@With</code> annotation to tell Play to invoke the corresponding interceptors as well:

bc. package controllers;
 
import play.*;
import play.mvc.*;
 
@With(Secure.class)
public class Posts extends CRUD {    
}

Do the same for the @Comments@, @Users@ and @Tags@ controllers.

Now if you try to access any admin action, you should get a log-in page:

!images/guide8-1!

In fact, for now you can try any user name/password pair, and it will just work.

h2. <a>Customizing the authentication process</a>

The application has to provide an instance of @controllers.Secure.Security@ to customize the authentication process. By creating our own version of this class we will be able to specify exactly how users should be authenticated.

Create a @yabe/app/controllers/Security.java@ file and override the @authenticate()@ method:

bc. package controllers;
 
import models.*;
 
public class Security extends Secure.Security {
	
    static boolean authenticate(String username, String password) {
        return true;
    }
    
}

As we already have the User objects part of the blog model, it is easy to implement a working version of this method:

bc. static boolean authenticate(String username, String password) {
    return User.connect(username, password) != null;
}

Now go to "http://localhost:9000/logout":http://localhost:9000/logout to log out and you can try logging in with one of the users imported in the @initial-data.yml@ file, like <code>bob@gmail.com/secret</code>.

h2. <a>Refactoring the administration area</a>

We’ve started the administration area using the CRUD module, but it is not yet well integrated with the blog UI. We will start to work on a new administration area. This one will give each author access to his/her own posts. The full-featured administration using CRUD will still be available for super administrator users.

Let’s create a new @Admin@ controller for the administration part:

bc.  package controllers;
 
import play.*;
import play.mvc.*;
 
import java.util.*;
 
import models.*;
 
@With(Secure.class)
public class Admin extends Controller {
    
    @Before
    static void setConnectedUser() {
        if(Security.isConnected()) {
            User user = User.find("byEmail", Security.connected()).first();
            renderArgs.put("user", user.fullname);
        }
    }
 
    public static void index() {
        render();
    }
    
}

And refactor the routes definition in @yabe/conf/routes@:

bc. # Administration
GET     /admin/?                                Admin.index
*       /admin                                  module:crud

Remember that order matters in the routes file; the first line that matches the incoming HTTP request is used. This means that the entries that map to the @Admin@ controller must come before the second line above, which maps all other @/admin@ requests to CRUD module pages. Otherwise, @/admin/@ will map to @CRUD.index@ instead of @Admin.index@.

Now link the ‘Log in to write something’ text from the @yabe/app/views/main.html@ template to this controller:

bc. …
<ul id="tools">
    <li>
        <a href="@{Admin.index()}">Log in to write something</a>
    </li>
</ul>
…

The last thing to make all this new stuff work is to create the @yabe/app/views/Admin/index.html@ template. Let’s start with something simple:

bc. Welcome ${user}!

Now, go to the blog home page, click the ‘Log in to write something’ link and you should get to the new administration area:

!images/guide8-2!

Good start! But since we will have several pages in this administration area, we need a super-template. Let’s create it in the @yabe/app/views/admin.html@ file:

bc. <!DOCTYPE html>
<html>
    <head>
        <title>Administration</title>		
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        #{get 'moreStyles' /}	
        <link rel="stylesheet" type="text/css" media="screen" 
                href="@{'/public/stylesheets/main.css'}" />
        <link rel="shortcut icon" type="image/png" 
                href="@{'/public/images/favicon.png'}" />
        <script src="@{'/public/javascripts/jquery-1.4.2.min.js'}"></script>
        <script src="@{'/public/javascripts/jquery.tools-1.2.5.toolbox.expose.min.js'}"></script>
    </head>
    <body id="admin">
        
        <div id="header">
            <div id="logo">
                yabe. <span>administration</span>
            </div>
            <ul id="tools">
                <li>
                    <a href="@{Secure.logout()}">Log out</a>
                </li>
            </ul>
        </div>
        
        <div id="main">
            #{doLayout /} 
        </div>
        
        <p id="footer">
            Yabe is a (not so) powerful blog engine built with the 
            <a href="https://www.playframework.com">Play framework</a>
            as a tutorial application.
        </p>
        
    </body>
</html>

As you can see, it’s very close to the template used for the front part of the blog engine. You have replaced the **Log in** link by a **Log out** link that calls the @Secure@ controller’s @logout@ action provided by the secure module.

Now let’s use it in the @yabe/app/views/Admin/index.html@ template:

bc. #{extends 'admin.html' /}
 
Welcome ${user}!

And refresh!

!images/guide8-3!

If you try the **log out** link it will send you back to the login form:

!images/guide8-4!

That’s the default way for the secure module to handle log out events. But it’s easily customizable simply by overriding the @onDisconnected()@ method in the @controllers.Security@ class:

bc. static void onDisconnected() {
    Application.index();
}

You can do the same for the @onAuthenticated()@ event:

bc. static void onAuthenticated() {
    Admin.index();
}

h2. <a>Adding roles</a>

Actually, we need two administration areas: one for simple editors and another one for the super administrator. As you’ve seen the @User@ model object has an @isAdmin@ field that indicates whether the user has super administrator rights.

The secure module not only provides @authentication@ but @authorization@ management too. It’s called @profiles@. To create an @admin@ profile, you just need to override the @check()@ method in the @controllers.Security@ class:

bc. static boolean check(String profile) {
    if("admin".equals(profile)) {
        return User.find("byEmail", connected()).<User>first().isAdmin;
    }
    return false;
}

Now we can show an administration menu if the user has the admin role. Update @app/views/admin.html@ to integrate a top level menu:

bc. …
<div id="main">
    
    <ul id="adminMenu">
        <li class="${request.controller == 'Admin' ? 'selected' : ''}">
            <a href="@{Admin.index()}">My posts</a>
        </li>
        #{secure.check 'admin'}
            <li class="${request.controller == 'Posts' ? 'selected' : ''}">
                <a href="@{Posts.list()}">Posts</a>
            </li>
            <li class="${request.controller == 'Tags' ? 'selected' : ''}">
                <a href="@{Tags.list()}">Tags</a>
            </li>
            <li class="${request.controller == 'Comments' ? 'selected' : ''}">
                <a href="@{Comments.list()}">Comments</a>
            </li>
            <li class="${request.controller == 'Users' ? 'selected' : ''}">
                <a href="@{Users.list()}">Users</a>
            </li>
        #{/secure.check}
    </ul>
    
    #{doLayout /} 
</div>
…

Note how we used the @#{secure.check /}@ tag to show part of the menu only to @admin@ users.

!images/guide8-5!

But that’s not yet enough to secure the site’s CRUD section! If a user knows the URL he can still access it. We have to protect the controllers as well. We can do so easily using the <code>@Check</code> annotation. For example, for the @Posts@ controller:

bc. package controllers;
 
import play.*;
import play.mvc.*;
 
@Check("admin")
@With(Secure.class)
public class Posts extends CRUD {    
}

Do the same for the @Tags@, @Comments@ and @Users@ controllers. Now try to log out and log in again with a standard user (like <code>jeff@gmail.com/secret</code>). You should not see the CRUD admin links. And if you try to access the "http://localhost:9000/admin/users":http://localhost:9000/admin/users URL directly you will get a **403 Forbidden** response.

!images/guide8-6!

h2. <a>Customizing the CRUD layout</a>

That’s fun but when we go to the CRUD part of the administration area, we lose the administration layout. That’s because the CRUD module provides its own layout. But we can of course override it. Use this Play command:

bc. play crud:ov --layout

And you get a new @/yabe/app/views/CRUD/layout.html@ template. Let’s replace its content to integrate it nicely with our @admin.html@ layout:

bc. #{extends 'admin.html' /}
#{set 'moreStyles'}
    <link rel="stylesheet" type="text/css" media="screen" 
        href="@{'/public/stylesheets/crud.css'}" />
#{/set}
 
<div id="crud">
 
    #{if flash.success}
    	<div class="crudFlash flashSuccess">
    		${flash.success}
    	</div>
    #{/if}
    #{if flash.error || error}
    	<div class="crudFlash flashError">
    		${error ?: flash.error}
    	</div>
    #{/if}
 
    <div id="crudContent">
    	#{doLayout /}
    </div>
 
</div>

As you can see, we reuse @crud.css@ and include it in @admin.html@ using the **get/set** template variables mechanism. Now if you try the CRUD part of the administration area, it’s correctly integrated with the administration layout:

!images/guide8-7!

!images/guide8-9!

h2. <a>Styling the login page</a>

The administration area is almost graphically coherent now. The last thing to style is the log-in page. As always it is easily customizable by overriding the default CSS:

bc. play secure:ov --css

We will just keep the CSS as is, but import our @main.css@ at the top. Just add this first line to the @yabe/public/stylesheets/secure.css@:

bc. @import url(main.css);
…

And customize the log-in screen messages, by adding these lines to your own @yabe/conf/messages@ file:

bc. secure.username=Your email:
secure.password=Your password:
secure.signin=Log in now

!images/guide8-8!

p(note). Next: %(next)"Creating a custom editor area":guide9%. 
