package se.gu.fire.backend;
import java.io.Serializable;
import javax.ejb.EJB;
import javax.enterprise.context.ConversationScoped;
import javax.inject.Named;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import se.gu.fire.core.FireUser;
import se.gu.fire.core.Password;
import se.gu.fire.backend.constraints.EmailConstraint;
import se.gu.fire.data.inter.IPasswordManager;
import se.gu.fire.data.inter.IUserManager;
import se.gu.fire.util.FireFaces;
import se.gu.fire.util.FireLogger;
import se.gu.fire.util.FireUtil;
import se.gu.fire.core.UserRole;
/**
* Provides login and authentication functionality. The users name and password
* will be read from the XHTML form, verified against the database, and finally
* grafted into a Session for the user who just logged in.
*
* @author christopher
*/
@Named("loginBean")
@ConversationScoped
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
@EJB
private IUserManager userManager;
@EJB
private IPasswordManager passwordManager;
@EmailConstraint
private String userEmail;
private String userPassword;
private boolean rememberMe;
public LoginBean() {
FireLogger.logInfo("Created LoginBean for user {0}", FireUtil.getLoggedinUserEmail());
}
/**
* Attempt to log the requesting user into the system
*/
public String doLogin() {
FireLogger.logInfo("Attempting to log in user: {0}", userEmail);
boolean succeded = false;
debugCreateTestUser();
Subject currentUser = SecurityUtils.getSubject();
/*
* Break if user is already authenticated
*/
if (currentUser.isAuthenticated()) {
return null;
}
/*
* Create a authentication token for the user, and attempt to log
* the user in
*/
UsernamePasswordToken currentUserToken = new UsernamePasswordToken(userEmail, userPassword);
currentUserToken.setRememberMe(rememberMe);
try {
SecurityUtils.getSubject().login(currentUserToken);
succeded = true;
}
catch (UnknownAccountException uae) {
FireLogger.logSevere("Caught UnknownAccountException for user {0}: {1}",userEmail,uae.getMessage());
FireFaces.addErrorMessage("Email not found in system", userEmail);
}
catch (IncorrectCredentialsException ice) {
FireLogger.logSevere("Caught IncorrectCredentialsException for user {0}: {1}",userEmail,ice.getMessage());
FireFaces.addErrorMessage("Wrong username or password");
}
catch (AuthenticationException ae) {
FireLogger.logSevere("Caught AuthenticationException for user {0}: {1}",userEmail,ae.getMessage());
FireFaces.addErrorMessage("Authentication failed");
}
catch (Exception e) {
FireLogger.logSevere(
"Caught fatal system error for user {0}: {1}",userEmail,e.getMessage());
FireFaces.addFatalMessage("Database failure. Please contact your admin");
}
FireLogger.logInfo("Logged in user: {0}. Remembered: {1}:",userEmail,rememberMe);
return succeded ? "index?faces-redirect=true" : null;
}
private void debugCreateTestUser() {
FireUser newUser = userManager.findUser("christopher.svanefalk@gmail.com");
if (newUser == null) {
newUser = new FireUser.Builder()
.email("christopher.svanefalk@gmail.com")
.firstName("Oscar")
.lastName("Utbult")
.personNummer("1231231231")
.userRole(UserRole.ADMIN)
.build();
userManager.create(newUser);
RandomNumberGenerator numberGenerator = new SecureRandomNumberGenerator();
ByteSource salt = numberGenerator.nextBytes();
String hashedPassword = new Sha256Hash("haxx", salt, 1024).toBase64();
Password newPassword = new Password(newUser.getId(), hashedPassword, salt.getBytes());
passwordManager.create(newPassword);
FireLogger.logInfo(
"Created debug user "
+ newUser.getEmail()
+ " with password "
+ newPassword.getPassword()
+ " and salt "
+ newPassword.getSalt());
}
}
public String getUserEmail() {
return userEmail;
}
public boolean isRememberMe() {
return rememberMe;
}
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
}
public void setUserEmail(String userEmail) {
this.userEmail = userEmail;
}
public String getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
}