Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for 
change notification.

The following page has been changed by StephaneDecleire:
http://wiki.apache.org/tapestry/Tapestry5HowToControlAccess

The comment on the change is:
Adding Tapestry5HowToControlAccess to the wiki

New page:
##language:en
In the articles 
[http://wiki.apache.org/tapestry/Tapestry5HowToCreateADispatcher 
Tapestry5HowToCreateADispatcher] and 
[http://wiki.apache.org/tapestry/Tapestry5HowToCreateADispatcher2 
Tapestry5HowToCreateADispatcher2], Chris Lewis has explained how to create a 
dispatcher, get it into the pipeline, and use it to check user rights against 
the url requested.
What i need in my project is similar but i would rather check the rights of my 
users against an information stored in the page requested, say an annotation !

=== Page rights as an annotation ===
Our first task is to create a @Private annotation that we will put on pages 
where the authentication of the user is required. Our annotation will be 
associated to pages and will have no parameters. So, its implementation will be 
as simple as :
{{{
@Target(TYPE)
@Retention(RUNTIME)
@Documented
public @interface Private
{
}
}}}

=== User rights in the user session ===
The state of the user will be stored in his session. To keep it simple, the 
status of the user will be "logged in" or "logged out". So the interface of the 
user session will display a function to get the user state :
{{{
public interface UserSession
{
  ...
  public abstract boolean isUserLoggedIn();
  ...
}
}}}

=== The problem ===
With those implementations in hand, what we have to do is to get the Tapestry 
page associated with the request of the dispatcher and check on this page the 
presence of the @Private annotation.

=== The solution ===
We will just have to parse the path of the request and check it against the 
Tapestry ComponentClassResolver service (like in the Tapestry 
PageRenderDispatcher) to find the page name. Having the page name, we can get 
the Tapestry page from the Tapestry RequestPageCache. After we get the Tapestry 
Page, we can check the presence of our @Private annotation :

{{{
public class AccessController implements Dispatcher
{
  private final static String LOGIN_PAGE = "/login";

  private ApplicationStateManager asm;
  private UserSessionImpl newUserSession;
  private final ComponentClassResolver resolver;
  private final RequestPageCache cache;

  /**
   * Receive all the services needed as constructor arguments. When we bind this
   * service, T5 IoC will provide all the services !
   */
  public AccessController(ApplicationStateManager asm, ComponentClassResolver 
resolver, RequestPageCache cache, UserSessionImpl newUserSession)
  {
    this.asm = asm;
    this.newUserSession = newUserSession;
    this.resolver = resolver;
    this.cache = cache;
  }

  public boolean dispatch(Request request, Response response) throws IOException
  {
    /* We need to get the Tapestry page requested by the user.
     * So we parse the path extracted from the request
     */
    String path = request.getPath();
    if (path.equals("")) return false;

    int nextslashx = path.length();
    String pageName;

    while (true)
    {
      pageName = path.substring(1, nextslashx);
      if (!pageName.endsWith("/") && resolver.isPageName(pageName)) break;
      nextslashx = path.lastIndexOf('/', nextslashx - 1);
      if (nextslashx <= 1) return false;
    }
    return checkAccess(pageName, request, response);
  }

  /**
   * Check the rights of the user for the page requested
   */
  public boolean checkAccess(String pageName, Request request, Response 
response) {

    boolean canAccess = true;

    /* Is the requested page private ? */
    ComponentSource cs = new ComponentSourceImpl(cache);
    Component page = cs.getPage(pageName);
    Boolean privatePage = 
Boolean.valueOf(page.getComponentResources().getComponentModel().getMeta("private"));
        
    if (privatePage)
    {
      canAccess = false;
      /* Is the user already authentified ? */
      if(asm.exists(UserSessionImpl.class))
      {
        UserSessionImpl userSession = asm.get(UserSessionImpl.class);
        canAccess = userSession.isUserLoggedIn();
      }
    }
        
    /* This page can't be requested by a non authentified user => we redirect 
him on the signon page */
    if(!canAccess) {
      response.sendRedirect(request.getContextPath() + LOGIN_PAGE);
    }
        
    return false;
  }
}
}}}

== Conclusion ==
We have made the choice to use an annotation to set the page status but after 
we get the Tapestry page in the dispatcher, any other information of the page 
can be checked.
An interesting evolution would be to keep the initial request in the user 
session to be able to redirect the user on it after he has logged in ...
Any suggestions, corrections, or other ideas on this document are welcome. Feel 
free to contact me on [EMAIL PROTECTED] (Stephane Decleire).

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to