From 8ccbe83d999e7012ee65e6857664cf9b5b79f4f0 Mon Sep 17 00:00:00 2001 From: pfurio Date: Fri, 11 Oct 2024 11:45:21 +0200 Subject: [PATCH] server: add 3 new web services to handle events, #TASK-4178 --- .../app/cli/main/OpenCgaCompleter.java | 2 +- .../app/cli/main/OpencgaCliOptionsParser.java | 3 + .../OrganizationsCommandExecutor.java | 41 ++++++ .../options/OrganizationsCommandOptions.java | 69 +++++++++ .../catalog/db/api/EventDBAdaptor.java | 3 +- .../db/mongodb/EventMongoDBAdaptor.java | 7 +- .../catalog/managers/EventManager.java | 34 ++--- opencga-client/src/main/R/R/AllGenerics.R | 2 +- .../src/main/R/R/Organization-methods.R | 32 ++++- .../rest/clients/OrganizationClient.java | 41 ++++++ .../src/main/javascript/Organization.js | 31 +++++ .../rest_clients/organization_client.py | 40 ++++++ .../opencga/core/api/FieldConstants.java | 6 + .../server/rest/OrganizationWSServer.java | 131 ++++++++---------- 14 files changed, 343 insertions(+), 99 deletions(-) diff --git a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpenCgaCompleter.java b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpenCgaCompleter.java index 4d1ed716a4..47acc66581 100644 --- a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpenCgaCompleter.java +++ b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpenCgaCompleter.java @@ -89,7 +89,7 @@ public abstract class OpenCgaCompleter implements Completer { .map(Candidate::new) .collect(toList()); - private List organizationsList = asList( "create","notes-create","notes-search","notes-delete","notes-update","update-status-user","user-update","configuration-update","info","update") + private List organizationsList = asList( "create","notes-create","notes-search","notes-delete","notes-update","update-status-user","user-update","configuration-update","events-query","events-archive","events-retry","info","update") .stream() .map(Candidate::new) .collect(toList()); diff --git a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpencgaCliOptionsParser.java b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpencgaCliOptionsParser.java index d99dbba348..625e43b836 100644 --- a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpencgaCliOptionsParser.java +++ b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/OpencgaCliOptionsParser.java @@ -276,6 +276,9 @@ public OpencgaCliOptionsParser() { organizationsSubCommands.addCommand("update-status-user", organizationsCommandOptions.userUpdateStatusCommandOptions); organizationsSubCommands.addCommand("user-update", organizationsCommandOptions.updateUserCommandOptions); organizationsSubCommands.addCommand("configuration-update", organizationsCommandOptions.updateConfigurationCommandOptions); + organizationsSubCommands.addCommand("events-query", organizationsCommandOptions.queryEventsCommandOptions); + organizationsSubCommands.addCommand("events-archive", organizationsCommandOptions.archiveEventsCommandOptions); + organizationsSubCommands.addCommand("events-retry", organizationsCommandOptions.retryEventsCommandOptions); organizationsSubCommands.addCommand("info", organizationsCommandOptions.infoCommandOptions); organizationsSubCommands.addCommand("update", organizationsCommandOptions.updateCommandOptions); diff --git a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/executors/OrganizationsCommandExecutor.java b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/executors/OrganizationsCommandExecutor.java index c0ce6156d3..6859c154f3 100644 --- a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/executors/OrganizationsCommandExecutor.java +++ b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/executors/OrganizationsCommandExecutor.java @@ -16,6 +16,7 @@ import org.opencb.opencga.client.exceptions.ClientException; import org.opencb.opencga.core.common.JacksonUtils; import org.opencb.opencga.core.config.Optimizations; +import org.opencb.opencga.core.models.event.CatalogEvent; import org.opencb.opencga.core.models.notes.Note; import org.opencb.opencga.core.models.notes.NoteCreateParams; import org.opencb.opencga.core.models.notes.NoteUpdateParams; @@ -89,6 +90,15 @@ public void execute() throws Exception { case "configuration-update": queryResponse = updateConfiguration(); break; + case "events-query": + queryResponse = queryEvents(); + break; + case "events-archive": + queryResponse = archiveEvents(); + break; + case "events-retry": + queryResponse = retryEvents(); + break; case "info": queryResponse = info(); break; @@ -345,6 +355,37 @@ private RestResponse updateConfiguration() throws Exc return openCGAClient.getOrganizationClient().updateConfiguration(commandOptions.organization, organizationConfiguration, queryParams); } + private RestResponse queryEvents() throws Exception { + logger.debug("Executing queryEvents in Organizations command line"); + + OrganizationsCommandOptions.QueryEventsCommandOptions commandOptions = organizationsCommandOptions.queryEventsCommandOptions; + + ObjectMap queryParams = new ObjectMap(); + queryParams.putIfNotEmpty("study", commandOptions.study); + queryParams.putIfNotEmpty("creationDate", commandOptions.creationDate); + queryParams.putIfNotEmpty("modificationDate", commandOptions.modificationDate); + queryParams.putIfNotNull("successful", commandOptions.successful); + if (queryParams.get("study") == null && OpencgaMain.isShellMode()) { + queryParams.putIfNotEmpty("study", sessionManager.getSession().getCurrentStudy()); + } + + return openCGAClient.getOrganizationClient().queryEvents(commandOptions.organization, queryParams); + } + + private RestResponse archiveEvents() throws Exception { + logger.debug("Executing archiveEvents in Organizations command line"); + + OrganizationsCommandOptions.ArchiveEventsCommandOptions commandOptions = organizationsCommandOptions.archiveEventsCommandOptions; + return openCGAClient.getOrganizationClient().archiveEvents(commandOptions.organization, commandOptions.eventId); + } + + private RestResponse retryEvents() throws Exception { + logger.debug("Executing retryEvents in Organizations command line"); + + OrganizationsCommandOptions.RetryEventsCommandOptions commandOptions = organizationsCommandOptions.retryEventsCommandOptions; + return openCGAClient.getOrganizationClient().retryEvents(commandOptions.organization, commandOptions.eventId); + } + private RestResponse info() throws Exception { logger.debug("Executing info in Organizations command line"); diff --git a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/options/OrganizationsCommandOptions.java b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/options/OrganizationsCommandOptions.java index 68be35b6ca..c7e343a01e 100644 --- a/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/options/OrganizationsCommandOptions.java +++ b/opencga-app/src/main/java/org/opencb/opencga/app/cli/main/options/OrganizationsCommandOptions.java @@ -41,6 +41,9 @@ public class OrganizationsCommandOptions { public UserUpdateStatusCommandOptions userUpdateStatusCommandOptions; public UpdateUserCommandOptions updateUserCommandOptions; public UpdateConfigurationCommandOptions updateConfigurationCommandOptions; + public QueryEventsCommandOptions queryEventsCommandOptions; + public ArchiveEventsCommandOptions archiveEventsCommandOptions; + public RetryEventsCommandOptions retryEventsCommandOptions; public InfoCommandOptions infoCommandOptions; public UpdateCommandOptions updateCommandOptions; @@ -57,6 +60,9 @@ public OrganizationsCommandOptions(CommonCommandOptions commonCommandOptions, JC this.userUpdateStatusCommandOptions = new UserUpdateStatusCommandOptions(); this.updateUserCommandOptions = new UpdateUserCommandOptions(); this.updateConfigurationCommandOptions = new UpdateConfigurationCommandOptions(); + this.queryEventsCommandOptions = new QueryEventsCommandOptions(); + this.archiveEventsCommandOptions = new ArchiveEventsCommandOptions(); + this.retryEventsCommandOptions = new RetryEventsCommandOptions(); this.infoCommandOptions = new InfoCommandOptions(); this.updateCommandOptions = new UpdateCommandOptions(); @@ -354,6 +360,69 @@ public class UpdateConfigurationCommandOptions { } + @Parameters(commandNames = {"events-query"}, commandDescription ="Search events") + public class QueryEventsCommandOptions { + + @ParametersDelegate + public CommonCommandOptions commonOptions = commonCommandOptions; + + @Parameter(names = {"--organization"}, description = "Organization id", required = true, arity = 1) + public String organization; + + @Parameter(names = {"--study", "-s"}, description = "Study [[organization@]project:]study where study and project can be either the ID or UUID", required = false, arity = 1) + public String study; + + @Parameter(names = {"--creation-date", "--cd"}, description = "Creation date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805", required = false, arity = 1) + public String creationDate; + + @Parameter(names = {"--modification-date", "--md"}, description = "Modification date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805", required = false, arity = 1) + public String modificationDate; + + @Parameter(names = {"--successful"}, description = "Boolean indicating if the event was successful or not.", required = false, arity = 1) + public Boolean successful; + + } + + @Parameters(commandNames = {"events-archive"}, commandDescription ="Archive an event") + public class ArchiveEventsCommandOptions { + + @ParametersDelegate + public CommonCommandOptions commonOptions = commonCommandOptions; + + @Parameter(names = {"--json-file"}, description = "File with the body data in JSON format. Note, that using this parameter will ignore all the other parameters.", required = false, arity = 1) + public String jsonFile; + + @Parameter(names = {"--json-data-model"}, description = "Show example of file structure for body data.", help = true, arity = 0) + public Boolean jsonDataModel = false; + + @Parameter(names = {"--organization"}, description = "Organization id", required = true, arity = 1) + public String organization; + + @Parameter(names = {"--event-id"}, description = "Event id.", required = true, arity = 1) + public String eventId; + + } + + @Parameters(commandNames = {"events-retry"}, commandDescription ="Retry unsuccessful event") + public class RetryEventsCommandOptions { + + @ParametersDelegate + public CommonCommandOptions commonOptions = commonCommandOptions; + + @Parameter(names = {"--json-file"}, description = "File with the body data in JSON format. Note, that using this parameter will ignore all the other parameters.", required = false, arity = 1) + public String jsonFile; + + @Parameter(names = {"--json-data-model"}, description = "Show example of file structure for body data.", help = true, arity = 0) + public Boolean jsonDataModel = false; + + @Parameter(names = {"--organization"}, description = "Organization id", required = true, arity = 1) + public String organization; + + @Parameter(names = {"--event-id"}, description = "Event id.", required = true, arity = 1) + public String eventId; + + } + @Parameters(commandNames = {"info"}, commandDescription ="Return the organization information") public class InfoCommandOptions { diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/api/EventDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/api/EventDBAdaptor.java index 2e450dcb63..d872d0e24e 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/api/EventDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/api/EventDBAdaptor.java @@ -24,7 +24,8 @@ enum QueryParams implements QueryParam { SUBSCRIBERS("subscribers", OBJECT, ""), SUCCESSFUL("successful", BOOLEAN, ""), CREATION_DATE("creationDate", STRING, ""), - MODIFICATION_DATE("modificationDate", STRING, ""); + MODIFICATION_DATE("modificationDate", STRING, ""), + EVENT_STUDY_FQN("event.studyFqn", STRING, ""); private static Map map = new HashMap<>(); static { diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/EventMongoDBAdaptor.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/EventMongoDBAdaptor.java index ff3b6840aa..3202aeb897 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/EventMongoDBAdaptor.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/db/mongodb/EventMongoDBAdaptor.java @@ -3,7 +3,6 @@ import com.mongodb.client.ClientSession; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; -import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.StringUtils; import org.bson.Document; import org.bson.conversions.Bson; @@ -50,7 +49,10 @@ public EventMongoDBAdaptor(MongoDBCollection eventCollection, MongoDBCollection @Override public OpenCGAResult get(Query query, QueryOptions options) throws CatalogDBException, CatalogParameterException, CatalogAuthorizationException { - throw new NotImplementedException("Yet to implement"); + long startTime = startQuery(); + try (DBIterator dbIterator = iterator(null, query, options)) { + return endQuery(startTime, dbIterator); + } } @Override @@ -196,6 +198,7 @@ private Bson parseQuery(Query query) throws CatalogDBException { case MODIFICATION_DATE: addAutoOrQuery(PRIVATE_MODIFICATION_DATE, queryParam.key(), query, queryParam.type(), andBsonList); break; + case EVENT_STUDY_FQN: case SUCCESSFUL: case ID: case UUID: diff --git a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/managers/EventManager.java b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/managers/EventManager.java index 29170e4795..b4cf545d9f 100644 --- a/opencga-catalog/src/main/java/org/opencb/opencga/catalog/managers/EventManager.java +++ b/opencga-catalog/src/main/java/org/opencb/opencga/catalog/managers/EventManager.java @@ -1,5 +1,6 @@ package org.opencb.opencga.catalog.managers; +import org.apache.commons.lang3.StringUtils; import org.opencb.commons.datastore.core.ObjectMap; import org.opencb.commons.datastore.core.Query; import org.opencb.commons.datastore.core.QueryOptions; @@ -9,8 +10,10 @@ import org.opencb.opencga.catalog.exceptions.CatalogDBException; import org.opencb.opencga.catalog.exceptions.CatalogException; import org.opencb.opencga.catalog.exceptions.CatalogParameterException; +import org.opencb.opencga.catalog.utils.CatalogFqn; import org.opencb.opencga.catalog.utils.ParamUtils; import org.opencb.opencga.catalog.utils.UuidUtils; +import org.opencb.opencga.core.api.ParamConstants; import org.opencb.opencga.core.common.TimeUtils; import org.opencb.opencga.core.events.EventFactory; import org.opencb.opencga.core.events.IEventHandler; @@ -177,34 +180,25 @@ public CatalogEvent notify(String eventId, String organizationId, Supplier executeOperation) -// throws CatalogException { -// CatalogEvent catalogEvent = new CatalogEvent(eventId, new OpencgaEvent(organizationId, eventId, params, userId, study.getFqn(), -// id, payload.getToken(), null)); -// validateNewEvent(catalogEvent); -// try { -// logger.info("Executing '{}' event", eventId); -// OpenCGAResult execute = executeOperation.execute(organizationId, study, userId, queryOptions, payload); -// catalogEvent.getEvent().setResult(execute); -// } catch (Exception e) { -// eventHandler.notify(catalogEvent, e); -// throw new CatalogException(e.getMessage(), e); -// } -// -// logger.info("Notifying of event '{}'.", eventId); -// eventHandler.notify(catalogEvent); -// return catalogEvent; -// } - public OpenCGAResult search(String organizationId, Query query, String token) throws CatalogException { JwtPayload tokenPayload = catalogManager.getUserManager().validateToken(token); String userId = tokenPayload.getUserId(organizationId); catalogManager.getAuthorizationManager().checkIsAtLeastOrganizationOwnerOrAdmin(organizationId, userId); + fixQueryObject(query, tokenPayload); return dbAdaptorFactory.getEventDBAdaptor(organizationId).get(query, QueryOptions.empty()); } + void fixQueryObject(Query query, JwtPayload tokenPayload) throws CatalogException { + String studyParam = query.getString(ParamConstants.STUDY_PARAM); + if (StringUtils.isNotEmpty(studyParam)) { + CatalogFqn catalogFqn = CatalogFqn.extractFqnFromStudy(studyParam, tokenPayload); + Study study = catalogManager.getStudyManager().resolveId(catalogFqn, QueryOptions.empty(), tokenPayload); + query.put(EventDBAdaptor.QueryParams.EVENT_STUDY_FQN.key(), study.getFqn()); + query.remove(ParamConstants.STUDY_PARAM); + } + } + public OpenCGAResult archiveEvent(String organizationId, String eventId, String token) throws CatalogException { JwtPayload tokenPayload = catalogManager.getUserManager().validateToken(token); String userId = tokenPayload.getUserId(organizationId); diff --git a/opencga-client/src/main/R/R/AllGenerics.R b/opencga-client/src/main/R/R/AllGenerics.R index 5b3e3d890c..92387710ab 100644 --- a/opencga-client/src/main/R/R/AllGenerics.R +++ b/opencga-client/src/main/R/R/AllGenerics.R @@ -1,6 +1,6 @@ # ############################################################################## ## OrganizationClient -setGeneric("organizationClient", function(OpencgaR, id, organization, user, endpointName, params=NULL, ...) +setGeneric("organizationClient", function(OpencgaR, eventId, id, organization, user, endpointName, params=NULL, ...) standardGeneric("organizationClient")) # ############################################################################## diff --git a/opencga-client/src/main/R/R/Organization-methods.R b/opencga-client/src/main/R/R/Organization-methods.R index da241e16fb..eba7471a56 100644 --- a/opencga-client/src/main/R/R/Organization-methods.R +++ b/opencga-client/src/main/R/R/Organization-methods.R @@ -27,6 +27,9 @@ #' | userUpdateStatus | /{apiVersion}/organizations/user/{user}/status/update | include, exclude, user[*], organization, includeResult, body[*] | #' | updateUser | /{apiVersion}/organizations/user/{user}/update | include, exclude, user[*], organization, includeResult, body[*] | #' | updateConfiguration | /{apiVersion}/organizations/{organization}/configuration/update | include, exclude, organization[*], includeResult, authenticationOriginsAction, body[*] | +#' | queryEvents | /{apiVersion}/organizations/{organization}/events/query | organization[*], study, creationDate, modificationDate, successful | +#' | archiveEvents | /{apiVersion}/organizations/{organization}/events/{eventId}/archive | organization[*], eventId[*] | +#' | retryEvents | /{apiVersion}/organizations/{organization}/events/{eventId}/retry | organization[*], eventId[*] | #' | info | /{apiVersion}/organizations/{organization}/info | include, exclude, organization[*] | #' | update | /{apiVersion}/organizations/{organization}/update | include, exclude, organization[*], includeResult, adminsAction, body[*] | #' @@ -36,7 +39,7 @@ #' [*]: Required parameter #' @export -setMethod("organizationClient", "OpencgaR", function(OpencgaR, id, organization, user, endpointName, params=NULL, ...) { +setMethod("organizationClient", "OpencgaR", function(OpencgaR, eventId, id, organization, user, endpointName, params=NULL, ...) { switch(endpointName, #' @section Endpoint /{apiVersion}/organizations/create: @@ -125,6 +128,33 @@ setMethod("organizationClient", "OpencgaR", function(OpencgaR, id, organization, subcategory="configuration", subcategoryId=NULL, action="update", params=params, httpMethod="POST", as.queryParam=NULL, ...), + #' @section Endpoint /{apiVersion}/organizations/{organization}/events/query: + #' Search events. + #' @param organization Organization id. + #' @param study Study [[organization@]project:]study where study and project can be either the ID or UUID. + #' @param creationDate Creation date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + #' @param modificationDate Modification date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + #' @param successful Boolean indicating if the event was successful or not. + queryEvents=fetchOpenCGA(object=OpencgaR, category="organizations", categoryId=organization, + subcategory="events", subcategoryId=NULL, action="query", params=params, httpMethod="GET", + as.queryParam=NULL, ...), + + #' @section Endpoint /{apiVersion}/organizations/{organization}/events/{eventId}/archive: + #' Archive an event. + #' @param organization Organization id. + #' @param eventId Event id. + archiveEvents=fetchOpenCGA(object=OpencgaR, category="organizations", categoryId=organization, + subcategory="events", subcategoryId=eventId, action="archive", params=params, httpMethod="POST", + as.queryParam=NULL, ...), + + #' @section Endpoint /{apiVersion}/organizations/{organization}/events/{eventId}/retry: + #' Retry unsuccessful event. + #' @param organization Organization id. + #' @param eventId Event id. + retryEvents=fetchOpenCGA(object=OpencgaR, category="organizations", categoryId=organization, + subcategory="events", subcategoryId=eventId, action="retry", params=params, httpMethod="POST", + as.queryParam=NULL, ...), + #' @section Endpoint /{apiVersion}/organizations/{organization}/info: #' Return the organization information. #' @param include Fields included in the response, whole JSON path must be provided. diff --git a/opencga-client/src/main/java/org/opencb/opencga/client/rest/clients/OrganizationClient.java b/opencga-client/src/main/java/org/opencb/opencga/client/rest/clients/OrganizationClient.java index 67d55693b5..1aabd89870 100644 --- a/opencga-client/src/main/java/org/opencb/opencga/client/rest/clients/OrganizationClient.java +++ b/opencga-client/src/main/java/org/opencb/opencga/client/rest/clients/OrganizationClient.java @@ -20,6 +20,7 @@ import org.opencb.opencga.client.config.ClientConfiguration; import org.opencb.opencga.client.exceptions.ClientException; import org.opencb.opencga.client.rest.*; +import org.opencb.opencga.core.models.event.CatalogEvent; import org.opencb.opencga.core.models.notes.Note; import org.opencb.opencga.core.models.notes.NoteCreateParams; import org.opencb.opencga.core.models.notes.NoteUpdateParams; @@ -193,6 +194,46 @@ public RestResponse updateConfiguration(String organi return execute("organizations", organization, "configuration", null, "update", params, POST, OrganizationConfiguration.class); } + /** + * Search events. + * @param organization Organization id. + * @param params Map containing any of the following optional parameters. + * study: Study [[organization@]project:]study where study and project can be either the ID or UUID. + * creationDate: Creation date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * modificationDate: Modification date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * successful: Boolean indicating if the event was successful or not. + * @return a RestResponse object. + * @throws ClientException ClientException if there is any server error. + */ + public RestResponse queryEvents(String organization, ObjectMap params) throws ClientException { + params = params != null ? params : new ObjectMap(); + return execute("organizations", organization, "events", null, "query", params, GET, CatalogEvent.class); + } + + /** + * Archive an event. + * @param organization Organization id. + * @param eventId Event id. + * @return a RestResponse object. + * @throws ClientException ClientException if there is any server error. + */ + public RestResponse archiveEvents(String organization, String eventId) throws ClientException { + ObjectMap params = new ObjectMap(); + return execute("organizations", organization, "events", eventId, "archive", params, POST, CatalogEvent.class); + } + + /** + * Retry unsuccessful event. + * @param organization Organization id. + * @param eventId Event id. + * @return a RestResponse object. + * @throws ClientException ClientException if there is any server error. + */ + public RestResponse retryEvents(String organization, String eventId) throws ClientException { + ObjectMap params = new ObjectMap(); + return execute("organizations", organization, "events", eventId, "retry", params, POST, CatalogEvent.class); + } + /** * Return the organization information. * @param organization Organization id. diff --git a/opencga-client/src/main/javascript/Organization.js b/opencga-client/src/main/javascript/Organization.js index 1580a4a782..1659c3c1c8 100644 --- a/opencga-client/src/main/javascript/Organization.js +++ b/opencga-client/src/main/javascript/Organization.js @@ -151,6 +151,37 @@ export default class Organization extends OpenCGAParentClass { return this._post("organizations", organization, "configuration", null, "update", data, params); } + /** Search events + * @param {String} organization - Organization id. + * @param {Object} [params] - The Object containing the following optional parameters: + * @param {String} [params.study] - Study [[organization@]project:]study where study and project can be either the ID or UUID. + * @param {String} [params.creationDate] - Creation date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * @param {String} [params.modificationDate] - Modification date. Format: yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + * @param {Boolean} [params.successful] - Boolean indicating if the event was successful or not. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + queryEvents(organization, params) { + return this._get("organizations", organization, "events", null, "query", params); + } + + /** Archive an event + * @param {String} organization - Organization id. + * @param {String} eventId - Event id. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + archiveEvents(organization, eventId) { + return this._post("organizations", organization, "events", eventId, "archive"); + } + + /** Retry unsuccessful event + * @param {String} organization - Organization id. + * @param {String} eventId - Event id. + * @returns {Promise} Promise object in the form of RestResponse instance. + */ + retryEvents(organization, eventId) { + return this._post("organizations", organization, "events", eventId, "retry"); + } + /** Return the organization information * @param {String} organization - Organization id. * @param {Object} [params] - The Object containing the following optional parameters: diff --git a/opencga-client/src/main/python/pyopencga/rest_clients/organization_client.py b/opencga-client/src/main/python/pyopencga/rest_clients/organization_client.py index 0c695ca0a0..5822202373 100644 --- a/opencga-client/src/main/python/pyopencga/rest_clients/organization_client.py +++ b/opencga-client/src/main/python/pyopencga/rest_clients/organization_client.py @@ -168,6 +168,46 @@ def update_configuration(self, organization, data=None, **options): return self._post(category='organizations', resource='update', query_id=organization, subcategory='configuration', data=data, **options) + def query_events(self, organization, **options): + """ + Search events. + PATH: /{apiVersion}/organizations/{organization}/events/query + + :param str organization: Organization id. (REQUIRED) + :param str study: Study [[organization@]project:]study where study and + project can be either the ID or UUID. + :param str creation_date: Creation date. Format: yyyyMMddHHmmss. + Examples: >2018, 2017-2018, <201805. + :param str modification_date: Modification date. Format: + yyyyMMddHHmmss. Examples: >2018, 2017-2018, <201805. + :param bool successful: Boolean indicating if the event was successful + or not. + """ + + return self._get(category='organizations', resource='query', query_id=organization, subcategory='events', **options) + + def archive_events(self, organization, event_id, **options): + """ + Archive an event. + PATH: /{apiVersion}/organizations/{organization}/events/{eventId}/archive + + :param str event_id: Event id. (REQUIRED) + :param str organization: Organization id. (REQUIRED) + """ + + return self._post(category='organizations', resource='archive', query_id=organization, subcategory='events', second_query_id=event_id, **options) + + def retry_events(self, organization, event_id, **options): + """ + Retry unsuccessful event. + PATH: /{apiVersion}/organizations/{organization}/events/{eventId}/retry + + :param str event_id: Event id. (REQUIRED) + :param str organization: Organization id. (REQUIRED) + """ + + return self._post(category='organizations', resource='retry', query_id=organization, subcategory='events', second_query_id=event_id, **options) + def info(self, organization, **options): """ Return the organization information. diff --git a/opencga-core/src/main/java/org/opencb/opencga/core/api/FieldConstants.java b/opencga-core/src/main/java/org/opencb/opencga/core/api/FieldConstants.java index 835f89a61a..68f48887fb 100644 --- a/opencga-core/src/main/java/org/opencb/opencga/core/api/FieldConstants.java +++ b/opencga-core/src/main/java/org/opencb/opencga/core/api/FieldConstants.java @@ -50,6 +50,12 @@ public class FieldConstants { public static final String ORGANIZATION_CONFIGURATION_DESCRIPTION = "Organization configuration information."; public static final String ORGANIZATION_INTERNAL_DESCRIPTION = "Organization internal information."; + // Events + public static final String EVENT_ID_PARAM = "eventId"; + public static final String EVENT_ID_DESCRIPTION = "Event id."; + public static final String EVENT_SUCCESSFUL_PARAM = "successful"; + public static final String EVENT_SUCCESSFUL_DESCRIPTION = "Boolean indicating if the event was successful or not."; + // Notes public static final String NOTES_ID_DESCRIPTION = "Note unique identifier."; public static final String NOTES_SCOPE_DESCRIPTION = "Scope of the Note."; diff --git a/opencga-server/src/main/java/org/opencb/opencga/server/rest/OrganizationWSServer.java b/opencga-server/src/main/java/org/opencb/opencga/server/rest/OrganizationWSServer.java index 15085581bc..6ff4c12dbc 100644 --- a/opencga-server/src/main/java/org/opencb/opencga/server/rest/OrganizationWSServer.java +++ b/opencga-server/src/main/java/org/opencb/opencga/server/rest/OrganizationWSServer.java @@ -18,11 +18,13 @@ import org.opencb.commons.datastore.core.QueryOptions; import org.opencb.opencga.catalog.db.api.OrganizationDBAdaptor; +import org.opencb.opencga.catalog.managers.EventManager; import org.opencb.opencga.catalog.utils.Constants; import org.opencb.opencga.catalog.utils.ParamUtils; import org.opencb.opencga.core.api.FieldConstants; import org.opencb.opencga.core.api.ParamConstants; import org.opencb.opencga.core.exceptions.VersionException; +import org.opencb.opencga.core.models.event.CatalogEvent; import org.opencb.opencga.core.models.notes.Note; import org.opencb.opencga.core.models.notes.NoteCreateParams; import org.opencb.opencga.core.models.notes.NoteUpdateParams; @@ -33,7 +35,6 @@ import org.opencb.opencga.core.models.user.OrganizationUserUpdateParams; import org.opencb.opencga.core.models.user.User; import org.opencb.opencga.core.models.user.UserStatusUpdateParams; -import org.opencb.opencga.core.response.OpenCGAResult; import org.opencb.opencga.core.tools.annotations.*; import javax.servlet.http.HttpServletRequest; @@ -62,14 +63,8 @@ public OrganizationWSServer(@Context UriInfo uriInfo, @Context HttpServletReques dataType = "string", paramType = "query"), }) public Response getInfo( - @ApiParam(value = ParamConstants.ORGANIZATION_DESCRIPTION, required = true) @PathParam(ParamConstants.ORGANIZATION) String organizationId - ) { - try { - OpenCGAResult result = catalogManager.getOrganizationManager().get(organizationId, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + @ApiParam(value = ParamConstants.ORGANIZATION_DESCRIPTION, required = true) @PathParam(ParamConstants.ORGANIZATION) String organizationId) { + return run(() -> catalogManager.getOrganizationManager().get(organizationId, queryOptions, token)); } @POST @@ -86,18 +81,14 @@ public Response update( @ApiParam(value = "Action to be performed if the array of admins is being updated.", allowableValues = "ADD,REMOVE", defaultValue = "ADD") @QueryParam("adminsAction") ParamUtils.AddRemoveAction adminsAction, @ApiParam(value = "JSON containing the params to be updated.", required = true) OrganizationUpdateParams parameters) { - try { - if (adminsAction == null) { - adminsAction = ParamUtils.AddRemoveAction.ADD; + return run(() -> { + if (adminsAction != null) { + Map actionMap = new HashMap<>(); + actionMap.put(OrganizationDBAdaptor.QueryParams.ADMINS.key(), adminsAction); + queryOptions.put(Constants.ACTIONS, actionMap); } - Map actionMap = new HashMap<>(); - actionMap.put(OrganizationDBAdaptor.QueryParams.ADMINS.key(), adminsAction); - queryOptions.put(Constants.ACTIONS, actionMap); - OpenCGAResult result = catalogManager.getOrganizationManager().update(organizationId, parameters, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return catalogManager.getOrganizationManager().update(organizationId, parameters, queryOptions, token); + }); } @POST @@ -114,18 +105,14 @@ public Response updateConfiguration( @ApiParam(value = "Action to be performed if the array of authenticationOrigins is being updated.", allowableValues = "ADD,REMOVE,SET,REPLACE", defaultValue = "ADD") @QueryParam("authenticationOriginsAction") ParamUtils.UpdateAction authOriginsAction, @ApiParam(value = "JSON containing the params to be updated.", required = true) OrganizationConfiguration parameters) { - try { - if (authOriginsAction == null) { - authOriginsAction = ParamUtils.UpdateAction.ADD; + return run(() -> { + if (authOriginsAction != null) { + Map actionMap = new HashMap<>(); + actionMap.put(OrganizationDBAdaptor.AUTH_ORIGINS_FIELD, authOriginsAction); + queryOptions.put(Constants.ACTIONS, actionMap); } - Map actionMap = new HashMap<>(); - actionMap.put(OrganizationDBAdaptor.AUTH_ORIGINS_FIELD, authOriginsAction); - queryOptions.put(Constants.ACTIONS, actionMap); - OpenCGAResult result = catalogManager.getOrganizationManager().updateConfiguration(organizationId, parameters, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return catalogManager.getOrganizationManager().updateConfiguration(organizationId, parameters, queryOptions, token); + }); } @POST @@ -139,12 +126,7 @@ public Response updateConfiguration( public Response create( @ApiParam(value = ParamConstants.INCLUDE_RESULT_DESCRIPTION, defaultValue = "false") @QueryParam(ParamConstants.INCLUDE_RESULT_PARAM) boolean includeResult, @ApiParam(value = "JSON containing the organization to be created.", required = true) OrganizationCreateParams parameters) { - try { - OpenCGAResult result = catalogManager.getOrganizationManager().create(parameters, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return run(() -> catalogManager.getOrganizationManager().create(parameters, queryOptions, token)); } @GET @@ -167,12 +149,7 @@ public Response noteSearch( @ApiParam(value = FieldConstants.NOTES_TAGS_DESCRIPTION) @QueryParam(FieldConstants.NOTES_TAGS_PARAM) String tags, @ApiParam(value = FieldConstants.GENERIC_VERSION_DESCRIPTION) @QueryParam("version") String version ) { - try { - OpenCGAResult result = catalogManager.getNotesManager().searchOrganizationNote(query, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return run(() -> catalogManager.getNotesManager().searchOrganizationNote(query, queryOptions, token)); } @POST @@ -186,12 +163,7 @@ public Response noteSearch( public Response createNote( @ApiParam(value = ParamConstants.INCLUDE_RESULT_DESCRIPTION, defaultValue = "false") @QueryParam(ParamConstants.INCLUDE_RESULT_PARAM) boolean includeResult, @ApiParam(value = "JSON containing the Note to be added.", required = true) NoteCreateParams parameters) { - try { - OpenCGAResult result = catalogManager.getNotesManager().createOrganizationNote(parameters, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return run(() -> catalogManager.getNotesManager().createOrganizationNote(parameters, queryOptions, token)); } @POST @@ -206,12 +178,7 @@ public Response updateNote( @ApiParam(value = FieldConstants.NOTES_ID_DESCRIPTION) @PathParam(FieldConstants.NOTES_ID_PARAM) String noteId, @ApiParam(value = ParamConstants.INCLUDE_RESULT_DESCRIPTION, defaultValue = "false") @QueryParam(ParamConstants.INCLUDE_RESULT_PARAM) boolean includeResult, @ApiParam(value = "JSON containing the Note fields to be updated.", required = true) NoteUpdateParams parameters) { - try { - OpenCGAResult result = catalogManager.getNotesManager().updateOrganizationNote(noteId, parameters, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return run(() -> catalogManager.getNotesManager().updateOrganizationNote(noteId, parameters, queryOptions, token)); } @DELETE @@ -220,12 +187,40 @@ public Response updateNote( public Response deleteNote( @ApiParam(value = FieldConstants.NOTES_ID_DESCRIPTION) @PathParam(FieldConstants.NOTES_ID_PARAM) String noteId, @ApiParam(value = ParamConstants.INCLUDE_RESULT_DESCRIPTION, defaultValue = "false") @QueryParam(ParamConstants.INCLUDE_RESULT_PARAM) boolean includeResult) { - try { - OpenCGAResult result = catalogManager.getNotesManager().deleteOrganizationNote(noteId, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return run(() -> catalogManager.getNotesManager().deleteOrganizationNote(noteId, queryOptions, token)); + } + + @GET + @Path("/{organization}/events/query") + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Search events", response = CatalogEvent.class) + public Response searchEvents( + @ApiParam(value = ParamConstants.ORGANIZATION_DESCRIPTION, required = true) @PathParam(ParamConstants.ORGANIZATION) String organizationId, + @ApiParam(value = ParamConstants.STUDY_DESCRIPTION) @QueryParam(ParamConstants.STUDY_PARAM) String studyStr, + @ApiParam(value = ParamConstants.CREATION_DATE_DESCRIPTION) @QueryParam(ParamConstants.CREATION_DATE_PARAM) String creationDate, + @ApiParam(value = ParamConstants.MODIFICATION_DATE_DESCRIPTION) @QueryParam(ParamConstants.MODIFICATION_DATE_PARAM) String modificationDate, + @ApiParam(value = FieldConstants.EVENT_SUCCESSFUL_DESCRIPTION) @QueryParam(FieldConstants.EVENT_SUCCESSFUL_PARAM) Boolean successful) { + return run(() -> EventManager.getInstance().search(organizationId, query, token)); + } + + @POST + @Path("/{organization}/events/{eventId}/archive") + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Archive an event", response = CatalogEvent.class) + public Response archiveEvent( + @ApiParam(value = ParamConstants.ORGANIZATION_DESCRIPTION, required = true) @PathParam(ParamConstants.ORGANIZATION) String organizationId, + @ApiParam(value = FieldConstants.EVENT_ID_DESCRIPTION) @PathParam(FieldConstants.EVENT_ID_PARAM) String eventId) { + return run(() -> EventManager.getInstance().archiveEvent(organizationId, eventId, token)); + } + + @POST + @Path("/{organization}/events/{eventId}/retry") + @Consumes(MediaType.APPLICATION_JSON) + @ApiOperation(value = "Retry unsuccessful event", response = CatalogEvent.class) + public Response retryEvent( + @ApiParam(value = ParamConstants.ORGANIZATION_DESCRIPTION, required = true) @PathParam(ParamConstants.ORGANIZATION) String organizationId, + @ApiParam(value = FieldConstants.EVENT_ID_DESCRIPTION) @PathParam(FieldConstants.EVENT_ID_PARAM) String eventId) { + return run(() -> EventManager.getInstance().retryEvent(organizationId, eventId, token)); } @POST @@ -241,12 +236,7 @@ public Response updateUserInformation( @ApiParam(value = ParamConstants.ORGANIZATION_DESCRIPTION) @QueryParam(ParamConstants.ORGANIZATION) String organizationId, @ApiParam(value = ParamConstants.INCLUDE_RESULT_DESCRIPTION, defaultValue = "false") @QueryParam(ParamConstants.INCLUDE_RESULT_PARAM) boolean includeResult, @ApiParam(value = "JSON containing the User fields to be updated.", required = true) OrganizationUserUpdateParams parameters) { - try { - OpenCGAResult result = catalogManager.getOrganizationManager().updateUser(organizationId, userId, parameters, queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return run(() -> catalogManager.getOrganizationManager().updateUser(organizationId, userId, parameters, queryOptions, token)); } @POST @@ -262,12 +252,7 @@ public Response updateUserStatus( @ApiParam(value = ParamConstants.ORGANIZATION_DESCRIPTION) @QueryParam(ParamConstants.ORGANIZATION) String organizationId, @ApiParam(value = ParamConstants.INCLUDE_RESULT_DESCRIPTION, defaultValue = "false") @QueryParam(ParamConstants.INCLUDE_RESULT_PARAM) boolean includeResult, @ApiParam(value = "JSON containing the User fields to be updated.", required = true) UserStatusUpdateParams parameters) { - try { - OpenCGAResult result = catalogManager.getUserManager().changeStatus(organizationId, userId, parameters.getStatus(), queryOptions, token); - return createOkResponse(result); - } catch (Exception e) { - return createErrorResponse(e); - } + return run(() -> catalogManager.getUserManager().changeStatus(organizationId, userId, parameters.getStatus(), queryOptions, token)); }