View Javadoc
1   /**
2    * Copyright 2018 Internet2
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package edu.internet2.middleware.grouper.app.deprovisioning;
18  
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.Set;
23  
24  import org.apache.commons.lang3.StringUtils;
25  import org.apache.commons.logging.Log;
26  import org.quartz.DisallowConcurrentExecution;
27  
28  import edu.internet2.middleware.grouper.Group;
29  import edu.internet2.middleware.grouper.GroupFinder;
30  import edu.internet2.middleware.grouper.GrouperSession;
31  import edu.internet2.middleware.grouper.Member;
32  import edu.internet2.middleware.grouper.Stem;
33  import edu.internet2.middleware.grouper.Stem.Scope;
34  import edu.internet2.middleware.grouper.StemFinder;
35  import edu.internet2.middleware.grouper.app.loader.GrouperLoaderStatus;
36  import edu.internet2.middleware.grouper.app.loader.GrouperLoaderType;
37  import edu.internet2.middleware.grouper.app.loader.OtherJobBase;
38  import edu.internet2.middleware.grouper.app.loader.db.Hib3GrouperLoaderLog;
39  import edu.internet2.middleware.grouper.attr.assign.AttributeAssign;
40  import edu.internet2.middleware.grouper.attr.assign.AttributeAssignType;
41  import edu.internet2.middleware.grouper.attr.assign.AttributeAssignable;
42  import edu.internet2.middleware.grouper.exception.GrouperSessionException;
43  import edu.internet2.middleware.grouper.misc.GrouperDAOFactory;
44  import edu.internet2.middleware.grouper.misc.GrouperSessionHandler;
45  import edu.internet2.middleware.grouper.util.EmailObject;
46  import edu.internet2.middleware.grouper.util.GrouperUtil;
47  
48  /**
49   * deprovisioning daemon
50   */
51  @DisallowConcurrentExecution
52  public class GrouperDeprovisioningJob extends OtherJobBase {
53    
54  
55  
56    /**
57     * group that users who are allowed to deprovision other users are in
58     * @param affiliation deprovi
59     * @return the group name
60     */
61    public static String retrieveDeprovisioningManagersMustBeInGroupName(String affiliation) {
62      
63      //  # e.g. managersWhoCanDeprovision_<affiliationName>
64      //  # e.g. usersWhoHaveBeenDeprovisioned_<affiliationName>
65      //  deprovisioning.systemFolder = $$grouper.rootStemForBuiltinObjects$$:deprovisioning
66      
67      return GrouperDeprovisioningSettings.deprovisioningStemName() + ":managersWhoCanDeprovision_" + affiliation;
68  
69    }
70  
71    /**
72     * group name which has been deprovisioned
73     * @param affiliation
74     * @return the group name
75     */
76    public static String retrieveGroupNameWhichHasBeenDeprovisioned(String affiliation) {
77      
78      //  # e.g. managersWhoCanDeprovision_<affiliationName>
79      //  # e.g. usersWhoHaveBeenDeprovisioned_<affiliationName>
80      //  deprovisioning.systemFolder = $$grouper.rootStemForBuiltinObjects$$:deprovisioning
81      
82      return GrouperDeprovisioningSettings.deprovisioningStemName() + ":usersWhoHaveBeenDeprovisioned_" + affiliation;
83    }
84  
85    /**
86     * run the daemon
87     * @param args
88     */
89    public static void main(String[] args) {
90      runDaemonStandalone();
91    }
92  
93    /**
94     * run standalone
95     */
96    public static void runDaemonStandalone() {
97      
98      GrouperSession grouperSession = GrouperSession.startRootSession();
99      Hib3GrouperLoaderLog3GrouperLoaderLog.html#Hib3GrouperLoaderLog">Hib3GrouperLoaderLog hib3GrouperLoaderLog = new Hib3GrouperLoaderLog();
100     
101     hib3GrouperLoaderLog.setHost(GrouperUtil.hostname());
102     String jobName = "OTHER_JOB_deprovisioningDaemon";
103 
104     hib3GrouperLoaderLog.setJobName(jobName);
105     hib3GrouperLoaderLog.setJobType(GrouperLoaderType.OTHER_JOB.name());
106     hib3GrouperLoaderLog.setStatus(GrouperLoaderStatus.STARTED.name());
107     hib3GrouperLoaderLog.store();
108     
109     OtherJobInput otherJobInput = new OtherJobInput();
110     otherJobInput.setJobName(jobName);
111     otherJobInput.setHib3GrouperLoaderLog(hib3GrouperLoaderLog);
112     otherJobInput.setGrouperSession(grouperSession);
113     new GrouperDeprovisioningJob().run(otherJobInput);
114   }
115 
116   /**
117    * get map of email addresses to email objects for stem attributes 
118    * @param attributeDef
119    * @return
120    */
121   private Map<String, Set<EmailObject>> buildDeprovisioningStemEmails() {
122   
123     //TODO only look at direct assignments?  are there duplicate assignments?
124     Set<AttributeAssign> attributeAssigns = GrouperDAOFactory.getFactory().getAttributeAssign().findAttributeAssignments(
125         AttributeAssignType.stem,
126         null, GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameBase().getId(), null, 
127         null, null, null, 
128         null, 
129         Boolean.TRUE, false);
130     
131     Map<String, Set<EmailObject>> emails = new HashMap<String, Set<EmailObject>>();
132     
133     for (AttributeAssign attributeAssign: attributeAssigns) {
134       
135       String deprovisioningSendEmail = attributeAssign.getAttributeValueDelegate().retrieveValueString(GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameSendEmail().getName());
136       
137 //      Map<String, Set<EmailObject>> localEmailMap = stemDeprovisioningProcessHelper(attributeAssign.getOwnerStem(), attributeAssign);
138 //
139 //      boolean sendEmailAttributeValue = GrouperUtil.booleanValue(deprovisioningSendEmail, true);
140 //      
141 //      // skip sending email for this attribute assign
142 //      if (!sendEmailAttributeValue) {
143 //        LOG.debug("For "+attributeAssign.getOwnerStem().getDisplayName()+" deprovisioningSendEmail attribute is not set to true so skipping sending email.");
144 //        continue;
145 //      }
146 //
147 //      if (sendEmailAttributeValue) {
148 //        mergeEmailObjects(emails, localEmailMap);
149 //      }
150     }
151     
152     return emails;
153     
154   }
155 
156   /**
157    * get the list of recently deprovisioned users
158    * @param affiliation 
159    * @return the list of members
160    */
161   public static Set<Member> retrieveRecentlyDeprovisionedUsers(final String affiliation) {
162     
163     //switch over to admin so attributes work
164     return (Set<Member>)GrouperSession.internal_callbackRootGrouperSession(new GrouperSessionHandler() {
165       
166       @Override
167       public Object callback(GrouperSession grouperSession) throws GrouperSessionException {
168         
169         Group deprovisionedGroup = GroupFinder.findByName(grouperSession, retrieveGroupNameWhichHasBeenDeprovisioned(affiliation), true);
170         
171         Set<Member> members = deprovisionedGroup.getMembers();
172         return members;
173       }
174     });
175 
176   }
177   
178   /**
179    * logger 
180    */
181   private static final Log LOG = GrouperUtil.getLog(GrouperDeprovisioningJob.class);
182   
183   /**
184    * @see edu.internet2.middleware.grouper.app.loader.OtherJobBase#run(edu.internet2.middleware.grouper.app.loader.OtherJobBase.OtherJobInput)
185    */
186   @Override
187   public OtherJobOutput run(OtherJobInput otherJobInput) {
188     GrouperSession grouperSession = GrouperSession.startRootSession();
189     
190     //update metadata
191     GrouperDeprovisioningLogic.updateDeprovisioningMetadata(StemFinder.findRootStem(grouperSession));
192     
193     GrouperDeprovisioningEmailServiceuperDeprovisioningEmailService.html#GrouperDeprovisioningEmailService">GrouperDeprovisioningEmailService emailService = new GrouperDeprovisioningEmailService();
194     emailService.sendEmailForAllAffiliations(otherJobInput.getGrouperSession());
195     return null;
196   }
197   
198   /**
199    * if this is in cache it means null and it is in cache
200    */
201   private static final AttributeAssign/AttributeAssign.html#AttributeAssign">AttributeAssign nullAttributeAssign = new AttributeAssign();
202   
203   /**
204    * 
205    * @param attributeAssignable
206    * @return the id
207    */
208   private static String retrieveAttributeAssignableId(AttributeAssignable attributeAssignable) {
209     if (attributeAssignable == null) {
210       return null;
211     }
212     if (attributeAssignable instanceof Group) {
213       return ((Group)attributeAssignable).getId();
214     }
215     if (attributeAssignable instanceof Stem) {
216       return ((Stem)attributeAssignable).getId();
217     }
218     throw new RuntimeException("Not expecting object type: " + attributeAssignable.getClass() + ", " + attributeAssignable);
219   }
220   
221   /**
222    * 
223    * @param attributeAssignable
224    * @return the id
225    */
226   private static Stem retrieveAttributeAssignableParentStem(AttributeAssignable attributeAssignable) {
227     if (attributeAssignable == null) {
228       return null;
229     }
230     if (attributeAssignable instanceof Group) {
231       return ((Group)attributeAssignable).getParentStem();
232     }
233     if (attributeAssignable instanceof Stem) {
234       return ((Stem)attributeAssignable).getParentStem();
235     }
236     throw new RuntimeException("Not expecting object type: " + attributeAssignable.getClass() + ", " + attributeAssignable);
237   }
238   
239   /**
240    * take a stem attribute assign and process it, make sure child metadata is correct
241    * @param stem is the stem the attribute is on
242    * @param stemAttributeAssign
243    * @return the email objects
244    */
245   public static Map<String, Set<EmailObject>> stemDeprovisioningProcessHelper(Stem stem, AttributeAssign stemAttributeAssign) {
246     
247     Map<String, Set<EmailObject>> emails = new HashMap<String, Set<EmailObject>>();
248     
249     String affiliation = stemAttributeAssign.getAttributeValueDelegate()
250         .retrieveValueString(GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameAffiliation().getName());
251     
252     String stemHasDeprovisioningString = "false";
253 
254     if (stemAttributeAssign != null) {
255 
256       stemHasDeprovisioningString = stemAttributeAssign.getAttributeValueDelegate()
257           .retrieveValueString(GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameDeprovision().getName());
258         
259       // it needs this if it doesnt have it (from earlier upgrade)
260       if (StringUtils.isBlank(stemHasDeprovisioningString)) {
261         
262         stemAttributeAssign.getAttributeValueDelegate().assignValueString(GrouperDeprovisioningAttributeNames
263             .retrieveAttributeDefNameDeprovision().getName(), "true");
264         stemHasDeprovisioningString = "true";
265       }
266 
267     }
268 
269     String attestationStemScope = stemAttributeAssign == null ? Scope.SUB.name() : 
270       stemAttributeAssign.getAttributeValueDelegate().retrieveValueString(
271           GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameDeprovision().getName());
272 
273     // go through each group and check if they have their own deprovisioning attribute and use them if they are present.
274     // if not, then use the stem attributes.
275     Scope scope = GrouperUtil.defaultIfNull(Scope.valueOfIgnoreCase(attestationStemScope, false), Scope.SUB);
276         
277     Set<Group> childGroups = stem.getChildGroups(scope);
278     
279     for (Group group: childGroups) {
280       
281       AttributeAssign groupAttributeAssign = group.getAttributeDelegate().retrieveAssignment(null, 
282           GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameBase(), false, false);
283               
284       if (groupAttributeAssign == null) {
285         groupAttributeAssign = group.getAttributeDelegate().assignAttribute(
286             GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameBase()).getAttributeAssign();
287       }
288       
289       String directAssignmentString = groupAttributeAssign.getAttributeValueDelegate()
290           .retrieveValueString(GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameDirectAssignment().getName());
291       
292       if (StringUtils.isBlank(directAssignmentString)) {
293         groupAttributeAssign.getAttributeValueDelegate().assignValueString(
294             GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameDirectAssignment().getName(), "false");
295         directAssignmentString = "false";
296       }
297 
298       // group has direct attestation, don't use stem attributes at all.  This will be in group assignment calculations
299       if (GrouperUtil.booleanValue(directAssignmentString, false)) { 
300         continue;
301       }
302 //TODO needs affiliation
303       //start at stem and look for assignment, needs affiliation
304       AttributeAssignable attributeAssignable = group.getParentStem().getAttributeDelegate()
305         .getAttributeOrAncestorAttribute(
306             GrouperDeprovisioningAttributeNames.retrieveAttributeDefNameBase().getName(), false);
307 
308       //there is no direct assignment and no stem with attestation
309       if (attributeAssignable == null) {
310 
311 // TODO
312 //        groupAttributeAssign.getAttributeValueDelegate().assignValueString(
313 //            retrieveAttributeDefNameHasAttestation().getName(), "false");
314 //        groupAttributeAssign.getAttributeDelegate().removeAttribute(retrieveAttributeDefNameCalculatedDaysLeft());
315         continue;
316         
317       }
318       
319 //      //make sure its the right stem that has the assignment
320 //      if (!StringUtils.equals(((Stem)attributeAssignable).getName(), stem.getName())) {
321 //        continue;
322 //      }
323 //
324 //      //make sure group is in sync with stem
325 //      groupAttributeAssign.getAttributeValueDelegate().assignValueString(retrieveAttributeDefNameHasAttestation().getName(), stemHasDeprovisioningString);
326 //      
327 //      if (!GrouperUtil.booleanValue(stemHasDeprovisioningString, true)) {
328 //        continue;
329 //      }
330 //
331 //      Set<AttributeAssign> singleGroupAttributeAssign = new HashSet<AttributeAssign>();
332 //      singleGroupAttributeAssign.add(groupAttributeAssign);
333 //      
334 //      // skip sending email for this attribute assign
335 //      Map<String, Set<EmailObject>> buildAttestationGroupEmails = buildAttestationGroupEmails(stemAttributeAssign, singleGroupAttributeAssign);
336 //     
337 //      mergeEmailObjects(emails, buildAttestationGroupEmails);
338 
339     }
340     
341     return emails;
342   }
343   
344   class EmailPerPerson {
345     private List<CustomEmail> customEmails;
346     private StandardEmail standardEmail;
347   }
348   
349   class CustomEmail {
350     private String subject;
351     private String body;
352   }
353   
354   class StandardEmail {
355     private int groupsCount;
356     private int stemsCount;
357     private int attributeDefCount;
358   }
359 
360 }