/**
* =============================================================================
*
* ORCID (R) Open Source
* http://orcid.org
*
* Copyright (c) 2012-2014 ORCID, Inc.
* Licensed under an MIT-Style License (MIT)
* http://orcid.org/open-source-license
*
* This copyright and license information (including a link to the full license)
* shall be included in its entirety in all copies or substantial portion of
* the software.
*
* =============================================================================
*/
package org.orcid.frontend.web.controllers;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.annotation.Resource;
import org.orcid.core.manager.ClientDetailsManager;
import org.orcid.core.manager.MembersManager;
import org.orcid.core.manager.SalesForceManager;
import org.orcid.core.salesforce.model.Contact;
import org.orcid.core.salesforce.model.MemberDetails;
import org.orcid.jaxb.model.clientgroup.MemberType;
import org.orcid.jaxb.model.clientgroup.RedirectUriType;
import org.orcid.pojo.ajaxForm.Client;
import org.orcid.pojo.ajaxForm.ConsortiumForm;
import org.orcid.pojo.ajaxForm.Member;
import org.orcid.pojo.ajaxForm.PojoUtil;
import org.orcid.pojo.ajaxForm.RedirectUri;
import org.orcid.pojo.ajaxForm.Text;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
/**
* @author Angel Montenegro
*/
@Controller
@RequestMapping(value = { "/manage-members" })
public class ManageMembersController extends BaseController {
private static String SALESFORCE_ID_PATTERN = "[a-zA-Z0-9]{15}";
@Resource
MembersManager membersManager;
@Resource
ClientDetailsManager clientDetailsManager;
@Resource
private GroupAdministratorController groupAdministratorController;
@Resource
private SalesForceManager salesForceManager;
@RequestMapping
public ModelAndView getManageMembersPage() {
ModelAndView mav = new ModelAndView("/admin/manage_members");
return mav;
}
/**
* Get an empty group
*
* @return an empty group
* */
@RequestMapping(value = "/member.json", method = RequestMethod.GET)
public @ResponseBody
Member getEmptyGroup() {
Text empty = Text.valueOf("");
Member group = new Member();
group.setEmail(empty);
group.setGroupName(empty);
group.setGroupOrcid(empty);
group.setSalesforceId(empty);
// Set the default type as basic
group.setType(Text.valueOf(MemberType.BASIC.value()));
return group;
}
@RequestMapping(value = "/find.json", method = RequestMethod.GET)
public @ResponseBody ResultContainer find(@RequestParam("id") String id) {
ResultContainer result = new ResultContainer();
if(clientDetailsManager.exists(id)) {
result.setClient(true);
result.setClientObject(findClient(id));
} else {
result.setClient(false);
result.setMemberObject(findMember(id));
}
return result;
}
@RequestMapping(value = "/find-member.json", method = RequestMethod.GET)
public @ResponseBody
Member findMember(@RequestParam("orcidOrEmail") String orcidOrEmail) {
Member group = new Member();
if(PojoUtil.isEmpty(orcidOrEmail)) {
group.getErrors().add("manage_member.not_blank");
} else {
group = membersManager.getMember(orcidOrEmail);
}
return group;
}
/**
* Create a member
*
* @param the
* member to be created
* @return the member with the orcid information or with the error
* information
* */
@RequestMapping(value = "/create-member.json", method = RequestMethod.POST)
public @ResponseBody
Member createMember(@RequestBody Member member) {
member.setErrors(new ArrayList<String>());
validateGroupEmail(member);
validateGroupName(member);
validateGroupType(member);
validateSalesforceId(member);
copyErrors(member.getEmail(), member);
copyErrors(member.getGroupName(), member);
copyErrors(member.getType(), member);
copyErrors(member.getSalesforceId(), member);
if (member.getErrors().isEmpty()) {
member = membersManager.createMember(member);
}
return member;
}
@RequestMapping(value = "/update-member.json", method = RequestMethod.POST)
public @ResponseBody
Member updateMember(@RequestBody Member member) {
member.setErrors(new ArrayList<String>());
validateGroupEmail(member);
validateGroupName(member);
validateGroupType(member);
validateSalesforceId(member);
copyErrors(member.getEmail(), member);
copyErrors(member.getGroupName(), member);
copyErrors(member.getType(), member);
copyErrors(member.getSalesforceId(), member);
if (member.getErrors().isEmpty()) {
member = membersManager.updateMemeber(member);
}
return member;
}
@RequestMapping(value = "/find-client.json", method = RequestMethod.GET)
public @ResponseBody
Client findClient(@RequestParam("orcid") String orcid) {
Client result = new Client();
if(PojoUtil.isEmpty(orcid)) {
result.getErrors().add(getMessage("manage_member.not_blank"));
} else {
result = membersManager.getClient(orcid);
}
return result;
}
@RequestMapping(value = "/update-client.json", method = RequestMethod.POST)
public @ResponseBody
Client updateClient(@RequestBody Client client) {
// Clean the error list
client.setErrors(new ArrayList<String>());
// Validate fields
groupAdministratorController.validateDisplayName(client);
groupAdministratorController.validateWebsite(client);
groupAdministratorController.validateShortDescription(client);
groupAdministratorController.validateRedirectUris(client, true);
copyErrors(client.getDisplayName(), client);
copyErrors(client.getWebsite(), client);
copyErrors(client.getShortDescription(), client);
if(client.getAuthenticationProviderId() != null) {
validateIdP(client);
copyErrors(client.getAuthenticationProviderId(), client);
}
for (RedirectUri redirectUri : client.getRedirectUris()) {
copyErrors(redirectUri, client);
}
if (client.getErrors().isEmpty()) {
client = membersManager.updateClient(client);
}
return client;
}
@RequestMapping(value = "/empty-redirect-uri.json", method = RequestMethod.GET)
public @ResponseBody
RedirectUri getEmptyRedirectUri() {
RedirectUri rUri = new RedirectUri();
rUri.setType(Text.valueOf(RedirectUriType.DEFAULT.value()));
rUri.setValue(Text.valueOf(""));
rUri.setActType(Text.valueOf(""));
rUri.setGeoArea(Text.valueOf(""));
return rUri;
}
@RequestMapping(value = "/find-consortium.json", method = RequestMethod.GET)
public @ResponseBody ConsortiumForm findConsortium(@RequestParam("id") String id) {
MemberDetails memberDetails = salesForceManager.retrieveDetails(id);
ConsortiumForm consortiumForm = ConsortiumForm.fromMemberDetails(memberDetails);
List<Contact> contactsList = salesForceManager.retrieveContactsByAccountId(id);
salesForceManager.addOrcidsToContacts(contactsList);
consortiumForm.setContactsList(contactsList);
consortiumForm.setRoleMap(generateSalesForceRoleMap());
return consortiumForm;
}
@RequestMapping(value = "/update-consortium.json", method = RequestMethod.POST)
public @ResponseBody ConsortiumForm updateConsortium(@RequestBody ConsortiumForm consortium) {
consortium.setErrors(new ArrayList<String>());
salesForceManager.enableAccess(consortium.getAccountId(), consortium.getContactsList());
return consortium;
}
/**
* MODEL ATTRIBUTES
* */
@ModelAttribute("redirectUriTypes")
public Map<String, String> getRedirectUriTypes() {
Map<String, String> redirectUriTypes = new LinkedHashMap<String, String>();
for (RedirectUriType rType : RedirectUriType.values()) {
if (!RedirectUriType.SSO_AUTHENTICATION.equals(rType))
redirectUriTypes.put(rType.value(), rType.value());
}
return redirectUriTypes;
}
@ModelAttribute("groupTypes")
public Map<String, String> retrieveGroupTypes() {
MemberType[] groupTypes = MemberType.values();
Map<String, String> groupTypesMap = new TreeMap<String, String>();
for (MemberType groupType : groupTypes) {
String key = groupType.value();
String value = key.replace('-', ' ');
groupTypesMap.put(key, value);
}
return groupTypesMap;
}
/**
* VALIDATORS
* */
private void validateGroupEmail(Member group) {
group.getEmail().setErrors(new ArrayList<String>());
if (PojoUtil.isEmpty(group.getEmail())) {
setError(group.getEmail(), "NotBlank.group.email");
} else if (!validateEmailAddress(group.getEmail().getValue())) {
setError(group.getEmail(), "group.email.invalid_email");
} else if (PojoUtil.isEmpty(group.getGroupOrcid())) {
if (emailManager.emailExists(group.getEmail().getValue()))
setError(group.getEmail(), "group.email.already_used");
} else if (!PojoUtil.isEmpty(group.getGroupOrcid())) {
String newEmail = group.getEmail().getValue();
String userOrcid = group.getGroupOrcid().getValue();
if (emailManager.emailExists(newEmail)) {
Map<String, String> ids = emailManager.findOricdIdsByCommaSeparatedEmails(newEmail);
String orcidThatOwnsTheEmail = ids.get(newEmail);
// If the email is not the same, it means the member cannot use
// that email address
if (!userOrcid.equals(orcidThatOwnsTheEmail)) {
setError(group.getEmail(), "group.email.already_used");
}
}
}
}
private void validateGroupName(Member group) {
group.getGroupName().setErrors(new ArrayList<String>());
if (PojoUtil.isEmpty(group.getGroupName())) {
setError(group.getGroupName(), "NotBlank.group.name");
} else if (group.getGroupName().getValue().length() > 150) {
setError(group.getGroupName(), "group.name.too_long");
}
}
private void validateGroupType(Member group) {
group.getType().setErrors(new ArrayList<String>());
if (PojoUtil.isEmpty(group.getType())) {
setError(group.getType(), "NotBlank.group.type");
} else {
try {
MemberType.fromValue(group.getType().getValue());
} catch (IllegalArgumentException e) {
setError(group.getType(), "group.type.invalid");
}
}
}
private void validateSalesforceId(Member group) {
group.getSalesforceId().setErrors(new ArrayList<String>());
if (group != null && !PojoUtil.isEmpty(group.getSalesforceId())) {
if (group.getSalesforceId().getValue().length() != 15) {
setError(group.getSalesforceId(), "group.salesforce_id.invalid_length");
} else if (!group.getSalesforceId().getValue().matches(SALESFORCE_ID_PATTERN)) {
setError(group.getSalesforceId(), "group.salesforce_id.invalid");
}
}
}
private void validateIdP(Client client) {
if(client != null) {
if(!PojoUtil.isEmpty(client.getAuthenticationProviderId())) {
client.getAuthenticationProviderId().setErrors(new ArrayList<String>());
boolean redirectUriFound = false;
if(client.getRedirectUris() != null) {
for(RedirectUri rUri : client.getRedirectUris()) {
if(RedirectUriType.INSTITUTIONAL_SIGN_IN.value().equals(rUri.getType().getValue())) {
redirectUriFound = true;
}
}
}
if(!redirectUriFound) {
setError(client.getAuthenticationProviderId(), "manage.developer_tools.client.idp.error.no_redirect_uri_found");
}
}
}
}
}
class ResultContainer implements Serializable {
private static final long serialVersionUID = -3832431757948716851L;
boolean isClient = false;
Client clientObject;
Member memberObject;
public boolean isClient() {
return isClient;
}
public void setClient(boolean isClient) {
this.isClient = isClient;
}
public Client getClientObject() {
return clientObject;
}
public void setClientObject(Client clientObject) {
this.clientObject = clientObject;
}
public Member getMemberObject() {
return memberObject;
}
public void setMemberObject(Member memberObject) {
this.memberObject = memberObject;
}
}