/*
* Copyright 2012 SURFnet bv, The Netherlands
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-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 teams.control;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.view.RedirectView;
import teams.domain.ExternalGroup;
import teams.domain.Person;
import teams.domain.Team;
import teams.domain.TeamExternalGroup;
import teams.interceptor.LoginInterceptor;
import teams.service.GrouperTeamService;
import teams.service.TeamExternalGroupDao;
import teams.service.VootClient;
import teams.util.AuditLog;
import teams.util.ControllerUtil;
import teams.util.TokenUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
import static teams.util.TokenUtil.TOKENCHECK;
import static teams.util.TokenUtil.checkTokens;
import static teams.util.ViewUtil.escapeViewParameters;
@Controller
@SessionAttributes(TOKENCHECK)
public class AddExternalGroupController {
protected static final String EXTERNAL_GROUPS_SESSION_KEY = "externalGroups";
@Autowired
private VootClient vootClient;
@Autowired
private GrouperTeamService teamService;
@Autowired
private TeamExternalGroupDao teamExternalGroupDao;
@Autowired
private ControllerUtil controllerUtil;
@RequestMapping(value = "/addexternalgroup.shtml")
public String showAddExternalGroupsForm(@RequestParam String teamId, Model model, HttpServletRequest request) {
Person person = (Person) request.getSession().getAttribute(LoginInterceptor.PERSON_SESSION_KEY);
Team team = teamService.findTeamById(teamId);
checkUserHasAdministrativePrivileges(person, team);
List<ExternalGroup> myExternalGroups = filterLinkedExternalGroups(team, getExternalGroups(person.getId(), request.getSession()));
request.getSession().setAttribute(EXTERNAL_GROUPS_SESSION_KEY, myExternalGroups);
model.addAttribute(TOKENCHECK, TokenUtil.generateSessionToken());
model.addAttribute("teamId", team.getId());
model.addAttribute("team", team);
return "addexternalgroup";
}
@RequestMapping(value = "/deleteexternalgroup.shtml")
public RedirectView deleteTeamExternalGroupLink(
@ModelAttribute(TOKENCHECK) String sessionToken,
@RequestParam String teamId,
@RequestParam String groupIdentifier,
@RequestParam String token,
ModelMap modelMap, SessionStatus status, HttpServletRequest request) {
Person person = (Person) request.getSession().getAttribute(LoginInterceptor.PERSON_SESSION_KEY);
checkTokens(sessionToken, token, status);
Team team = controllerUtil.getTeamById(teamId);
checkUserIsAdmin(person, team);
TeamExternalGroup teamExternalGroup = teamExternalGroupDao.getByTeamIdentifierAndExternalGroupIdentifier(teamId, groupIdentifier);
if (teamExternalGroup != null) {
teamExternalGroupDao.delete(teamExternalGroup);
AuditLog.log("User {} deleted external group from team {}: {}", person.getId(), teamId, teamExternalGroup.getExternalGroup());
}
status.setComplete();
modelMap.clear();
return new RedirectView(escapeViewParameters("detailteam.shtml?team=%s", teamId), false, true, false);
}
/*
* Gets a List of {@link ExternalGroup}'s the person is a member of. First
* tries to get the list from the session. If this returns nothing, the groups are retrieved from the VootService.
*/
@SuppressWarnings("unchecked")
private List<ExternalGroup> getExternalGroups(String personId, HttpSession session) {
List<ExternalGroup> externalGroups = (List<ExternalGroup>) session.getAttribute(EXTERNAL_GROUPS_SESSION_KEY);
if (!CollectionUtils.isEmpty(externalGroups)) {
return externalGroups;
}
return vootClient.groups(personId);
}
private List<ExternalGroup> filterLinkedExternalGroups(Team team, List<ExternalGroup> externalGroups) {
if (externalGroups.isEmpty()) {
return externalGroups;
}
List<String> existingLinkedGroups = teamExternalGroupDao.getByTeamIdentifier(team.getId()).stream()
.map(teg -> teg.getExternalGroup().getIdentifier())
.collect(toList());
return externalGroups.stream()
.filter(externalGroup -> !existingLinkedGroups.contains(externalGroup.getIdentifier()))
.collect(toList());
}
@RequestMapping(value = "/doaddexternalgroup.shtml", method = RequestMethod.POST)
public RedirectView addExternalGroups(@ModelAttribute(TOKENCHECK) String sessionToken,
@ModelAttribute("teamId") String teamId,
@RequestParam String token,
ModelMap modelMap, SessionStatus status, HttpServletRequest request) {
Person person = (Person) request.getSession().getAttribute(LoginInterceptor.PERSON_SESSION_KEY);
checkTokens(sessionToken, token, status);
Team team = controllerUtil.getTeamById(teamId);
checkUserHasAdministrativePrivileges(person, team);
String personId = person.getId();
Map<String, ExternalGroup> externalGroupMap = getExternalGroups(personId, request.getSession()).stream()
.collect(Collectors.toMap(ExternalGroup::getIdentifier, Function.identity()));
List<TeamExternalGroup> teamExternalGroups = Arrays.stream(request.getParameterValues(EXTERNAL_GROUPS_SESSION_KEY))
.map(identifier -> {
TeamExternalGroup t = new TeamExternalGroup();
t.setGrouperTeamId(teamId);
t.setExternalGroup(externalGroupMap.get(identifier));
return t;
}).collect(toList());
teamExternalGroups.forEach(teamExternalGroupDao::saveOrUpdate);
teamExternalGroups.forEach(eg -> AuditLog.log("User {} added external group to team {}: {}", personId, teamId, eg));
request.getSession().removeAttribute(EXTERNAL_GROUPS_SESSION_KEY);
status.setComplete();
modelMap.clear();
return new RedirectView(escapeViewParameters("detailteam.shtml?team=%s", teamId), false, true, false);
}
private void checkUserHasAdministrativePrivileges(Person person, Team team) {
if (!controllerUtil.hasUserAdministrativePrivileges(person, team)) {
throw new RuntimeException(String.format("Requester (%s) is not member or does not have the correct privileges", person.getId()));
}
}
private void checkUserIsAdmin(Person person, Team team) {
if (!controllerUtil.hasUserAdminPrivileges(person, team)) {
throw new RuntimeException(String.format("Requester (%s) is not member or does not have the correct privileges", person.getId()));
}
}
}