Reputation: 584
I am trying to create a login feature for my apache tapestry
website, where after logging in, instead of the 'Log In' and 'Register' button, the email of the logged user should be displayed, along with a 'Log Out' button.
Could anyone please tell how should this be implemented the best way?
I can't seem to figure out how should i detect if the user is logged in, in the frontend part, in order to display a different menu options (i am new in tapestry).
Best regards, Marius.
Upvotes: 0
Views: 943
Reputation: 584
After a little bit of research regarding this matter, i found the following approach:
1) I created an Authenticator interface
public interface Authenticator {
Users getLoggedUser();
boolean isLoggedIn();
void login(String email, String password) throws AuthenticationException;
void logout();
}
2) Also created an AuthenticatorImpl.java class that implements that interface
public class AuthenticatorImpl implements Authenticator {
public static final String AUTH_TOKEN = "authToken";
@Inject
private StartDAO dao;
@Inject
private Request request;
public void login(String email, String password) throws AuthenticationException
{
Users user = dao.findUniqueWithNamedQuery("from Users u where u.Email = '" + email + "' and u.Password = '" + password + "'");
if (user == null) { throw new AuthenticationException("The user doesn't exist"); }
request.getSession(true).setAttribute(AUTH_TOKEN, user);
}
public boolean isLoggedIn()
{
Session session = request.getSession(false);
if (session != null) { return session.getAttribute(AUTH_TOKEN) != null; }
return false;
}
public void logout()
{
Session session = request.getSession(false);
if (session != null)
{
session.setAttribute(AUTH_TOKEN, null);
session.invalidate();
}
}
public Users getLoggedUser()
{
Users user = null;
if (isLoggedIn())
{
user = (Users) request.getSession(true).getAttribute(AUTH_TOKEN);
}
return user;
}
}
3) Created the corresponding binding in the AppModule.java class
public static void bind(ServiceBinder binder)
{
binder.bind(StartDAO.class, StartDAOImpl.class);
binder.bind(Authenticator.class, AuthenticatorImpl.class);
}
4) And on my Layout.java page i used it in the following way
@Property
private Users user;
@Inject
private Authenticator authenticator;
void setupRender()
{
if(authenticator.getLoggedUser().getAccountType().equals("Administrator")){
administrator = authenticator.getLoggedUser();
}
user = authenticator.getLoggedUser();
}
Object onLogout(){
authenticator.logout();
return Login.class;
}
Layout.tml
<t:if test="user">
<span class="navbar-right btn navbar-btn" style="color: white;">
Welcome ${user.Name}! <a t:type="eventLink" t:event="Logout" href="#">(Logout)</a>
</span>
</t:if>
<t:if negate="true" test="user">
<span class="navbar-right">
<t:pagelink page="user/create" class="btn btn-default navbar-btn">Register</t:pagelink>
<t:pagelink page="user/login" class="btn btn-default navbar-btn">Sign in</t:pagelink>
</span>
</t:if>
This worked for me without any problems. Hope that it helps others.
Best regards, Marius.
Upvotes: 0
Reputation: 549
Authentication (of which login is a part) is very application specific. How you define a User (or do you call it a "Customer", for example) is not something the framework does.
Typically, you will have a SessionStateObject representing your User. You can then use something like this in your layout:
<t:if test="user">
<t:logoutLink/>
<p:else>
<t:signInForm/>
</t:if>
Again, components LogoutLink and SignInForm are for you to implement.
The user may be exposed from the Java code as:
@Property @sessionState(create=false) private User user;
This says that the user field is linked to a value stored in the HTTP session; further, the User will not be created when the field is first read; instead, your SignInForm component should assign to its user field.
Upvotes: 2