/** * Koya is an alfresco module that provides a corporate orientated dataroom. * * Copyright (C) Itl Developpement 2014 * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero 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 Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see `<http://www.gnu.org/licenses/>`. */ package fr.itldev.koya.alfservice; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.service.cmr.invitation.InvitationService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.site.SiteService; import org.alfresco.util.PropertyMap; import org.apache.log4j.Logger; import org.mybatis.spring.SqlSessionTemplate; import fr.itldev.koya.exception.KoyaServiceException; import fr.itldev.koya.model.KoyaModel; import fr.itldev.koya.model.exceptions.KoyaErrorCodes; import fr.itldev.koya.model.impl.User; import fr.itldev.koya.model.impl.UserConnection; import fr.itldev.koya.repo.security.authentication.UserMailEntity; /** * */ public class UserService { private final Logger logger = Logger.getLogger(this.getClass()); protected NodeService nodeService; protected PersonService personService; protected SearchService searchService; protected MutableAuthenticationService authenticationService; protected SiteService siteService; protected InvitationService invitationService; protected KoyaNodeService koyaNodeService; protected SqlSessionTemplate template; // <editor-fold defaultstate="collapsed" desc="getters/setters"> public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } public void setPersonService(PersonService personService) { this.personService = personService; } public void setSearchService(SearchService searchService) { this.searchService = searchService; } public void setAuthenticationService(MutableAuthenticationService authenticationService) { this.authenticationService = authenticationService; } public void setSiteService(SiteService siteService) { this.siteService = siteService; } public void setInvitationService(InvitationService invitationService) { this.invitationService = invitationService; } public void setKoyaNodeService(KoyaNodeService koyaNodeService) { this.koyaNodeService = koyaNodeService; } public void setTemplate(SqlSessionTemplate template) { this.template = template; } // </editor-fold> /** * User creation method. * * @param userToCreate * @throws fr.itldev.koya.exception.KoyaServiceException */ public void createUser(User userToCreate) throws KoyaServiceException { PropertyMap propsUser = new PropertyMap(); propsUser.put(ContentModel.PROP_USERNAME, userToCreate.getUserName()); propsUser.put(ContentModel.PROP_FIRSTNAME, userToCreate.getFirstName()); propsUser.put(ContentModel.PROP_LASTNAME, userToCreate.getName()); propsUser.put(ContentModel.PROP_EMAIL, userToCreate.getEmail()); if (!personService.personExists(userToCreate.getUserName())) { authenticationService.createAuthentication(userToCreate.getUserName(), userToCreate.getPassword().toCharArray()); personService.createPerson(propsUser); NodeRef userNr = personService.getPerson(userToCreate.getUserName()); nodeService.addAspect(userNr, KoyaModel.ASPECT_CIVILTITLED, null); nodeService.setProperty(userNr, KoyaModel.PROP_CIVILTITLE, userToCreate.getCivilTitle()); } else { throw new KoyaServiceException(KoyaErrorCodes.LOGIN_ALREADY_EXISTS); } } /** * Modify user fields according to user object. * * @param userToModify * @throws KoyaServiceException */ public void modifyUser(User userToModify) throws KoyaServiceException { // TODO check who request user modification : user can only modify his // own information // admin can modify everyone informations if (personService.personExists(userToModify.getUserName())) { NodeRef userNr = personService.getPerson(userToModify.getUserName()); // update 4 fields : firstname,lastname,email,emailFeedDisabled nodeService.setProperty(userNr, ContentModel.PROP_FIRSTNAME, userToModify.getFirstName()); nodeService.setProperty(userNr, ContentModel.PROP_LASTNAME, userToModify.getName()); nodeService.setProperty(userNr, ContentModel.PROP_EMAIL, userToModify.getEmail()); nodeService.setProperty(userNr, ContentModel.PROP_EMAIL_FEED_DISABLED, userToModify.getEmailFeedDisabled()); if (!nodeService.hasAspect(userNr, KoyaModel.ASPECT_CIVILTITLED)) { nodeService.addAspect(userNr, KoyaModel.ASPECT_CIVILTITLED, null); } nodeService.setProperty(userNr, KoyaModel.PROP_CIVILTITLE, userToModify.getCivilTitle()); // TODO change password if necessary + uncrypted password // nodeService.setProperty(userNr, ContentModel.PROP_PASSWORD, // userToModify.getPassword()); } else { throw new KoyaServiceException(KoyaErrorCodes.UNKNOWN_USER); } } /** * Change users password * * @param oldPassword * @param newPassword * @throws fr.itldev.koya.exception.KoyaServiceException */ public void changePassword(String oldPassword, String newPassword) throws KoyaServiceException { try { authenticationService.updateAuthentication(authenticationService.getCurrentUserName(), oldPassword.toCharArray(), newPassword.toCharArray()); } catch (AuthenticationException aex) { throw new KoyaServiceException(KoyaErrorCodes.CANT_MODIFY_USER_PASSWORD); } } /** * Admin force Change users password * * @param oldPassword * @param newPassword * @throws fr.itldev.koya.exception.KoyaServiceException */ public void adminForceChangePassword(String userName, String newPassword) throws KoyaServiceException { try { authenticationService.setAuthentication(userName, newPassword.toCharArray()); } catch (AuthenticationException aex) { throw new KoyaServiceException(KoyaErrorCodes.CANT_MODIFY_USER_PASSWORD); } } /** * return users list that matches query . email, lastname or first name * starts with query String. * * * * @param queryStartsWith * @param maxResults * - 0 = no limit * @param companyName * @param companyRolesFilter * @return */ public List<User> find(String queryStartsWith, int maxResults, String companyName, List<String> companyRolesFilter) { List<User> users = new ArrayList<>(); if (queryStartsWith == null) { queryStartsWith = ""; } queryStartsWith = queryStartsWith.toLowerCase(); // application global search if (companyName == null || companyName.isEmpty()) { String luceneRequest = "TYPE:\"cm:person\" AND (@cm\\:lastName:\"" + queryStartsWith + "*\" OR @cm\\:firstName:\"" + queryStartsWith + "*\" OR @cm\\:email:\"" + queryStartsWith + "*\" )"; logger.trace(luceneRequest); ResultSet rs = null; try { rs = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_LUCENE, luceneRequest); for (ResultSetRow r : rs) { users.add(buildUser(r.getNodeRef())); if (users.size() >= maxResults) { break; } } } finally { if (rs != null) { rs.close(); } } } else { // TODO apply user filter Map<String, String> companyMembers = new HashMap<>(); if (companyRolesFilter != null && companyRolesFilter.size() > 0) { for (String role : companyRolesFilter) { companyMembers .putAll(siteService.listMembers(companyName, null, role, 0, true)); } } else { companyMembers.putAll(siteService.listMembers(companyName, null, null, 0, true)); } for (String userName : companyMembers.keySet()) { // remove from results where query is not name|firstname|email // substring // ---> prevent display changed mail adress (username not // changed ) User u = buildUser(personService.getPerson(userName)); if (u.getName().toLowerCase().startsWith(queryStartsWith) || u.getFirstName().toLowerCase().startsWith(queryStartsWith) || u.getEmail().toLowerCase().startsWith(queryStartsWith)) { users.add(buildUser(personService.getPerson(userName))); } if (users.size() >= maxResults) { break; } } } logger.trace(users.size() + " results found"); return users; } public User buildUser(NodeRef userNodeRef) { User u = new User(); // TODO complete build with all properties u.setUserName((String) nodeService.getProperty(userNodeRef, ContentModel.PROP_USERNAME)); u.setFirstName((String) nodeService.getProperty(userNodeRef, ContentModel.PROP_FIRSTNAME)); u.setName((String) nodeService.getProperty(userNodeRef, ContentModel.PROP_LASTNAME)); u.setEmail((String) nodeService.getProperty(userNodeRef, ContentModel.PROP_EMAIL)); u.setEmailFeedDisabled((Boolean) nodeService.getProperty(userNodeRef, ContentModel.PROP_EMAIL_FEED_DISABLED)); u.setEnabled( !(Boolean) nodeService.hasAspect(userNodeRef, ContentModel.ASPECT_PERSON_DISABLED)); u.setNodeRef(userNodeRef); u.setCivilTitle((String) nodeService.getProperty(userNodeRef, KoyaModel.PROP_CIVILTITLE)); return u; } public User getUserByUsername(final String username) { if (personService.personExists(username)) { return buildUser(personService.getPerson(username)); } else { return null; } } /** * Execute db query to get unique username from given email * * @param email * @return * @throws KoyaServiceException */ public User getUserByEmail(final String email) throws KoyaServiceException { UserMailEntity ume = new UserMailEntity(); ume.setMail(email); ume.setMailPropName("email"); ume.setMailPropUri("http://www.alfresco.org/model/content/1.0"); ume.setUserNamePropName("userName"); ume.setUserNamePropUri("http://www.alfresco.org/model/content/1.0"); List<UserMailEntity> users = (List<UserMailEntity>) template .selectList("koya.mailtousername.select_username", ume); if (users.isEmpty()) { throw new KoyaServiceException(KoyaErrorCodes.NO_SUCH_USER_IDENTIFIED_BY_AUTHKEY, email); } else if (users.size() > 1) { throw new KoyaServiceException(KoyaErrorCodes.MANY_USERS_IDENTIFIED_BY_AUTHKEY, email); } else { UserMailEntity un = users.get(0); User u = buildUser(personService.getPerson(users.get(0).getUserName())); return u; } } public List<UserConnection> getConnectionLog(String userName, List<String> companyFilter, Integer maxResults) { List<UserConnection> connectionLog = new ArrayList<>(); // TODO build full connection log return connectionLog; } /** * Checks if user has disabled aspect * * @param u * @return */ public Boolean isDisabled(User u) { return nodeService.getAspects(u.getNodeRef()).contains(ContentModel.ASPECT_PERSON_DISABLED); } }