package fr.ippon.tatami.service;
import com.google.common.base.Preconditions;
import fr.ippon.tatami.domain.Group;
import fr.ippon.tatami.domain.User;
import fr.ippon.tatami.repository.*;
import fr.ippon.tatami.security.AuthenticationService;
import fr.ippon.tatami.service.dto.UserGroupDTO;
import fr.ippon.tatami.service.util.DomainUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.TreeSet;
/**
* Service bean for managing groups.
*/
@Service
public class GroupService {
private final Logger log = LoggerFactory.getLogger(GroupService.class);
@Inject
private AuthenticationService authenticationService;
@Inject
private GroupRepository groupRepository;
@Inject
private GroupDetailsRepository groupDetailsRepository;
@Inject
private GroupMembersRepository groupMembersRepository;
@Inject
private GroupCounterRepository groupCounterRepository;
@Inject
private UserGroupRepository userGroupRepository;
@Inject
private UserRepository userRepository;
@Inject
private SearchService searchService;
@Inject
private FriendRepository friendRepository;
@CacheEvict(value = "group-user-cache", allEntries = true)
public void createGroup(String name, String description, boolean publicGroup) {
log.debug("Creating group : {}", name);
User currentUser = authenticationService.getCurrentUser();
String domain = DomainUtil.getDomainFromLogin(currentUser.getLogin());
String groupId = groupRepository.createGroup(domain);
groupDetailsRepository.createGroupDetails(groupId, name, description, publicGroup);
groupMembersRepository.addAdmin(groupId, currentUser.getLogin());
groupCounterRepository.incrementGroupCounter(domain, groupId);
userGroupRepository.addGroupAsAdmin(currentUser.getLogin(), groupId);
Group group = getGroupById(domain, groupId);
searchService.addGroup(group);
}
@CacheEvict(value = {"group-user-cache", "group-cache"}, allEntries = true)
public void editGroup(Group group) {
log.debug("Editing group : {}", group.getGroupId());
groupDetailsRepository.editGroupDetails(group.getGroupId(),
group.getName(),
group.getDescription(),
group.isArchivedGroup());
searchService.removeGroup(group);
searchService.addGroup(group);
}
public Collection<UserGroupDTO> getMembersForGroup(String groupId, String login) {
Map<String, String> membersMap = groupMembersRepository.findMembers(groupId);
Collection<String> friendLogins = friendRepository.findFriendsForUser(login);
Collection<UserGroupDTO> userGroupDTOs = new TreeSet<UserGroupDTO>();
for (Map.Entry<String, String> member : membersMap.entrySet()) {
User user = userRepository.findUserByLogin(member.getKey());
if(user != null) { //User might be deleted
UserGroupDTO dto = new UserGroupDTO();
dto.setLogin(user.getLogin());
dto.setUsername(user.getUsername());
dto.setAvatar(user.getAvatar());
dto.setFirstName(user.getFirstName());
dto.setLastName(user.getLastName());
dto.setRole(member.getValue());
dto.setActivated(user.getActivated());
if (friendLogins.contains(user.getLogin())) {
dto.setFriend(true);
}
if (login.equals(user.getLogin())) {
dto.setYou(true);
}
userGroupDTOs.add(dto);
}
}
return userGroupDTOs;
}
public UserGroupDTO getMembersForGroup(String groupId, User userWanted) {
Preconditions.checkNotNull(userWanted);
Preconditions.checkNotNull(userWanted.getLogin());
Map<String, String> membersMap = groupMembersRepository.findMembers(groupId);
for (Map.Entry<String, String> member : membersMap.entrySet()) {
User user = userRepository.findUserByLogin(member.getKey());
if (user != null && userWanted.getLogin().equals(user.getLogin())) {
UserGroupDTO dto = new UserGroupDTO();
dto.setLogin(user.getLogin());
dto.setUsername(user.getUsername());
dto.setAvatar(user.getAvatar());
dto.setFirstName(user.getFirstName());
dto.setLastName(user.getLastName());
dto.setRole(member.getValue());
return dto;
}
}
return null;
}
@Cacheable(value = "group-user-cache", key = "#user.login")
public Collection<Group> getGroupsForUser(User user) {
Collection<String> groupIds = userGroupRepository.findGroups(user.getLogin());
return buildGroupIdsList(groupIds);
}
@Cacheable(value = "group-user-cache", key = "#user.login")
public Collection<Group> getGroupsOfUser(User user) {
Collection<String> groupIds = userGroupRepository.findGroups(user.getLogin());
return getGroupDetails(user, groupIds);
}
@Cacheable(value = "group-cache")
public Group getGroupById(String domain, String groupId) {
return internalGetGroupById(domain, groupId);
}
public Collection<Group> getGroupsWhereUserIsAdmin(User user) {
Collection<String> groupIds = userGroupRepository.findGroupsAsAdmin(user.getLogin());
return getGroupDetails(user, groupIds);
}
private Collection<Group> getGroupDetails(User currentUser, Collection<String> groupIds) {
String domain = DomainUtil.getDomainFromLogin(currentUser.getLogin());
Collection<Group> groups = new TreeSet<Group>();
for (String groupId : groupIds) {
Group group = internalGetGroupById(domain, groupId);
groups.add(group);
}
return groups;
}
public Collection<Group> getGroupsWhereCurrentUserIsAdmin() {
User currentUser = authenticationService.getCurrentUser();
return getGroupsWhereUserIsAdmin(currentUser);
}
private Group internalGetGroupById(String domain, String groupId) {
Group group = groupRepository.getGroupById(domain, groupId);
Group groupDetails = groupDetailsRepository.getGroupDetails(groupId);
group.setName(groupDetails.getName());
group.setPublicGroup(groupDetails.isPublicGroup());
group.setArchivedGroup(groupDetails.isArchivedGroup());
group.setDescription(groupDetails.getDescription());
long counter = groupCounterRepository.getGroupCounter(domain, groupId);
group.setCounter(counter);
return group;
}
@CacheEvict(value = {"group-user-cache", "group-cache"}, allEntries = true)
public void addMemberToGroup(User user, Group group) {
String groupId = group.getGroupId();
Collection<String> userCurrentGroupIds = userGroupRepository.findGroups(user.getLogin());
boolean userIsAlreadyAMember = false;
for (String testGroupId : userCurrentGroupIds) {
if (testGroupId.equals(groupId)) {
userIsAlreadyAMember = true;
}
}
if (!userIsAlreadyAMember) {
groupMembersRepository.addMember(groupId, user.getLogin());
log.debug("user=" + user);
groupCounterRepository.incrementGroupCounter(user.getDomain(), groupId);
userGroupRepository.addGroupAsMember(user.getLogin(), groupId);
} else {
log.debug("User {} is already a member of group {}", user.getLogin(), group.getName());
}
}
@CacheEvict(value = {"group-user-cache", "group-cache"}, allEntries = true)
public void removeMemberFromGroup(User user, Group group) {
String groupId = group.getGroupId();
Collection<String> userCurrentGroupIds = userGroupRepository.findGroups(user.getLogin());
boolean userIsAlreadyAMember = false;
for (String testGroupId : userCurrentGroupIds) {
if (testGroupId.equals(groupId)) {
userIsAlreadyAMember = true;
}
}
if (userIsAlreadyAMember) {
groupMembersRepository.removeMember(groupId, user.getLogin());
groupCounterRepository.decrementGroupCounter(user.getDomain(), groupId);
userGroupRepository.removeGroup(user.getLogin(), groupId);
} else {
log.debug("User {} is not a member of group {}", user.getLogin(), group.getName());
}
}
public Collection<Group> buildGroupList(Collection<Group> groups) {
User currentUser = authenticationService.getCurrentUser();
return buildGroupList(currentUser, groups);
}
public Collection<Group> buildGroupList(User user, Collection<Group> groups) {
for (Group group : groups) {
buildGroup(user, group);
}
return groups;
}
public Group buildGroup(Group group) {
User currentUser = authenticationService.getCurrentUser();
return buildGroup(currentUser, group);
}
private Group getGroupFromUser(User currentUser, String groupId) {
Collection<Group> groups = getGroupsOfUser(currentUser);
for (Group testGroup : groups) {
if (testGroup.getGroupId().equals(groupId)) {
return testGroup;
}
}
return null;
}
private boolean isGroupManagedByCurrentUser(Group group) {
Collection<Group> groups = getGroupsWhereCurrentUserIsAdmin();
boolean isGroupManagedByCurrentUser = false;
for (Group testGroup : groups) {
if (testGroup.getGroupId().equals(group.getGroupId())) {
isGroupManagedByCurrentUser = true;
break;
}
}
return isGroupManagedByCurrentUser;
}
public Group buildGroup(User user, Group group) {
if(group != null ) {
if (isGroupManagedByCurrentUser(group)) {
group.setAdministrator(true);
group.setMember(true);
}
else if(group.isPublicGroup()) {
Group result = getGroupFromUser(user, group.getGroupId());
if (result != null) {
group.setMember(true);
}
}
else {
Group result = getGroupFromUser(user, group.getGroupId());
if (result == null) {
log.info("Permission denied! User {} tried to access group ID = {} ", user.getLogin(), group.getGroupId());
return null;
} else {
group.setMember(true);
}
}
long counter = 0;
for ( UserGroupDTO userGroup : getMembersForGroup(group.getGroupId(),authenticationService.getCurrentUser().getLogin()) ) {
if(userGroup.isActivated()) {
counter++;
}
}
group.setCounter(counter);
}
return group;
}
public Collection<Group> buildGroupIdsList(Collection<String> groupIds) {
Collection<Group> groups = new TreeSet<Group>();
for (String groupId : groupIds) {
groups.add(buildGroupIds(groupId));
}
return groups;
}
public Group buildGroupIds(String groupId) {
User currentUser = authenticationService.getCurrentUser();
return buildGroupIds(currentUser, groupId);
}
public Group buildGroupIds(User user, String groupId) {
String domain = DomainUtil.getDomainFromLogin(user.getLogin());
Group group = getGroupById(domain, groupId);
return buildGroup(group);
}
}