package org.cloudfoundry.identity.uaa.login;
import org.cloudfoundry.identity.uaa.authentication.Origin;
import org.cloudfoundry.identity.uaa.authentication.UaaPrincipal;
import org.cloudfoundry.identity.uaa.error.UaaException;
import org.cloudfoundry.identity.uaa.login.ExpiringCodeService.CodeNotFoundException;
import org.cloudfoundry.identity.uaa.user.UaaAuthority;
import org.hibernate.validator.constraints.Email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Map;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
@Controller
@RequestMapping("/invitations")
public class InvitationsController {
private InvitationsService invitationsService;
@Autowired
private ExpiringCodeService expiringCodeService;
public InvitationsController(InvitationsService invitationsService) {
this.invitationsService = invitationsService;
}
@RequestMapping(value = "/new", method = GET)
public String newInvitePage(Model model) {
return "invitations/new_invite";
}
@RequestMapping(value = "/new.do", method = POST, params = {"email"})
public String sendInvitationEmail(@Valid @ModelAttribute("email") ValidEmail email, BindingResult result, Model model, HttpServletResponse response) {
if (result.hasErrors()) {
return handleUnprocessableEntity(model, response, "invalid_email", "invitations/new_invite");
}
UaaPrincipal p = ((UaaPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal());
String currentUser = p.getName();
try {
invitationsService.inviteUser(email.getEmail(), currentUser);
} catch (UaaException e) {
return handleUnprocessableEntity(model, response, "existing_user", "invitations/new_invite");
}
return "redirect:sent";
}
@RequestMapping(value = "sent", method = GET)
public String inviteSentPage(Model model) {
return "invitations/invite_sent";
}
@RequestMapping(value = "/accept", method = GET, params = {"code"})
public String acceptInvitePage(@RequestParam String code, Model model, HttpServletResponse response) throws IOException {
try {
Map<String, String> codeData = expiringCodeService.verifyCode(code);
UaaPrincipal uaaPrincipal = new UaaPrincipal(codeData.get("user_id"), codeData.get("email"), codeData.get("email"), Origin.UAA, null);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(uaaPrincipal, null, UaaAuthority.USER_AUTHORITIES);
SecurityContextHolder.getContext().setAuthentication(token);
model.addAllAttributes(codeData);
return "invitations/accept_invite";
} catch (CodeNotFoundException e) {
return handleUnprocessableEntity(model, response, "code_expired", "invitations/accept_invite");
}
}
@RequestMapping(value = "/accept.do", method = POST)
public String acceptInvitation(@RequestParam("password") String password,
@RequestParam("password_confirmation") String passwordConfirmation,
@RequestParam("client_id") String clientId,
Model model, HttpServletResponse servletResponse) throws IOException {
ChangePasswordValidation validation = new ChangePasswordValidation(password, passwordConfirmation);
UaaPrincipal principal = (UaaPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (!validation.valid()) {
model.addAttribute("email", principal.getEmail());
return handleUnprocessableEntity(model, servletResponse, validation.getMessageCode(), "invitations/accept_invite");
}
String redirectLocation = invitationsService.acceptInvitation(principal.getId(), principal.getEmail(), password, clientId);
if (redirectLocation != null) {
return "redirect:" + redirectLocation;
}
return "redirect:/home";
}
private String handleUnprocessableEntity(Model model, HttpServletResponse response, String errorMessage, String view) {
model.addAttribute("error_message_code", errorMessage);
response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value());
return view;
}
public static class ValidEmail {
@Email
String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}