diff --git a/site-manage/site-manage-impl/impl/pom.xml b/site-manage/site-manage-impl/impl/pom.xml index 21fd69ba1e16..f2c55ec85202 100644 --- a/site-manage/site-manage-impl/impl/pom.xml +++ b/site-manage/site-manage-impl/impl/pom.xml @@ -86,6 +86,14 @@ jdom 1.0 + + org.sakaiproject.userauditservice + userauditservice-api + + + org.sakaiproject.userauditservice + userauditservice-util + diff --git a/site-manage/site-manage-impl/impl/src/bundle/UserAuditService.properties b/site-manage/site-manage-impl/impl/src/bundle/UserAuditService.properties new file mode 100644 index 000000000000..83f5da155526 --- /dev/null +++ b/site-manage/site-manage-impl/impl/src/bundle/UserAuditService.properties @@ -0,0 +1,6 @@ +#M will display as Last Name, First Name (user's eid) +M = {0} ({1}) +S = Self +#M will display as Last Name, First Name (user's eid) +M = {0} ({1}) +S = Self \ No newline at end of file diff --git a/site-manage/site-manage-impl/impl/src/java/org/sakaiproject/sitemanage/impl/UserAuditSiteManageImpl.java b/site-manage/site-manage-impl/impl/src/java/org/sakaiproject/sitemanage/impl/UserAuditSiteManageImpl.java new file mode 100644 index 000000000000..40bb031a1b25 --- /dev/null +++ b/site-manage/site-manage-impl/impl/src/java/org/sakaiproject/sitemanage/impl/UserAuditSiteManageImpl.java @@ -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); + } + +} diff --git a/site-manage/site-manage-impl/pack/src/webapp/WEB-INF/components.xml b/site-manage/site-manage-impl/pack/src/webapp/WEB-INF/components.xml index 0ac2e42d1343..6609f6c0107a 100644 --- a/site-manage/site-manage-impl/pack/src/webapp/WEB-INF/components.xml +++ b/site-manage/site-manage-impl/pack/src/webapp/WEB-INF/components.xml @@ -83,5 +83,22 @@ bean="org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory" /> + + + UserAuditService + M + true + + + + UserAuditService + S + diff --git a/site-manage/site-manage-participant-helper/pom.xml b/site-manage/site-manage-participant-helper/pom.xml index 920737f4fbd8..b697f47899de 100644 --- a/site-manage/site-manage-participant-helper/pom.xml +++ b/site-manage/site-manage-participant-helper/pom.xml @@ -56,6 +56,10 @@ org.sakaiproject.velocity sakai-velocity-tool-api + + org.sakaiproject.userauditservice + userauditservice-api + commons-lang commons-lang diff --git a/site-manage/site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java b/site-manage/site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java index e349c5e64b2d..a46458ba5c9f 100644 --- a/site-manage/site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java +++ b/site-manage/site-manage-participant-helper/src/java/org/sakaiproject/site/tool/helper/participant/impl/SiteAddParticipantHandler.java @@ -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 class SiteAddParticipantHandler { 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 @@ private List addUsersRealm( boolean notify) { 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 @@ private List addUsersRealm( boolean notify) { 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 @@ private List addUsersRealm( boolean notify) { 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)); diff --git a/site-manage/site-manage-tool/tool/pom.xml b/site-manage/site-manage-tool/tool/pom.xml index 7a3b8a2b8694..258f0b8f45b1 100644 --- a/site-manage/site-manage-tool/tool/pom.xml +++ b/site-manage/site-manage-tool/tool/pom.xml @@ -74,6 +74,10 @@ org.sakaiproject.velocity sakai-velocity-tool + + org.sakaiproject.userauditservice + userauditservice-api + commons-beanutils commons-beanutils diff --git a/site-manage/site-manage-tool/tool/src/bundle/sitesetupgeneric.properties b/site-manage/site-manage-tool/tool/src/bundle/sitesetupgeneric.properties index c272b631cda8..968878aa9430 100644 --- a/site-manage/site-manage-tool/tool/src/bundle/sitesetupgeneric.properties +++ b/site-manage/site-manage-tool/tool/src/bundle/sitesetupgeneric.properties @@ -28,6 +28,7 @@ java.import = Import from Site 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. diff --git a/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java b/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java index a41f5233b94a..e3dc5fa372cc 100644 --- a/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java +++ b/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/MembershipAction.java @@ -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 @@ public class MembershipAction extends PagedResourceActionII 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 @@ public void doJoin(RunData data) 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 @@ public void doUnjoin(RunData data) 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 @@ public void doUnjoin(RunData data) } } 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 diff --git a/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/SiteAction.java b/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/SiteAction.java index 026c81021da0..efc7a09373e7 100644 --- a/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/SiteAction.java +++ b/site-manage/site-manage-tool/tool/src/java/org/sakaiproject/site/tool/SiteAction.java @@ -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 @@ public class SiteAction extends PagedResourceActionII { 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 @@ else if (state.getAttribute(STATE_CM_REQUESTED_SECTIONS) != null) { } } + if (allowUpdateSite) + { + // show add parent sites menu + if (!isMyWorkspace) { + boolean eventLog = "true".equals(ServerConfigurationService.getString("user_audit_log_display", "true")); + if (notStealthOrHiddenTool("sakai.useraudit") && eventLog) { + b.add(new MenuEntry(rb.getString("java.userAuditEventLog"), + "doUserAuditEventLog")); + } + } + } + if (b.size() > 0) { // add the menus to vm @@ -3801,6 +3819,19 @@ public void doExternalHelper(RunData data) { 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); @@ -7818,6 +7849,9 @@ public void doUpdate_participant(RunData data) { // 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++) { @@ -7872,6 +7906,9 @@ public void doUpdate_participant(RunData data) { } 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; @@ -7921,6 +7958,9 @@ public void doUpdate_participant(RunData data) { } 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); } } } catch (UserNotDefinedException e) { @@ -7952,6 +7992,13 @@ public void doUpdate_participant(RunData data) { } } 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);