Skip to content

Commit 1069537

Browse files
Merge pull request #72 from ral-facilities/36_sessionIds
Use functional credentials for prepareData queue calls to IDS
2 parents 9a0c90b + 2b05ea8 commit 1069537

File tree

6 files changed

+91
-37
lines changed

6 files changed

+91
-37
lines changed

src/main/config/run.properties.example

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ defaultPlugin=simple
9393
# Facility to use if it is not specified in the login request
9494
defaultFacilityName=LILS
9595

96+
# Queued Downloads are authorized with the user's sessionId, but this may expire before
97+
# the Download is ready to be prepared so these will be submitted to the IDS with a
98+
# functional read all account.
99+
queue.account.LILS.plugin=simple
100+
queue.account.LILS.username=username
101+
queue.account.LILS.password=password
102+
96103
# Limit the number maximum of active RESTORING downloads. Does not affect user submitted carts,
97104
# but queued requests will only be started when there are less than this many RESTORING downloads.
98105
# Negative values will start all queued jobs immediately, regardless of load.

src/main/java/org/icatproject/topcat/IcatClient.java

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,26 @@ public IcatClient(String url, String sessionId) {
3838
/**
3939
* Login to create a session
4040
*
41-
* @param jsonString with plugin and credentials which takes the form
42-
* <code>{"plugin":"db", "credentials:[{"username":"root"}, {"password":"guess"}]}</code>
41+
* @param plugin ICAT authentication plugin
42+
* @param username ICAT username
43+
* @param password ICAT password
4344
* @return json with sessionId of the form
4445
* <samp>{"sessionId","0d9a3706-80d4-4d29-9ff3-4d65d4308a24"}</samp>
4546
* @throws BadRequestException
4647
*/
47-
public String login(String jsonString) throws BadRequestException {
48+
public String login(String plugin, String username, String password) throws BadRequestException {
4849
try {
50+
JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
51+
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
52+
JsonObjectBuilder usernameBuilder = Json.createObjectBuilder();
53+
JsonObjectBuilder passwordBuilder = Json.createObjectBuilder();
54+
usernameBuilder.add("username", username);
55+
passwordBuilder.add("password", password);
56+
arrayBuilder.add(usernameBuilder);
57+
arrayBuilder.add(passwordBuilder);
58+
objectBuilder.add("plugin", plugin);
59+
objectBuilder.add("credentials", arrayBuilder);
60+
String jsonString = "json=" + objectBuilder.build().toString();
4961
Response response = httpClient.post("session", new HashMap<String, String>(), jsonString);
5062
return response.toString();
5163
} catch (Exception e) {
@@ -379,7 +391,8 @@ public int getQueuePriority(String userName) throws TopcatException {
379391
}
380392
}
381393

382-
if (!userName.equals(Properties.getInstance().getProperty("anonUserName"))) {
394+
if (!userName.startsWith(Properties.getInstance().getProperty("anonUserName"))) {
395+
// The anonymous cart username will end with the user's sessionId so cannot do .equals
383396
return priorityMap.getAuthenticatedPriority();
384397
} else {
385398
return priorityMap.getDefaultPriority();

src/main/java/org/icatproject/topcat/StatusCheck.java

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -236,18 +236,22 @@ private void sendDownloadReadyEmail(Download download) throws InternalException{
236236
}
237237

238238
private void prepareDownload(Download download, IdsClient injectedIdsClient) throws Exception {
239+
prepareDownload(download, injectedIdsClient, download.getSessionId());
240+
}
241+
242+
private void prepareDownload(Download download, IdsClient injectedIdsClient, String sessionId) throws Exception {
239243

240244
try {
241245
IdsClient idsClient = injectedIdsClient;
242246
if( idsClient == null ) {
243247
idsClient = new IdsClient(getDownloadUrl(download.getFacilityName(),download.getTransport()));
244248
}
245249
logger.info("Requesting prepareData for Download " + download.getFileName());
246-
String preparedId = idsClient.prepareData(download.getSessionId(), download.getInvestigationIds(), download.getDatasetIds(), download.getDatafileIds());
250+
String preparedId = idsClient.prepareData(sessionId, download.getInvestigationIds(), download.getDatasetIds(), download.getDatafileIds());
247251
download.setPreparedId(preparedId);
248252

249253
try {
250-
Long size = idsClient.getSize(download.getSessionId(), download.getInvestigationIds(), download.getDatasetIds(), download.getDatafileIds());
254+
Long size = idsClient.getSize(sessionId, download.getInvestigationIds(), download.getDatasetIds(), download.getDatafileIds());
251255
download.setSize(size);
252256
} catch(Exception e) {
253257
logger.error("prepareDownload: setting size to -1 as getSize threw exception: " + e.getMessage());
@@ -274,7 +278,31 @@ private void prepareDownload(Download download, IdsClient injectedIdsClient) thr
274278
}
275279

276280
}
277-
281+
282+
/**
283+
* Gets a functional sessionId to use for submitting to the queue, logging in if needed.
284+
*
285+
* @param sessionIds Map from Facility to functional sessionId
286+
* @param facilityName Name of ICAT Facility to get the sessionId for
287+
* @return Functional ICAT sessionId
288+
* @throws InternalException If the facilityName cannot be mapped to an ICAT url
289+
* @throws BadRequestException If the login fails
290+
*/
291+
private String getQueueSessionId(Map<String, String> sessionIds, String facilityName)
292+
throws InternalException, BadRequestException {
293+
String sessionId = sessionIds.get(facilityName);
294+
if (sessionId == null) {
295+
IcatClient icatClient = new IcatClient(FacilityMap.getInstance().getIcatUrl(facilityName));
296+
Properties properties = Properties.getInstance();
297+
String plugin = properties.getProperty("queue.account." + facilityName + ".plugin");
298+
String username = properties.getProperty("queue.account." + facilityName + ".username");
299+
String password = properties.getProperty("queue.account." + facilityName + ".password");
300+
sessionId = icatClient.login(plugin, username, password);
301+
sessionIds.put(facilityName, sessionId);
302+
}
303+
return sessionId;
304+
}
305+
278306
/**
279307
* Prepares Downloads which are queued (PAUSED with no preparedId) up to the
280308
* maxActiveDownloads limit.
@@ -295,43 +323,48 @@ public void startQueuedDownloads(int maxActiveDownloads) throws Exception {
295323
String restoringCondition = "download.status = org.icatproject.topcat.domain.DownloadStatus.RESTORING";
296324
String pausedCondition = "download.status = org.icatproject.topcat.domain.DownloadStatus.PAUSED";
297325

326+
int availableDownloads = maxActiveDownloads;
298327
if (maxActiveDownloads > 0) {
328+
// Work out how many "available" spaces there are by accounting for the active Downloads
299329
String activeQueryString = selectString + " and " + restoringCondition;
300330
TypedQuery<Download> activeDownloadsQuery = em.createQuery(activeQueryString, Download.class);
301331
List<Download> activeDownloads = activeDownloadsQuery.getResultList();
302-
maxActiveDownloads -= activeDownloads.size();
303-
if (maxActiveDownloads <= 0) {
332+
int activeDownloadsSize = activeDownloads.size();
333+
if (activeDownloadsSize >= maxActiveDownloads) {
304334
String format = "More downloads currently RESTORING {} than maxActiveDownloads {}, cannot prepare queued jobs";
305-
logger.info(format, activeDownloads.size(), maxActiveDownloads);
335+
logger.info(format, activeDownloadsSize, maxActiveDownloads);
306336
return;
307337
}
338+
availableDownloads -= activeDownloadsSize;
308339
}
309340

310341
String queuedQueryString = selectString + " and " + pausedCondition + " and download.preparedId = null";
311342
queuedQueryString += " order by download.createdAt";
312343
TypedQuery<Download> queuedDownloadsQuery = em.createQuery(queuedQueryString, Download.class);
313344
List<Download> queuedDownloads = queuedDownloadsQuery.getResultList();
314345

346+
Map<String, String> sessionIds = new HashMap<>();
315347
if (maxActiveDownloads <= 0) {
316-
logger.info("Preparing {} queued downloads", queuedDownloads.size());
317348
// No limits on how many to submit
349+
logger.info("Preparing {} queued downloads", queuedDownloads.size());
318350
for (Download queuedDownload : queuedDownloads) {
319351
queuedDownload.setStatus(DownloadStatus.PREPARING);
320-
prepareDownload(queuedDownload, null);
352+
prepareDownload(queuedDownload, null, getQueueSessionId(sessionIds, queuedDownload.getFacilityName()));
321353
}
322354
} else {
323-
logger.info("Preparing up to {} queued downloads", maxActiveDownloads);
355+
logger.info("Preparing up to {} queued downloads", availableDownloads);
324356
HashMap<Integer, List<Download>> mapping = new HashMap<>();
325357
for (Download queuedDownload : queuedDownloads) {
358+
String sessionId = getQueueSessionId(sessionIds, queuedDownload.getFacilityName());
326359
String icatUrl = FacilityMap.getInstance().getIcatUrl(queuedDownload.getFacilityName());
327-
IcatClient icatClient = new IcatClient(icatUrl, queuedDownload.getSessionId());
360+
IcatClient icatClient = new IcatClient(icatUrl, sessionId);
328361
int priority = icatClient.getQueuePriority(queuedDownload.getUserName());
329362
if (priority == 1) {
330363
// Highest priority, prepare now
331364
queuedDownload.setStatus(DownloadStatus.PREPARING);
332-
prepareDownload(queuedDownload, null);
333-
maxActiveDownloads -= 1;
334-
if (maxActiveDownloads <= 0) {
365+
prepareDownload(queuedDownload, null, sessionId);
366+
availableDownloads -= 1;
367+
if (availableDownloads <= 0) {
335368
return;
336369
}
337370
} else {
@@ -350,9 +383,9 @@ public void startQueuedDownloads(int maxActiveDownloads) throws Exception {
350383
List<Download> downloadList = mapping.get(key);
351384
for (Download download : downloadList) {
352385
download.setStatus(DownloadStatus.PREPARING);
353-
prepareDownload(download, null);
354-
maxActiveDownloads -= 1;
355-
if (maxActiveDownloads <= 0) {
386+
prepareDownload(download, null, getQueueSessionId(sessionIds, download.getFacilityName()));
387+
availableDownloads -= 1;
388+
if (availableDownloads <= 0) {
356389
return;
357390
}
358391
}

src/main/java/org/icatproject/topcat/web/rest/UserResource.java

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,7 @@ public String login(@QueryParam("facilityName") String facilityName, @FormParam(
108108
}
109109
String icatUrl = getIcatUrl(facilityName);
110110
IcatClient icatClient = new IcatClient(icatUrl);
111-
112-
JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
113-
JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
114-
JsonObjectBuilder usernameBuilder = Json.createObjectBuilder();
115-
JsonObjectBuilder passwordBuilder = Json.createObjectBuilder();
116-
usernameBuilder.add("username", username);
117-
passwordBuilder.add("password", password);
118-
arrayBuilder.add(usernameBuilder);
119-
arrayBuilder.add(passwordBuilder);
120-
objectBuilder.add("plugin", plugin);
121-
objectBuilder.add("credentials", arrayBuilder);
122-
123-
return icatClient.login("json=" + objectBuilder.build().toString());
111+
return icatClient.login(plugin, username, password);
124112
}
125113

126114
/**
@@ -330,8 +318,8 @@ public Response setDownloadStatus(
330318
if (!download.getUserName().equals(cartUserName)) {
331319
throw new ForbiddenException("you do not have permission to delete this download");
332320
}
333-
if (download.getPreparedId() == null && download.getStatus().equals(DownloadStatus.PAUSED)) {
334-
throw new ForbiddenException("Cannot modify status of a queued download");
321+
if (download.getPreparedId() == null) {
322+
throw new ForbiddenException("Cannot modify status of a download before it's prepared");
335323
}
336324

337325
download.setStatus(DownloadStatus.valueOf(value));

src/test/java/org/icatproject/topcat/UserResourceTest.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,13 @@ public void testSubmitCart() throws Exception {
240240
if (newDownload.getStatus().equals(DownloadStatus.valueOf(downloadStatus))) {
241241
downloadStatus = "PAUSED";
242242
}
243-
243+
// We cannot modify the status of a download without a prepared id
244+
// Using downloadRepository will create a new Download with a different id,
245+
// so remove the old one without the preparedId.
246+
newDownload.setPreparedId("preparedId");
247+
Download preparedDownload = downloadRepository.save(newDownload);
248+
downloadRepository.removeDownload(downloadId);
249+
downloadId = preparedDownload.getId();
244250
response = userResource.setDownloadStatus(downloadId, facilityName, sessionId, downloadStatus);
245251
assertEquals(200, response.getStatus());
246252

@@ -368,6 +374,7 @@ public void testQueueAllowed() throws Exception {
368374
assertEquals(true, response.getEntity());
369375
}
370376

377+
@Test
371378
public void testSetDownloadStatus() throws Exception {
372379
Long downloadId = null;
373380
try {
@@ -383,9 +390,10 @@ public void testSetDownloadStatus() throws Exception {
383390
downloadRepository.save(testDownload);
384391
downloadId = testDownload.getId();
385392

386-
assertThrows("Cannot modify status of a queued download", ForbiddenException.class, () -> {
393+
ForbiddenException exception = assertThrows(ForbiddenException.class, () -> {
387394
userResource.setDownloadStatus(testDownload.getId(), facilityName, sessionId, DownloadStatus.RESTORING.toString());
388395
});
396+
assertEquals("(403) : Cannot modify status of a download before it's prepared", exception.getMessage());
389397

390398
Response response = userResource.getDownloads(facilityName, sessionId, null);
391399
assertEquals(200, response.getStatus());

src/test/resources/run.properties

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ ids.timeout=10s
1111

1212
# Disable scheduled Download status checks (DO THIS FOR TESTS ONLY!)
1313
test.disableDownloadStatusChecks = true
14+
15+
queue.account.LILS.plugin=simple
16+
queue.account.LILS.username=root
17+
queue.account.LILS.password=pw
18+
1419
# Test data has 100 files per Dataset, set this to a small number to ensure coverage of the batching logic
1520
queue.maxFileCount = 1
1621
queue.priority.user = {"simple/test": 1}

0 commit comments

Comments
 (0)