Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement login endpoint #46 #47

Open
wants to merge 2 commits into
base: 36_queuing
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/main/config/run.properties.example
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,7 @@ maxCacheSize=100000
# ids.timeout=3m

# Username that corresponds with the anonymous user - this is used to make anonymous carts unique
anonUserName=anon/anon
anonUserName=anon/anon

# Authentication plugin to use if it is not specified in the login request
defaultPlugin=simple
27 changes: 27 additions & 0 deletions src/main/java/org/icatproject/topcat/FacilityMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ public FacilityMap(Properties injectedProperties) throws InternalException{
}

public String getIcatUrl( String facility ) throws InternalException{
if (facility == null) {
if (facilityIcatUrl.size() == 1) {
facility = facilityIcatUrl.keySet().iterator().next();
} else {
String error = "FacilityMap.getIcatUrl: facility is null and more than one facility set in config ";
logger.error( error );
throw new InternalException( error );
}
}
String url = facilityIcatUrl.get( facility );
if( url == null ){
String error = "FacilityMap.getIcatUrl: unknown facility: " + facility;
Expand All @@ -82,6 +91,15 @@ public String getIcatUrl( String facility ) throws InternalException{
}

public String getIdsUrl( String facility ) throws InternalException{
if (facility == null) {
if (facilityIdsUrl.size() == 1) {
facility = facilityIdsUrl.keySet().iterator().next();
} else {
String error = "FacilityMap.getIdsUrl: facility is null and more than one facility set in config ";
logger.error( error );
throw new InternalException( error );
}
}
String url = facilityIdsUrl.get( facility );
if( url == null ){
String error = "FacilityMap.getIdsUrl: unknown facility: " + facility;
Expand All @@ -92,6 +110,15 @@ public String getIdsUrl( String facility ) throws InternalException{
}

public String getDownloadUrl( String facility, String downloadType ) throws InternalException{
if (facility == null) {
if (facilityIdsUrl.size() == 1) {
facility = facilityIdsUrl.keySet().iterator().next();
} else {
String error = "FacilityMap.getDownloadUrl: facility is null and more than one facility set in config ";
logger.error( error );
throw new InternalException( error );
}
}
String url = "";
// First, look for the property directly
url = properties.getProperty( "facility." + facility + ".downloadType." + downloadType, "" );
Expand Down
26 changes: 24 additions & 2 deletions src/main/java/org/icatproject/topcat/IcatClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,34 @@ public class IcatClient {

private HttpClient httpClient;
private String sessionId;
public IcatClient(String url, String sessionId){

public IcatClient(String url) {
this.httpClient = new HttpClient(url + "/icat");
}

public IcatClient(String url, String sessionId) {
this(url);
this.sessionId = sessionId;
}

/**
* Login to create a session
*
* @param jsonString with plugin and credentials which takes the form
* <code>{"plugin":"db", "credentials:[{"username":"root"}, {"password":"guess"}]}</code>
* @return json with sessionId of the form
* <samp>{"sessionId","0d9a3706-80d4-4d29-9ff3-4d65d4308a24"}</samp>
* @throws BadRequestException
*/
public String login(String jsonString) throws BadRequestException {
try {
Response response = httpClient.post("session", new HashMap<String, String>(), jsonString);
return response.toString();
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
}

public String getUserName() throws TopcatException {
try {
Response response = httpClient.get("session/" + sessionId, new HashMap<String, String>());
Expand Down
52 changes: 37 additions & 15 deletions src/main/java/org/icatproject/topcat/web/rest/UserResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,15 @@ public class UserResource {
private CacheRepository cacheRepository;

private String anonUserName;
private String defaultPlugin;

@PersistenceContext(unitName = "topcat")
EntityManager em;

public UserResource() {
Properties properties = Properties.getInstance();
this.anonUserName = properties.getProperty("anonUserName", "");
this.defaultPlugin = properties.getProperty("defaultPlugin", "simple");
}

/**
Expand All @@ -83,6 +85,41 @@ private String getCartUserName(String userName, String sessionId) {
}
}

/**
* Login to create a session
*
* @param facilityName A facility name - properties must map this to a url to a valid ICAT REST api, if set.
* Can be null iff one Facility set in the config for the API.
* @param username ICAT username
* @param password Password for the specified authentication plugin
* @param plugin ICAT authentication plugin. If null, a default value will be used.
* @return json with sessionId of the form
* <samp>{"sessionId","0d9a3706-80d4-4d29-9ff3-4d65d4308a24"}</samp>
* @throws BadRequestException
*/
@POST
@Path("/session")
public String login(@QueryParam("facilityName") String facilityName, @FormParam("username") String username, @FormParam("password") String password, @FormParam("plugin") String plugin) throws BadRequestException {
if (plugin == null) {
plugin = defaultPlugin;
}
String icatUrl = getIcatUrl(facilityName);
IcatClient icatClient = new IcatClient(icatUrl);

JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
JsonObjectBuilder usernameBuilder = Json.createObjectBuilder();
JsonObjectBuilder passwordBuilder = Json.createObjectBuilder();
usernameBuilder.add("username", username);
passwordBuilder.add("password", password);
arrayBuilder.add(usernameBuilder);
arrayBuilder.add(passwordBuilder);
objectBuilder.add("plugin", plugin);
objectBuilder.add("credentials", arrayBuilder);

return icatClient.login("json=" + objectBuilder.build().toString());
}

/**
* Returns a list of downloads associated with a particular sessionId
* filtered by a partial JPQL expression.
Expand Down Expand Up @@ -841,7 +878,6 @@ private Response emptyCart(String facilityName, String userName) {
}

private String getIcatUrl( String facilityName ) throws BadRequestException{
testFacilityName( facilityName, "getIcatUrl" );
try {
return FacilityMap.getInstance().getIcatUrl(facilityName);
} catch (InternalException ie){
Expand All @@ -850,7 +886,6 @@ private String getIcatUrl( String facilityName ) throws BadRequestException{
}

private String getIdsUrl( String facilityName ) throws BadRequestException{
testFacilityName( facilityName, "getIdsUrl" );
try {
return FacilityMap.getInstance().getIdsUrl(facilityName);
} catch (InternalException ie){
Expand All @@ -859,23 +894,10 @@ private String getIdsUrl( String facilityName ) throws BadRequestException{
}

private String getDownloadUrl( String facilityName, String downloadType ) throws BadRequestException{
testFacilityName( facilityName, "getDownloadUrl" );
try {
return FacilityMap.getInstance().getDownloadUrl(facilityName, downloadType);
} catch (InternalException ie){
throw new BadRequestException( ie.getMessage() );
}
}

private void testFacilityName( String facilityName, String methodName ) throws BadRequestException{
if( facilityName == null ){
// Most likely an old-style API request using icat/idsUrl
// rather than facilityName; so log and raise a specific error here.
String message = "UserResource." + methodName + ": facilityName is null. Perhaps request is using old API?";
logger.error( message );
throw new BadRequestException( message );
}
}


}
112 changes: 112 additions & 0 deletions src/test/java/org/icatproject/topcat/FacilityMapTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import org.icatproject.topcat.exceptions.InternalException;
import org.junit.*;
import org.junit.function.ThrowingRunnable;

public class FacilityMapTest {

Expand Down Expand Up @@ -113,4 +114,115 @@ public void testComplexConstruction() throws InternalException {
}
}

@Test
public void testGetIcatUrl() throws InternalException{
String facilityList = "Fac1";
String icatUrl = "DummyIcatUrl";
String idsUrl = "DummyIdsUrl";

MockProperties props = new MockProperties();

props.setMockProperty("facility.list", facilityList);
props.setMockProperty("facility.Fac1.icatUrl", icatUrl);
props.setMockProperty("facility.Fac1.idsUrl", idsUrl);

FacilityMap facilityMap = new FacilityMap(props);

assertEquals(icatUrl, facilityMap.getIcatUrl(null));
}

@Test
public void testGetIcatUrlFailure() throws InternalException{
String facilityList = "Fac1, Fac2";
String icatUrl = "DummyIcatUrl";
String idsUrl = "DummyIdsUrl";

MockProperties props = new MockProperties();

props.setMockProperty("facility.list", facilityList);
props.setMockProperty("facility.Fac1.icatUrl", icatUrl);
props.setMockProperty("facility.Fac1.idsUrl", idsUrl);
props.setMockProperty("facility.Fac2.icatUrl", icatUrl);
props.setMockProperty("facility.Fac2.idsUrl", idsUrl);

FacilityMap facilityMap = new FacilityMap(props);

ThrowingRunnable runnable = () -> {facilityMap.getIcatUrl(null);};
assertThrows(InternalException.class, runnable);
}

@Test
public void testGetIdsUrl() throws InternalException{
String facilityList = "Fac1";
String icatUrl = "DummyIcatUrl";
String idsUrl = "DummyIdsUrl";

MockProperties props = new MockProperties();

props.setMockProperty("facility.list", facilityList);
props.setMockProperty("facility.Fac1.icatUrl", icatUrl);
props.setMockProperty("facility.Fac1.idsUrl", idsUrl);

FacilityMap facilityMap = new FacilityMap(props);

assertEquals(idsUrl, facilityMap.getIdsUrl(null));
}

@Test
public void testGetIdsUrlFailure() throws InternalException{
String facilityList = "Fac1, Fac2";
String icatUrl = "DummyIcatUrl";
String idsUrl = "DummyIdsUrl";

MockProperties props = new MockProperties();

props.setMockProperty("facility.list", facilityList);
props.setMockProperty("facility.Fac1.icatUrl", icatUrl);
props.setMockProperty("facility.Fac1.idsUrl", idsUrl);
props.setMockProperty("facility.Fac2.icatUrl", icatUrl);
props.setMockProperty("facility.Fac2.idsUrl", idsUrl);

FacilityMap facilityMap = new FacilityMap(props);

ThrowingRunnable runnable = () -> {facilityMap.getIdsUrl(null);};
assertThrows(InternalException.class, runnable);
}

@Test
public void testGetDownloadUrl() throws InternalException{
String facilityList = "Fac1";
String icatUrl = "DummyIcatUrl";
String idsUrl = "DummyIdsUrl";

MockProperties props = new MockProperties();

props.setMockProperty("facility.list", facilityList);
props.setMockProperty("facility.Fac1.icatUrl", icatUrl);
props.setMockProperty("facility.Fac1.idsUrl", idsUrl);

FacilityMap facilityMap = new FacilityMap(props);

assertEquals(idsUrl, facilityMap.getDownloadUrl(null, "https"));
}

@Test
public void testGetDownloadUrlFailure() throws InternalException{
String facilityList = "Fac1, Fac2";
String icatUrl = "DummyIcatUrl";
String idsUrl = "DummyIdsUrl";

MockProperties props = new MockProperties();

props.setMockProperty("facility.list", facilityList);
props.setMockProperty("facility.Fac1.icatUrl", icatUrl);
props.setMockProperty("facility.Fac1.idsUrl", idsUrl);
props.setMockProperty("facility.Fac2.icatUrl", icatUrl);
props.setMockProperty("facility.Fac2.idsUrl", idsUrl);

FacilityMap facilityMap = new FacilityMap(props);

ThrowingRunnable runnable = () -> {facilityMap.getDownloadUrl(null, "https");};
assertThrows(InternalException.class, runnable);
}

}
15 changes: 13 additions & 2 deletions src/test/java/org/icatproject/topcat/UserResourceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,25 @@ public static void beforeAll() {
@Before
public void setup() throws Exception {
HttpClient httpClient = new HttpClient("https://localhost:8181/icat");
String data = "json=" + URLEncoder.encode(
String loginData = "json=" + URLEncoder.encode(
"{\"plugin\":\"simple\", \"credentials\":[{\"username\":\"root\"}, {\"password\":\"pw\"}]}", "UTF8");
String response = httpClient.post("session", new HashMap<String, String>(), data).toString();
String response = httpClient.post("session", new HashMap<String, String>(), loginData).toString();
sessionId = Utils.parseJsonObject(response).getString("sessionId");

connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/icatdb", "icatdbuser", "icatdbuserpw");
}

@Test
public void testLogin() throws Exception {
String loginResponseString = userResource.login(null, "root", "pw", null);
JsonObject loginResponseObject = Utils.parseJsonObject(loginResponseString);

assertEquals(loginResponseObject.toString(), 1, loginResponseObject.keySet().size());
assertTrue(loginResponseObject.containsKey("sessionId"));
// Will throw if not a UUID
UUID.fromString(loginResponseObject.getString("sessionId"));
}

@Test
public void testGetSize() throws Exception {
String facilityName = "LILS";
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/run.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ facility.LILS.icatUrl = https://localhost:8181
facility.LILS.idsUrl = https://localhost:8181
adminUserNames=simple/root
anonUserName=anon/anon
defaultPlugin=simple

# Disable scheduled Download status checks (DO THIS FOR TESTS ONLY!)
test.disableDownloadStatusChecks = true
Loading