/*
* 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.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;
import teams.Application;
import teams.domain.*;
import teams.service.GrouperTeamService;
import teams.service.TeamInviteService;
import teams.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import static teams.control.AddMemberController.INVITE_SEND_INVITE_SUBJECT;
import static teams.interceptor.LoginInterceptor.PERSON_SESSION_KEY;
import static teams.util.TokenUtil.TOKENCHECK;
import static teams.util.TokenUtil.checkTokens;
import static teams.util.ViewUtil.escapeViewParameters;
/**
* {@link Controller} that handles the add team page of a logged in user.
*/
@Controller
@SessionAttributes(TokenUtil.TOKENCHECK)
public class AddTeamController {
@Autowired
private GrouperTeamService grouperTeamService;
@Autowired
private MessageSource messageSource;
@Autowired
private Environment environment;
@Autowired
private ControllerUtil controllerUtil;
@Autowired
private TeamInviteService teamInviteService;
@Value("${defaultStemName}")
private String defaultStemName;
@Value("${grouperPowerUser}")
private String grouperPowerUser;
@InitBinder
protected void initBinder(ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Stem.class, "stem", new PropertyEditorSupport() {
@Override
public void setAsText(String text) {
Stem stem = new Stem(text, "", "");
setValue(stem);
}
});
}
@RequestMapping(value = "/addteam.shtml", method = GET)
public String addTeam(Model model, Locale locale, HttpServletRequest request) {
if (PermissionUtil.isGuest(request)) {
return "redirect:home.shtml";
}
Person person = (Person) request.getSession().getAttribute(PERSON_SESSION_KEY);
List<Stem> stems = getStemsForMember(person);
AddTeamCommand command = new AddTeamCommand();
command.setAdmin2Language(Language.find(locale).orElse(Language.English));
model.addAttribute("hasMultipleStems", stems.size() > 1);
model.addAttribute("stems", stems);
model.addAttribute(TOKENCHECK, TokenUtil.generateSessionToken());
model.addAttribute("addTeamCommand", command);
return "addteam";
}
@RequestMapping(value = "/doaddteam.shtml", method = POST)
public String doAddTeam(
@RequestParam String token,
@ModelAttribute(TOKENCHECK) String sessionToken,
@Valid @ModelAttribute AddTeamCommand addTeamCommand,
BindingResult bindingResult,
Model model,
HttpServletRequest request, SessionStatus status) throws IOException {
Person person = (Person) request.getSession().getAttribute(PERSON_SESSION_KEY);
checkTokens(sessionToken, token, status);
checkNotGuest(request);
checkAllowedStem(addTeamCommand.getStem(), person);
if (bindingResult.hasErrors()) {
return "addteam";
}
String stemId = addTeamCommand.getStem() != null ? addTeamCommand.getStem().getId() : defaultStemName;
String teamName = addTeamCommand.getTeamName().replace(":", "");
String teamDescription = addTeamCommand.getTeamDescription();
String teamId;
try {
teamId = grouperTeamService.addTeam(teamName, teamName, teamDescription, stemId);
AuditLog.log("User {} added team (name: {}, id: {}) with stem {}", person.getId(), teamName, teamId, stemId);
} catch (DuplicateTeamException e) {
bindingResult.rejectValue("teamName", "jsp.addteam.error.duplicate");
return "addteam";
}
Team team = grouperTeamService.findTeamById(teamId);
inviteAdmin(team, addTeamCommand, teamId, person);
grouperTeamService.setVisibilityGroup(teamId, addTeamCommand.isViewable());
grouperTeamService.addMember(team, person);
grouperTeamService.addMemberRole(team, person.getId(), Role.Admin, grouperPowerUser);
status.setComplete();
if (environment.acceptsProfiles(Application.GROUPZY_PROFILE_NAME)) {
return escapeViewParameters("redirect:/%s/service-providers.shtml", teamId);
} else {
return escapeViewParameters("redirect:detailteam.shtml?team=%s", teamId);
}
}
@ModelAttribute("languages")
public Language[] languages() {
Locale locale = LocaleContextHolder.getLocale();
if (locale.toString().equals("en")) {
return Language.enLanguages();
} else {
return Language.nlLanguages();
}
}
private void checkAllowedStem(Stem stem, Person person) {
if (stem != null && !isPersonUsingAllowedStem(person, stem.getId())) {
throw new RuntimeException("User is not allowed to add a team!");
}
}
private void checkNotGuest(HttpServletRequest request) {
if (PermissionUtil.isGuest(request)) {
throw new RuntimeException("User is not allowed to add a team!");
}
}
private void inviteAdmin(Team team, AddTeamCommand command, String teamId, Person inviter) {
if (!StringUtils.hasText(command.getAdmin2Email())) {
return;
}
Invitation invitation = new Invitation(command.getAdmin2Email(), teamId);
invitation.setIntendedRole(Role.Admin);
invitation.setTimestamp(new Date().getTime());
invitation.setLanguage(command.getAdmin2Language());
InvitationMessage message = new InvitationMessage(command.getAdmin2Message(), inviter.getDisplayName());
invitation.addInvitationMessage(message);
teamInviteService.saveOrUpdate(invitation);
String subject = messageSource.getMessage(INVITE_SEND_INVITE_SUBJECT, new Object[] {command.getTeamName()}, command.getAdmin2Language().locale());
controllerUtil.sendInvitationMail(team, invitation, subject, inviter);
AuditLog.log("Sent invitation and saved to database: team: {}, inviter: {}, hash: {}, email: {}, role: {}",
teamId, inviter.getId(), invitation.getInvitationHash(), command.getAdmin2Email(), invitation.getIntendedRole());
}
private List<Stem> getStemsForMember(Person person) {
return grouperTeamService.findStemsByMember(person.getId()).stream()
.filter(stem -> stem.getId().equalsIgnoreCase(defaultStemName) || controllerUtil.isPersonMemberOfTeam(person, grouperTeamService.findTeamById(stem.getId() + ":" + "members")))
.collect(Collectors.toList());
}
private boolean isPersonUsingAllowedStem(Person person, String stemId) {
return getStemsForMember(person).stream()
.anyMatch(allowedStem -> allowedStem.getId().equalsIgnoreCase(stemId));
}
}