diff --git a/portal/portal-api/api/pom.xml b/portal/portal-api/api/pom.xml index 1bbf45aabb..20a2e6fb81 100644 --- a/portal/portal-api/api/pom.xml +++ b/portal/portal-api/api/pom.xml @@ -27,10 +27,30 @@ org.sakaiproject.kernel sakai-component-manager + + org.sakaiproject.message + sakai-message-api + + + org.sakaiproject.announcement + sakai-announcement-api + + + org.sakaiproject.assignment + sakai-assignment-api + + + org.sakaiproject.commons + commons-api + javax.portlet portlet-api + + org.sakaiproject.profile2 + profile2-api + javax.servlet javax.servlet-api @@ -39,6 +59,14 @@ org.hibernate hibernate-core + + org.apache.commons + commons-lang3 + + + org.springframework + spring-context + diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/api/BullhornData.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/api/BullhornData.java new file mode 100644 index 0000000000..0c35ff90eb --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/api/BullhornData.java @@ -0,0 +1,15 @@ +package org.sakaiproject.portal.api; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor @Getter +public class BullhornData { + + private String from; + private String to; + private String siteId; + private String title; + private String url; + private boolean social; +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/api/BullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/api/BullhornHandler.java new file mode 100644 index 0000000000..46ffee36f6 --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/api/BullhornHandler.java @@ -0,0 +1,41 @@ +/********************************************************************************** + * $URL$ + * $Id$ + *********************************************************************************** + * + * Copyright (c) 2005, 2006, 2007, 2008 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.portal.api; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.sakaiproject.event.api.Event; +import org.sakaiproject.memory.api.Cache; + +/** + * A handler of events for the bullhorns service. Produces BullhornData objects for + * the service to add to the bullhorn alerts table + * + * @author Adrian Fish + */ +public interface BullhornHandler { + + public String getHandledEvent(); + public Optional> handleEvent(Event e, Cache countCache); +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AbstractBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AbstractBullhornHandler.java new file mode 100644 index 0000000000..5e75c98756 --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AbstractBullhornHandler.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.Arrays; + +import javax.inject.Inject; + +import org.sakaiproject.authz.api.SecurityAdvisor; +import org.sakaiproject.authz.api.SecurityService; +import org.sakaiproject.portal.api.BullhornHandler; + +abstract class AbstractBullhornHandler implements BullhornHandler { + + @Inject + protected SecurityService securityService; + + protected SecurityAdvisor unlock(final String[] functions) { + + SecurityAdvisor securityAdvisor = (String userId, String function, String reference) -> { + + if (functions != null) { + if (Arrays.asList(functions).contains(function)) { + return SecurityAdvisor.SecurityAdvice.ALLOWED; + } else { + return SecurityAdvisor.SecurityAdvice.NOT_ALLOWED; + } + } else { + return SecurityAdvisor.SecurityAdvice.ALLOWED; + } + }; + + securityService.pushAdvisor(securityAdvisor); + return securityAdvisor; + } + + protected void lock(SecurityAdvisor sa) { + securityService.popAdvisor(sa); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AddAssignmentBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AddAssignmentBullhornHandler.java new file mode 100644 index 0000000000..269c508c1e --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AddAssignmentBullhornHandler.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import java.time.Instant; + +import javax.inject.Inject; + +import org.sakaiproject.assignment.api.AssignmentConstants; +import org.sakaiproject.assignment.api.AssignmentService; +import org.sakaiproject.assignment.api.AssignmentServiceConstants; +import org.sakaiproject.assignment.api.model.Assignment; +import org.sakaiproject.authz.api.AuthzGroupService; +import org.sakaiproject.authz.api.SecurityAdvisor; +import org.sakaiproject.event.api.Event; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.SiteService; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class AddAssignmentBullhornHandler extends AbstractBullhornHandler { + + @Inject + private AssignmentService assignmentService; + + @Inject + private AuthzGroupService authzGroupService; + + @Inject + private SiteService siteService; + + @Override + public String getHandledEvent() { + return AssignmentConstants.EVENT_ADD_ASSIGNMENT; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + String siteId = pathParts[3]; + String assignmentId = pathParts[pathParts.length - 1]; + SecurityAdvisor sa = unlock(new String[] {AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT, AssignmentServiceConstants.SECURE_ADD_ASSIGNMENT_SUBMISSION}); + try { + Assignment assignment = assignmentService.getAssignment(assignmentId); + Instant openTime = assignment.getOpenDate(); + if (openTime == null || openTime.isBefore(Instant.now())) { + Site site = siteService.getSite(siteId); + String title = assignment.getTitle(); + String url = assignmentService.getDeepLink(siteId, assignmentId); + Set groupIds = assignment.getGroups(); + Collection groupsUsers = authzGroupService.getAuthzUsersInGroups(groupIds); + + List bhEvents = new ArrayList<>(); + + // Get all the members of the site with read ability + for (String to : site.getUsersIsAllowed(AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT)) { + // If this is a grouped assignment, is 'to' in one of the groups? + if (groupIds.size() == 0 || groupsUsers.contains(to)) { + if (!from.equals(to) && !securityService.isSuperUser(to)) { + bhEvents.add(new BullhornData(from, to, siteId, title, url, false)); + countCache.remove(to); + } + } + } + + return Optional.of(bhEvents); + } + } catch (Exception ex) { + log.error("Failed to find either the assignment or the site", ex); + } finally { + lock(sa); + } + + return Optional.empty(); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AnnouncementsBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AnnouncementsBullhornHandler.java new file mode 100644 index 0000000000..0bebb70349 --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/AnnouncementsBullhornHandler.java @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; + +import org.sakaiproject.announcement.api.AnnouncementMessage; +import org.sakaiproject.announcement.api.AnnouncementMessageHeader; +import org.sakaiproject.announcement.api.AnnouncementService; +import org.sakaiproject.authz.api.SecurityAdvisor; +import org.sakaiproject.component.api.ServerConfigurationService; +import org.sakaiproject.entity.api.EntityManager; +import org.sakaiproject.event.api.Event; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.SiteService; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class AnnouncementsBullhornHandler extends AbstractBullhornHandler { + + @Inject + private AnnouncementService announcementService; + + @Inject + private EntityManager entityManager; + + @Inject + private ServerConfigurationService serverConfigurationService; + + @Inject + private SiteService siteService; + + @Override + public String getHandledEvent() { + return AnnouncementService.SECURE_ANNC_ADD; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + String siteId = pathParts[3]; + + SecurityAdvisor sa = unlock(new String[] {AnnouncementService.SECURE_ANNC_READ}); + try { + AnnouncementMessage message + = (AnnouncementMessage) announcementService.getMessage( + entityManager.newReference(ref)); + + if (announcementService.isMessageViewable(message)) { + Site site = siteService.getSite(siteId); + String toolId = site.getToolForCommonId("sakai.announcements").getId(); + String url = serverConfigurationService.getPortalUrl() + "/directtool/" + toolId + + "?itemReference=" + ref + "&sakai_action=doShowmetadata"; + + // In this case title = announcement subject + String title + = ((AnnouncementMessageHeader) message.getHeader()).getSubject(); + + List bhEvents = new ArrayList<>(); + + // Get all the members of the site with read ability + for (String to : site.getUsersIsAllowed(AnnouncementService.SECURE_ANNC_READ)) { + if (!from.equals(to) && !securityService.isSuperUser(to)) { + bhEvents.add(new BullhornData(from, to, siteId, title, url, false)); + countCache.remove(to); + } + } + return Optional.of(bhEvents); + } + } catch (Exception ex) { + log.error("No site with id '" + siteId + "'", ex); + } finally { + lock(sa); + } + + return Optional.empty(); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/CommonsCommentBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/CommonsCommentBullhornHandler.java new file mode 100644 index 0000000000..a74f7b6890 --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/CommonsCommentBullhornHandler.java @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; + +import org.sakaiproject.commons.api.CommonsEvents; +import org.sakaiproject.commons.api.CommonsManager; +import org.sakaiproject.commons.api.datamodel.Comment; +import org.sakaiproject.commons.api.datamodel.Post; +import org.sakaiproject.component.api.ServerConfigurationService; +import org.sakaiproject.event.api.Event; +import org.sakaiproject.exception.IdUnusedException; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.SiteService; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class CommonsCommentBullhornHandler extends AbstractBullhornHandler { + + @Inject + private CommonsManager commonsManager; + + @Inject + private ServerConfigurationService serverConfigurationService; + + @Inject + private SiteService siteService; + + @Override + public String getHandledEvent() { + return CommonsEvents.COMMENT_CREATED; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String commentCreator = e.getUserId(); + + String ref = e.getResource(); + final String siteId = e.getContext(); + String[] pathParts = ref.split("/"); + + String postId = pathParts[4]; + + // To is always going to be the author of the original post + Post post = commonsManager.getPost(postId, true); + if (post != null) { + if ("SOCIAL".equals(siteId)) { + return Optional.empty(); + } + + String postCreator = post.getCreatorId(); + + String url = null; + String siteTitle = null; + try { + Site site = siteService.getSite(siteId); + siteTitle = site.getTitle(); + //ToolConfiguration toolConfig = site.getToolForCommonId("sakai.commons"); + String toolId = site.getToolForCommonId("sakai.commons").getId(); + url = serverConfigurationService.getPortalUrl() + "/directtool/" + + toolId + "/posts/" + postId; + } catch (IdUnusedException ex) { + log.error("Couldn't find site " + siteId, ex); + return Optional.empty(); + } + + List bhEvents = new ArrayList<>(); + + // First, send an alert to the post author + if (!commentCreator.equals(postCreator)) { + bhEvents.add(new BullhornData(commentCreator, postCreator, siteId, siteTitle, url, false)); + countCache.remove(postCreator); + } + + List sentAlready = new ArrayList<>(); + + // Now, send an alert to anybody else who has commented on this post. + for (Comment comment : post.getComments()) { + + String to = comment.getCreatorId(); + + // If we're commenting on our own post, no alert needed + if (to.equals(post.getCreatorId()) || to.equals(commentCreator)) { + continue; + } + + if (!sentAlready.contains(to)) { + bhEvents.add(new BullhornData(commentCreator, to, siteId, siteTitle, url, false)); + countCache.remove(to); + sentAlready.add(to); + } + } + return Optional.of(bhEvents); + } + + return Optional.empty(); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendConfirmBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendConfirmBullhornHandler.java new file mode 100644 index 0000000000..aafa0cfcee --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendConfirmBullhornHandler.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.sakaiproject.event.api.Event; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.profile2.logic.ProfileLinkLogic; +import org.sakaiproject.profile2.util.ProfileConstants; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class FriendConfirmBullhornHandler extends AbstractBullhornHandler { + + @Inject + private ProfileLinkLogic profileLinkLogic; + + @Inject @Named("org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory") + private SessionFactory sessionFactory; + + @Override + public String getHandledEvent() { + return ProfileConstants.EVENT_FRIEND_CONFIRM; + } + + public boolean isAcademic() { + return false; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + String to = pathParts[2]; + Session session = sessionFactory.openSession(); + Transaction tx = session.beginTransaction(); + try { + session.createQuery("delete BullhornAlert where event = :event and fromUser = :fromUser") + .setString("event", ProfileConstants.EVENT_FRIEND_REQUEST) + .setString("fromUser", to).executeUpdate(); + tx.commit(); + } catch (Exception e1) { + log.error("Failed to delete bullhorn request event", e1); + tx.rollback(); + } finally { + session.close(); + } + String url = profileLinkLogic.getInternalDirectUrlToUserConnections(to); + countCache.remove(to); + countCache.remove(from); + return Optional.of(Collections.singletonList(new BullhornData(from, to, "", "", url, true))); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendIgnoreBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendIgnoreBullhornHandler.java new file mode 100644 index 0000000000..60a7fbb359 --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendIgnoreBullhornHandler.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; +import javax.inject.Named; + +import org.sakaiproject.event.api.Event; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.profile2.util.ProfileConstants; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class FriendIgnoreBullhornHandler extends AbstractBullhornHandler { + + @Inject @Named("org.sakaiproject.springframework.orm.hibernate.GlobalSessionFactory") + private SessionFactory sessionFactory; + + @Override + public String getHandledEvent() { + return ProfileConstants.EVENT_FRIEND_IGNORE; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + String to = pathParts[2]; + Session session = sessionFactory.openSession(); + Transaction tx = session.beginTransaction(); + try { + session.createQuery("delete BullhornAlert where event = :event and fromUser = :fromUser") + .setString("event", ProfileConstants.EVENT_FRIEND_REQUEST) + .setString("fromUser", to).executeUpdate(); + tx.commit(); + } catch (Exception e1) { + log.error("Failed to delete bullhorn request event", e1); + tx.rollback(); + } finally { + session.close(); + } + countCache.remove(from); + return Optional.empty(); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendMessageBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendMessageBullhornHandler.java new file mode 100644 index 0000000000..fc6c955571 --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendMessageBullhornHandler.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; + +import org.sakaiproject.component.api.ServerConfigurationService; +import org.sakaiproject.event.api.Event; +import org.sakaiproject.exception.IdUnusedException; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.profile2.util.ProfileConstants; +import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.SiteService; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class FriendMessageBullhornHandler extends AbstractBullhornHandler { + + @Inject + private ServerConfigurationService serverConfigurationService; + + @Inject + private SiteService siteService; + + @Override + public String getHandledEvent() { + return ProfileConstants.EVENT_MESSAGE_SENT; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + String to = pathParts[2]; + String siteId = "~" + to; + + try { + Site site = siteService.getSite(siteId); + String toolId = site.getToolForCommonId("sakai.profile2").getId(); + String url = serverConfigurationService.getPortalUrl() + "/site/" + siteId + + "/tool/" + toolId + "/messages"; + countCache.remove(to); + return Optional.of(Collections.singletonList(new BullhornData(from, to, siteId, "", url, true))); + } catch (IdUnusedException idue) { + log.error("No site for id: " + siteId); + } + + return Optional.empty(); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendRequestBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendRequestBullhornHandler.java new file mode 100644 index 0000000000..a49e735e0e --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendRequestBullhornHandler.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; + +import org.sakaiproject.component.api.ServerConfigurationService; +import org.sakaiproject.event.api.Event; +import org.sakaiproject.exception.IdUnusedException; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.profile2.util.ProfileConstants; +import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.SiteService; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class FriendRequestBullhornHandler extends AbstractBullhornHandler { + + @Inject + private ServerConfigurationService serverConfigurationService; + + @Inject + private SiteService siteService; + + @Override + public String getHandledEvent() { + return ProfileConstants.EVENT_FRIEND_REQUEST; + } + + public boolean isAcademic() { + return false; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + String to = pathParts[2]; + String siteId = "~" + to; + try { + Site site = siteService.getSite(siteId); + String toolId = site.getToolForCommonId("sakai.profile2").getId(); + String url = serverConfigurationService.getPortalUrl() + "/site/" + siteId + + "/tool/" + toolId + "/connections"; + countCache.remove(to); + return Optional.of(Collections.singletonList(new BullhornData(from, to, siteId, "", url, true))); + } catch (IdUnusedException idue) { + log.error("No site for id: " + siteId); + } + + return Optional.empty(); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendStatusBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendStatusBullhornHandler.java new file mode 100644 index 0000000000..4f9d0ef72e --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/FriendStatusBullhornHandler.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; + +import org.sakaiproject.event.api.Event; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.profile2.logic.ProfileConnectionsLogic; +import org.sakaiproject.profile2.logic.ProfileLinkLogic; +import org.sakaiproject.profile2.util.ProfileConstants; +import org.sakaiproject.user.api.User; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class FriendStatusBullhornHandler extends AbstractBullhornHandler { + + @Inject + private ProfileConnectionsLogic profileConnectionsLogic; + + @Inject + private ProfileLinkLogic profileLinkLogic; + + @Override + public String getHandledEvent() { + return ProfileConstants.EVENT_STATUS_UPDATE; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + List bhEvents = new ArrayList<>(); + + // Get all the posters friends + List connections = profileConnectionsLogic.getConnectedUsersForUserInsecurely(from); + for (User connection : connections) { + String to = connection.getId(); + String url = profileLinkLogic.getInternalDirectUrlToUserProfile(to, from); + bhEvents.add(new BullhornData(from, to, "", "", url, true)); + countCache.remove(to); + } + + return Optional.of(bhEvents); + } +} diff --git a/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/GradeAssignmentBullhornHandler.java b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/GradeAssignmentBullhornHandler.java new file mode 100644 index 0000000000..5c67ecf655 --- /dev/null +++ b/portal/portal-api/api/src/java/org/sakaiproject/portal/beans/bullhornhandlers/GradeAssignmentBullhornHandler.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2003-2017 The Apereo 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://opensource.org/licenses/ecl2 + * + * 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.portal.beans.bullhornhandlers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; + +import org.sakaiproject.assignment.api.AssignmentConstants; +import org.sakaiproject.assignment.api.AssignmentService; +import org.sakaiproject.assignment.api.AssignmentServiceConstants; +import org.sakaiproject.assignment.api.model.Assignment; +import org.sakaiproject.assignment.api.model.AssignmentSubmission; +import org.sakaiproject.authz.api.SecurityAdvisor; +import org.sakaiproject.event.api.Event; +import org.sakaiproject.memory.api.Cache; +import org.sakaiproject.portal.api.BullhornData; + +import org.springframework.stereotype.Component; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +public class GradeAssignmentBullhornHandler extends AbstractBullhornHandler { + + @Inject + private AssignmentService assignmentService; + + @Override + public String getHandledEvent() { + return AssignmentConstants.EVENT_GRADE_ASSIGNMENT_SUBMISSION; + } + + @Override + public Optional> handleEvent(Event e, Cache countCache) { + + String from = e.getUserId(); + + String ref = e.getResource(); + String[] pathParts = ref.split("/"); + + String siteId = pathParts[3]; + String submissionId = pathParts[pathParts.length - 1]; + SecurityAdvisor sa = unlock(new String[] {AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT_SUBMISSION + , AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT + , AssignmentServiceConstants.SECURE_ADD_ASSIGNMENT_SUBMISSION}); + + // Without hacking assignment's permissions model, this is only way to + // get a submission, other than switching to the submitting user. + try { + AssignmentSubmission submission = assignmentService.getSubmission(submissionId); + if (submission.getGradeReleased()) { + Assignment assignment = submission.getAssignment(); + String title = assignment.getTitle(); + String url = assignmentService.getDeepLink(siteId, assignment.getId()); + List bhEvents = new ArrayList<>(); + submission.getSubmitters().forEach(to -> { + bhEvents.add(new BullhornData(from, to.getSubmitter(), siteId, title, url, false)); + countCache.remove(to.getSubmitter()); + }); + + return Optional.of(bhEvents); + } + } catch (Exception ex) { + log.error("Failed to find either the submission or the site", ex); + } finally { + lock(sa); + } + + return Optional.empty(); + } +} diff --git a/portal/portal-impl/impl/src/bundle/bullhorns.properties b/portal/portal-impl/impl/src/bundle/bullhorns.properties index a3e91635f6..ee484800c6 100644 --- a/portal/portal-impl/impl/src/bundle/bullhorns.properties +++ b/portal/portal-impl/impl/src/bundle/bullhorns.properties @@ -15,5 +15,5 @@ assignmentCreated = \u0020created a new assignment "{0}" in "{1}" assignmentSubmissionGraded = \u0020graded your submission for assignment "{0}" in "{1}" clearAll = Clear All unrecognisedAlert = Unrecognised alert -academicCommentCreated = \u0020commented on your post in "{0}" +academicCommentCreated = \u0020commented on your post, or on a post you commented on, in "{0}" academicLessonBuilderCommentCreate = \u0020commented on a lessons page in "{0}" diff --git a/portal/portal-service-impl/impl/pom.xml b/portal/portal-service-impl/impl/pom.xml index cb226173e9..b6bc126860 100644 --- a/portal/portal-service-impl/impl/pom.xml +++ b/portal/portal-service-impl/impl/pom.xml @@ -35,30 +35,10 @@ org.sakaiproject.kernel sakai-kernel-util - - org.sakaiproject.announcement - sakai-announcement-api - - - org.sakaiproject.assignment - sakai-assignment-api - - - org.sakaiproject.message - sakai-message-api - - - org.sakaiproject.profile2 - profile2-api - org.sakaiproject.lessonbuilder lessonbuilder-api - - org.sakaiproject.commons - commons-api - ${project.groupId} sakai-portal-api diff --git a/portal/portal-service-impl/impl/src/java/org/sakaiproject/portal/service/BullhornServiceImpl.java b/portal/portal-service-impl/impl/src/java/org/sakaiproject/portal/service/BullhornServiceImpl.java index 3fbc91d4b7..99d74e5d2e 100644 --- a/portal/portal-service-impl/impl/src/java/org/sakaiproject/portal/service/BullhornServiceImpl.java +++ b/portal/portal-service-impl/impl/src/java/org/sakaiproject/portal/service/BullhornServiceImpl.java @@ -15,37 +15,25 @@ */ package org.sakaiproject.portal.service; -import java.time.Instant; -import java.util.*; -import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.function.Function; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Observable; +import java.util.Observer; +import java.util.Optional; +import java.util.stream.Collectors; import org.apache.commons.lang.StringUtils; -import org.hibernate.criterion.Restrictions; -import org.hibernate.criterion.Projections; -import org.hibernate.HibernateException; -import org.hibernate.Session; import org.hibernate.SessionFactory; -import org.hibernate.Transaction; - -import org.sakaiproject.announcement.api.AnnouncementMessage; -import org.sakaiproject.announcement.api.AnnouncementMessageHeader; -import org.sakaiproject.announcement.api.AnnouncementService; -import org.sakaiproject.assignment.api.AssignmentConstants; -import org.sakaiproject.assignment.api.AssignmentService; -import org.sakaiproject.assignment.api.AssignmentServiceConstants; -import org.sakaiproject.assignment.api.model.Assignment; -import org.sakaiproject.assignment.api.model.AssignmentSubmission; -import org.sakaiproject.authz.api.AuthzGroupService; -import org.sakaiproject.authz.api.SecurityAdvisor; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; import org.sakaiproject.authz.api.SecurityService; -import org.sakaiproject.commons.api.CommonsEvents; -import org.sakaiproject.commons.api.CommonsManager; -import org.sakaiproject.commons.api.datamodel.Comment; -import org.sakaiproject.commons.api.datamodel.Post; -import org.sakaiproject.component.api.ComponentManager; import org.sakaiproject.component.api.ServerConfigurationService; -import org.sakaiproject.entity.api.EntityManager; import org.sakaiproject.event.api.Event; import org.sakaiproject.event.api.EventTrackingService; import org.sakaiproject.exception.IdUnusedException; @@ -56,20 +44,18 @@ import org.sakaiproject.lessonbuildertool.SimplePageComment; import org.sakaiproject.lessonbuildertool.SimplePageItem; import org.sakaiproject.memory.api.Cache; import org.sakaiproject.memory.api.MemoryService; +import org.sakaiproject.portal.api.BullhornData; +import org.sakaiproject.portal.api.BullhornHandler; import org.sakaiproject.portal.api.BullhornService; import org.sakaiproject.portal.beans.BullhornAlert; -import org.sakaiproject.profile2.logic.ProfileConnectionsLogic; -import org.sakaiproject.profile2.logic.ProfileLinkLogic; -import org.sakaiproject.profile2.logic.ProfileStatusLogic; -import org.sakaiproject.profile2.util.ProfileConstants; -import org.sakaiproject.site.api.Site; -import org.sakaiproject.site.api.SitePage; import org.sakaiproject.site.api.SiteService; import org.sakaiproject.time.api.Time; import org.sakaiproject.user.api.User; import org.sakaiproject.user.api.UserDirectoryService; import org.sakaiproject.user.api.UserNotDefinedException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; @@ -77,6 +63,7 @@ import org.springframework.transaction.TransactionStatus; import javax.inject.Inject; + import lombok.Setter; import lombok.extern.slf4j.Slf4j; @@ -85,27 +72,11 @@ public class BullhornServiceImpl implements BullhornService, Observer { private static final List HANDLED_EVENTS = new ArrayList<>(); - @Setter - private AnnouncementService announcementService; - @Setter - private AssignmentService assignmentService; @Inject - private AuthzGroupService authzGroupService; - @Inject - private CommonsManager commonsManager; - @Setter - private EntityManager entityManager; - @Setter private EventTrackingService eventTrackingService; @Setter private MemoryService memoryService; @Setter - private ProfileConnectionsLogic profileConnectionsLogic; - @Setter - private ProfileLinkLogic profileLinkLogic; - @Setter - private ProfileStatusLogic profileStatusLogic; - @Setter private UserDirectoryService userDirectoryService; @Setter private SecurityService securityService; @@ -122,20 +93,20 @@ public class BullhornServiceImpl implements BullhornService, Observer { private Cache countCache = null; + @Autowired + private List handlers; + + private Map handlerMap; + public void init() { if (serverConfigurationService.getBoolean("portal.bullhorns.enabled", true)) { - HANDLED_EVENTS.add(ProfileConstants.EVENT_STATUS_UPDATE); - HANDLED_EVENTS.add(ProfileConstants.EVENT_FRIEND_REQUEST); - HANDLED_EVENTS.add(ProfileConstants.EVENT_FRIEND_CONFIRM); - HANDLED_EVENTS.add(ProfileConstants.EVENT_FRIEND_IGNORE); - HANDLED_EVENTS.add(ProfileConstants.EVENT_MESSAGE_SENT); - HANDLED_EVENTS.add(AnnouncementService.SECURE_ANNC_ADD); - HANDLED_EVENTS.add(AssignmentConstants.EVENT_ADD_ASSIGNMENT); - HANDLED_EVENTS.add(AssignmentConstants.EVENT_GRADE_ASSIGNMENT_SUBMISSION); - HANDLED_EVENTS.add(CommonsEvents.COMMENT_CREATED); HANDLED_EVENTS.add(LessonBuilderEvents.COMMENT_CREATE); HANDLED_EVENTS.add(SiteService.EVENT_SITE_PUBLISH); + + HANDLED_EVENTS.addAll(handlers.stream().map(h -> h.getHandledEvent()).collect(Collectors.toList())); + handlerMap = handlers.stream().collect(Collectors.toMap(BullhornHandler::getHandledEvent, Function.identity())); + eventTrackingService.addLocalObserver(this); } @@ -156,156 +127,21 @@ public class BullhornServiceImpl implements BullhornService, Observer { String from = e.getUserId(); long at = e.getEventTime().getTime(); try { - if (ProfileConstants.EVENT_STATUS_UPDATE.equals(event)) { - // Get all the posters friends - List connections = profileConnectionsLogic.getConnectedUsersForUserInsecurely(from); - for (User connection : connections) { - String to = connection.getId(); - String url = profileLinkLogic.getInternalDirectUrlToUserProfile(to, from); - doSocialInsert(from, to, event, ref, e.getEventTime(), url); - countCache.remove(to); - } - } else if (ProfileConstants.EVENT_FRIEND_REQUEST.equals(event)) { - String to = pathParts[2]; - String siteId = "~" + to; - Site site = siteService.getSite(siteId); - String toolId = site.getToolForCommonId("sakai.profile2").getId(); - String url = serverConfigurationService.getPortalUrl() + "/site/" + siteId - + "/tool/" + toolId + "/connections"; - doSocialInsert(from, to, event, ref, e.getEventTime(), url); - countCache.remove(to); - } else if (ProfileConstants.EVENT_FRIEND_CONFIRM.equals(event) - || ProfileConstants.EVENT_FRIEND_IGNORE.equals(event)) { - String to = pathParts[2]; - Session session = sessionFactory.openSession(); - Transaction tx = session.beginTransaction(); - try { - session.createQuery("delete BullhornAlert where event = :event and fromUser = :fromUser") - .setString("event", ProfileConstants.EVENT_FRIEND_REQUEST) - .setString("fromUser", to).executeUpdate(); - tx.commit(); - } catch (Exception e1) { - log.error("Failed to delete bullhorn request event", e1); - tx.rollback(); - } finally { - session.close(); - } - String url = profileLinkLogic.getInternalDirectUrlToUserConnections(to); - doSocialInsert(from, to, event, ref, e.getEventTime(), url); - countCache.remove(from); - countCache.remove(to); - } else if (ProfileConstants.EVENT_MESSAGE_SENT.equals(event)) { - String to = pathParts[2]; - String siteId = "~" + to; - Site site = siteService.getSite(siteId); - String toolId = site.getToolForCommonId("sakai.profile2").getId(); - String url = serverConfigurationService.getPortalUrl() + "/site/" + siteId - + "/tool/" + toolId + "/messages"; - doSocialInsert(from, to, event, ref, e.getEventTime(), url); - countCache.remove(to); - } else if (CommonsEvents.COMMENT_CREATED.equals(event)) { - String type = pathParts[2]; - String postId = pathParts[4]; - // To is always going to be the author of the original post - Post post = commonsManager.getPost(postId, true); - if (post != null) { - Set tos = new HashSet<>(); - String siteId = post.getSiteId(); - String to = post.getCreatorId(); - tos.add(to); - for (Comment comment : post.getComments()) { - to = comment.getCreatorId(); - tos.add(to); - } - doCommonsCommentInserts(from, event, ref, e, siteId, postId, tos); - } - } else if (AnnouncementService.SECURE_ANNC_ADD.equals(event)) { - String siteId = pathParts[3]; - String announcementId = pathParts[pathParts.length - 1]; - - SecurityAdvisor sa = unlock(new String[] {AnnouncementService.SECURE_ANNC_READ}); - try { - AnnouncementMessage message - = (AnnouncementMessage) announcementService.getMessage( - entityManager.newReference(ref)); - - if (announcementService.isMessageViewable(message)) { - Site site = siteService.getSite(siteId); - String toolId = site.getToolForCommonId("sakai.announcements").getId(); - String url = serverConfigurationService.getPortalUrl() + "/directtool/" + toolId - + "?itemReference=" + ref + "&sakai_action=doShowmetadata"; - - // In this case title = announcement subject - String title - = ((AnnouncementMessageHeader) message.getHeader()).getSubject(); - - // Get all the members of the site with read ability - for (String to : site.getUsersIsAllowed(AnnouncementService.SECURE_ANNC_READ)) { - if (!from.equals(to) && !securityService.isSuperUser(to)) { - doAcademicInsert(from, to, event, ref, title, siteId, e.getEventTime(), url); - countCache.remove(to); - } - } - } - } catch (IdUnusedException idue) { - log.error("No site with id '" + siteId + "'", idue); - } finally { - lock(sa); - } - } else if (AssignmentConstants.EVENT_ADD_ASSIGNMENT.equals(event)) { - String siteId = pathParts[3]; - String assignmentId = pathParts[pathParts.length - 1]; - SecurityAdvisor sa = unlock(new String[] {AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT, AssignmentServiceConstants.SECURE_ADD_ASSIGNMENT_SUBMISSION}); - try { - Assignment assignment = assignmentService.getAssignment(assignmentId); - Instant openTime = assignment.getOpenDate(); - if (openTime == null || openTime.isBefore(Instant.now())) { - Site site = siteService.getSite(siteId); - String title = assignment.getTitle(); - String url = assignmentService.getDeepLink(siteId, assignmentId); - Set groupIds = assignment.getGroups(); - Collection groupsUsers = authzGroupService.getAuthzUsersInGroups(groupIds); - // Get all the members of the site with read ability - for (String to : site.getUsersIsAllowed(AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT)) { - // If this is a grouped assignment, is 'to' in one of the groups? - if (groupIds.size() == 0 || groupsUsers.contains(to)) { - if (!from.equals(to) && !securityService.isSuperUser(to)) { - doAcademicInsert(from, to, event, ref, title, siteId, e.getEventTime(), url); - countCache.remove(to); - } - } + BullhornHandler handler = handlerMap.get(event); + + if (handler != null ) { + Optional> result = handler.handleEvent(e, countCache); + if (result.isPresent()) { + result.get().forEach(bd -> System.out.println(bd.getTo() + " : " + bd.getTitle())); + result.get().forEach(bd -> { + + if (bd.isSocial()) { + doSocialInsert(bd.getFrom(), bd.getTo(), event, ref, e.getEventTime(), bd.getUrl()); + } else { + doAcademicInsert(from, bd.getTo(), event, ref, bd.getTitle(), + bd.getSiteId(), e.getEventTime(), bd.getUrl()); } - } - } catch (IdUnusedException idue) { - log.error("Failed to find either the assignment or the site", idue); - } finally { - lock(sa); - } - } else if (AssignmentConstants.EVENT_GRADE_ASSIGNMENT_SUBMISSION.equals(event)) { - String siteId = pathParts[3]; - String submissionId = pathParts[pathParts.length - 1]; - SecurityAdvisor sa = unlock(new String[] {AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT_SUBMISSION - , AssignmentServiceConstants.SECURE_ACCESS_ASSIGNMENT - , AssignmentServiceConstants.SECURE_ADD_ASSIGNMENT_SUBMISSION}); - - // Without hacking assignment's permissions model, this is only way to - // get a submission, other than switching to the submitting user. - try { - AssignmentSubmission submission = assignmentService.getSubmission(submissionId); - if (submission.getGradeReleased()) { - Site site = siteService.getSite(siteId); - Assignment assignment = submission.getAssignment(); - String title = assignment.getTitle(); - String url = assignmentService.getDeepLink(siteId, assignment.getId()); - submission.getSubmitters().forEach(to -> { - doAcademicInsert(from, to.getSubmitter(), event, ref, title, siteId, e.getEventTime(), url); - countCache.remove(to.getSubmitter()); - }); - } - } catch (IdUnusedException idue) { - log.error("Failed to find either the submission or the site", idue); - } finally { - lock(sa); + }); } } else if (LessonBuilderEvents.COMMENT_CREATE.equals(event)) { try { @@ -377,38 +213,9 @@ public class BullhornServiceImpl implements BullhornService, Observer { } } - /** - * Supply null to this and everything will be allowed. Supply - * a list of functions and only they will be allowed. - */ - private SecurityAdvisor unlock(final String[] functions) { - - SecurityAdvisor securityAdvisor = new SecurityAdvisor() { - public SecurityAdvice isAllowed(String userId, String function, String reference) { - - if (functions != null) { - if (Arrays.asList(functions).contains(function)) { - return SecurityAdvice.ALLOWED; - } else { - return SecurityAdvice.NOT_ALLOWED; - } - } else { - return SecurityAdvice.ALLOWED; - } - } - }; - securityService.pushAdvisor(securityAdvisor); - return securityAdvisor; - } - - private void lock(SecurityAdvisor securityAdvisor) { - securityService.popAdvisor(securityAdvisor); - } - private void doAcademicInsert(String from, String to, String event, String ref , String title, String siteId, Date eventDate, String url) { - transactionTemplate.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status) { @@ -460,39 +267,6 @@ public class BullhornServiceImpl implements BullhornService, Observer { }); } - private void doCommonsCommentInserts(String from, String event, String ref, Event e, String siteId, String postId, Set tos) { - - log.debug("Inserting Commons comment alerts: from is {}, tos is {}, siteId is {}", from, tos, siteId); - boolean isSocial = siteId.equals("SOCIAL"); - for (String to : tos) { - // If we're commenting on our own post, no alert needed - if (!from.equals(to)) { - String mySiteId = siteId; - if (isSocial) { - mySiteId = "~" + to; - } - Site site = null; - try { - site = siteService.getSite(mySiteId); - } catch (IdUnusedException ex) { - log.error("Couldn't find site " + mySiteId, ex); - } - if (site != null) { - String toolId = site.getToolForCommonId("sakai.commons").getId(); - String url = serverConfigurationService.getPortalUrl() + "/directtool/" - + toolId + "/posts/" + postId; - if (isSocial) { - doSocialInsert(from, to, event, ref, e.getEventTime(), url); - } else { - String title = ""; - doAcademicInsert(from, to, event, ref, title, siteId, e.getEventTime(), url); - } - countCache.remove(to); - } - } - } - } - @Transactional public List getSocialAlerts(String userId) { diff --git a/portal/portal-service-impl/impl/src/webapp/WEB-INF/components.xml b/portal/portal-service-impl/impl/src/webapp/WEB-INF/components.xml index 0e156bb8dd..08c0cfc6f2 100644 --- a/portal/portal-service-impl/impl/src/webapp/WEB-INF/components.xml +++ b/portal/portal-service-impl/impl/src/webapp/WEB-INF/components.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> - + - - - - - - -