/*
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.seam.wiki.core.action;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.*;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;
import org.jboss.seam.security.Credentials;
import org.jboss.seam.util.Base64;
import org.jboss.seam.wiki.core.action.prefs.UserManagementPreferences;
import org.jboss.seam.wiki.core.dao.UserDAO;
import org.jboss.seam.wiki.core.dao.WikiNodeDAO;
import org.jboss.seam.wiki.core.wikitext.renderer.MacroWikiTextRenderer;
import org.jboss.seam.wiki.core.ui.WikiURLRenderer;
import org.jboss.seam.wiki.core.model.*;
import org.jboss.seam.wiki.core.model.Role;
import org.jboss.seam.wiki.util.Hash;
import org.jboss.seam.wiki.util.WikiUtil;
import org.jboss.seam.wiki.preferences.Preferences;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Name("authenticator")
public class Authenticator {
@Logger
Log log;
@In
private UserDAO userDAO;
@In
private Hash hashUtil;
private String activationCode;
public String getActivationCode() { return activationCode; }
public void setActivationCode(String activationCode) { this.activationCode = activationCode; }
public boolean authenticateBasicHttp(HttpServletRequest request) {
String auth = request.getHeader("Authorization");
if (auth == null || !!auth.toUpperCase().startsWith("Basic ")) {
log.debug("Basic HTTP authorization header not found");
return false;
}
String userpassEncoded = auth.substring(6);
String userpassDecoded = new String(Base64.decode(userpassEncoded));
if (!userpassDecoded.contains(":")) {
log.debug("Basic HTTP authorization password not supplied");
return false;
}
String username = userpassDecoded.substring(0, userpassDecoded.indexOf(":"));
String password = userpassDecoded.substring(userpassDecoded.indexOf(":")+1);
log.debug("Basic HTTP authentication for user: " + username);
User user = getUserForCredentials(username, password);
if (user == null) return false;
setRolesAndAccessLevels(user);
return true;
}
public boolean authenticate() {
Credentials credentials = Identity.instance().getCredentials();
log.debug("attempting authentication of user: " + credentials.getUsername());
User user = getUserForCredentials(credentials.getUsername(), credentials.getPassword());
if (user == null) return false;
setRolesAndAccessLevels(user);
// Set last login (storing the previous last login too, so we can create deltas between the two logins)
user.setPreviousLastLoginOn(user.getLastLoginOn());
user.setLastLoginOn(new Date());
return true;
}
private User getUserForCredentials(String username, String password) {
if (User.GUEST_USERNAME.equals(username)) {
log.warn("denying attempted 'guest' login");
return null;
}
User user = userDAO.findUser(username, true, true);
if (user == null || password == null || !user.getPasswordHash().equalsIgnoreCase(hashUtil.hash(password))) {
log.debug("Invalid authentication credentials for username '" + username + "'");
return null;
}
log.debug("Successfully authenticated user: " + user.getUsername());
return user;
}
private void setRolesAndAccessLevels(User user) {
// We don't use Seams Role class, wiki currently only uses numeric access levels
Role bestRole = (Role)Component.getInstance("guestRole");
for (Role role : user.getRoles()) {
if (role.getAccessLevel() > bestRole.getAccessLevel()) bestRole = role;
}
if (user.getMemberHome() != null && user.getMemberHome().getName() != null) {
log.debug("initializing users member home instance before detaching currentUser into HTTP session");
}
// Outject current user and access level
Contexts.getSessionContext().set("currentUser", user);
Contexts.getSessionContext().set("currentAccessLevel", bestRole.getAccessLevel());
}
public String activate() {
User user = userDAO.findUserWithActivationCode(activationCode);
if (user != null) {
user.setActivated(true);
user.setActivationCode(null);
Contexts.getEventContext().set("activatedUser", user);
// Optionally, create home directory
if ( Preferences.instance().get(UserManagementPreferences.class).getCreateHomeAfterUserActivation() ) {
createHomeDirectory(user);
}
return "activated";
} else {
return "notFound";
}
}
public void createHomeDirectory(User user) {
WikiNodeDAO nodeDAO = (WikiNodeDAO)Component.getInstance(WikiNodeDAO.class);
WikiURLRenderer urlRenderer = (WikiURLRenderer)Component.getInstance(WikiURLRenderer.class);
// Create home directory
WikiDirectory memberArea = (WikiDirectory)Component.getInstance("memberArea");
WikiDirectory homeDirectory = new WikiDirectory();
homeDirectory.setName(user.getUsername());
homeDirectory.setWikiname(WikiUtil.convertToWikiName(homeDirectory.getName()));
homeDirectory.setAreaNumber(memberArea.getAreaNumber());
homeDirectory.setCreatedBy(user);
homeDirectory.setWriteAccessLevel(Role.ADMINROLE_ACCESSLEVEL);
homeDirectory.setReadAccessLevel(Role.GUESTROLE_ACCESSLEVEL);
homeDirectory.setParent(memberArea);
user.setMemberHome(homeDirectory);
// Create feed for home directory
WikiFeed feed = new WikiFeed();
feed.setLink(urlRenderer.renderURL(homeDirectory));
feed.setDirectory(homeDirectory);
feed.setAuthor(homeDirectory.getCreatedBy().getFullname());
feed.setTitle(homeDirectory.getName());
homeDirectory.setFeed(feed);
nodeDAO.makePersistent(homeDirectory);
// Create home page
WikiDocument homePage = new WikiDocument();
homePage.setName("Home of " + user.getUsername());
homePage.setWikiname(WikiUtil.convertToWikiName(homePage.getName()));
homePage.setCreatedBy(user);
homePage.setAreaNumber(homeDirectory.getAreaNumber());
homePage.setContent(Preferences.instance().get(UserManagementPreferences.class).getHomepageDefaultContent());
homePage.setWriteAccessLevel(Role.ADMINROLE_ACCESSLEVEL);
homePage.setReadAccessLevel(Role.GUESTROLE_ACCESSLEVEL);
MacroWikiTextRenderer renderer = MacroWikiTextRenderer.renderMacros(homePage.getContent());
homePage.setContentMacros(renderer.getMacros());
homePage.setParent(homeDirectory);
homeDirectory.setDefaultFile(homePage);
nodeDAO.makePersistent(homePage);
}
public String logout() {
Identity.instance().logout();
return "loggedOut";
}
}