1 /*******************************************************************************
2 * Copyright � Igor Barma, Alexandre Desoubeaux, Christian Martel, Eric Brun, Mathieu Amblard, Gwenael Gevet, Pierre Guillot, 2012
3 * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Alexandre Lefevre, Marc Salvat 2014-2016
4 * Copyright Alexandre Desoubeaux, Christian Martel, Cedric Lecarpentier, Marc Salvat, Marc Suarez, Harifetra Ramamonjy 2017
6 * This file is part of the work and learning management system Pentila Nero.
8 * Pentila Nero is free software. You can redistribute it and/or modify since
9 * you respect the terms of either (at least one of the both license) :
10 * - under the terms of the GNU Affero General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 * - the CeCILL-C as published by CeCILL-C; either version 1 of the
14 * License, or any later version
15 * - the GNU Lesser General Public License as published by the
16 * Free Software Foundation, either version 3 of the license,
17 * or (at your option) any later version.
19 * There are special exceptions to the terms and conditions of the
20 * licenses as they are applied to this software. View the full text of
21 * the exception in file LICENSE-PROJECT.txt in the directory of this software
24 * Pentila Nero is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * Licenses for more details.
29 * You should have received a copy of the GNU Affero General Public License
30 * and the CeCILL-C and the GNU Lesser General Public License along with
31 * Pentila Nero. If not, see :
32 * <http://www.gnu.org/licenses/> and
33 * <http://www.cecill.info/licences.fr.html>.
34 ******************************************************************************/
35 package com.pentila.entSavoie.listeners;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
40 import javax.naming.NamingException;
41 import javax.naming.directory.Attribute;
42 import javax.naming.directory.Attributes;
43 import javax.naming.ldap.LdapContext;
45 import com.liferay.portal.ModelListenerException;
46 import com.liferay.portal.kernel.exception.PortalException;
47 import com.liferay.portal.kernel.exception.SystemException;
48 import com.liferay.portal.kernel.log.Log;
49 import com.liferay.portal.kernel.log.LogFactoryUtil;
50 import com.liferay.portal.kernel.util.PrefsPropsUtil;
51 import com.liferay.portal.model.ModelListener;
52 import com.liferay.portal.model.Organization;
53 import com.liferay.portal.model.OrganizationConstants;
54 import com.liferay.portal.model.Role;
55 import com.liferay.portal.model.RoleConstants;
56 import com.liferay.portal.model.User;
57 import com.liferay.portal.model.UserGroup;
58 import com.liferay.portal.security.ldap.PortalLDAPUtil;
59 import com.liferay.portal.service.OrganizationLocalServiceUtil;
60 import com.liferay.portal.service.RoleLocalServiceUtil;
61 import com.liferay.portal.service.UserGroupLocalServiceUtil;
62 import com.liferay.portal.service.UserGroupRoleLocalServiceUtil;
63 import com.liferay.portal.service.UserLocalServiceUtil;
64 import com.pentila.entSavoie.ENTRolesConstants;
65 import com.pentila.entSavoie.directory.OrganizationFinderServiceUtil;
66 import com.pentila.entSavoie.utils.ENTCacheUtils;
67 import com.pentila.entSavoie.utils.ENTMainUtilsLocalServiceUtil;
68 import com.pentila.entSavoie.utils.ENTOrganizationsUtil;
71 * @author Lancelot SIX
73 * Cette classe est utilisée pour monitorer les evenements sur les UserGroup.
74 * Ces groupes sont ceux qui sont importés du LDAP. Ainsi, nous pouvons
75 * dupliquer les changements de ces groupes vers les Organizations (groupes
76 * institutionnels du Liferay).
79 public class UserGroupListener implements ModelListener<UserGroup> {
81 public void onAfterAddAssociation(Object arg0, String arg1, Object arg2)
82 throws ModelListenerException {
83 //Quand un utilisateur est ajout� dans un UserGroup, on l'ajoute dans
84 //les organizations correspondantes ainsi que dans les organizations
85 //parentes de celle-ci.
87 final UserGroup gr = UserGroupLocalServiceUtil.getUserGroup(
88 ((Long)arg0).longValue());
89 final User u = UserLocalServiceUtil.getUser(
90 ((Long) arg2).longValue());
92 if (gr.getName().toLowerCase().contains("groupAccessReport".toLowerCase())) {
96 if (isEntLdapObject(gr)) {
97 long currOrgId = OrganizationLocalServiceUtil.getOrganization(
98 gr.getCompanyId(), getOrgName(gr)).getOrganizationId();
101 OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
102 final Organization currOrg = OrganizationLocalServiceUtil.
103 getOrganization(currOrgId);
105 //add the user into all the orgs and parent orgs
106 if (!OrganizationLocalServiceUtil.hasUserOrganization(
107 u.getUserId(), currOrgId, false, true)) {
108 if (_log.isDebugEnabled()) {
109 _log.debug("Adding user "+u.getScreenName()+" to organization "+currOrg.getName());
111 long[] users = new long[1]; users[0] = u.getUserId();
112 UserLocalServiceUtil.addOrganizationUsers(currOrgId,
117 currOrgId = currOrg.getParentOrganizationId();
120 } catch (Exception e) {
121 if (_log.isDebugEnabled()) {
127 public void onAfterCreate(UserGroup gr) throws ModelListenerException {
129 //A la création d'un UserGroup, on crée si necessaire une Organization
132 if (isEntLdapObject(gr)) {
133 //recupere le groupe de l'etab parent (et le cree s'il n'exite
136 Organization college = ENTOrganizationsUtil.getOrCreateSchool(gr.getCompanyId(), getEtabName(gr));
138 //cree l'org correspondant au userGroup ainsi qu'aux parents
139 ENTOrganizationsUtil.getOrCreateOrganization(gr.getCompanyId(), getOrgName(gr), college.getOrganizationId());
140 if (ENTMainUtilsLocalServiceUtil.getEntSchoolImportType(gr.getCompanyId())) {
141 ENTOrganizationsUtil.getOrCreateOrganization(gr.getCompanyId(), getOrgName(gr)+" - Parents", college.getOrganizationId());
144 } catch (Exception e) {
145 if (_log.isErrorEnabled()) {
151 public void onAfterRemove(UserGroup arg0) throws ModelListenerException {}
153 public void onAfterRemoveAssociation(Object arg0, String arg1, Object arg2)
154 throws ModelListenerException {}
156 public void onAfterUpdate(UserGroup arg0) throws ModelListenerException {}
158 public void onBeforeAddAssociation(Object arg0, String arg1, Object arg2)
159 throws ModelListenerException {}
161 public void onBeforeCreate(UserGroup gr) throws ModelListenerException {}
163 public void onBeforeRemove(UserGroup arg0) throws ModelListenerException {}
167 * @see com.liferay.portal.model.ModelListener#onBeforeRemoveAssociation(java.lang.Object, java.lang.String, java.lang.Object)
169 * Vas retirer l'utilisateur de l'organization associ�e.
172 public void onBeforeRemoveAssociation(Object arg0, String arg1, Object arg2)
173 throws ModelListenerException {
175 // Retire egalement l'user de l'organization correspondante.
176 final UserGroup gr = UserGroupLocalServiceUtil.getUserGroup(
177 ((Long)arg0).longValue());
178 final User u = UserLocalServiceUtil.getUser(
179 ((Long) arg2).longValue());
180 //verifie que l'user n'est plus dans le group
181 if (isEntLdapObject(gr)) {
182 long currOrgId = OrganizationLocalServiceUtil.getOrganization(
183 gr.getCompanyId(), getOrgName(gr)).getOrganizationId();
185 //Retire l'user quoi qu'il arrive du groupe correspondant au usergroupe d'appel
186 removeUserFromOrganization(currOrgId, u);
188 //Retire l'user de toutes les organisations suivantes:
189 // - celles dont l'utilisateur n'est plus dans les sous-organisations si et ssi
190 // - l'org n'est pas cartable de savoie
191 // - l'org n'est pas celle de ratachement
192 final long cartSavoieId = ENTOrganizationsUtil.getOrCreateRootOrg(u.getCompanyId()).getOrganizationId();
193 final long etabRatachementId = OrganizationFinderServiceUtil.getEtabRatachement(u).getOrganizationId();
195 while (currOrgId != cartSavoieId && currOrgId != etabRatachementId &&
196 currOrgId != OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
197 final Organization currOrg = OrganizationLocalServiceUtil.getOrganization(currOrgId);
199 //Retire l'user s'il ne fait plus parti
200 if (!OrganizationLocalServiceUtil.hasUserOrganization(
201 u.getUserId(), currOrgId, true, true)) {
202 removeUserFromOrganization(currOrgId, u);
205 currOrgId = currOrg.getParentOrganizationId();
208 } catch (Exception e) {
209 if (_log.isDebugEnabled()) {
215 public void onBeforeUpdate(UserGroup arg0) throws ModelListenerException {}
218 private boolean isEntLdapObject(UserGroup gr) throws Exception {
220 String cacheKey="UserGroupCache_"+gr.getUserGroupId();
222 // Get value from cache instance
223 Boolean cacheBool= (Boolean) ENTCacheUtils.getObjectFromCache(cacheKey);
225 // On regarde si le cache est null ou non
227 //if misscache, set new value to variable
229 cacheBool= isEntClass(gr) || isEntGroupe(gr);
230 } catch (Exception e) {
233 ENTCacheUtils.storeObjectIntoCache(cacheKey,cacheBool,-1);
236 //could find and get value from cache instance
242 private boolean isEntClass(UserGroup gr) throws Exception {
243 LdapContext ct = getLdapContext(gr);
246 Attributes attrs = ct.getAttributes("cn="+gr.getName()+
247 ",ou=groups,"+PrefsPropsUtil.getString(gr.getCompanyId(),
249 Attribute cl = attrs.get("objectClass");
250 for (int i=0; i<cl.size(); i++) {
251 if (cl.get(i).equals("ENTClasse"))
254 } catch (NamingException e) {
255 //en cas d'erreur, considere que ce n'est pas une classe.
262 private boolean isEntGroupe(UserGroup gr) throws Exception {
263 LdapContext ct = getLdapContext(gr);
266 Attributes attrs = ct.getAttributes("cn="+gr.getName()+
267 ",ou=groups,"+PrefsPropsUtil.getString(gr.getCompanyId(),
269 Attribute cl = attrs.get("objectClass");
270 for (int i=0; i<cl.size(); i++) {
271 if (cl.get(i).equals("ENTGroupe"))
274 } catch (NamingException e) {
275 //en cas d'erreur, considere que ce n'est pas une classe.
282 private String getOrgName(UserGroup gr) {
283 String initName = gr.getName();
284 String retName = initName;
285 Pattern classPattern = Pattern.compile("^[0-9]+\\$");
286 Matcher classMatcher = classPattern.matcher(initName);
287 if (classMatcher.find()) {
288 //Le nom correspond au nom d'une classe ou d'un gr d'user dans le
290 retName = getEtabName(gr)+" - "+initName.substring(classMatcher.end());
295 private String getEtabName(UserGroup gr) {
296 String initName = gr.getName();
297 String cacheName = null;
300 Pattern classPattern = Pattern.compile("^[0-9]+\\$");
301 Matcher classMatcher = classPattern.matcher(initName);
302 if (classMatcher.find()) {
303 //Le nom correspond au nom d'une classe ou d'un gr d'user dans le
305 String retName = initName.substring(classMatcher.start(),
306 classMatcher.end()-1);
309 //key for user group etab name
310 String cacheKey="UG_ENCache_"+gr.getUserGroupId();
312 // Get value from cache instance
313 cacheName = (String) ENTCacheUtils.getObjectFromCache(cacheKey);
314 // On regarde si le cache est null ou non
316 //if misscache, set new value to variable
318 LdapContext ct = getLdapContext(gr);
319 Attributes attrs = ct.getAttributes("ou="+retName+
320 ",ou=etablissements,"+
321 PrefsPropsUtil.getString(gr.getCompanyId(),
323 cacheName = attrs.get("ENTStructureNomCourant").get(0).toString();
325 // si classic --> ENTStructureNomCourant
326 // si full --> ENTStructureNomCourant + l + RNE
327 String etabNameType = ENTMainUtilsLocalServiceUtil.getENTSynchroEtabName(gr.getCompanyId());
328 if (etabNameType.equals("full")) {
329 if (attrs.get("l")!=null) {
330 cacheName += " - " + attrs.get(
331 "l").get().toString();
333 if (attrs.get("ENTStructureUAI")!=null) {
334 cacheName += " - " + attrs.get(
335 "ENTStructureUAI").get().toString();
340 } catch (Exception e) {
341 //e.printStackTrace();
343 ENTCacheUtils.storeObjectIntoCache(cacheKey,cacheName,-1);
346 //could find and get value from cache instance
349 } catch (Exception e) {
350 //if (_log.isErrorEnabled()) {
357 private LdapContext getLdapContext(UserGroup gr) throws Exception {
359 ctx = PortalLDAPUtil.getContext(gr.getCompanyId());
364 private void manageManager(User user) {
366 if (RoleLocalServiceUtil.hasUserRole(user.getUserId(), user.getCompanyId(), ENTRolesConstants.NATIONAL_4, true)) {
367 Organization coll = OrganizationFinderServiceUtil.getEtabRatachement(user);
369 //met l'user dans l'organization
370 UserLocalServiceUtil.addOrganizationUsers(coll.getOrganizationId(), new long[]{user.getUserId()});
372 Role adminRole = RoleLocalServiceUtil.getRole(user.getCompanyId(), RoleConstants.ORGANIZATION_ADMINISTRATOR);
373 UserGroupRoleLocalServiceUtil.addUserGroupRoles(user.getUserId(), coll.getGroup().getGroupId(), new long[]{adminRole.getRoleId()});
375 if (_log.isDebugEnabled()) {
376 _log.debug("The user "+user.getScreenName()+" is now admin of "+coll.getName());
380 } catch (Exception e) {
381 if (_log.isErrorEnabled()) {
387 private void removeUserFromOrganization(final long organizationId, final User user) throws PortalException, SystemException {
388 UserLocalServiceUtil.unsetOrganizationUsers(organizationId, new long[]{user.getUserId()});
389 if (_log.isDebugEnabled()) {
390 final String userName = user.getScreenName();
391 _log.debug("Removed user " + userName + " from an organization");
395 private LdapContext ctx = null;
396 private Log _log = LogFactoryUtil.getLog(this.getClass());