package uk.ac.ebi.fg.myequivalents.webservices.server;
import java.io.StringReader;
import java.util.List;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.ac.ebi.fg.myequivalents.access_control.model.User;
import uk.ac.ebi.fg.myequivalents.access_control.model.User.Role;
import uk.ac.ebi.fg.myequivalents.exceptions.SecurityException;
import uk.ac.ebi.fg.myequivalents.managers.impl.db.DbManagerFactory;
import uk.ac.ebi.fg.myequivalents.managers.interfaces.AccessControlManager;
import uk.ac.ebi.fg.myequivalents.managers.interfaces.ManagerFactory;
import uk.ac.ebi.fg.myequivalents.resources.Resources;
/**
* <p>The web service version of the {@link AccessControlManager} interface. This uses Jersey and set up a REST web service
* See {@link uk.ac.ebi.fg.myequivalents.webservices.client.AccessControlWSClientIT} for usage examples.</p>
*
* <p>The web services are backed by a {@link ManagerFactory}, which needs to be configured via Spring, see {@link Resources}.
* By default {@link DbManagerFactory} is used.</p>
*
* <p>Usually these services are located at /ws/mapping, e.g.,
* "https://localhost:8080/ws/mapping/get?entityId=service1:acc1". You can build the path by appending the value in
* @Path (which annotates every service method) to /mapping.</p>
*
* <dl><dt>date</dt><dd>16 Oct 2013</dd></dl>
* @author Marco Brandizi
*
*/
@Path ( "/access-control" )
public class AccessControlWebService
{
protected final Logger log = LoggerFactory.getLogger ( this.getClass () );
/**
* @see AccessControlManager#getUser(String).
*/
@POST
@Path( "/user/get" )
@Produces ( MediaType.APPLICATION_XML )
public User getUser (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-pwd" ) String authPassword,
@FormParam ( "login-secret" ) String authApiPassword,
@FormParam ( "email" ) String email
)
{
AccessControlManager mgr = getAccessControlManager ( authEmail, authPassword, authApiPassword );
User result = mgr.getUser ( email );
mgr.close ();
return result;
}
@GET
@Path( "/user/get" )
@Produces ( MediaType.APPLICATION_XML )
public User getUserViaGET (
@QueryParam ( "login" ) String authEmail,
@QueryParam ( "login-pwd" ) String authPassword,
@QueryParam ( "login-secret" ) String authApiPassword,
@QueryParam ( "email" ) String email
)
{
return getUser ( authEmail, authPassword, authApiPassword, email );
}
/**
* @see AccessControlManager#storeUser(User).
*/
@POST
@Path( "/user/store" )
@Produces ( MediaType.APPLICATION_XML )
public void storeUser (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-pwd" ) String authPassword,
@FormParam ( "email" ) String email,
@FormParam ( "name" ) String name,
@FormParam ( "surname" ) String surname,
@FormParam ( "password" ) String userPassword,
@FormParam ( "notes" ) String notes,
@FormParam ( "role" ) String role,
@FormParam ( "secret" ) String apiPassword )
{
AccessControlManager mgr = getAccessControlManager ( authEmail, authPassword, null );
mgr.storeUser ( new User (
email, name, surname, userPassword, notes,
Role.valueOf ( StringUtils.upperCase ( role ) ),
apiPassword
));
mgr.close ();
}
/**
* @see AccessControlManager#storeUserFromXml(java.io.Reader).
*/
@POST
@Path ( "/user/store/from-xml" )
@Produces ( MediaType.APPLICATION_XML )
public void storeUserFromXml (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-pwd" ) String authPassword,
@FormParam ( "user-xml" ) String userXml )
{
AccessControlManager mgr = getAccessControlManager ( authEmail, authPassword, null );
mgr.storeUserFromXml ( new StringReader ( userXml ) );
mgr.close ();
}
/**
* @see AccessControlManager#setUserRole(String, Role).
*/
@POST
@Path( "/user/role/set" )
@Produces ( MediaType.APPLICATION_XML )
public void setUserRole (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-pwd" ) String authPassword,
@FormParam ( "login-secret" ) String authApiPassword,
@FormParam ( "email" ) String email,
@FormParam ( "role" ) String role
)
{
AccessControlManager mgr = getAccessControlManager ( authEmail, authPassword, authApiPassword );
mgr.setUserRole ( email, Role.valueOf ( StringUtils.upperCase ( role ) ) );
mgr.close ();
}
/**
* @see AccessControlManager#deleteUser(String).
* @return a boolean in the form of a string, cause Jersey doesn't like other types very much.
*/
@POST
@Path( "/user/delete" )
@Produces ( MediaType.APPLICATION_XML )
public String deleteUser (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-pwd" ) String authPassword,
@FormParam ( "login-secret" ) String authApiPassword,
@FormParam ( "email" ) String email
)
{
AccessControlManager mgr = getAccessControlManager ( authEmail, authPassword, authApiPassword );
boolean result = mgr.deleteUser ( email );
mgr.close ();
return String.valueOf ( result );
}
/**
* @see AccessControlManager#setServicesVisibility(String, String, boolean, String...).
*/
@POST
@Path( "/visibility/service/set" )
@Produces ( MediaType.APPLICATION_XML )
public void setServicesVisibility (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-secret" ) String authApiPassword,
@FormParam ( "public-flag" ) String publicFlagStr,
@FormParam ( "release-date" ) String releaseDateStr,
@FormParam ( "cascade" ) boolean cascade,
@FormParam ( "service" ) List<String> serviceNames
)
{
AccessControlManager mgr = getAccessControlManager ( authEmail, null, authApiPassword );
mgr.setServicesVisibility ( publicFlagStr, releaseDateStr, cascade, serviceNames.toArray ( new String [ 0 ] ) );
mgr.close ();
}
/**
* @see AccessControlManager#setRepositoriesVisibility(String, String, boolean, String...).
*/
@POST
@Path( "/visibility/repository/set" )
@Produces ( MediaType.APPLICATION_XML )
public void setRepositoriesVisibility (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-secret" ) String authApiPassword,
@FormParam ( "public-flag" ) String publicFlagStr,
@FormParam ( "release-date" ) String releaseDateStr,
@FormParam ( "cascade" ) boolean cascade,
@FormParam ( "repository" ) List<String> repositoryNames
)
{
AccessControlManager mgr = getAccessControlManager ( authEmail, null, authApiPassword );
mgr.setRepositoriesVisibility ( publicFlagStr, releaseDateStr, cascade, repositoryNames.toArray ( new String [ 0 ] ) );
mgr.close ();
}
/**
* @see AccessControlManager#setServiceCollectionsVisibility(String, String, boolean, String...).
*/
@POST
@Path( "/visibility/service-collection/set" )
@Produces ( MediaType.APPLICATION_XML )
public void setServiceCollectionVisibility (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-secret" ) String authApiPassword,
@FormParam ( "public-flag" ) String publicFlagStr,
@FormParam ( "release-date" ) String releaseDateStr,
@FormParam ( "cascade" ) boolean cascade,
@FormParam ( "service-coll" ) List<String> serviceCollNames
)
{
AccessControlManager mgr = getAccessControlManager ( authEmail, null, authApiPassword );
mgr.setServiceCollectionsVisibility ( publicFlagStr, releaseDateStr, cascade, serviceCollNames.toArray ( new String [ 0 ] ) );
mgr.close ();
}
/**
* @see AccessControlManager#setEntitiesVisibility(String, String, String...).
*/
@POST
@Path( "/visibility/entity/set" )
@Produces ( MediaType.APPLICATION_XML )
public void setEntitiesVisibility (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-secret" ) String authApiPassword,
@FormParam ( "public-flag" ) String publicFlagStr,
@FormParam ( "release-date" ) String releaseDateStr,
@FormParam ( "entity" ) List<String> entityIds
)
{
AccessControlManager mgr = getAccessControlManager ( authEmail, null, authApiPassword );
mgr.setEntitiesVisibility ( publicFlagStr, releaseDateStr, entityIds.toArray ( new String [ 0 ] ) );
mgr.close ();
}
/**
* Performs {@link AccessControlManager#setAuthenticationCredentials(String, String)} or
* {@link AccessControlManager#setFullAuthenticationCredentials(String, String)}, depending on whether
* the authPassword or authApiPassword parameter is specified.
*
* TODO: auth requests should be factorised to an Access service (they're not used by other WS requests).
* TODO: it's being done in an inefficient way (authentication done twice).
*/
@POST
@Path( "/login" )
@Produces ( MediaType.APPLICATION_XML )
public User setAuthenticationCredentials (
@FormParam ( "login" ) String authEmail,
@FormParam ( "login-pwd" ) String authPassword,
@FormParam ( "login-secret" ) String authApiPassword
)
throws SecurityException
{
AccessControlManager mgr = getAccessControlManager ( authEmail, authPassword, authApiPassword );
User result = authPassword == null
? mgr.setAuthenticationCredentials ( authEmail, authApiPassword )
: mgr.setFullAuthenticationCredentials ( authEmail, authPassword );
mgr.close ();
return result;
}
/**
* The GET variant of {@link #setAuthenticationCredentials(String, String)}, used for testing purposes only.
*/
@GET
@Path( "/login" )
@Produces ( MediaType.APPLICATION_XML )
public User setAuthenticationCredentialsViaGET (
@QueryParam ( "login" ) String authEmail,
@QueryParam ( "login-pwd" ) String authPassword,
@QueryParam ( "login-secret" ) String authApiPassword
)
throws SecurityException
{
return setAuthenticationCredentials ( authEmail, authPassword, authApiPassword );
}
/**
* Gets the {@link AccessControlManager} that is used internally in this web service.
*
* This is obtained from
* {@link Resources} and hence it depends on the Spring configuration, accessed through {@link WebInitializer}
*
* TODO: AOP
*/
private AccessControlManager getAccessControlManager ( String email, String userPassword, String apiPassword )
{
log.trace ( String.format ( "Returning access manager for the user %s, %s, %s",
email, userPassword == null ? null: "***", apiPassword == null ? null : "***" ));
ManagerFactory fact = Resources.getInstance ().getMyEqManagerFactory ();
return userPassword == null
? fact.newAccessControlManager ( email, apiPassword )
: fact.newAccessControlManagerFullAuth ( email, userPassword );
}
}