001/* 002 * Copyright 2023 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.workspaces.activities.projects; 017 018import java.util.List; 019import java.util.Map; 020import java.util.stream.Collectors; 021import java.util.stream.Stream; 022 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.commons.lang3.StringUtils; 026import org.apache.commons.lang3.tuple.Pair; 027 028import org.ametys.core.group.Group; 029import org.ametys.core.group.GroupIdentity; 030import org.ametys.core.group.GroupManager; 031import org.ametys.core.user.User; 032import org.ametys.core.user.UserIdentity; 033import org.ametys.plugins.repository.AmetysObject; 034import org.ametys.plugins.repository.activities.Activity; 035import org.ametys.plugins.repository.activities.ActivityType; 036import org.ametys.plugins.workspaces.activities.AbstractWorkspacesActivityNotifier; 037import org.ametys.plugins.workspaces.activities.AbstractWorkspacesActivityType; 038import org.ametys.plugins.workspaces.members.JCRProjectMember.MemberType; 039import org.ametys.plugins.workspaces.members.ProjectMemberManager; 040import org.ametys.plugins.workspaces.members.ProjectMemberManager.ProjectMember; 041import org.ametys.plugins.workspaces.project.notification.preferences.NotificationPreferencesHelper.Frequency; 042import org.ametys.plugins.workspaces.project.objects.Project; 043 044/** 045 * Class representing a activity notifier for member added in workspaces 046 */ 047public class MemberAddedActivityNotifier extends AbstractWorkspacesActivityNotifier 048{ 049 /** The group manager */ 050 protected GroupManager _groupManager; 051 052 /** The project member manager */ 053 protected ProjectMemberManager _projectMemberManager; 054 055 @Override 056 public void service(ServiceManager manager) throws ServiceException 057 { 058 super.service(manager); 059 _groupManager = (GroupManager) manager.lookup(GroupManager.ROLE); 060 _projectMemberManager = (ProjectMemberManager) manager.lookup(ProjectMemberManager.ROLE); 061 } 062 063 public boolean supports(ActivityType activityType) 064 { 065 return activityType instanceof MemberAddedActivityType; 066 } 067 068 @Override 069 public Map<String, List<String>> getUsersToNotifyByLanguage(Activity activity) 070 { 071 Stream<User> previousUser = null; 072 Project project = _projectManager.getProject(activity.getValue(AbstractWorkspacesActivityType.PROJECT_NAME)); 073 074 // if the new member is a user, we just need to inform all other user 075 // we have already check that it is in fact a new member 076 MemberType memberType = MemberType.valueOf(activity.<String> getValue(MemberAddedActivityType.MEMBER_TYPE).toUpperCase()); 077 if (MemberType.USER.equals(memberType)) 078 { 079 UserIdentity userIdentity = UserIdentity.stringToUserIdentity(activity.getValue(MemberAddedActivityType.MEMBER)); 080 if (userIdentity != null) 081 { 082 User newUser = _userManager.getUser(userIdentity); 083 if (newUser != null) 084 { 085 previousUser = _projectMemberManager.getProjectMembers(project, true).stream().map(ProjectMember::getUser).filter(u -> !u.equals(newUser)); 086 } 087 } 088 } 089 else 090 { 091 GroupIdentity groupIdentity = GroupIdentity.stringToGroupIdentity(activity.getValue(MemberAddedActivityType.MEMBER)); 092 if (groupIdentity != null) 093 { 094 Group group = _groupManager.getGroup(groupIdentity); 095 if (group != null) 096 { 097 previousUser = _projectMemberManager.getProjectMembers(project, false).stream() 098 // we remove the new group from the project members. 099 .filter(member -> MemberType.USER.equals(member.getType()) || group.equals(member.getGroup())) 100 // now we can expand all the group. If a user from 101 // the new group was already present he shall 102 // receive a notification as an activity was created 103 .flatMap(member -> { 104 if (MemberType.USER.equals(member.getType())) 105 { 106 return Stream.<User> of(member.getUser()); 107 } 108 else 109 { 110 return member.getGroup().getUsers().stream().map(_userManager::getUser); 111 } 112 }); 113 } 114 } 115 } 116 if (previousUser != null) 117 { 118 String defaultLanguage = _userLanguagesManager.getDefaultLanguage(); 119 return previousUser.filter(user -> _notificationPreferenceHelper.askedToBeNotified(user.getIdentity(), activity.getValue(AbstractWorkspacesActivityType.PROJECT_NAME), 120 Frequency.EACH)) 121 .map(user -> Pair.of(user.getLanguage(), user.getEmail())) 122 .filter(p -> StringUtils.isNotEmpty(p.getRight())) 123 .collect(Collectors.groupingBy( 124 p -> { 125 return StringUtils.defaultIfBlank(p.getLeft(), defaultLanguage); 126 }, 127 Collectors.mapping( 128 Pair::getRight, 129 Collectors.toList() 130 ) 131 ) 132 ); 133 } 134 else 135 { 136 // Something bad happened… 137 return Map.of(); 138 } 139 } 140 141 142 @Override 143 public String getMailBodyURI(Activity activity) 144 { 145 return "cocoon://_plugins/workspaces/notification-mail-member"; 146 } 147 148 @Override 149 public AmetysObject getTargetAmetysObject(Activity activity) 150 { 151 // we don't need this method as we override the AbstractWorkspacesActivityNotifier::getUsersEmailToNotify method 152 return null; 153 } 154}