/**
* $Id: CheckValidations.java 106391 2012-03-30 07:45:31Z david.horwitz@uct.ac.za $
* $URL: https://source.sakaiproject.org/svn/reset-pass/trunk/account-validator-impl/src/java/org/sakaiproject/accountvalidator/impl/jobs/CheckValidations.java $
*
**************************************************************************
* Copyright (c) 2008, 2009 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sakaiproject.accountvalidator.impl.jobs;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.sakaiproject.accountvalidator.logic.ValidationLogic;
import org.sakaiproject.accountvalidator.model.ValidationAccount;
import org.sakaiproject.authz.api.AuthzGroup;
import org.sakaiproject.authz.api.AuthzGroupService;
import org.sakaiproject.authz.api.AuthzPermissionException;
import org.sakaiproject.authz.api.GroupNotDefinedException;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.emailtemplateservice.service.EmailTemplateService;
import org.sakaiproject.entitybroker.EntityReference;
import org.sakaiproject.site.api.SiteService;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.api.SessionManager;
import org.sakaiproject.user.api.PreferencesService;
import org.sakaiproject.user.api.User;
import org.sakaiproject.user.api.UserDirectoryService;
import org.sakaiproject.user.api.UserEdit;
import org.sakaiproject.user.api.UserLockedException;
import org.sakaiproject.user.api.UserNotDefinedException;
import org.sakaiproject.user.api.UserPermissionException;
public class CheckValidations implements Job {
private static Log log = LogFactory.getLog(CheckValidations.class);
private ValidationLogic validationLogic;
public void setValidationLogic(ValidationLogic vl) {
validationLogic = vl;
}
private UserDirectoryService userDirectoryService;
public void setUserDirectoryService(UserDirectoryService uds) {
userDirectoryService = uds;
}
private AuthzGroupService authzGroupService;
public void setAuthzGroupService(AuthzGroupService authzGroupService) {
this.authzGroupService = authzGroupService;
}
private EmailTemplateService emailTemplateService;
public void setEmailTemplateService(EmailTemplateService emailTemplateService) {
this.emailTemplateService = emailTemplateService;
}
private ServerConfigurationService serverConfigurationService;
public void setServerConfigurationService(
ServerConfigurationService serverConfigurationService) {
this.serverConfigurationService = serverConfigurationService;
}
public SiteService siteService;
public void setSiteService(SiteService siteService) {
this.siteService = siteService;
}
private SessionManager sessionManager;
public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
}
private PreferencesService preferencesService;
public void setPreferencesService(PreferencesService preferencesService) {
this.preferencesService = preferencesService;
}
private int maxDays = 90;
public void setMaxDays(int maxDays) {
this.maxDays = maxDays;
}
public void execute(JobExecutionContext arg0) throws JobExecutionException {
//set the user information into the current session
Session sakaiSession = sessionManager.getCurrentSession();
sakaiSession.setUserId("admin");
sakaiSession.setUserEid("admin");
Calendar cal = new GregorianCalendar();
String maxDaysLocalStr = serverConfigurationService.getString("accountValidator.maxDays", "" + maxDays);
try{
maxDays = Integer.parseInt(maxDaysLocalStr);
}catch (Exception e) {}
cal.add(Calendar.DAY_OF_MONTH, (maxDays * -1));
Date maxAge = cal.getTime();
int maxAttempts =10;
String maxAttemptsStr = serverConfigurationService.getString("accountValidator.maxResendAttempts", "" + maxAttempts);
try{
maxAttempts = Integer.parseInt(maxAttemptsStr);
}catch (Exception e) {}
StringBuilder usedAccounts = new StringBuilder();
List<String> oldAccounts = new ArrayList<String>();
//we need sent and resent
List<ValidationAccount> list = validationLogic.getValidationAccountsByStatus(ValidationAccount.STATUS_SENT);
List<ValidationAccount> list2 = validationLogic.getValidationAccountsByStatus(ValidationAccount.STATUS_RESENT);
if (list2 != null) {
list.addAll(list2);
}
int loggedInAccounts = 0;
int notLogedIn = 0;
for (int i = 0; i < list.size(); i++) {
ValidationAccount account = list.get(i);
log.debug("account " + account.getUserId() + " created on " + account.getValidationSent());
//has the user logged in - check for a authz realm
String userSiteId = siteService.getUserSiteId(account.getUserId());
if (siteService.siteExists(userSiteId)) {
log.info("looks like this user logged in!");
loggedInAccounts++;
if (account.getValidationsSent().intValue() < maxAttempts
&& serverConfigurationService.getBoolean(
"accountValidator.resendValidations", true)) {
validationLogic.resendValidation(account.getValidationToken());
} else if (account.getValidationSent().before(maxAge) || account.getValidationsSent().intValue() >= maxAttempts) {
account.setStatus(ValidationAccount.STATUS_EXPIRED);
//set the received date so that it will create a new token the next time the user requests a reset
cal = new GregorianCalendar();
account.setvalidationReceived(cal.getTime());
validationLogic.save(account);
} else {
//TODO What do we do in this case?
}
usedAccounts.append(account.getUserId() + "\n");
} else {
//user has never logged in
log.debug("realm: " + "/site/~" + account.getUserId() + " does not seem to exist");
notLogedIn++;
if (account.getValidationSent().before(maxAge)) {
oldAccounts.add(account.getUserId());
}
}
}
log.info("users have logged in: " + loggedInAccounts + " not logged in: " + notLogedIn);
log.info("we would delete: " + oldAccounts.size() + " accounts");
if (log.isDebugEnabled()) {
log.debug("users:" + usedAccounts.toString());
}
//as potentially a user could have added lots of accounts we don't want to spam them
Map<String, List<String>> addedMap = buildAddedMap(oldAccounts);
//Ok now we have a map of each user and who they added
Set<Entry<String,List<String>>> entrySet = addedMap.entrySet();
Iterator<Entry<String,List<String>>> it = entrySet.iterator();
while (it.hasNext()) {
Entry<String,List<String>> entry = it.next();
String creatorId = entry.getKey();
try {
User creator = userDirectoryService.getUser(creatorId);
Locale locale = getUserLocale(creatorId);
List<String> users = entry.getValue();
StringBuilder userText = new StringBuilder();
for (int i = 0; i < users.size(); i++) {
try {
User u = userDirectoryService.getUser(users.get(i));
//added the added date
DateTime dt = new DateTime(u.getCreatedDate());
DateTimeFormatter fmt = DateTimeFormat.longDate();
String str = fmt.withLocale(locale).print(dt);
userText.append(u.getEid() + " (" + str +")\n");
removeCleaUpUser(u.getId());
}
catch (UserNotDefinedException e) {
//this is an orphaned validation token
ValidationAccount va = validationLogic.getVaLidationAcountByUserId(users.get(i));
validationLogic.deleteValidationAccount(va);
}
}
List<String> userReferences = new ArrayList<String>();
userReferences.add(creator.getReference());
Map<String, String> replacementValues = new HashMap<String, String>();
replacementValues.put("userList", userText.toString());
replacementValues.put("creatorName", creator.getDisplayName());
replacementValues.put("deleteDays", Integer.valueOf(maxDays).toString());
//now we send an email
emailTemplateService.sendRenderedMessages("validation.deleted", userReferences, replacementValues, "help@vula.uct.ac.za", "Vula Help");
} catch (UserNotDefinedException e) {
e.printStackTrace();
}
}
}
private void removeCleaUpUser(String id) {
UserEdit user;
try {
Set<String> groups = authzGroupService.getAuthzGroupsIsAllowed(EntityReference.getIdFromRef(id), "site.visit", null);
Iterator<String> it = groups.iterator();
while (it.hasNext()) {
AuthzGroup group = authzGroupService.getAuthzGroup(it.next());
group.removeMember(id);
authzGroupService.save(group);
}
user = userDirectoryService.editUser(id);
userDirectoryService.removeUser(user);
ValidationAccount va = validationLogic.getVaLidationAcountByUserId(id);
validationLogic.deleteValidationAccount(va);
} catch (UserNotDefinedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserPermissionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UserLockedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GroupNotDefinedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (AuthzPermissionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Map<String, List<String>> buildAddedMap(List<String> oldAccounts) {
Map<String, List<String>> ret = new HashMap<String, List<String>>();
for (int i =0; i < oldAccounts.size(); i++) {
try {
User u = userDirectoryService.getUser(oldAccounts.get(i));
String createdBy = u.getCreatedBy().getId();
if (ret.containsKey(createdBy)) {
List<String> l = ret.get(createdBy);
l.add(u.getId());
ret.put(createdBy, l);
} else {
List<String> l = new ArrayList<String>();
l.add(u.getId());
ret.put(createdBy, l);
}
} catch (UserNotDefinedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return ret;
}
protected Locale getUserLocale(String userId) {
Locale loc = preferencesService.getLocale(userId);
//the user has no preference set - get the system default
if (loc == null ) {
String lang = System.getProperty("user.language");
String region = System.getProperty("user.region");
if (region != null) {
log.debug("getting system locale for: " + lang + "_" + region);
loc = new Locale(lang,region);
} else {
log.debug("getting system locale for: " + lang );
loc = new Locale(lang);
}
}
return loc;
}
}