/* * Copyright (C) 2007 - 2012 GeoSolutions S.A.S. * http://www.geo-solutions.it * * GPLv3 + Classpath exception * * 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 it.geosolutions.geostore.init; import it.geosolutions.geostore.core.model.Category; import it.geosolutions.geostore.core.model.User; import it.geosolutions.geostore.core.model.UserGroup; import it.geosolutions.geostore.core.security.password.GeoStoreAESEncoder; import it.geosolutions.geostore.core.security.password.GeoStorePasswordEncoder; import it.geosolutions.geostore.core.security.password.PwEncoder; import it.geosolutions.geostore.init.model.InitUserList; import it.geosolutions.geostore.services.CategoryService; import it.geosolutions.geostore.services.UserGroupService; import it.geosolutions.geostore.services.UserService; import it.geosolutions.geostore.services.exception.BadRequestServiceEx; import it.geosolutions.geostore.services.exception.NotFoundServiceEx; import it.geosolutions.geostore.services.exception.ReservedUserGroupNameEx; import it.geosolutions.geostore.services.rest.model.CategoryList; import it.geosolutions.geostore.services.rest.model.RESTUserGroup; import it.geosolutions.geostore.services.rest.model.UserGroupList; import it.geosolutions.geostore.services.rest.utils.GeoStoreJAXBContext; import java.io.File; import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import org.apache.log4j.Logger; import org.springframework.beans.factory.InitializingBean; /** * * @author ETj (etj at geo-solutions.it) */ public class GeoStoreInit implements InitializingBean { private final static Logger LOGGER = Logger.getLogger(GeoStoreInit.class); protected UserService userService; protected CategoryService categoryService; protected UserGroupService userGroupService; protected File userListInitFile = null; protected File categoryListInitFile = null; protected File userGroupListInitFile = null; /** * The password encoder to be set as default */ protected GeoStorePasswordEncoder passwordEncoder = null; /** * If set to true, the recoding of the password is automatic */ protected boolean allowPasswordRecoding = false; @Override public void afterPropertiesSet() throws Exception { LOGGER.info("===== Starting GeoStore services ====="); //initialize password encoding initPasswordEncoding(); long catCnt = categoryService.getCount(null); if (catCnt == 0) { LOGGER.warn("No category found."); if (categoryListInitFile != null) { LOGGER.warn("Initializing categories from file " + categoryListInitFile); initCategories(categoryListInitFile); } else { LOGGER.info("No category initializer defined."); } } else { LOGGER.info("Categories already in db: " + catCnt); } long userGroupCnt = userGroupService.getAll(null, null).size(); if (userGroupCnt == 0) { LOGGER.warn("No usersgroup found."); if (userGroupListInitFile != null) { LOGGER.warn("Initializing users from file " + userGroupListInitFile); initUsersGroup(userGroupListInitFile); } else { LOGGER.info("No usersgroup initializer defined."); } } else { LOGGER.info("UsersGroup already in db: " + userGroupCnt); } long userCnt = userService.getCount(null); if (userCnt == 0) { LOGGER.warn("No user found."); if (userListInitFile != null) { LOGGER.warn("Initializing users from file " + userListInitFile); initUsers(userListInitFile); } else { LOGGER.info("No user initializer defined."); } } else { LOGGER.info("Users already in db: " + userCnt); } } private void initPasswordEncoding(){ LOGGER.info("=== Set up the security system ===="); LOGGER.info("Encoding Type:" + passwordEncoder.getEncodingType()); PwEncoder.setEncoder(this.passwordEncoder); //check and convert passwords try { List<User> users = userService.getAll(0, 1); if(users != null && users.size()>0){ //check password encription of the first user availabe boolean responsible = this.passwordEncoder.isResponsibleForEncoding(users.get(0).getPassword()); //if the current password encoder is the responsible for the encoding of the password //we suppose the conversion is already happended if(responsible) return; LOGGER.warn("======================================================================================="); LOGGER.warn(" WARNING: USERS PASSWORDS ARE NOT SYNCRONIZED WITH THE CONFIGURED PASSWORD ENCODER "); LOGGER.warn("======================================================================================="); //check if the password is old legacy, so GeoStoreAESEncoder is the responsible for the encoding GeoStoreAESEncoder e = new GeoStoreAESEncoder(); boolean isLegacy = e.isResponsibleForEncoding(users.get(0).getPassword()); if(isLegacy){ if (!allowPasswordRecoding){ LOGGER.warn("To convert old passwords to new ones use geostoreInitializer.allowPasswordRecoding=true"); return; } LOGGER.info("Starting password conversion..."); for(User u : userService.getAll(null, null)){ String p = u.getPassword(); if (e.isResponsibleForEncoding(p)){ String dec = e.decode(p); String enc = this.passwordEncoder.encodePassword(dec.toCharArray(), null); u.setPassword(enc); try { userService.update(u); LOGGER.info("UPDATED USER PASSWORD for the user:"+u.getName()); } catch (NotFoundServiceEx e1) { LOGGER.error("===> ERROR updating user password for user" + u.getName() ); } } } LOGGER.info("Password conversion finished!"); } } } catch (BadRequestServiceEx e) { //error getting users is not a problem at this stage. //e.printStackTrace(); } } private void initCategories(File file) { try { JAXBContext context = GeoStoreJAXBContext.getContext(); CategoryList list = (CategoryList) context.createUnmarshaller().unmarshal(file); for (Category item : list.getList()) { LOGGER.info("Adding category " + item); categoryService.insert(item); } } catch (JAXBException ex) { throw new RuntimeException("Error reading categories init file " + file, ex); } catch (Exception e) { LOGGER.error("Error while initting categories. Rolling back.", e); List<Category> removeList; try { removeList = categoryService.getAll(null, null); } catch (BadRequestServiceEx ex) { throw new RuntimeException( "Error while rolling back categories initialization. Your DB may now contain an incomplete category list. Please check manually.", e); } for (Category cat : removeList) { categoryService.delete(cat.getId()); } throw new RuntimeException("Error while initting categories."); } } private void initUsers(File file) { try { userService.insertSpecialUsers(); JAXBContext context = getUserContext(); InitUserList list = (InitUserList) context.createUnmarshaller().unmarshal(file); for (User user : list.getList()) { LOGGER.info("Adding user " + user); userService.insert(user); } } catch (JAXBException ex) { throw new RuntimeException("Error reading users init file " + file, ex); } catch (Exception e) { LOGGER.error("Error while initting users. Rolling back.", e); List<User> removeList; try { removeList = userService.getAll(null, null); } catch (BadRequestServiceEx ex) { throw new RuntimeException( "Error while rolling back user initialization. Your DB may now contain an incomplete user list. Please check manually.", e); } for (User user : removeList) { userService.delete(user.getId()); } throw new RuntimeException("Error while initting users."); } } private void initUsersGroup(File file) throws NotFoundServiceEx, BadRequestServiceEx { try { userGroupService.insertSpecialUsersGroups(); JAXBContext context = GeoStoreJAXBContext.getContext(); UserGroupList list = (UserGroupList) context.createUnmarshaller().unmarshal(file); for (RESTUserGroup userGroup : list.getUserGroupList()) { LOGGER.info("Adding user group " + userGroup); UserGroup ug = new UserGroup(); ug.setGroupName(userGroup.getGroupName()); ug.setDescription(userGroup.getDescription()); try{ userGroupService.insert(ug); } catch(ReservedUserGroupNameEx e){ // If a reserved username is in the init usergroup file log the exception and skip this insertion LOGGER.warn(e.getMessage()); } } } catch (JAXBException ex) { throw new RuntimeException("Error reading usersgroup init file " + file, ex); } catch (Exception e) { LOGGER.error("Error while initting usersgroups. Rolling back.", e); List<UserGroup> removeList; try { removeList = userGroupService.getAll(null, null); } catch (BadRequestServiceEx ex) { throw new RuntimeException( "Error while rolling back usergroup initialization. Your DB may now contain an incomplete usergroup list. Please check manually.", e); } for (UserGroup ug : removeList) { userGroupService.delete(ug.getId()); } throw new RuntimeException("Error while initting usersgroup."); } } private static JAXBContext getUserContext() { List<Class> allClasses = GeoStoreJAXBContext.getGeoStoreClasses(); allClasses.add(InitUserList.class); if (LOGGER.isDebugEnabled()) LOGGER.debug("Initializing JAXBContext with " + allClasses.size() + " classes " + allClasses); try { return JAXBContext.newInstance(allClasses.toArray(new Class[allClasses.size()])); } catch (JAXBException ex) { LOGGER.error("Can't create GeoStore context: " + ex.getMessage(), ex); return null; } } // ========================================================================== public void setUserListInitFile(File userListInitFile) { this.userListInitFile = userListInitFile; } public void setCategoryListInitFile(File categoryListInitFile) { this.categoryListInitFile = categoryListInitFile; } public void setUserGroupListInitFile(File userGroupListInitFile) { this.userGroupListInitFile = userGroupListInitFile; } // ========================================================================== public void setCategoryService(CategoryService categoryService) { this.categoryService = categoryService; } public void setUserService(UserService userService) { this.userService = userService; } public void setUserGroupService(UserGroupService userGroupService) { this.userGroupService = userGroupService; } // ========================================================================== public GeoStorePasswordEncoder getPasswordEncoder() { return passwordEncoder; } public void setPasswordEncoder(GeoStorePasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } // =========================================================================== public boolean isAllowPasswordRecoding() { return allowPasswordRecoding; } public void setAllowPasswordRecoding(boolean allowPasswordRecoding) { this.allowPasswordRecoding = allowPasswordRecoding; } }