Index: pom.xml =================================================================== --- pom.xml (revision 131416) +++ pom.xml (working copy) @@ -59,6 +59,7 @@ entitybroker jsf sakai-mock + userauditservice webservices @@ -140,6 +141,7 @@ entitybroker jsf sakai-mock + userauditservice webservices Index: authz/authz-tool/tool/pom.xml =================================================================== --- authz/authz-tool/tool/pom.xml (revision 131416) +++ authz/authz-tool/tool/pom.xml (working copy) @@ -45,6 +45,10 @@ org.sakaiproject.velocity sakai-velocity-tool + + org.sakaiproject.userauditservice + userauditservice-api + Index: authz/authz-tool/tool/src/java/org/sakaiproject/authz/tool/RealmsAction.java =================================================================== --- authz/authz-tool/tool/src/java/org/sakaiproject/authz/tool/RealmsAction.java (revision 131416) +++ authz/authz-tool/tool/src/java/org/sakaiproject/authz/tool/RealmsAction.java (working copy) @@ -21,6 +21,7 @@ package org.sakaiproject.authz.tool; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -61,6 +62,8 @@ import org.sakaiproject.user.api.User; import org.sakaiproject.user.api.UserNotDefinedException; import org.sakaiproject.user.cover.UserDirectoryService; +import org.sakaiproject.userauditservice.api.UserAuditRegistration; +import org.sakaiproject.userauditservice.api.UserAuditService; import org.sakaiproject.util.ResourceLoader; /** @@ -77,6 +80,9 @@ private org.sakaiproject.authz.api.GroupProvider groupProvider = (org.sakaiproject.authz.api.GroupProvider) ComponentManager .get(org.sakaiproject.authz.api.GroupProvider.class); + private static UserAuditRegistration userAuditRegistration = (UserAuditRegistration) ComponentManager.get("org.sakaiproject.userauditservice.api.UserAuditRegistration.sitemanage"); + private static UserAuditService userAuditService = (UserAuditService) ComponentManager.get(UserAuditService.class); + private static Log M_log = LogFactory.getLog(RealmsAction.class); /** @@ -704,6 +710,13 @@ try { AuthzGroupService.save(realm); + // Grab the list from session state and save it, if appropriate + List userAuditList = (List) state.getAttribute("userAuditList"); + if (userAuditList!=null && !userAuditList.isEmpty()) + { + userAuditRegistration.addToUserAuditing(userAuditList); + state.removeAttribute("userAuditList"); + } } catch (GroupNotDefinedException e) { @@ -1285,8 +1298,38 @@ if (realm != null && user != null) { + // Need to grab the role before removing the user from the realm + String roleId = realm.getUserRole(user.getId()).getId(); + // clear out this user's settings realm.removeMember(user.getId()); + + // Grab the userAuditList from the SessionState if it exists, then make the appropriate String[] to log the audit + List userAuditList = (List) state.getAttribute("userAuditList"); + if (userAuditList!=null) + { + state.removeAttribute("userAuditList"); + } + else + { + userAuditList = new ArrayList(); + } + String realmId = realm.getId(); + String siteId = ""; + String fullReferenceRoot = SiteService.REFERENCE_ROOT + Entity.SEPARATOR; + if (realmId.startsWith(fullReferenceRoot)) + { + siteId = realmId.substring(fullReferenceRoot.length()); + } + else + { + // this will likely never happen + siteId = realmId; + } + String[] userAuditString = {siteId,user.getEid(),roleId,userAuditService.USER_AUDIT_ACTION_REMOVE,userAuditRegistration.getDatabaseSourceKey(),UserDirectoryService.getCurrentUser().getEid()}; + userAuditList.add(userAuditString); + + state.setAttribute("userAuditList", userAuditList); // done with the user state.removeAttribute("user"); @@ -1391,6 +1434,41 @@ { // TODO: active, provided realm.addMember(user.getId(), roles, status, false); + + // user auditing + List userAuditList = (List) state.getAttribute("userAuditList"); + if (userAuditList!=null && !userAuditList.isEmpty()) + { + state.removeAttribute("userAuditList"); + } + else + { + userAuditList = new ArrayList(); + } + String realmId = realm.getId(); + String siteId = ""; + String fullReferenceRoot = SiteService.REFERENCE_ROOT + Entity.SEPARATOR; + if (realmId.startsWith(fullReferenceRoot)) + { + siteId = realmId.substring(fullReferenceRoot.length()); + } + else + { + // this will likely never happen, but adding it in as a backup + siteId = realmId; + } + String newOrExistingUser = (String) state.getAttribute("newUser"); + String userAuditAction = userAuditService.USER_AUDIT_ACTION_UPDATE; + + // if this using the Grant As functionality, it will be a new user being added + if (newOrExistingUser!=null && "true".equals(newOrExistingUser)) + { + userAuditAction = userAuditService.USER_AUDIT_ACTION_ADD; + } + String[] userAuditString = {siteId,user.getEid(),roles,userAuditAction,userAuditRegistration.getDatabaseSourceKey(),UserDirectoryService.getCurrentUser().getEid()}; + userAuditList.add(userAuditString); + + state.setAttribute("userAuditList", userAuditList); } } @@ -1413,6 +1491,7 @@ state.removeAttribute("allLocks"); state.removeAttribute("roles"); state.removeAttribute("locks"); + state.removeAttribute("userAuditList"); } // cleanState Index: config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties =================================================================== --- config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties (revision 131416) +++ config/configuration/bundles/src/bundle/org/sakaiproject/config/bundle/default.sakai.properties (working copy) @@ -2266,6 +2266,12 @@ # DEFAULT: none (null) # site.types= +# This determines if you want user audit event logging in your instance of Sakai +# This setting controls if the page renders to display user auditing information in Site Info. +# This does NOT prevent writing audit information to the database +# DEFAULT: true +# user_audit_log=true + ### Sites admin permissions tool ## You may want to adjust these values up if you have a massive number of sites ## or a lot of load on your server. These values are probably OK for maybe 10k sites. Index: master/pom.xml =================================================================== --- master/pom.xml (revision 131416) +++ master/pom.xml (working copy) @@ -1104,6 +1104,17 @@ provided + org.sakaiproject.userauditservice + userauditservice-api + ${sakai.version} + provided + + + org.sakaiproject.userauditservice + userauditservice-util + ${sakai.version} + + org.sakaiproject sakai-usermembership-api ${sakai.version} Index: reference/docs/conversion/sakai_2_10_0_mysql_conversion.sql =================================================================== --- reference/docs/conversion/sakai_2_10_0_mysql_conversion.sql (revision 131416) +++ reference/docs/conversion/sakai_2_10_0_mysql_conversion.sql (working copy) @@ -944,3 +944,18 @@ update GB_GRADEBOOK_T set TOTAL_POINTS_DISPLAYED=FALSE, COURSE_AVERAGE_DISPLAYED=FALSE where COURSE_GRADE_DISPLAYED=FALSE; -- END SAK-24337 - Gradebook edu-services new features for display + +-- SAK-23634 - new table to track user add/drop/update actions done in sites +create table USER_AUDITS_LOG ( + ID bigint AUTO_INCREMENT NOT NULL, + SITE_ID varchar(255) not null, + USER_ID varchar(255) not null, + ROLE_NAME varchar(255) not null, + ACTION_TAKEN varchar(1) not null, + AUDIT_STAMP timestamp not null, + SOURCE varchar(1), + ACTION_USER_ID varchar(255), + PRIMARY KEY(ID) +); + +-- END SAK-23634 Index: reference/docs/conversion/sakai_2_10_0_oracle_conversion.sql =================================================================== --- reference/docs/conversion/sakai_2_10_0_oracle_conversion.sql (revision 131416) +++ reference/docs/conversion/sakai_2_10_0_oracle_conversion.sql (working copy) @@ -919,3 +919,19 @@ update GB_GRADEBOOK_T set TOTAL_POINTS_DISPLAYED=1, COURSE_AVERAGE_DISPLAYED=1 where COURSE_GRADE_DISPLAYED=1; update GB_GRADEBOOK_T set TOTAL_POINTS_DISPLAYED=0, COURSE_AVERAGE_DISPLAYED=0 where COURSE_GRADE_DISPLAYED=0; -- END SAK-24337 Gradebook edu service features + +-- SAK-23634 - new table to track user add/drop/update actions done in sites +create table USER_AUDITS_LOG ( + ID number(19,0) not null, + SITE_ID varchar2(255) not null, + USER_ID varchar2(255) not null, + ROLE_NAME varchar2(255) not null, + ACTION_TAKEN varchar2(1) not null, + AUDIT_STAMP timestamp not null, + SOURCE varchar2(1), + ACTION_USER_ID varchar2(255), + PRIMARY KEY(ID) +); + +CREATE SEQUENCE USER_AUDITS_LOG_SEQ; +-- END SAK-23634 Index: site-manage/site-manage-impl/impl/pom.xml =================================================================== --- site-manage/site-manage-impl/impl/pom.xml (revision 131416) +++ site-manage/site-manage-impl/impl/pom.xml (working copy) @@ -86,6 +86,14 @@ jdom 1.0 + + org.sakaiproject.userauditservice + userauditservice-api + + + org.sakaiproject.userauditservice + userauditservice-util + Index: site-manage/site-manage-impl/impl/src/bundle/UserAuditService.properties =================================================================== --- site-manage/site-manage-impl/impl/src/bundle/UserAuditService.properties (revision 0) +++ site-manage/site-manage-impl/impl/src/bundle/UserAuditService.properties (working copy) @@ -0,0 +1,3 @@ +#M will display as Last Name, First Name (user's eid) +M = {0} ({1}) +S = Self \ No newline at end of file Index: site-manage/site-manage-impl/impl/src/java/org/sakaiproject/sitemanage/impl/UserAuditSiteManageImpl.java =================================================================== --- site-manage/site-manage-impl/impl/src/java/org/sakaiproject/sitemanage/impl/UserAuditSiteManageImpl.java (revision 0) +++ site-manage/site-manage-impl/impl/src/java/org/sakaiproject/sitemanage/impl/UserAuditSiteManageImpl.java (working copy) @@ -0,0 +1,33 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2013 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.sitemanage.impl; + +import org.sakaiproject.userauditservice.util.UserAuditRegistrationUtil; +import org.sakaiproject.util.ResourceLoader; + +public class UserAuditSiteManageImpl extends UserAuditRegistrationUtil { + + public ResourceLoader getResourceLoader(String location) { + return new ResourceLoader(location); + } + +} Index: site-manage/site-manage-impl/pack/src/webapp/WEB-INF/components.xml =================================================================== --- site-manage/site-manage-impl/pack/src/webapp/WEB-INF/components.xml (revision 131416) +++ site-manage/site-manage-impl/pack/src/webapp/WEB-INF/components.xml (working copy) @@ -83,5 +83,22 @@ bean="org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory" /> + + + UserAuditService + M + true + + + + UserAuditService + S + Index: site-manage/site-manage-participant-helper/pom.xml =================================================================== --- site-manage/site-manage-participant-helper/pom.xml (revision 131416) +++ site-manage/site-manage-participant-helper/pom.xml (working copy) @@ -57,6 +57,10 @@ sakai-velocity-tool-api + org.sakaiproject.userauditservice + userauditservice-api + + commons-lang commons-lang Index: site-manage/site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java =================================================================== --- site-manage/site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java (revision 131416) +++ site-manage/site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java (working copy) @@ -23,6 +23,7 @@ import org.sakaiproject.authz.api.Role; import org.sakaiproject.authz.api.SecurityService; import org.sakaiproject.component.api.ServerConfigurationService; +import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.event.cover.EventTrackingService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.site.api.Site; @@ -43,6 +44,8 @@ import org.sakaiproject.user.api.UserIdInvalidException; import org.sakaiproject.user.api.UserNotDefinedException; import org.sakaiproject.user.api.UserPermissionException; +import org.sakaiproject.userauditservice.api.UserAuditRegistration; +import org.sakaiproject.userauditservice.api.UserAuditService; import uk.org.ponder.messageutil.MessageLocator; import uk.org.ponder.messageutil.TargettedMessage; @@ -84,6 +87,8 @@ public SessionManager sessionManager = null; public ServerConfigurationService serverConfigurationService; private final String HELPER_ID = "sakai.tool.helper.id"; + private static UserAuditRegistration userAuditRegistration = (UserAuditRegistration) ComponentManager.get("org.sakaiproject.userauditservice.api.UserAuditRegistration.sitemanage"); + private static UserAuditService userAuditService = (UserAuditService) ComponentManager.get(UserAuditService.class); public MessageLocator messageLocator; @@ -539,6 +544,10 @@ AuthzGroup realmEdit = authzGroupService.getAuthzGroup(realmId); boolean allowUpdate = authzGroupService.allowUpdate(realmId); SetokRoles = new HashSet(); + + // List used for user auditing + List userAuditList = new ArrayList(); + for (UserRoleEntry entry: userRoleEntries) { String eId = entry.userEId; String role =entry.role; @@ -573,6 +582,11 @@ false); addedUserEIds.add(eId); addedUserInfos.add("uid=" + user.getId() + ";role=" + role + ";active=" + statusChoice.equals("active") + ";provided=false"); + + // Add the user to the list for the User Auditing Event Log + String currentUserId = userDirectoryService.getUserEid(sessionManager.getCurrentSessionUserId()); + String[] userAuditString = {site.getId(),eId,role,userAuditService.USER_AUDIT_ACTION_ADD,userAuditRegistration.getDatabaseSourceKey(),currentUserId}; + userAuditList.add(userAuditString); // send notification if (notify) { @@ -591,6 +605,14 @@ try { authzGroupService.save(realmEdit); + + // do the audit logging - Doing this in one bulk call to the database will cause the actual audit stamp to be off by maybe 1 second at the most + // but seems to be a better solution than call this multiple time for every update + if (!userAuditList.isEmpty()) + { + userAuditRegistration.addToUserAuditing(userAuditList); + } + // post event about adding participant EventTrackingService.post(EventTrackingService.newEvent(SiteService.SECURE_UPDATE_SITE_MEMBERSHIP, realmEdit.getId(),false)); Index: site-manage/site-manage-tool/tool/pom.xml =================================================================== --- site-manage/site-manage-tool/tool/pom.xml (revision 131416) +++ site-manage/site-manage-tool/tool/pom.xml (working copy) @@ -75,6 +75,10 @@ sakai-velocity-tool + org.sakaiproject.userauditservice + userauditservice-api + + commons-beanutils commons-beanutils 1.7.0 Index: site-manage/site-manage-tool/tool/src/bundle/sitesetupgeneric.properties =================================================================== --- site-manage/site-manage-tool/tool/src/bundle/sitesetupgeneric.properties (revision 131416) +++ site-manage/site-manage-tool/tool/src/bundle/sitesetupgeneric.properties (working copy) @@ -28,6 +28,7 @@ java.importFile = Import from Archive File java.link = Link to Parent Site java.external = External Tools +java.userAuditEventLog=User Audit Log ### (moot) java.newsite = New Site ### (moot) java.saveas = Save As java.dontperm = {0} could not be deleted. You do not have permission to remove this site. Index: site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java =================================================================== --- site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java (revision 131416) +++ site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java (working copy) @@ -31,6 +31,7 @@ import org.sakaiproject.cheftool.PagedResourceActionII; import org.sakaiproject.cheftool.RunData; import org.sakaiproject.cheftool.VelocityPortlet; +import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.event.api.SessionState; import org.sakaiproject.exception.IdUnusedException; @@ -39,6 +40,10 @@ import org.sakaiproject.javax.PagingPosition; import org.sakaiproject.site.cover.SiteService; import org.sakaiproject.site.util.SiteTextEditUtil; +import org.sakaiproject.user.api.User; +import org.sakaiproject.user.api.UserDirectoryService; +import org.sakaiproject.userauditservice.api.UserAuditRegistration; +import org.sakaiproject.userauditservice.api.UserAuditService; import org.sakaiproject.util.ResourceLoader; /** @@ -63,6 +68,10 @@ private static String SEARCH_TERM = "search"; private static final String STATE_TOP_PAGE_MESSAGE = "msg-top"; + + private static UserAuditRegistration userAuditRegistration = (UserAuditRegistration) ComponentManager.get("org.sakaiproject.userauditservice.api.UserAuditRegistration.membership"); + private static UserAuditService userAuditService = (UserAuditService) ComponentManager.get(UserAuditService.class); + private static UserDirectoryService userDirectoryService = (UserDirectoryService) ComponentManager.get(UserDirectoryService.class); /* * (non-Javadoc) @@ -396,6 +405,17 @@ SiteService.join(id); String msg = rb.getString("mb.youhave2") + " " + SiteService.getSite(id).getTitle(); addAlert(state, msg); + + // add to user auditing + List userAuditList = new ArrayList(); + String currentUserEid = userDirectoryService.getCurrentUser().getEid(); + String roleId = SiteService.getSite(id).getJoinerRole(); + String[] userAuditString = {id,currentUserEid,roleId,userAuditService.USER_AUDIT_ACTION_ADD,userAuditRegistration.getDatabaseSourceKey(),currentUserEid}; + userAuditList.add(userAuditString); + if (!userAuditList.isEmpty()) + { + userAuditRegistration.addToUserAuditing(userAuditList); + } } catch (IdUnusedException e) { @@ -431,13 +451,27 @@ if (id != null) { String msg = rb.getString("mb.youhave") + " "; + + // add to user auditing + List userAuditList = new ArrayList(); + // get the User object since we need a couple of lookups + User tempUser = userDirectoryService.getCurrentUser(); + String currentUserId = tempUser.getId(); + String currentUserEid = tempUser.getEid(); + for(int i=0; i< id.length; i++){ try { + // Get the user's role before unjoining the site + String roleId = SiteService.getSite(id[i]).getUserRole(currentUserId).getId(); + SiteService.unjoin(id[i]); if (i>0) msg=msg+" ,"; msg = msg+SiteService.getSite(id[i]).getTitle(); + + String[] userAuditString = {id[i],currentUserEid,roleId,userAuditService.USER_AUDIT_ACTION_REMOVE,userAuditRegistration.getDatabaseSourceKey(),currentUserEid}; + userAuditList.add(userAuditString); } catch (IdUnusedException ignore) { @@ -455,6 +489,10 @@ } } addAlert(state, msg); + if (!userAuditList.isEmpty()) + { + userAuditRegistration.addToUserAuditing(userAuditList); + } } // TODO: hard coding this frame id is fragile, portal dependent, and needs to be fixed -ggolden Index: site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/SiteAction.java =================================================================== --- site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/SiteAction.java (revision 131416) +++ site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/SiteAction.java (working copy) @@ -144,6 +144,8 @@ import org.sakaiproject.user.api.User; import org.sakaiproject.user.api.UserNotDefinedException; import org.sakaiproject.user.cover.UserDirectoryService; +import org.sakaiproject.userauditservice.api.UserAuditRegistration; +import org.sakaiproject.userauditservice.api.UserAuditService; import org.sakaiproject.util.ArrayUtil; import org.sakaiproject.util.BaseResourcePropertiesEdit; import org.sakaiproject.util.FileItem; @@ -760,6 +762,10 @@ private String m_filePath; private String moreInfoPath; private String libraryPath; + + private static UserAuditRegistration userAuditRegistration = (UserAuditRegistration) ComponentManager.get("org.sakaiproject.userauditservice.api.UserAuditRegistration.sitemanage"); + private static UserAuditService userAuditService = (UserAuditService) ComponentManager.get(UserAuditService.class); + /** * what are the tool ids within Home page? * If this is for a newly added Home tool, get the tool ids from template site or system set default @@ -2006,6 +2012,18 @@ } } + if (allowUpdateSite) + { + // show add parent sites menu + if (!isMyWorkspace) { + boolean eventLog = "true".equals(ServerConfigurationService.getString("user_audit_log", "true")); + if (notStealthOrHiddenTool("sakai.useraudit") && eventLog) { + b.add(new MenuEntry(rb.getString("java.userAuditEventLog"), + "doUserAuditEventLog")); + } + } + } + if (b.size() > 0) { // add the menus to vm @@ -3796,6 +3814,19 @@ startHelper(data.getRequest(), "sakai.basiclti.admin.helper"); } + public void doUserAuditEventLog(RunData data) { + SessionState state = ((JetspeedRunData) data) + .getPortletSessionState(((JetspeedRunData) data).getJs_peid()); + + // pass in the siteId of the site to be ordered (so it can configure + // sites other then the current site) + SessionManager.getCurrentToolSession().setAttribute( + HELPER_ID + ".siteId", ((Site) getStateSite(state)).getId()); + + // launch the helper + startHelper(data.getRequest(), "sakai.useraudit"); + } + public boolean setHelper(String helperName, String defaultHelperId, SessionState state, String stateHelperString) { String helperId = ServerConfigurationService.getString(helperName, defaultHelperId); @@ -4630,6 +4661,7 @@ Site site = SiteService.getSite(id); site_title = site.getTitle(); SiteService.removeSite(site); + userAuditRegistration.deleteUserAuditingFromSite(id); } catch (IdUnusedException e) { M_log.warn(this +".doSite_delete_confirmed - IdUnusedException " + id, e); addAlert(state, rb.getFormattedMessage("java.couldnt", new Object[]{site_title,id})); @@ -7752,6 +7784,9 @@ // list of roles being added or removed HashSetroles = new HashSet(); + + // List used for user auditing + List userAuditList = new ArrayList(); // remove all roles and then add back those that were checked for (int i = 0; i < participants.size(); i++) { @@ -7806,6 +7841,9 @@ } realmEdit.addMember(id, roleId, activeGrant, fromProvider); + String currentUserId = (String) state.getAttribute(STATE_CM_CURRENT_USERID); + String[] userAuditString = {s.getId(),participant.getEid(),roleId,userAuditService.USER_AUDIT_ACTION_UPDATE,userAuditRegistration.getDatabaseSourceKey(),currentUserId}; + userAuditList.add(userAuditString); // construct the event string String userUpdatedString = "uid=" + id; @@ -7864,6 +7902,9 @@ } realmEdit.removeMember(userId); usersDeleted.add("uid=" + userId); + String currentUserId = (String) state.getAttribute(STATE_CM_CURRENT_USERID); + String[] userAuditString = {s.getId(),user.getEid(),role.getId(),userAuditService.USER_AUDIT_ACTION_REMOVE,userAuditRegistration.getDatabaseSourceKey(),currentUserId}; + userAuditList.add(userAuditString); } } } @@ -7896,6 +7937,13 @@ } } AuthzGroupService.save(realmEdit); + + // do the audit logging - Doing this in one bulk call to the database will cause the actual audit stamp to be off by maybe 1 second at the most + // but seems to be a better solution than call this multiple time for every update + if (!userAuditList.isEmpty()) + { + userAuditRegistration.addToUserAuditing(userAuditList); + } // then update all related group realms for the role doUpdate_related_group_participants(s, realmId); Index: userauditservice/api/pom.xml =================================================================== --- userauditservice/api/pom.xml (revision 0) +++ userauditservice/api/pom.xml (working copy) @@ -0,0 +1,43 @@ + + 4.0.0 + + + org.sakaiproject.userauditservice + userauditservice + 2.10-SNAPSHOT + + + Sakai Userauditservice API (userauditservice-api) + org.sakaiproject.userauditservice + userauditservice-api + + Sakai Project + http://sakaiproject.org/ + + 2013 + Userauditservice interfaces (API) + jar + + + shared + + + + + org.simpleframework + simple-xml + + + + + + + ${basedir}/src/java + + **/*.xml + + false + + + + Index: userauditservice/api/src/java/org/sakaiproject/userauditservice/api/UserAuditRegistration.java =================================================================== --- userauditservice/api/src/java/org/sakaiproject/userauditservice/api/UserAuditRegistration.java (revision 0) +++ userauditservice/api/src/java/org/sakaiproject/userauditservice/api/UserAuditRegistration.java (working copy) @@ -0,0 +1,57 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2013 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.userauditservice.api; + +import java.util.List; + +/** + *

+ * UserAuditRegistrationService controls calls relating to tracking user auditing. + *

+ */ +public interface UserAuditRegistration +{ + /** One character key a tool will use to show where the change came from */ + public String getDatabaseSourceKey(); + + /** The text to register that will be associated with the databaseSourceKey */ + public String getSourceText(String[] parameter); + + /** + * Processes a list of String[] to add records into the database about + * @param userAuditList List of String[] to process + */ + public void addToUserAuditing(List userAuditList); + + /** + * Method to delete all the user auditing log entries for a site. Used when deleting a site + * @param siteId String site id to delete user auditing logs + */ + public void deleteUserAuditingFromSite(String siteId); + + /** + * This method will allow registering tools to supply their own location for resource loaders + * @param location + * @return + */ + public Object getResourceLoader(String location); +} Index: userauditservice/api/src/java/org/sakaiproject/userauditservice/api/UserAuditService.java =================================================================== --- userauditservice/api/src/java/org/sakaiproject/userauditservice/api/UserAuditService.java (revision 0) +++ userauditservice/api/src/java/org/sakaiproject/userauditservice/api/UserAuditService.java (working copy) @@ -0,0 +1,58 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2013 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.userauditservice.api; + +import java.util.List; + +/** + * Service interface that allows tools to register their own database key and associated text for User Auditing + * + */ +public interface UserAuditService { + + /** Database action value for logging a user was added to a site */ + static final String USER_AUDIT_ACTION_ADD = "A"; + + /** Database action value for logging a user was removed from a site */ + static final String USER_AUDIT_ACTION_REMOVE = "D"; + + /** Database action value for logging a user was updated in a site, typically in a different role */ + static final String USER_AUDIT_ACTION_UPDATE = "U"; + + /** + * Method to register a UserAuditRegistration object + * @param ua + */ + public void register(UserAuditRegistration uar); + + /** + * Gets all UserAuditRegistration objects that have been registered + * @return + */ + public List getRegisteredItems(); + + /** + * Get the keys for all UserAuditRegistration objects that have been registered + * @return + */ + public List getKeys(); +} Index: userauditservice/deploy/pom.xml =================================================================== --- userauditservice/deploy/pom.xml (revision 0) +++ userauditservice/deploy/pom.xml (working copy) @@ -0,0 +1,38 @@ + + 4.0.0 + + + org.sakaiproject.userauditservice + userauditservice + 2.10-SNAPSHOT + + + Sakai Userauditservice Deploy POM + org.sakaiproject.userauditservice + userauditservice-deploy + 2.10-SNAPSHOT + pom + + Userauditservice deploy POM. + + + Sakai Project + http://sakaiproject.org/ + + 2013 + + + shared + + + + + + org.simpleframework + simple-xml + ${sakai.simple-xml.version} + compile + + + + Index: userauditservice/deploy/shared/pom.xml =================================================================== --- userauditservice/deploy/shared/pom.xml (revision 0) +++ userauditservice/deploy/shared/pom.xml (working copy) @@ -0,0 +1,34 @@ + + + 4.0.0 + + + org.sakaiproject.userauditservice + userauditservice-deploy + 2.10-SNAPSHOT + + + Sakai userauditservice Shared Deploy + org.sakaiproject.userauditservice + userauditservice-shared + pom + + userauditservice shared deploy POM. + + + Sakai Project + http://sakaiproject.org/ + + 2013 + + + shared + + + + + org.simpleframework + simple-xml + + + \ No newline at end of file Index: userauditservice/impl/pom.xml =================================================================== --- userauditservice/impl/pom.xml (revision 0) +++ userauditservice/impl/pom.xml (working copy) @@ -0,0 +1,54 @@ + + 4.0.0 + + + org.sakaiproject.userauditservice + userauditservice + 2.10-SNAPSHOT + ../pom.xml + + + Sakai Userauditservice Implementation (userauditservice-impl) + org.sakaiproject.userauditservice + userauditservice-impl + + Sakai Project + http://sakaiproject.org/ + + 2013 + Userauditservice implementation + jar + + + + + + + + ${project.groupId} + userauditservice-api + + + org.sakaiproject.kernel + sakai-kernel-api + + + + + + + ${basedir}/src/java + + **/*.xml + + false + + + ${basedir}/src/sql + + **/*.sql + + + + + Index: userauditservice/impl/src/java/org/sakaiproject/userauditservice/impl/UserAuditServiceImpl.java =================================================================== --- userauditservice/impl/src/java/org/sakaiproject/userauditservice/impl/UserAuditServiceImpl.java (revision 0) +++ userauditservice/impl/src/java/org/sakaiproject/userauditservice/impl/UserAuditServiceImpl.java (working copy) @@ -0,0 +1,110 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2013 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.userauditservice.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.sakaiproject.db.api.SqlService; +import org.sakaiproject.userauditservice.api.UserAuditRegistration; +import org.sakaiproject.userauditservice.api.UserAuditService; + +public class UserAuditServiceImpl implements UserAuditService { + + private List registeredItems = new ArrayList(); + private List keys = new ArrayList(); + + /** + * {@inheritDoc} + */ + public void register(UserAuditRegistration uar) { + getRegisteredItems().add(uar); + getKeys().add(uar.getDatabaseSourceKey()); + } + + /** + * Setter + * @param registeredItems + */ + public void setRegisteredItems(List registeredItems) { + this.registeredItems = registeredItems; + } + + /** + * {@inheritDoc} + */ + public List getRegisteredItems() { + return registeredItems; + } + + /** + * {@inheritDoc} + */ + public List getKeys() { + return keys; + } + + /** + * Setter + * @param keys + */ + public void setKeys(List keys) { + this.keys = keys; + } + + /** Dependency: SqlService */ + protected SqlService m_sqlService = null; + + /** + * Dependency: SqlService. + * + * @param service + * The SqlService. + */ + public void setSqlService(SqlService service) + { + m_sqlService = service; + } + + /** Configuration: to run the ddl on init or not. */ + protected boolean m_autoDdl = false; + + /** + * Configuration: to run the ddl on init or not. + * + * @param value + * the auto ddl value. + */ + public void setAutoDdl(String value) + { + m_autoDdl = Boolean.valueOf(value).booleanValue(); + } + + public void init() { + // if we are auto-creating our schema, check and create + if (m_autoDdl) + { + m_sqlService.ddl(this.getClass().getClassLoader(), "user_audits"); + } + } + +} Index: userauditservice/impl/src/sql/hsqldb/user_audits.sql =================================================================== --- userauditservice/impl/src/sql/hsqldb/user_audits.sql (revision 0) +++ userauditservice/impl/src/sql/hsqldb/user_audits.sql (working copy) @@ -0,0 +1,12 @@ +-- SAK-23634 - new table to track user add/drop/update actions done in sites +create table USER_AUDITS_LOG ( + ID bigint generated by default as identity (start with 1), + SITE_ID varchar(255) not null, + USER_ID varchar(255) not null, + ROLE_NAME varchar(255) not null, + ACTION_TAKEN varchar(1) not null, + AUDIT_STAMP timestamp not null, + SOURCE varchar(1), + ACTION_USER_ID varchar(255), + PRIMARY KEY(ID) +); \ No newline at end of file Index: userauditservice/impl/src/sql/mysql/user_audits.sql =================================================================== --- userauditservice/impl/src/sql/mysql/user_audits.sql (revision 0) +++ userauditservice/impl/src/sql/mysql/user_audits.sql (working copy) @@ -0,0 +1,12 @@ +-- SAK-23634 - new table to track user add/drop/update actions done in sites +create table USER_AUDITS_LOG ( + ID bigint AUTO_INCREMENT NOT NULL, + SITE_ID varchar(255) not null, + USER_ID varchar(255) not null, + ROLE_NAME varchar(255) not null, + ACTION_TAKEN varchar(1) not null, + AUDIT_STAMP timestamp not null, + SOURCE varchar(1), + ACTION_USER_ID varchar(255), + PRIMARY KEY(ID) +); \ No newline at end of file Index: userauditservice/impl/src/sql/oracle/user_audits.sql =================================================================== --- userauditservice/impl/src/sql/oracle/user_audits.sql (revision 0) +++ userauditservice/impl/src/sql/oracle/user_audits.sql (working copy) @@ -0,0 +1,14 @@ +-- SAK-23634 - new table to track user add/drop/update actions done in sites +create table USER_AUDITS_LOG ( + ID number(19,0) not null, + SITE_ID varchar2(255) not null, + USER_ID varchar2(255) not null, + ROLE_NAME varchar2(255) not null, + ACTION_TAKEN varchar2(1) not null, + AUDIT_STAMP timestamp not null, + SOURCE varchar2(1), + ACTION_USER_ID varchar2(255), + PRIMARY KEY(ID) +); + +CREATE SEQUENCE USER_AUDITS_LOG_SEQ; \ No newline at end of file Index: userauditservice/pack/pom.xml =================================================================== --- userauditservice/pack/pom.xml (revision 0) +++ userauditservice/pack/pom.xml (working copy) @@ -0,0 +1,41 @@ + + 4.0.0 + + + org.sakaiproject.userauditservice + userauditservice + 2.10-SNAPSHOT + + + Sakai Userauditservice Components Package (userauditservice-pack) + org.sakaiproject.userauditservice + userauditservice-pack + + Sakai Project + http://sakaiproject.org/ + + 2013 + + Userauditservice components pack (special Sakai convention). + + sakai-component + + + components + + + + + ${project.groupId} + userauditservice-impl + runtime + + + ${project.groupId} + userauditservice-util + runtime + + + + + \ No newline at end of file Index: userauditservice/pack/src/webapp/WEB-INF/components.xml =================================================================== --- userauditservice/pack/src/webapp/WEB-INF/components.xml (revision 0) +++ userauditservice/pack/src/webapp/WEB-INF/components.xml (working copy) @@ -0,0 +1,18 @@ + + + + + + + ${auto.ddl} + + + + + + + Index: userauditservice/pom.xml =================================================================== --- userauditservice/pom.xml (revision 0) +++ userauditservice/pom.xml (working copy) @@ -0,0 +1,100 @@ + + 4.0.0 + + org.sakaiproject + master + 2.10-SNAPSHOT + ../master/pom.xml + + + Sakai Userauditservice Base POM (userauditservice) + org.sakaiproject.userauditservice + userauditservice + pom + 2.10-SNAPSHOT + + Sakai Project + http://sakaiproject.org/ + + 2013 + + + 2.6 + UTF-8 + + + + api + deploy + impl + pack + tool + util + + + + scm:svn:https://source.sakaiproject.org/svn/userauditservice/trunk + scm:svn:https://source.sakaiproject.org/svn/userauditservice/trunk + https://source.sakaiproject.org/svn/userauditservice/trunk + + + + + sakai-site + Sakai release Site + scpexe://source.sakaiproject.org/var/www/html/release/userauditservice/${project.version} + + + + + + + ${project.groupId} + userauditservice-api + ${project.version} + provided + + + ${project.groupId} + userauditservice-impl + ${project.version} + + + org.simpleframework + simple-xml + ${sakai.simple-xml.version} + provided + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + aggregate + + UTF-8 + + http://download.oracle.com/javase/6/docs/api/ + http://docs.oracle.com/javaee/5/api/ + http://junit.sourceforge.net/javadoc/ + + true + false + 512m + -J-Xmx512m -J-XX:MaxPermSize=160m + + + aggregate + + + + + + + + \ No newline at end of file Index: userauditservice/tool/pom.xml =================================================================== --- userauditservice/tool/pom.xml (revision 0) +++ userauditservice/tool/pom.xml (working copy) @@ -0,0 +1,59 @@ + + + 4.0.0 + + + org.sakaiproject.userauditservice + userauditservice + 2.10-SNAPSHOT + ../pom.xml + + + Sakai Userauditservice Tool (userauditservice-tool) + org.sakaiproject.userauditservice + userauditservice-tool + + The Sakai Foundation + http://sakaiproject.org/ + + 2013 + war + + + + org.sakaiproject.kernel + sakai-kernel-api + + + org.sakaiproject.kernel + sakai-component-manager + + + ${project.groupId} + userauditservice-api + + + ${project.groupId} + userauditservice-util + + + org.sakaiproject.jsf + myfaces-widgets-depend + pom + + + org.sakaiproject.jsf + jsf-app + + + javax.faces + jsf-api + + + + + javax.servlet.jsp + jsp-api + + + Index: userauditservice/tool/src/bundle/UserAuditMessages.properties =================================================================== --- userauditservice/tool/src/bundle/UserAuditMessages.properties (revision 0) +++ userauditservice/tool/src/bundle/UserAuditMessages.properties (working copy) @@ -0,0 +1,19 @@ +navbar_eventLog=User Audit Log + +title_event_log=User Audit Log + +# Event Log Text - headers +event_log_name = Name +event_log_user_id = User ID +event_log_role = Role +event_log_date = Date +event_log_event = Event +event_log_source = Source + +# Event Log Text - actions +event_log_add = Add +event_log_remove = Remove +event_log_update = Update + +# Event Log Text - source texts +event_log_not_available = n/a Index: userauditservice/tool/src/java/org/sakaiproject/userauditservice/tool/UserAuditEventLog.java =================================================================== --- userauditservice/tool/src/java/org/sakaiproject/userauditservice/tool/UserAuditEventLog.java (revision 0) +++ userauditservice/tool/src/java/org/sakaiproject/userauditservice/tool/UserAuditEventLog.java (working copy) @@ -0,0 +1,474 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2013 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.userauditservice.tool; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.text.Collator; +import java.text.DateFormat; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.faces.context.FacesContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.component.cover.ComponentManager; +import org.sakaiproject.db.api.SqlService; +import org.sakaiproject.jsf.util.LocaleUtil; +import org.sakaiproject.site.api.SiteService; +import org.sakaiproject.tool.api.ToolManager; +import org.sakaiproject.userauditservice.api.UserAuditRegistration; +import org.sakaiproject.userauditservice.api.UserAuditService; +import org.sakaiproject.user.api.User; +import org.sakaiproject.user.api.UserDirectoryService; +import org.sakaiproject.user.api.UserNotDefinedException; + +public class UserAuditEventLog { + private static final Log log = LogFactory.getLog(UserAuditEventLog.class); + protected List eventLog = new ArrayList(); + // Static comparators + public static final Comparator displayNameComparatorEL; + public static final Comparator userIdComparatorEL; + public static final Comparator roleNameComparatorEL; + public static final Comparator auditStampComparatorEL; + public static final Comparator actionTextComparatorEL; + public static final Comparator sourceTextComparatorEL; + protected String sortColumn; + protected boolean sortAscending; + private int totalItems = -1; + private int firstItem = 0; + private int pageSize = 0; + private Map userMap = new HashMap(); + private transient SqlService sqlService = (SqlService) ComponentManager.get(SqlService.class.getName()); + private transient UserAuditRegistration userAuditRegistration = (UserAuditRegistration) ComponentManager.get(UserAuditRegistration.class.getName()); + private transient UserAuditService userAuditService = (UserAuditService) ComponentManager.get(UserAuditService.class.getName()); + private transient SiteService siteService = (SiteService) ComponentManager.get(SiteService.class.getName()); + private transient ToolManager toolManager = (ToolManager) ComponentManager.get(ToolManager.class.getName()); + private transient UserDirectoryService userDirectoryService = (UserDirectoryService) ComponentManager.get(UserDirectoryService.class.getName()); + + static { + displayNameComparatorEL = new Comparator() { + public int compare(EventLog one, EventLog another) { + int comparison = one.getUserDisplayName().compareToIgnoreCase(another.getUserDisplayName()); + return comparison == 0 ? userIdComparatorEL.compare(one,another) : comparison; + } + }; + + userIdComparatorEL = new Comparator() { + public int compare(EventLog one, EventLog another) { + return Collator.getInstance().compare(one.getUser().getEid(),another.getUser().getEid()); + } + }; + + roleNameComparatorEL = new Comparator() { + public int compare(EventLog one, EventLog another) { + int comparison = Collator.getInstance().compare(one.getRoleName(),another.getRoleName()); + return comparison == 0 ? userIdComparatorEL.compare(one,another) : comparison; + } + }; + + auditStampComparatorEL = new Comparator() { + public int compare(EventLog one, EventLog another) { + // calling auditStamp directly so it does a comparison to the actual date versus a string style comparison, which isn't quite right. + int comparison = (one.auditStamp.compareTo(another.auditStamp)); + return comparison == 0 ? userIdComparatorEL.compare(one,another) : comparison; + } + }; + + actionTextComparatorEL = new Comparator() { + public int compare(EventLog one, EventLog another) { + int comparison = Collator.getInstance().compare(one.getActionText(),another.getActionText()); + return comparison == 0 ? userIdComparatorEL.compare(one,another) : comparison; + } + }; + + sourceTextComparatorEL = new Comparator() { + public int compare(EventLog one, EventLog another) { + int comparison = Collator.getInstance().compare(one.getSourceText(),another.getSourceText()); + return comparison == 0 ? userIdComparatorEL.compare(one,another) : comparison; + } + }; + } + + protected Comparator getComparatorEL() + { + String sortColumn = getSortColumn(); + Comparator comparator; + if ("userDisplayName".equals(sortColumn)) + { + comparator = displayNameComparatorEL; + } + else if ("userId".equals(sortColumn)) + { + comparator = userIdComparatorEL; + } + else if("roleName".equals(sortColumn)) + { + comparator = roleNameComparatorEL; + } + else if("auditStamp".equals(sortColumn)) + { + comparator = auditStampComparatorEL; + } + else if("actionText".equals(sortColumn)) + { + comparator = actionTextComparatorEL; + } + else if("sourceText".equals(sortColumn)) + { + comparator = sourceTextComparatorEL; + } + else + { + // Default to the sort name + comparator = auditStampComparatorEL; + } + return comparator; + } + + public class EventLog { + protected String actionTaken; + protected String actionText; + protected User actionUser; + protected Date auditStamp; + protected String roleName; + protected String source; + protected String sourceText; + protected User user; + protected String userDisplayName; + + /** + * Constructs a EventLogImpl. + * + * @param user - this is a User object for who was add/dropped from a site + * @param roleName - the user's role in the site + * @param actionTaken - this interprets the A, D, and U and return the appropriate text from the bundle + * @param auditStamp - will return a String, although a Date object is passed in. This is the date and time the user was added or dropped from the site + * @param source - interprets the letter key registered from a tool and returns the appropriate text from the bundle + * @param actionUser - User object for who performed the add/drop action + * @param childSiteId - Used for logging something specific with parent/child sites + */ + public EventLog(User user, String roleName, String actionTaken, Date auditStamp, String source, User actionUser) { + this.user = user; + this.roleName = roleName; + this.actionTaken = actionTaken; + this.auditStamp = auditStamp; + this.source = source; + this.actionUser = actionUser; + } + + public String getActionTaken() { + return actionTaken; + } + + public String getActionText() { + if (userAuditService.USER_AUDIT_ACTION_ADD.equals(actionTaken)) + { + actionText = LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(),"UserAuditMessages", "event_log_add"); + } + else if (userAuditService.USER_AUDIT_ACTION_REMOVE.equals(actionTaken)) + { + actionText = LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(),"UserAuditMessages", "event_log_remove"); + } + else if (userAuditService.USER_AUDIT_ACTION_UPDATE.equals(actionTaken)) + { + actionText = LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(),"UserAuditMessages", "event_log_update"); + } + return actionText; + } + + public User getActionUser() { + return actionUser; + } + + public String getAuditStamp() { + DateFormat df = DateFormat.getDateTimeInstance(); + return df.format(auditStamp); + } + + public String getRoleName() { + return roleName; + } + + public String getSource() { + return source; + } + + public String getSourceText() { + for(UserAuditRegistration uar : userAuditService.getRegisteredItems()) + { + if (uar.getDatabaseSourceKey().equals(source)) + { + String[] params = new String[] {actionUser.getSortName(), actionUser.getEid()}; + sourceText = uar.getSourceText(params); + break; + } + else + { + // if we didn't find an appropriate source, use the not available option + sourceText = LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(),"UserAuditMessages", "event_log_not_available"); + } + } + + return sourceText; + } + + public User getUser() { + return user; + } + + public String getUserDisplayName() { + userDisplayName = user.getSortName(); + return userDisplayName; + } + + public void setActionTaken(String actionTaken) { + this.actionTaken = actionTaken; + } + + public void setActionText(String actionText) { + this.actionText = actionText; + } + + public void setActionUser(User actionUser) { + this.actionUser = actionUser; + } + + public void setAuditStamp(Date auditStamp) { + this.auditStamp = auditStamp; + } + + public void setRoleName(String roleName) { + this.roleName = roleName; + } + + public void setSource(String source) { + this.source = source; + } + + public void setSourceText(String sourceText) { + this.sourceText = sourceText; + } + + public void setUser(User user) { + this.user = user; + } + + public void setUserDisplayName(String userDisplayName) { + this.userDisplayName = userDisplayName; + } + } + + public List getEventLog() { + return eventLog; + } + + private void getEvents() + { + if (this.eventLog == null || this.eventLog.isEmpty()) + { + eventLog = new ArrayList(); + Connection conn = null; + Statement statement = null; + ResultSet result = null; + String sql = ""; + String siteId = toolManager.getCurrentPlacement().getContext(); + try + { + conn = sqlService.borrowConnection(); + statement = conn.createStatement(); + sql = "select * from USER_AUDITS_LOG where SITE_ID = '" + siteId + "' order by AUDIT_STAMP desc"; + result = statement.executeQuery(sql); + while (result.next()) + { + String userId = result.getString("USER_ID"); + String roleName = result.getString("ROLE_NAME"); + String actionTaken = result.getString("ACTION_TAKEN"); + Timestamp auditStamp = result.getTimestamp("AUDIT_STAMP"); + String source = result.getString("SOURCE"); + String actionUserId = result.getString("ACTION_USER_ID"); + + User cachedUser; + if (userMap.containsKey(userId)) + { + cachedUser = userMap.get(userId); + } + else + { + cachedUser = userDirectoryService.getUserByEid(userId); + userMap.put(userId, cachedUser); + } + + if (actionUserId!=null && !"".equals(actionUserId)) + { + User cachedActionUser; + if (userMap.containsKey(actionUserId)) + { + cachedActionUser = userMap.get(actionUserId); + } + else + { + cachedActionUser = userDirectoryService.getUserByEid(actionUserId); + userMap.put(actionUserId, cachedActionUser); + } + eventLog.add(new EventLog(cachedUser,roleName,actionTaken,auditStamp,source,cachedActionUser)); + } + else + { + eventLog.add(new EventLog(cachedUser,roleName,actionTaken,auditStamp,source,null)); + } + } + } + catch (UserNotDefinedException e) + { + log.warn("ERROR getting the user audit logs!", e); + } + catch (SQLException e) + { + log.warn("ERROR getting the user audit logs!", e); + } + finally + { + try + { + if (result!=null) + { + result.close(); + } + } + catch (SQLException e) + { + log.warn("Error trying to close the result set in the Roster Event Log!", e); + } + try + { + if (statement!=null) + { + statement.close(); + } + } + catch (SQLException e) + { + log.warn("Error trying to close the statement in the Roster Event Log!", e); + } + try + { + if (conn!=null) + { + conn.close(); + } + } + catch (SQLException e) + { + log.warn("Error trying to close the database connection in the Roster Event Log!", e); + } + } + } + this.totalItems = eventLog.size(); + } + + public String getInitValues() { + getEvents(); + + if (eventLog != null && eventLog.size() >= 1) { + Collections.sort(eventLog, getComparatorEL()); + if(!isSortAscending()) { + Collections.reverse(eventLog); + } + } + + return ""; + } + + public String getPageTitle() { + return LocaleUtil.getLocalizedString(FacesContext.getCurrentInstance(), + "UserAuditMessages", "title_event_log"); + } + + public String getSortColumn() { + if (this.sortColumn == null) { + this.sortColumn = "auditStamp"; + } + return this.sortColumn; + } + + public boolean isExportablePage() { + return false; + } + + public boolean isSortAscending() { + return sortAscending; + } + + public void setEventLog(List eventLog) { + this.eventLog = eventLog; + } + + public void setSortAscending(boolean sortAscending) { + this.sortAscending = sortAscending; + } + + public void setSortColumn(String sortColumn) { + this.sortColumn = sortColumn; + } + + public int getRowsNumber() { + if(totalItems <= pageSize){ + return totalItems; + } + return pageSize; + } + + public int getFirstItem() { + return firstItem; + } + + public void setFirstItem(int firstItem) { + this.firstItem = firstItem; + } + + public int getPageSize() { + return pageSize; + } + + public void setPageSize(int pageSize) { + this.pageSize = pageSize; + } + + public int getTotalItems() { + return this.totalItems; + } + + public void setTotalItems(int totalItems) { + this.totalItems = totalItems; + } +} Index: userauditservice/tool/src/webapp/WEB-INF/faces-config.xml =================================================================== --- userauditservice/tool/src/webapp/WEB-INF/faces-config.xml (revision 0) +++ userauditservice/tool/src/webapp/WEB-INF/faces-config.xml (working copy) @@ -0,0 +1,24 @@ + + + + + + + UserAuditMessages + + en + + + + + eventLog + org.sakaiproject.userauditservice.tool.UserAuditEventLog + session + + + + /eventLog.jsp + + Index: userauditservice/tool/src/webapp/WEB-INF/web.xml =================================================================== --- userauditservice/tool/src/webapp/WEB-INF/web.xml (revision 0) +++ userauditservice/tool/src/webapp/WEB-INF/web.xml (working copy) @@ -0,0 +1,131 @@ + + + + sakai-useraudit + Site User Audit Tool + + + javax.faces.STATE_SAVING_METHOD + server + + + + org.apache.myfaces.SERIALIZE_STATE_IN_SESSION + false + + + + org.apache.myfaces.COMPRESS_STATE_IN_SESSION + false + + + + org.apache.myfaces.ALLOW_JAVASCRIPT + true + + + + org.apache.myfaces.DETECT_JAVASCRIPT + false + + + + org.apache.myfaces.PRETTY_HTML + true + + + + org.apache.myfaces.AUTO_SCROLL + true + + + + org.apache.myfaces.webapp.StartupServletContextListener + + + + MyFacesExtensionsFilter + org.apache.myfaces.webapp.filter.ExtensionsFilter + + maxFileSize + 20m + Set the size limit for uploaded files. + Format: 10 - 10 bytes + 10k - 10 KB + 10m - 10 MB + 1g - 1 GB + + + + + + MyFacesExtensionsFilter + /* + REQUEST + INCLUDE + FORWARD + + + + MyFacesExtensionsFilter + /faces/myFacesExtensionResource/* + + + + Faces Servlet + javax.faces.webapp.FacesServlet + 2 + + + + Faces Servlet + *.jsf + + + + sakai.request + org.sakaiproject.util.RequestFilter + + + + sakai.request + Faces Servlet + REQUEST + FORWARD + INCLUDE + + + + org.sakaiproject.util.ToolListener + + + + sakai.useraudit + org.sakaiproject.userauditservice.tool.servlet.UserAuditJsfTool + + default + eventLog + + + path + / + + + default.last.view + false + + 1 + + + + + + *.jsp + + + + Index: userauditservice/tool/src/webapp/eventLog.jsp =================================================================== --- userauditservice/tool/src/webapp/eventLog.jsp (revision 0) +++ userauditservice/tool/src/webapp/eventLog.jsp (working copy) @@ -0,0 +1,84 @@ +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> +<%@ taglib uri="http://sakaiproject.org/jsf/sakai" prefix="sakai"%> +<%@ taglib uri="http://myfaces.apache.org/tomahawk" prefix="t"%> +<% +response.setContentType("text/html; charset=UTF-8"); +%> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: userauditservice/tool/src/webapp/tools/sakai.useraudit.xml =================================================================== --- userauditservice/tool/src/webapp/tools/sakai.useraudit.xml (revision 0) +++ userauditservice/tool/src/webapp/tools/sakai.useraudit.xml (working copy) @@ -0,0 +1,11 @@ + + + + + + + + Index: userauditservice/util/pom.xml =================================================================== --- userauditservice/util/pom.xml (revision 0) +++ userauditservice/util/pom.xml (working copy) @@ -0,0 +1,72 @@ + + 4.0.0 + + + org.sakaiproject.userauditservice + userauditservice + 2.10-SNAPSHOT + ../pom.xml + + + Sakai Userauditservice Util (userauditservice-util) + org.sakaiproject.userauditservice + userauditservice-util + + Sakai Project + http://sakaiproject.org/ + + 2013 + Userauditservice utility + jar + + + + + + + + ${project.groupId} + userauditservice-api + + + org.sakaiproject.kernel + sakai-kernel-api + + + org.sakaiproject.kernel + sakai-kernel-storage-util + + + org.sakaiproject.kernel + sakai-component-manager + + + org.springframework + spring-test + + + org.sakaiproject.jsf + jsf-tool + + + javax.servlet + servlet-api + + + commons-logging + commons-logging + + + + + + + ${basedir}/src/java + + **/*.xml + + false + + + + Index: userauditservice/util/src/java/org/sakaiproject/userauditservice/util/UserAuditJsfTool.java =================================================================== --- userauditservice/util/src/java/org/sakaiproject/userauditservice/util/UserAuditJsfTool.java (revision 0) +++ userauditservice/util/src/java/org/sakaiproject/userauditservice/util/UserAuditJsfTool.java (working copy) @@ -0,0 +1,325 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2013 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.userauditservice.tool.servlet; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Map; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.sakaiproject.component.cover.ComponentManager; +import org.sakaiproject.tool.api.ToolSession; +import org.sakaiproject.tool.api.SessionManager; +import org.sakaiproject.tool.api.ActiveTool; +import org.sakaiproject.tool.api.Tool; +import org.sakaiproject.tool.api.ToolException; +import org.sakaiproject.tool.api.ActiveToolManager; +import org.sakaiproject.tool.api.ToolManager; +import org.sakaiproject.jsf.util.JsfTool; +import org.sakaiproject.util.Web; + +public class UserAuditJsfTool extends JsfTool { + + /** + * + */ + private static final long serialVersionUID = -976719461956856669L; + + private static final Log logger = LogFactory.getLog(UserAuditJsfTool.class); + + private SessionManager sessionManager; + + private ActiveToolManager activeToolManager; + + private ToolManager toolManager; + + private static final String HELPER_EXT = ".helper"; + + private static final String PANEL = "panel"; + + private static final String HELPER_SESSION_PREFIX = "session."; + + // FIXME: http://bugs.sakaiproject.org/jira/browse/GM-88 + private static final String MYFACES_VIEW_COLLECTION = "org.apache.myfaces.application.jsp.JspStateManagerImpl.SERIALIZED_VIEW"; + + private static final String STORED_MYFACES_VIEW_COLLECTION = "STORED_" + + MYFACES_VIEW_COLLECTION; + + // If this URL is requested, the helper is done and ready to return + public static final String HELPER_RETURN_NOTIFICATION = "/returnToSender"; + + // Override init to inject necessary components via ComponentManager cover + @Override + public void init(ServletConfig config) throws ServletException { + + super.init(config); + + sessionManager = (SessionManager) ComponentManager + .get("org.sakaiproject.tool.api.SessionManager"); + activeToolManager = (ActiveToolManager) ComponentManager + .get("org.sakaiproject.tool.api.ActiveToolManager"); + toolManager = (ToolManager) ComponentManager + .get("org.sakaiproject.tool.api.ToolManager"); + } + + @Override + protected void dispatch(HttpServletRequest req, HttpServletResponse res) + throws ServletException, IOException { + logger.debug("dispatch()"); + + String target = req.getPathInfo(); + + ToolSession session = sessionManager.getCurrentToolSession(); + + if (logger.isDebugEnabled()) { + Map reqParms = req.getParameterMap(); + for(Map.Entry entry : reqParms.entrySet()) + { + String reqParmKey = entry.getKey(); + StringBuffer sb = new StringBuffer(); + sb.append("REQ_PARM: "); + sb.append(reqParmKey); + sb.append(" = "); + sb.append('['); + String[] reqParm = reqParms.get(reqParmKey); + for (int i = 0; i < reqParm.length;) { + sb.append(reqParm[i]); + if (++i < reqParm.length) { + sb.append(", "); + } + } + sb.append(']'); + logger.debug(sb.toString()); + } + Enumeration sessionParmNames = session.getAttributeNames(); + while (sessionParmNames.hasMoreElements()) { + String sessionParmName = sessionParmNames.nextElement(); + logger.debug("SESS_PARM: " + sessionParmName + " = " + + session.getAttribute(sessionParmName)); + } + } + + // see if this is the helper trying to return to caller + if (HELPER_RETURN_NOTIFICATION.equals(target)) { + target = (String) session.getAttribute(toolManager.getCurrentTool() + .getId() + + Tool.HELPER_DONE_URL); + if (target != null) { + + // FIXME: Workaround for + // http://bugs.sakaiproject.org/jira/browse/GM-88 + Object viewCollection = session + .getAttribute(STORED_MYFACES_VIEW_COLLECTION); + if (viewCollection != null) { + session.removeAttribute(STORED_MYFACES_VIEW_COLLECTION); + session.setAttribute(MYFACES_VIEW_COLLECTION, + viewCollection); + } + + session.removeAttribute(toolManager.getCurrentTool().getId() + + Tool.HELPER_DONE_URL); + res.sendRedirect(target); + return; + } + } + + // Need this here until ToolServlet is updated to support this in + // sendToHelper method + // http://bugs.sakaiproject.org/jira/browse/SAK-9043 + // http://bugs.sakaiproject.org/jira/browse/GM-69 + Enumeration params = req.getParameterNames(); + while (params.hasMoreElements()) { + String paramName = params.nextElement(); + if (paramName.startsWith(HELPER_SESSION_PREFIX)) { + String attributeName = paramName + .substring(HELPER_SESSION_PREFIX.length()); + session + .setAttribute(attributeName, req + .getParameter(paramName)); + } + } + + if (sendToHelper(req, res, target)) { + return; + } + + // see if we have a resource request - i.e. a path with an extension, + // and one that is not the JSF_EXT + if (isResourceRequest(target)) { + // get a dispatcher to the path + RequestDispatcher resourceDispatcher = getServletContext() + .getRequestDispatcher(target); + if (resourceDispatcher != null) { + resourceDispatcher.forward(req, res); + return; + } + } + + if ("Title".equals(req.getParameter(PANEL))) { + // This allows only one Title JSF for each tool + target = "/title.jsf"; + + } else { + + if ((target == null) || "/".equals(target)) { + target = computeDefaultTarget(); + + // make sure it's a valid path + if (!target.startsWith("/")) { + target = "/" + target; + } + + // now that we've messed with the URL, send a redirect to make + // it official + res.sendRedirect(Web.returnUrl(req, target)); + return; + } + + // see if we want to change the specifically requested view + String newTarget = redirectRequestedTarget(target); + + // make sure it's a valid path + if (!newTarget.startsWith("/")) { + newTarget = "/" + newTarget; + } + + if (!newTarget.equals(target)) { + // now that we've messed with the URL, send a redirect to make + // it official + res.sendRedirect(Web.returnUrl(req, newTarget)); + return; + } + target = newTarget; + + // store this + if (m_defaultToLastView) { + session.setAttribute(LAST_VIEW_VISITED, target); + } + } + + // add the configured folder root and extension (if missing) + target = m_path + target; + + // add the default JSF extension (if we have no extension) + int lastSlash = target.lastIndexOf('/'); + int lastDot = target.lastIndexOf('.'); + if ((lastDot < 0) || (lastDot < lastSlash)) { + target += JSF_EXT; + } + + // set the information that can be removed from return URLs + req.setAttribute(URL_PATH, m_path); + req.setAttribute(URL_EXT, ".jsp"); + + // set the sakai request object wrappers to provide the native, not + // Sakai set up, URL information + // - this assures that the FacesServlet can dispatch to the proper view + // based on the path info + req.setAttribute(Tool.NATIVE_URL, Tool.NATIVE_URL); + + // TODO: Should setting the HTTP headers be moved up to the portal level + // as well? + res.setContentType("text/html; charset=UTF-8"); + res.addDateHeader("Expires", System.currentTimeMillis() + - (1000L * 60L * 60L * 24L * 365L)); + res.addDateHeader("Last-Modified", System.currentTimeMillis()); + res + .addHeader("Cache-Control", + "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"); + res.addHeader("Pragma", "no-cache"); + + // dispatch to the target + /* + * M_log.debug("dispatching path: " + req.getPathInfo() + " to: " + + * target + " context: " + getServletContext().getServletContextName()); + */ + + RequestDispatcher dispatcher = getServletContext() + .getRequestDispatcher(target); + dispatcher.forward(req, res); + + // restore the request object + req.removeAttribute(Tool.NATIVE_URL); + req.removeAttribute(URL_PATH); + req.removeAttribute(URL_EXT); + } + + protected boolean sendToHelper(HttpServletRequest req, + HttpServletResponse res, String target) throws ToolException { + if (target == null) { + target = "/"; + } + + // 0 parts means the target was just "/", otherwise parts[0] = "", + // parts[1] = item id, parts[2] if present is "edit"... + String[] parts = target.split("/"); + + if (parts.length < 2) { + return false; + } + + if (!parts[1].endsWith(HELPER_EXT)) { + return false; + } + + // calc helper id + int posEnd = parts[1].lastIndexOf('.'); + + String helperId = target.substring(1, posEnd + 1); + ActiveTool helperTool = activeToolManager.getActiveTool(helperId); + + ToolSession toolSession = sessionManager.getCurrentToolSession(); + + if (toolSession.getAttribute(helperTool.getId() + Tool.HELPER_DONE_URL) == null) { + toolSession.setAttribute(helperTool.getId() + Tool.HELPER_DONE_URL, + req.getContextPath() + req.getServletPath() + + computeDefaultTarget()); + } + + String context = req.getContextPath() + req.getServletPath() + + Web.makePath(parts, 1, 2); + String toolPath = Web.makePath(parts, 2, parts.length); + + // FIXME: Workaround for http://bugs.sakaiproject.org/jira/browse/GM-88 + // Don't overwrite if already stored + if (toolSession.getAttribute(STORED_MYFACES_VIEW_COLLECTION) == null) { + Object viewCollection = toolSession + .getAttribute(MYFACES_VIEW_COLLECTION); + if (viewCollection != null) { + toolSession.removeAttribute(MYFACES_VIEW_COLLECTION); + toolSession.setAttribute(STORED_MYFACES_VIEW_COLLECTION, + viewCollection); + } + } + + helperTool.help(req, res, context, toolPath); + + return true; // was handled as helper call + } +} Index: userauditservice/util/src/java/org/sakaiproject/userauditservice/util/UserAuditRegistrationUtil.java =================================================================== --- userauditservice/util/src/java/org/sakaiproject/userauditservice/util/UserAuditRegistrationUtil.java (revision 0) +++ userauditservice/util/src/java/org/sakaiproject/userauditservice/util/UserAuditRegistrationUtil.java (working copy) @@ -0,0 +1,243 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2013 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.userauditservice.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.sakaiproject.db.api.SqlService; +import org.sakaiproject.userauditservice.api.UserAuditRegistration; +import org.sakaiproject.userauditservice.api.UserAuditService; +import org.sakaiproject.util.ResourceLoader; + +/** + * UserAuditUtil + */ +public class UserAuditRegistrationUtil implements UserAuditRegistration +{ + /** Our log (commons). */ + private static Log M_log = LogFactory.getLog(UserAuditRegistrationUtil.class); + + // Services needed + protected SqlService sqlService; + protected UserAuditService userAuditService; + + // Other variables + private String bundleLocation = ""; + private ResourceLoader rl = null; + private String databaseSourceKey = ""; + private String sourceText = ""; + + // flag for telling the UI there's parameters to consider + public boolean hasParameters = false; + + /** UserAuditService init() */ + public void init() + { + ResourceLoader loader = getLocalResourceLoader(); + if (loader != null) { + this.sourceText = loader.getString(getDatabaseSourceKey()); + } + getUserAuditService().register(this); + } + + public SqlService getSqlService() { + return sqlService; + } + + public void setSqlService(SqlService sqlService) { + this.sqlService = sqlService; + } + + public UserAuditService getUserAuditService() { + return userAuditService; + } + + public void setUserAuditService(UserAuditService userAuditService) { + this.userAuditService = userAuditService; + } + + /** + * Get the fully qualified package of where the message bundle is located. + * @return + */ + public String getBundleLocation() { + return bundleLocation; + } + + /** + * Setter + * @param bundleLocation + */ + public void setBundleLocation(String bundleLocation) { + this.bundleLocation = bundleLocation; + } + + public ResourceLoader getResourceLoader(String location) { + return new ResourceLoader(location); + } + + /** + * Gets the ResourceLoader specified by the bundleLocation. + * @return + */ + private ResourceLoader getLocalResourceLoader() { + if (rl == null) { + rl = (ResourceLoader)getResourceLoader(getBundleLocation()); + } + return rl; + } + + public String getDatabaseSourceKey() { + return databaseSourceKey; + } + + public void setDatabaseSourceKey(String databaseSourceKey) { + this.databaseSourceKey = databaseSourceKey; + } + + public String getSourceText(String[] parameter) { + if (isHasParameters()) + { + return rl.getFormattedMessage(getDatabaseSourceKey(), parameter); + } + + return sourceText; + } + + public void setSourceText(String sourceText) { + this.sourceText = sourceText; + } + + public boolean isHasParameters() { + return hasParameters; + } + + public void setHasParameters(boolean hasParameters) { + this.hasParameters = hasParameters; + } + + /** Pass in a List of String[] and this method will process them and write to the database */ + public void addToUserAuditing(List userAuditList) + { + // determine which flavor of database we're using + String sqlVendor = sqlService.getVendor(); + + for (String[] auditStrings : userAuditList) + { + String siteId = auditStrings[0]; + String username = auditStrings[1]; + String roleName = auditStrings[2]; + String actionTaken = auditStrings[3]; + String source = auditStrings[4]; + String actionUserId = auditStrings[5]; + Connection conn = null; + String sql = null; + try + { + conn = sqlService.borrowConnection(); + Object fields[] = new Object[7]; + if ("oracle".equals(sqlVendor)) + { + sql = "insert into USER_AUDITS_LOG (ID,SITE_ID,USER_ID,ROLE_NAME,ACTION_TAKEN,AUDIT_STAMP,SOURCE,ACTION_USER_ID) values (USER_AUDITS_LOG_SEQ.nextval,?,?,?,?,to_date(?,'YYYY-MM-DD HH24:MI:SS'),?,?)"; + } + else + { + sql = "insert into USER_AUDITS_LOG (SITE_ID,USER_ID,ROLE_NAME,ACTION_TAKEN,AUDIT_STAMP,SOURCE,ACTION_USER_ID) values (?,?,?,?,?,?,?)"; + } + fields[0] = siteId; + fields[1] = username; + fields[2] = roleName; + fields[3] = actionTaken; + Date currentDate = new Date(); + DateFormat actionDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + String actionDate = actionDateFormat.format(currentDate); + fields[4] = actionDate; + fields[5] = source; + fields[6] = actionUserId; + sqlService.dbWrite(sql, fields); + } + catch (SQLException e) + { + M_log.warn("ERROR logging information for the User Auditing process!", e); + } + finally + { + if (conn!=null) + { + try + { + conn.close(); + } + catch (SQLException e) + { + M_log.warn("Error trying to close the connection in the addToUserAuditing function."); + } + } + } + } + } + + /** Method to delete all the user auditing log entries for a site. Used when deleting a site */ + public void deleteUserAuditingFromSite(String siteId) + { + Connection conn = null; + String sql = null; + try + { + conn = sqlService.borrowConnection(); + Object fields[] = new Object[1]; + + sql = "delete from USER_AUDITS_LOG where SITE_ID = ?"; + + fields[0] = siteId; + sqlService.dbWrite(sql, fields); + } + catch (SQLException e) + { + M_log.warn("ERROR deleting user auditing logs from site: " + siteId, e); + } + finally + { + if (conn!=null) + { + try + { + conn.close(); + } + catch (SQLException e) + { + M_log.warn("Error trying to close the connection in the addToUserAuditing function."); + } + } + } + } +}