package org.bubblecloud.ilves.security;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.bubblecloud.ilves.api.ApiImplementation;
import org.bubblecloud.ilves.api.apis.RequestAccessTokenResult;
import org.bubblecloud.ilves.api.apis.SecurityApi;
import org.bubblecloud.ilves.model.*;
import org.bubblecloud.ilves.module.customer.CustomerModule;
import org.bubblecloud.ilves.site.SiteContext;
import org.bubblecloud.ilves.site.SiteModuleManager;
import org.bubblecloud.ilves.util.StringUtil;
import javax.persistence.EntityManager;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
/**
* The security API implementation.
*
* @author Tommi S.E. Laukkanen
*/
public class SecurityApiImpl implements SecurityApi, ApiImplementation {
/** The logger. */
private static final Logger LOGGER = Logger.getLogger(SecurityApiImpl.class);
/** The context. */
private SiteContext context;
@Override
public void setContext(final SiteContext context) {
this.context = context;
}
@Override
public RequestAccessTokenResult requestAccessToken(final String account, final String password) {
final String emailAddress = account;
final EntityManager entityManager = context.getEntityManager();
final Company company = context.getObject(Company.class);
final User user = UserDao.getUser(entityManager, company, emailAddress);
if (user == null) {
LOGGER.warn("Request access token failed due to account not found: " + emailAddress);
final RequestAccessTokenResult result = new RequestAccessTokenResult();
result.setErrorKey("message-login-failed");
return result;
}
final List<AuthenticationDevice> authenticationDevices = AuthenticationDeviceDao.getAuthenticationDevices(entityManager, user);
if (authenticationDevices.size() > 0) {
LOGGER.warn("Request access token failed due to account has authentication devices defined. OAuth should be used to get access token: " + emailAddress);
final RequestAccessTokenResult result = new RequestAccessTokenResult();
result.setErrorKey("message-login-failed");
return result;
}
final char[] accessToken = SecurityUtil.generateAccessToken();
final RequestAccessTokenResult result = new RequestAccessTokenResult();
result.setAccessToken(new String(accessToken));
result.setExpirationTime(new Date(System.currentTimeMillis() + SecurityUtil.ACCESS_TOKEN_LIFETIME_MILLIS));
final String errorKey = LoginService.login(context, company,
user, emailAddress, password.toCharArray(), context.getSession().getId(), accessToken);
if (errorKey == null) {
return result;
} else {
result.setAccessToken(null);
result.setExpirationTime(null);
result.setErrorKey(errorKey);
return result;
}
}
@Override
public void invalidateAccessToken(final String account, final String accessToken) {
final String emailAddress = account;
final EntityManager entityManager = context.getEntityManager();
final Company company = context.getObject(Company.class);
final User user = UserDao.getUser(entityManager, company, emailAddress);
if (user == null) {
LOGGER.warn("Invalidate access token failed due to account not found: " + emailAddress);
return;
}
final String accessTokenHash = SecurityUtil.getSecretHash(accessToken.toCharArray());
final UserSession userSession = SecurityService.getUserSessionByAccessTokenHash(entityManager, accessTokenHash);
if (userSession != null) {
SecurityService.removeUserSession(entityManager, userSession);
}
return;
}
@Override
public boolean selfRegisterUser(final String firstName, final String lastName, final String emailAddress, final String phoneNumber, final String password) {
final EntityManager entityManager = context.getEntityManager();
final Company company = context.getObject(Company.class);
final User existingUser = UserDao.getUser(entityManager, company, emailAddress);
if (existingUser != null) {
return false;
} else {
if (!company.isSelfRegistration()) {
return false;
}
final User newUser = new User(company, firstName, lastName, emailAddress, phoneNumber, "");
UserDao.addUser(entityManager, newUser, UserDao.getGroup(entityManager, company, "user"));
final byte[] passwordAndSaltBytes = SecurityUtil.convertCharactersToBytes(ArrayUtils.addAll((newUser.getUserId() + ":").toCharArray(), password.toCharArray()));
final MessageDigest md;
try {
md = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new SecurityException(e);
}
final byte[] passwordAndSaltDigest = md.digest(passwordAndSaltBytes);
newUser.setPasswordHash(StringUtil.toHexString(passwordAndSaltDigest));
UserDao.updateUser(entityManager, newUser);
if (SiteModuleManager.isModuleInitialized(CustomerModule.class)) {
final Customer customer = new Customer(firstName, lastName, emailAddress, phoneNumber, false, "", "");
customer.setCreated(new Date());
customer.setModified(customer.getCreated());
customer.setOwner(company);
final PostalAddress invoicingAddress = new PostalAddress();
invoicingAddress.setAddressLineOne("-");
invoicingAddress.setAddressLineTwo("-");
invoicingAddress.setAddressLineThree("-");
invoicingAddress.setCity("-");
invoicingAddress.setPostalCode("-");
invoicingAddress.setCountry("-");
final PostalAddress deliveryAddress = new PostalAddress();
deliveryAddress.setAddressLineOne("-");
deliveryAddress.setAddressLineTwo("-");
deliveryAddress.setAddressLineThree("-");
deliveryAddress.setCity("-");
deliveryAddress.setPostalCode("-");
deliveryAddress.setCountry("-");
customer.setInvoicingAddress(invoicingAddress);
customer.setDeliveryAddress(deliveryAddress);
CustomerDao.addCustomer(entityManager, customer);
UserDao.addGroupMember(context.getEntityManager(), customer.getAdminGroup(), newUser);
UserDao.addGroupMember(context.getEntityManager(), customer.getMemberGroup(), newUser);
}
AuditService.log(context, "api-self-register", "user", newUser.getUserId(), emailAddress);
return true;
}
}
}