nl.surfnet.coin.teams.control.JoinTeamController.java Source code

Java tutorial

Introduction

Here is the source code for nl.surfnet.coin.teams.control.JoinTeamController.java

Source

/*
 * 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 nl.surfnet.coin.teams.control;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.servlet.http.HttpServletRequest;

import nl.surfnet.coin.api.client.domain.Person;
import nl.surfnet.coin.shared.service.MailService;
import nl.surfnet.coin.teams.domain.JoinTeamRequest;
import nl.surfnet.coin.teams.domain.Member;
import nl.surfnet.coin.teams.domain.Team;
import nl.surfnet.coin.teams.interceptor.LoginInterceptor;
import nl.surfnet.coin.teams.service.GrouperTeamService;
import nl.surfnet.coin.teams.service.JoinTeamRequestService;
import nl.surfnet.coin.teams.util.AuditLog;
import nl.surfnet.coin.teams.util.ControllerUtil;
import nl.surfnet.coin.teams.util.TeamEnvironment;
import nl.surfnet.coin.teams.util.ViewUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.view.RedirectView;

import freemarker.template.Configuration;
import freemarker.template.TemplateException;
import static nl.surfnet.coin.teams.util.PersonUtil.getFirstEmail;

/**
 * {@link Controller} that handles the join team page of a logged in
 * user.
 */
@Controller
@SessionAttributes(JoinTeamController.JOIN_TEAM_REQUEST)
public class JoinTeamController {

    private static final String REQUEST_MEMBERSHIP_SUBJECT = "request.MembershipSubject";
    private static final Logger log = LoggerFactory.getLogger(JoinTeamController.class);

    public static final String JOIN_TEAM_REQUEST = "joinTeamRequest";

    @Autowired
    private GrouperTeamService grouperTeamService;

    @Autowired
    private JoinTeamRequestService joinTeamRequestService;

    @Autowired
    private MessageSource messageSource;

    @Autowired
    private LocaleResolver localeResolver;

    @Autowired
    private MailService mailService;

    @Autowired
    private TeamEnvironment environment;

    @Autowired
    private ControllerUtil controllerUtil;

    @Autowired
    private Configuration freemarkerConfiguration;

    @RequestMapping("/jointeam.shtml")
    public String start(ModelMap modelMap, HttpServletRequest request) {

        String teamId = request.getParameter("team");
        Team team = null;

        if (StringUtils.hasText(teamId)) {
            team = grouperTeamService.findTeamById(teamId);
        }

        if (team == null) {
            throw new RuntimeException("Cannot find team for parameter 'team'");
        }
        Person person = (Person) request.getSession().getAttribute(LoginInterceptor.PERSON_SESSION_KEY);

        modelMap.addAttribute("team", team);
        JoinTeamRequest joinTeamRequest = joinTeamRequestService.findPendingRequest(person, team);
        if (joinTeamRequest == null) {
            joinTeamRequest = new JoinTeamRequest(person.getId(), team.getId());
        }

        modelMap.addAttribute(JOIN_TEAM_REQUEST, joinTeamRequest);

        ViewUtil.addViewToModelMap(request, modelMap);

        return "jointeam";
    }

    @RequestMapping(value = "/dojointeam.shtml", method = RequestMethod.POST)
    public RedirectView joinTeam(ModelMap modelMap,
            @ModelAttribute(JOIN_TEAM_REQUEST) JoinTeamRequest joinTeamRequest, HttpServletRequest request)
            throws IOException {

        ViewUtil.addViewToModelMap(request, modelMap);

        Team team = controllerUtil.getTeamById(joinTeamRequest.getGroupId());

        if (!team.isViewable()) {
            throw new IllegalStateException("The team you requested to join is private.");
        }

        Person person = (Person) request.getSession().getAttribute(LoginInterceptor.PERSON_SESSION_KEY);

        String message = joinTeamRequest.getMessage();
        // First send mail, then optionally create record in db
        sendJoinTeamMessage(team, person, message, localeResolver.resolveLocale(request));

        joinTeamRequest.setTimestamp(new Date().getTime());
        joinTeamRequestService.saveOrUpdate(joinTeamRequest);
        AuditLog.log("User {} requested to join team {}", joinTeamRequest.getPersonId(), team.getId());
        return new RedirectView("home.shtml?teams=my&view=" + ViewUtil.getView(request));
    }

    private void sendJoinTeamMessage(final Team team, final Person person, final String message,
            final Locale locale) throws IllegalStateException, IOException {

        Object[] subjectValues = { team.getName() };
        final String subject = messageSource.getMessage(REQUEST_MEMBERSHIP_SUBJECT, subjectValues, locale);

        final Set<Member> admins = grouperTeamService.findAdmins(team);
        if (CollectionUtils.isEmpty(admins)) {
            throw new RuntimeException("Team '" + team.getName() + "' has no admins to mail invites");
        }

        final String html = composeJoinRequestMailMessage(team, person, message, locale, "html");
        final String plainText = composeJoinRequestMailMessage(team, person, message, locale, "plaintext");

        final List<InternetAddress> bcc = new ArrayList<InternetAddress>();
        for (Member admin : admins) {
            try {
                bcc.add(new InternetAddress(admin.getEmail()));
            } catch (AddressException ae) {
                log.debug("Admin has malformed email address", ae);
            }
        }
        if (bcc.isEmpty()) {
            throw new RuntimeException(
                    "Team '" + team.getName() + "' has no admins with valid email addresses to mail invites");
        }

        MimeMessagePreparator preparator = new MimeMessagePreparator() {
            public void prepare(MimeMessage mimeMessage) throws MessagingException {
                mimeMessage.addHeader("Precedence", "bulk");

                mimeMessage.setFrom(new InternetAddress(environment.getSystemEmail()));
                mimeMessage.setRecipients(Message.RecipientType.BCC, bcc.toArray(new InternetAddress[bcc.size()]));
                mimeMessage.setSubject(subject);

                MimeMultipart rootMixedMultipart = controllerUtil.getMimeMultipartMessageBody(plainText, html);
                mimeMessage.setContent(rootMixedMultipart);
            }
        };

        mailService.sendAsync(preparator);

    }

    String composeJoinRequestMailMessage(final Team team, final Person person, final String message,
            final Locale locale, final String variant) {
        String templateName;
        if ("plaintext".equals(variant)) {
            templateName = "joinrequestmail-plaintext.ftl";
        } else {
            templateName = "joinrequestmail.ftl";
        }
        Map<String, Object> templateVars = new HashMap<String, Object>();
        templateVars.put("requesterName", person.getDisplayName());
        // for unknown reasons Freemarker cannot call person.getEmail()
        templateVars.put("requesterEmail", getFirstEmail(person));
        templateVars.put("team", team);
        templateVars.put("teamsURL", environment.getTeamsURL());
        templateVars.put("message", message);

        try {
            return FreeMarkerTemplateUtils.processTemplateIntoString(
                    freemarkerConfiguration.getTemplate(templateName, locale), templateVars);
        } catch (IOException e) {
            throw new RuntimeException("Failed to create invitation mail", e);
        } catch (TemplateException e) {
            throw new RuntimeException("Failed to create invitation mail", e);
        }
    }

    /**
     * Setter for {@link TeamEnvironment} in case {@link @Autowired} is not used
     *
     * @param environment TeamEnvironment to set
     */
    void setTeamEnvironment(TeamEnvironment environment) {
        this.environment = environment;
    }
}