/**
* Copyright 2013 Tommi S.E. Laukkanen
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bubblecloud.ilves.security;
import com.vaadin.server.Page;
import com.vaadin.server.VaadinServletRequest;
import com.vaadin.server.VaadinSession;
import com.vaadin.ui.Notification;
import com.vaadin.ui.UI;
import com.yubico.u2f.data.DeviceRegistration;
import org.apache.log4j.Logger;
import org.bubblecloud.ilves.model.*;
import org.bubblecloud.ilves.site.AbstractSiteUI;
import org.bubblecloud.ilves.site.DefaultSiteUI;
import org.bubblecloud.ilves.site.Site;
import org.bubblecloud.ilves.site.SiteContext;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
/**
* Service for user login and logout functionality.
*/
public class SiteAuthenticationService {
/** The logger. */
private static final Logger LOGGER = Logger.getLogger(LoginService.class);
/**
* Gets current authentication device type for email address.
* @param emailAddress_ the email address
* @return the current authentication device type or null if multiple device types exist.
*/
public static AuthenticationDeviceType getAuthenticationDeviceType(final String emailAddress_) {
final String emailAddress = emailAddress_.toLowerCase();
final AbstractSiteUI ui = ((AbstractSiteUI) UI.getCurrent());
final EntityManager entityManager = ui.getSite().getSiteContext().getEntityManager();
final Company company = ui.getSite().getSiteContext().getObject(Company.class);
final User user = UserDao.getUser(entityManager, company, emailAddress);
if (user == null) {
return AuthenticationDeviceType.NONE;
}
entityManager.refresh(user);
final List<AuthenticationDevice> authenticationDevices = SiteAuthenticationService.getAuthenticationDevices(emailAddress);
if (authenticationDevices.size() == 0) {
return AuthenticationDeviceType.NONE;
}
AuthenticationDeviceType authenticationDeviceType = null;
for (final AuthenticationDevice authenticationDevice : authenticationDevices) {
if (authenticationDeviceType == null) {
authenticationDeviceType = authenticationDevice.getType();
} else {
if (authenticationDevice.getType() != authenticationDeviceType) {
return null;
}
}
}
return authenticationDeviceType;
}
/**
* Gets device registrations.
* @param emailAddress the email address
* @return list of device registrations
*/
public static List<AuthenticationDevice> getAuthenticationDevices(final String emailAddress) {
final AbstractSiteUI ui = ((AbstractSiteUI) UI.getCurrent());
final SiteContext context = ui.getSite().getSiteContext();
final Company company = context.getObject(Company.class);
final EntityManager entityManager = context.getEntityManager();
final User user = UserDao.getUser(entityManager, company, emailAddress);
return AuthenticationDeviceDao.getAuthenticationDevices(entityManager, user);
}
/**
* Logs user in to the site.
* @param emailAddress_ the email address
* @param password the password
* @param accessToken the access token
* @return true if login succeeded
*/
public static boolean login(final String emailAddress_, final char[] password, final char[] accessToken) {
final String emailAddress = emailAddress_.toLowerCase();
final AbstractSiteUI ui = ((AbstractSiteUI)UI.getCurrent());
final EntityManager entityManager = ui.getSite().getSiteContext().getEntityManager();
final Company company = ui.getSite().getSiteContext().getObject(Company.class);
final User user = UserDao.getUser(entityManager, company, emailAddress);
final Locale locale;
if (ui.getLocale() == null) {
locale = Locale.ENGLISH;
} else {
locale = ui.getLocale();
}
if (user == null) {
new Notification(DefaultSiteUI.getLocalizationProvider().localize("message-login-failed", locale),
Notification.Type.WARNING_MESSAGE).show(Page.getCurrent());
return false;
}
entityManager.refresh(user);
final String errorKey = LoginService.login(ui.getSite().getSiteContext(), company,
user, emailAddress, password, VaadinSession.getCurrent().getSession().getId(), accessToken);
if (errorKey == null) {
login(locale, entityManager, company, user);
return true;
} else if (errorKey.equals("message-login-failed-duplicate-login-for-login-transaction-id")) {
return false;
// Silently fail.
} else {
// Login failure
new Notification(DefaultSiteUI.getLocalizationProvider().localize(errorKey, locale),
Notification.Type.WARNING_MESSAGE).show(Page.getCurrent());
return false;
}
}
/**
* Helper function for final login.
* @param locale the locale
* @param entityManager the entity manager
* @param company the company
* @param user the user
*/
private static void login(Locale locale, EntityManager entityManager, Company company, User user) {
final AbstractSiteUI ui = ((AbstractSiteUI)UI.getCurrent());
final List<Group> groups = UserDao.getUserGroups(entityManager, company, user);
DefaultSiteUI.getSecurityProvider().setUser(user, groups);
// Check for imminent password expiration.
if (user.getPasswordExpirationDate() != null
&& new DateTime().plusDays(14).toDate().getTime()
> user.getPasswordExpirationDate().getTime() ) {
final DateTime expirationDate = new DateTime(user.getPasswordExpirationDate());
final DateTime currentDate = new DateTime();
final long daysUntilExpiration = new Duration(currentDate.toDate().getTime(),
expirationDate.toDate().getTime()).getStandardDays();
new Notification(DefaultSiteUI.getLocalizationProvider().localize(
"message-password-expires-in-days", locale)
+ ": " + daysUntilExpiration, Notification.Type.WARNING_MESSAGE).show(Page.getCurrent());
} else {
ui.setNotification(DefaultSiteUI.getLocalizationProvider().localize(
"message-login-success", locale), Notification.Type.TRAY_NOTIFICATION);
}
ui.getPage().setLocation(company.getUrl());
}
/**
* Removes user device registratoins.
* @param emailAddress the user email address
*/
public static void removeDeviceRegistrations(final String emailAddress) {
final AbstractSiteUI ui = ((AbstractSiteUI) UI.getCurrent());
final SiteContext context = ui.getSite().getSiteContext();
final Company company = context.getObject(Company.class);
final EntityManager entityManager = context.getEntityManager();
final User user = UserDao.getUser(entityManager, company, emailAddress);
final List<AuthenticationDevice> authenticationDevices = AuthenticationDeviceDao.getAuthenticationDevices(entityManager, user);
for (final AuthenticationDevice authenticationDevice : authenticationDevices) {
AuthenticationDeviceDao.removeAuthenticationDevice(context.getEntityManager(), authenticationDevice);
}
}
}