Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e8fb0c7
catalog: implement Notification functionality, #TASK-7413
pfurio Mar 21, 2025
5aca67d
catalog: add field receiver, #TASK-7413
pfurio Mar 25, 2025
bb526b0
catalog: not working commit, #TASK-7413
pfurio Apr 23, 2025
48bda06
core: still not compile ;-)
imedina Apr 23, 2025
0b584c9
core: still not compilegit diff!
imedina Apr 23, 2025
37d6bdd
catalog: implement last changes of notifications, #TASK-7413
pfurio Apr 24, 2025
7553176
server: implement notification web services, #TASK-7413
pfurio Apr 24, 2025
435cd33
catalog: change notification type for level, #TASK-7413
pfurio Apr 25, 2025
4f24742
catalog: support a list of targets, #TASK-7413
pfurio Apr 25, 2025
ee38fd2
catalog: add new permission checks, #TASK-7413
pfurio Apr 30, 2025
9a4de87
server: add WS to mark notification as visited, #TASK-7413
pfurio Apr 30, 2025
2b13c01
catalog: add junits tests for Notification core methods, #TASK-7413
pfurio Apr 30, 2025
d90a3b7
core: add webhookutils tests, #TASK-7413
pfurio May 2, 2025
9e440e5
catalog: support filtering by visited flag, #TASK-7413
pfurio May 2, 2025
7603530
Merge branch 'develop' into TASK-7413
pfurio May 22, 2025
eeab4b7
catalog: allow updating notification object from user, #TASK-7413
pfurio May 23, 2025
a82b5d4
catalog: fix internalStatus query param, #TASK-7413
pfurio May 26, 2025
0b23fd7
catalog: fix query object from iterator, #TASK-7413
pfurio May 26, 2025
b3a05d7
master: fix notification update, #TASK-7413
pfurio May 27, 2025
e32836e
Merge branch 'develop' into TASK-7413
ifiancu Jul 15, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,7 @@ protected VariantStorageEngine getVariantStorageEngineByProject(String project,
private VariantStorageEngine getVariantStorageEngineByDatastore(DataStore dataStore, String alias, String projectFqnStr, String token) throws StorageEngineException, CatalogException {
VariantStorageEngine variantStorageEngine = storageEngineFactory
.getVariantStorageEngine(dataStore.getStorageEngine(), dataStore.getDbName(), alias);
CatalogFqn projectFqn = CatalogFqn.fromProjectFqn(projectFqnStr);
CatalogFqn projectFqn = CatalogFqn.extractFqnFromProjectFqn(projectFqnStr);
variantStorageEngine.getOptions().put("catalog.organization", projectFqn.getOrganizationId());
variantStorageEngine.getOptions().put("catalog.project", projectFqn.getProjectId());
setCellbaseConfiguration(variantStorageEngine, projectFqnStr, token);
Expand Down
1 change: 1 addition & 0 deletions opencga-app/app/misc/clients/r_client_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def __init__(self, server_url, output_dir):
self.categories = {
'Federations': 'Federation',
'Organizations': 'Organization',
'Notifications': 'Notification',
'Users': 'User',
'Projects': 'Project',
'Studies': 'Study',
Expand Down
1 change: 1 addition & 0 deletions opencga-app/app/misc/clients/rest_client_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def __init__(self, rest_api_file, output_dir):
self.categories = {
'Federations': 'Federation',
'Organizations': 'Organization',
'Notifications': 'Notification',
'Users': 'User',
'Projects': 'Project',
'Studies': 'Study',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public AdminCliOptionsParser() {
usersSubCommands.addCommand("import", usersCommandOptions.importCommandOptions);
usersSubCommands.addCommand("sync", usersCommandOptions.syncCommandOptions);
usersSubCommands.addCommand("delete", usersCommandOptions.deleteUserCommandOptions);
usersSubCommands.addCommand("quota", usersCommandOptions.quotaUserCommandOptions);
usersSubCommands.addCommand("stats", usersCommandOptions.statsUserCommandOptions);

auditCommandOptions = new AuditCommandOptions();
Expand Down Expand Up @@ -238,7 +237,6 @@ public class UsersCommandOptions extends CommandOptions {
public SyncCommandOptions syncCommandOptions;
public DeleteUserCommandOptions deleteUserCommandOptions;
public StatsUserCommandOptions statsUserCommandOptions;
public QuotaUserCommandOptions quotaUserCommandOptions;

public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions;

Expand All @@ -248,7 +246,6 @@ public UsersCommandOptions() {
this.syncCommandOptions = new SyncCommandOptions();
this.deleteUserCommandOptions = new DeleteUserCommandOptions();
this.statsUserCommandOptions = new StatsUserCommandOptions();
this.quotaUserCommandOptions = new QuotaUserCommandOptions();
}
}

Expand Down Expand Up @@ -656,21 +653,6 @@ public class DeleteUserCommandOptions extends CatalogDatabaseCommandOptions {

}


@Parameters(commandNames = {"quota"}, commandDescription = "Set a new disk quota for an user")
public class QuotaUserCommandOptions extends CatalogDatabaseCommandOptions {

@ParametersDelegate
public AdminCommonCommandOptions commonOptions = AdminCliOptionsParser.this.commonCommandOptions;


@Parameter(names = {"-u", "--user-id"}, description = "User id to get stats from", required = true, arity = 1)
public String userId;

@Parameter(names = {"--quota"}, description = "Disk quota in GB", required = true, arity = 1)
public long quota;
}

@Parameters(commandNames = {"stats"}, commandDescription = "Print summary stats for an user")
public class StatsUserCommandOptions extends CatalogDatabaseCommandOptions {

Expand All @@ -683,7 +665,6 @@ public class StatsUserCommandOptions extends CatalogDatabaseCommandOptions {

}


/*
* TOOL SUB-COMMANDS
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@
import org.apache.commons.lang3.StringUtils;
import org.opencb.commons.datastore.core.DataResult;
import org.opencb.commons.datastore.core.Event;
import org.opencb.commons.datastore.core.ObjectMap;
import org.opencb.commons.datastore.core.QueryOptions;
import org.opencb.commons.utils.ListUtils;
import org.opencb.opencga.app.cli.admin.AdminCliOptionsParser;
import org.opencb.opencga.catalog.db.api.UserDBAdaptor;
import org.opencb.opencga.catalog.exceptions.CatalogException;
import org.opencb.opencga.catalog.managers.CatalogManager;
import org.opencb.opencga.core.models.user.User;
Expand Down Expand Up @@ -63,9 +61,6 @@ public void execute() throws Exception {
case "delete":
delete();
break;
case "quota":
setQuota();
break;
default:
logger.error("Subcommand not valid");
break;
Expand Down Expand Up @@ -189,20 +184,4 @@ private void delete() throws CatalogException, IOException {
}
}

private void setQuota() throws CatalogException {
setCatalogDatabaseCredentials(usersCommandOptions.quotaUserCommandOptions.databaseHost,
usersCommandOptions.quotaUserCommandOptions.prefix, usersCommandOptions.quotaUserCommandOptions.databaseUser,
usersCommandOptions.quotaUserCommandOptions.databasePassword,
usersCommandOptions.quotaUserCommandOptions.commonOptions.adminPassword);

try (CatalogManager catalogManager = new CatalogManager(configuration)) {
catalogManager.getUserManager().loginAsAdmin(usersCommandOptions.quotaUserCommandOptions.commonOptions.adminPassword);

User user = catalogManager.getUserManager().update(usersCommandOptions.quotaUserCommandOptions.userId, new ObjectMap
(UserDBAdaptor.QueryParams.QUOTA.key(), usersCommandOptions.quotaUserCommandOptions.quota * 1073741824), null, null).first();

System.out.println("The disk quota has been properly updated: " + user.toString());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

public abstract class OpenCgaCompleter implements Completer {

protected List<Candidate> commands = asList("login","logout","help","use","variant","projects","panels","clinical","jobs","admin","workflows","individuals","families","users","samples","alignments","meta","organizations","studies","files","operations","cohorts")
protected List<Candidate> commands = asList("login","logout","help","use","variant","projects","panels","clinical","jobs","admin","workflows","individuals","families","users","samples","alignments","meta","organizations","studies","files","operations","notifications","cohorts")
.stream()
.map(Candidate::new)
.collect(toList());
Expand Down Expand Up @@ -114,6 +114,11 @@ public abstract class OpenCgaCompleter implements Completer {
.map(Candidate::new)
.collect(toList());

private List<Candidate> notificationsList = asList( "aggregationstats","create","search","info","visit")
.stream()
.map(Candidate::new)
.collect(toList());

private List<Candidate> cohortsList = asList( "acl-update","aggregationstats","annotation-sets-load","create","distinct","generate","search","acl","delete","info","update","annotation-sets-annotations-update")
.stream()
.map(Candidate::new)
Expand Down Expand Up @@ -144,6 +149,7 @@ public void complete(LineReader lineReader, ParsedLine parsedLine, List<Candidat
mapCandidates.put( "studies", studiesList);
mapCandidates.put( "files", filesList);
mapCandidates.put( "operations", operationsList);
mapCandidates.put( "notifications", notificationsList);
mapCandidates.put( "cohorts", cohortsList);
candidates.addAll(checkCandidates(mapCandidates,command));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class OpencgaCliOptionsParser extends CustomCliOptionsParser {
private final StudiesCommandOptions studiesCommandOptions;
private final FilesCommandOptions filesCommandOptions;
private final OperationsVariantStorageCommandOptions operationsVariantStorageCommandOptions;
private final NotificationsCommandOptions notificationsCommandOptions;
private final CohortsCommandOptions cohortsCommandOptions;

enum OutputFormat {IDS, ID_CSV, NAME_ID_MAP, ID_LIST, RAW, PRETTY_JSON, PLAIN_JSON}
Expand Down Expand Up @@ -397,6 +398,15 @@ public OpencgaCliOptionsParser() {
operationsVariantStorageSubCommands.addCommand("variant-stats-index", operationsVariantStorageCommandOptions.indexVariantStatsCommandOptions);
operationsVariantStorageSubCommands.addCommand("variant-study-delete", operationsVariantStorageCommandOptions.deleteVariantStudyCommandOptions);

notificationsCommandOptions = new NotificationsCommandOptions(commonCommandOptions, jCommander);
jCommander.addCommand("notifications", notificationsCommandOptions);
JCommander notificationsSubCommands = jCommander.getCommands().get("notifications");
notificationsSubCommands.addCommand("aggregationstats", notificationsCommandOptions.aggregationStatsCommandOptions);
notificationsSubCommands.addCommand("create", notificationsCommandOptions.createCommandOptions);
notificationsSubCommands.addCommand("search", notificationsCommandOptions.searchCommandOptions);
notificationsSubCommands.addCommand("info", notificationsCommandOptions.infoCommandOptions);
notificationsSubCommands.addCommand("visit", notificationsCommandOptions.visitCommandOptions);

cohortsCommandOptions = new CohortsCommandOptions(commonCommandOptions, jCommander);
jCommander.addCommand("cohorts", cohortsCommandOptions);
JCommander cohortsSubCommands = jCommander.getCommands().get("cohorts");
Expand Down Expand Up @@ -499,6 +509,11 @@ public OperationsVariantStorageCommandOptions getOperationsVariantStorageCommand
}


public NotificationsCommandOptions getNotificationsCommandOptions() {
return notificationsCommandOptions;
}


public CohortsCommandOptions getCohortsCommandOptions() {
return cohortsCommandOptions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public static OpencgaCommandExecutor getOpencgaCommandExecutor(OpencgaCliOptions
case "organizations":
commandExecutor = new OrganizationsCommandExecutor(cliOptionsParser.getOrganizationsCommandOptions());
break;
case "notifications":
commandExecutor = new NotificationsCommandExecutor(cliOptionsParser.getNotificationsCommandOptions());
break;
case "users":
commandExecutor = new UsersCommandExecutor(cliOptionsParser.getUsersCommandOptions());
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package org.opencb.opencga.app.cli.main.executors;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.HashMap;
import java.util.List;
import org.opencb.commons.datastore.core.FacetField;
import org.opencb.commons.datastore.core.ObjectMap;
import org.opencb.commons.utils.PrintUtils;
import org.opencb.opencga.app.cli.main.*;
import org.opencb.opencga.app.cli.main.executors.OpencgaCommandExecutor;
import org.opencb.opencga.app.cli.main.options.NotificationsCommandOptions;
import org.opencb.opencga.catalog.exceptions.CatalogAuthenticationException;
import org.opencb.opencga.core.common.JacksonUtils;
import org.opencb.opencga.core.exceptions.ClientException;
import org.opencb.opencga.core.models.notification.Notification;
import org.opencb.opencga.core.models.notification.NotificationCreateParams;
import org.opencb.opencga.core.models.notification.NotificationLevel;
import org.opencb.opencga.core.models.notification.NotificationScope;
import org.opencb.opencga.core.response.QueryType;
import org.opencb.opencga.core.response.RestResponse;


/*
* WARNING: AUTOGENERATED CODE
*
* This code was generated by a tool.
*
* Manual changes to this file may cause unexpected behavior in your application.
* Manual changes to this file will be overwritten if the code is regenerated.
*
*/
/**
* This class contains methods for the Notifications command line.
* PATH: /{apiVersion}/notifications
*/
public class NotificationsCommandExecutor extends OpencgaCommandExecutor {

public String categoryName = "notifications";
public NotificationsCommandOptions notificationsCommandOptions;

public NotificationsCommandExecutor(NotificationsCommandOptions notificationsCommandOptions) throws CatalogAuthenticationException {
super(notificationsCommandOptions.commonCommandOptions);
this.notificationsCommandOptions = notificationsCommandOptions;
}

@Override
public void execute() throws Exception {

logger.debug("Executing Notifications command line");

String subCommandString = getParsedSubCommand(notificationsCommandOptions.jCommander);

RestResponse queryResponse = null;

switch (subCommandString) {
case "aggregationstats":
queryResponse = aggregationStats();
break;
case "create":
queryResponse = create();
break;
case "search":
queryResponse = search();
break;
case "info":
queryResponse = info();
break;
case "visit":
queryResponse = visit();
break;
default:
logger.error("Subcommand not valid");
break;
}

createOutput(queryResponse);

}

private RestResponse<FacetField> aggregationStats() throws Exception {
logger.debug("Executing aggregationStats in Notifications command line");

NotificationsCommandOptions.AggregationStatsCommandOptions commandOptions = notificationsCommandOptions.aggregationStatsCommandOptions;

ObjectMap queryParams = new ObjectMap();
queryParams.putIfNotEmpty("organization", commandOptions.organization);
queryParams.putIfNotEmpty("uuid", commandOptions.uuid);
queryParams.putIfNotEmpty("type", commandOptions.type);
queryParams.putIfNotEmpty("scope", commandOptions.scope);
queryParams.putIfNotEmpty("fqn", commandOptions.fqn);
queryParams.putIfNotEmpty("sender", commandOptions.sender);
queryParams.putIfNotEmpty("target", commandOptions.target);
queryParams.putIfNotEmpty("receiver", commandOptions.receiver);
queryParams.putIfNotEmpty("internalStatus", commandOptions.internalStatus);
queryParams.putIfNotNull("visited", commandOptions.visited);
queryParams.putIfNotEmpty("creationDate", commandOptions.creationDate);
queryParams.putIfNotEmpty("modificationDate", commandOptions.modificationDate);
queryParams.putIfNotEmpty("field", commandOptions.field);

return openCGAClient.getNotificationClient().aggregationStats(queryParams);
}

private RestResponse<Notification> create() throws Exception {
logger.debug("Executing create in Notifications command line");

NotificationsCommandOptions.CreateCommandOptions commandOptions = notificationsCommandOptions.createCommandOptions;

NotificationCreateParams notificationCreateParams = null;
if (commandOptions.jsonDataModel) {
RestResponse<Notification> res = new RestResponse<>();
res.setType(QueryType.VOID);
PrintUtils.println(getObjectAsJSON(categoryName,"/{apiVersion}/notifications/create"));
return res;
} else if (commandOptions.jsonFile != null) {
notificationCreateParams = JacksonUtils.getDefaultObjectMapper()
.readValue(new java.io.File(commandOptions.jsonFile), NotificationCreateParams.class);
} else {
ObjectMap beanParams = new ObjectMap();
putNestedIfNotEmpty(beanParams, "subject", commandOptions.subject, true);
putNestedIfNotEmpty(beanParams, "content", commandOptions.content, true);
putNestedIfNotNull(beanParams, "level", commandOptions.level, true);
putNestedIfNotNull(beanParams, "scope", commandOptions.scope, true);
putNestedIfNotEmpty(beanParams, "fqn", commandOptions.fqn, true);
putNestedIfNotNull(beanParams, "targets", commandOptions.targets, true);

notificationCreateParams = JacksonUtils.getDefaultObjectMapper().copy()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
.readValue(beanParams.toJson(), NotificationCreateParams.class);
}
return openCGAClient.getNotificationClient().create(notificationCreateParams);
}

private RestResponse<Notification> search() throws Exception {
logger.debug("Executing search in Notifications command line");

NotificationsCommandOptions.SearchCommandOptions commandOptions = notificationsCommandOptions.searchCommandOptions;

ObjectMap queryParams = new ObjectMap();
queryParams.putIfNotEmpty("include", commandOptions.include);
queryParams.putIfNotEmpty("exclude", commandOptions.exclude);
queryParams.putIfNotNull("limit", commandOptions.limit);
queryParams.putIfNotNull("skip", commandOptions.skip);
queryParams.putIfNotNull("count", commandOptions.count);
queryParams.putIfNotEmpty("organization", commandOptions.organization);
queryParams.putIfNotEmpty("uuid", commandOptions.uuid);
queryParams.putIfNotEmpty("type", commandOptions.type);
queryParams.putIfNotEmpty("scope", commandOptions.scope);
queryParams.putIfNotEmpty("fqn", commandOptions.fqn);
queryParams.putIfNotEmpty("sender", commandOptions.sender);
queryParams.putIfNotEmpty("target", commandOptions.target);
queryParams.putIfNotEmpty("receiver", commandOptions.receiver);
queryParams.putIfNotEmpty("internalStatus", commandOptions.internalStatus);
queryParams.putIfNotNull("visited", commandOptions.visited);
queryParams.putIfNotEmpty("creationDate", commandOptions.creationDate);
queryParams.putIfNotEmpty("modificationDate", commandOptions.modificationDate);

return openCGAClient.getNotificationClient().search(queryParams);
}

private RestResponse<Notification> info() throws Exception {
logger.debug("Executing info in Notifications command line");

NotificationsCommandOptions.InfoCommandOptions commandOptions = notificationsCommandOptions.infoCommandOptions;

ObjectMap queryParams = new ObjectMap();
queryParams.putIfNotEmpty("include", commandOptions.include);
queryParams.putIfNotEmpty("exclude", commandOptions.exclude);
queryParams.putIfNotEmpty("organization", commandOptions.organization);

return openCGAClient.getNotificationClient().info(commandOptions.notification, queryParams);
}

private RestResponse<Notification> visit() throws Exception {
logger.debug("Executing visit in Notifications command line");

NotificationsCommandOptions.VisitCommandOptions commandOptions = notificationsCommandOptions.visitCommandOptions;

ObjectMap queryParams = new ObjectMap();
queryParams.putIfNotEmpty("organization", commandOptions.organization);

return openCGAClient.getNotificationClient().visit(commandOptions.notification, queryParams);
}
}
Loading