/*
* Copyright (C) 2013 Pavel Stastny
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cz.cas.lib.proarc.authentication.desa;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cz.cas.lib.proarc.authentication.Authenticator;
import cz.cas.lib.proarc.authentication.ProarcPrincipal;
import cz.cas.lib.proarc.common.config.AppConfiguration;
import cz.cas.lib.proarc.common.config.AppConfigurationException;
import cz.cas.lib.proarc.common.config.AppConfigurationFactory;
import cz.cas.lib.proarc.common.export.desa.DesaServices;
import cz.cas.lib.proarc.common.export.desa.DesaServices.DesaConfiguration;
import cz.cas.lib.proarc.common.user.Group;
import cz.cas.lib.proarc.common.user.Permissions;
import cz.cas.lib.proarc.common.user.UserManager;
import cz.cas.lib.proarc.common.user.UserProfile;
import cz.cas.lib.proarc.common.user.UserUtil;
import cz.cas.lib.proarc.desa.DesaClient;
import cz.cas.lib.proarc.desa.soap.AuthenticateUserFault;
import cz.cas.lib.proarc.desa.soap.AuthenticateUserResponse;
import cz.cas.lib.proarc.desa.soap.Role;
/**
* DESA authentication.
* It authenticates credentials in all registered DESA services. At least one
* authentication response must contain required role to pass.
* @author pavels
*/
public class DESAAuthenticator implements Authenticator {
public static Logger LOGGER = Logger.getLogger(DESAAuthenticator.class.getName());
public static final String KOD_PUVODCE = "kod";
public static final String REMOTE_TYPE = DesaServices.REMOTE_USER_TYPE;
public static final String USER_PREFIX = "desa";
private static final String ROLE = "producer_submit";
public DESAAuthenticator() {
}
/**
* @return the authenticated user or {@code null}
*/
private UserProfile authenticateDesaUser(String tUser, String tPass, String code) {
try {
AppConfiguration appConfig = AppConfigurationFactory.getInstance().defaultInstance();
DesaServices desaServices = appConfig.getDesaServices();
List<DesaConfiguration> configurations = desaServices.getConfigurations();
AuthenticateUserResponse authorizedUser = null;
for (DesaConfiguration desConf : configurations) {
if (authorizedUser != null && Boolean.getBoolean("desa.oneAuthIsEnough")) {
break;
}
DesaClient client = desaServices.getDesaClient(desConf);
AuthenticateUserResponse desaUser = client.authenticateUser(tUser, tPass, code);
if (desaUser == null) {
return null;
}
if (isAuthorized(desaUser)) {
authorizedUser = desaUser;
}
}
if (authorizedUser != null) {
return createLocalUser(authorizedUser, tUser, code);
}
} catch (AppConfigurationException e) {
LOGGER.log(Level.SEVERE,e.getMessage(),e);
throw new IllegalStateException("Cannot initialize configuration! See server log.");
} catch (AuthenticateUserFault e) {
LOGGER.log(Level.FINE, e.getMessage(), e);
}
return null;
}
private UserProfile createLocalUser(AuthenticateUserResponse desaUser, String desaUserName, String producerCode) {
UserManager userManger = UserUtil.getDefaultManger();
Group remoteGroup = userManger.findRemoteGroup(producerCode, REMOTE_TYPE);
if (remoteGroup == null) {
remoteGroup = Group.createRemote(
UserUtil.toUserName(USER_PREFIX, producerCode),
"DESA " + producerCode,
producerCode, REMOTE_TYPE);
userManger.addGroup(remoteGroup, Arrays.asList(Permissions.REPO_SEARCH_GROUPOWNER),
"proarc", "Add remote DESA group.");
}
UserProfile proarcUser = userManger.find(desaUserName, REMOTE_TYPE);
if (proarcUser == null) {
String surname = isNullString(desaUser.getSurname()) ? desaUserName : desaUser.getSurname();
proarcUser = UserProfile.createRemote(desaUserName, REMOTE_TYPE, surname);
proarcUser.setUserName(UserUtil.toUserName(USER_PREFIX, desaUserName));
proarcUser.setEmail(desaUser.getEmail());
proarcUser.setForename(desaUser.getName());
// set default ownership
proarcUser.setDefaultGroup(remoteGroup.getId());
userManger.add(proarcUser, Arrays.asList(remoteGroup), "proarc", "Add remote DESA user.");
}
return proarcUser;
}
boolean isAuthorized(AuthenticateUserResponse desaUser) {
if (desaUser != null && desaUser.getRoles() != null) {
for (Role role : desaUser.getRoles().getItem()) {
if (ROLE.equals(role.getRoleAcr())) {
return true;
}
}
}
return false;
}
@Override
public AuthenticatedState authenticate(Map<String, String> loginProperties,
HttpServletRequest request, HttpServletResponse response,
ProarcPrincipal principal) {
String user = loginProperties.get(LOGINNAME);
String pswd = loginProperties.get(PASSWORD);
String kod = loginProperties.get(KOD_PUVODCE);
if (isNullString(kod)) return AuthenticatedState.IGNORED;
if (isNullString(user) || isNullString(pswd)) {
return AuthenticatedState.FORBIDDEN;
}
UserProfile authenticated = authenticateDesaUser(user, pswd, kod);
if (authenticated != null) {
principal.associateUserProfile(authenticated);
}
return authenticated != null ? AuthenticatedState.AUTHENTICATED : AuthenticatedState.FORBIDDEN;
}
boolean isNullString(String str) {
return str == null || str.trim().equals("");
}
}