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

TASK-6013 - Extend User Management capabilities #2432

Merged
merged 29 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bec0ed5
catalog: implement update user information for admins, #TASK-6013
pfurio Apr 17, 2024
4b7c935
catalog: implement ban option after several attempts, #TASK-6013
pfurio Apr 18, 2024
3da2c67
app: add migration script, #TASK-6013
pfurio Apr 19, 2024
af2bb26
catalog: fix compilation issues, #TASK-6013
pfurio Apr 19, 2024
7687a08
Merge branch 'develop' into TASK-6013
pfurio Apr 19, 2024
8d3fcc0
app: fix target migration version, #TASK-6013
pfurio Apr 19, 2024
49987a6
catalog: fix default expirationDate, #TASK-6013
pfurio Apr 23, 2024
240badc
Merge branch 'develop' into TASK-6013
pfurio Apr 23, 2024
216628d
catalog: add a variable with the max. login attempts, #TASK-6013
pfurio Apr 23, 2024
3e238e8
catalog: reset login attempts if it was not already 0, #TASK-6013
pfurio Apr 23, 2024
d1e95fd
catalog: exclude non OPENCGA users from being banned, #TASK-6013
pfurio Apr 29, 2024
7a85964
catalog: fix organization Id null error, #TASK-6013
pfurio Apr 29, 2024
1f441b3
Merge branch 'develop' into TASK-6013
pfurio May 22, 2024
9d304ef
core: deprecate and remove old Configuration fields, #TASK-6013
pfurio May 22, 2024
8f33068
catalog: add maxLoginAttempts to configuration.yml file, #TASK-6013
pfurio May 22, 2024
848188b
core: add maxLoginAttempts description, #TASK-6013
pfurio May 22, 2024
a68e09a
Merge branch 'develop' into TASK-6013
pfurio May 23, 2024
9c9cfc6
app: remove catalog search configuration, #TASK-6013
pfurio May 23, 2024
3b434fa
Merge branch 'TASK-6013' of github.com:opencb/opencga into TASK-6013
pfurio May 23, 2024
2834fcf
app: remove catalog search configuration, #TASK-6013
pfurio May 23, 2024
59461f7
app: completely remove catalog search config, #TASK-6013
pfurio May 23, 2024
e9cb0a5
client: update clients, #TASK-6013
pfurio May 24, 2024
52fa900
Merge branch 'develop' into TASK-6013
pfurio Jun 6, 2024
e7f1966
Merge branch 'develop' into TASK-6013
pfurio Jun 25, 2024
a6485b6
catalog: ensure new installs have a secretKey, #TASK-6013
pfurio Jun 25, 2024
e53ef29
Merge branch 'develop' into TASK-6013
pfurio Jun 27, 2024
b57c260
catalog: pass mail configuration to AuthFactory, #TASK-6013
pfurio Jul 2, 2024
eb53ffe
Merge branch 'develop' into TASK-6013
pfurio Jul 2, 2024
978efa6
catalog: use simplifyPermissions from Org configuration, #TASK-6013
pfurio Jul 4, 2024
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 @@ -214,8 +214,6 @@ public Path isolateOpenCGA() throws IOException {
Files.createDirectories(conf);
Files.createDirectories(userHome);

catalogManagerExternalResource.getConfiguration().getAdmin().setSecretKey(null);
catalogManagerExternalResource.getConfiguration().getAdmin().setAlgorithm(null);
catalogManagerExternalResource.getConfiguration().serialize(
new FileOutputStream(conf.resolve("configuration.yml").toFile()));
InputStream inputStream = StorageManager.class.getClassLoader().getResourceAsStream("storage-configuration.yml");
Expand Down
10 changes: 0 additions & 10 deletions opencga-app/app/cloud/docker/opencga-init/override_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@
parser.add_argument("--catalog-database-authentication-database", required=False, default="admin")
parser.add_argument("--catalog-database-authentication-mechanism", required=False)
parser.add_argument("--catalog-database-replica-set", required=False)
parser.add_argument("--catalog-search-hosts", required=True)
parser.add_argument("--catalog-search-user", required=False)
parser.add_argument("--catalog-search-password", required=False)
parser.add_argument("--rest-host", required=True)
parser.add_argument("--grpc-host", required=True)
parser.add_argument("--analysis-execution-mode", required=False)
Expand Down Expand Up @@ -138,13 +135,6 @@ def hostOverride(conf,hosts_var):
if args.catalog_database_authentication_mechanism is not None:
config["catalog"]["database"]["options"]["authenticationMechanism"] = args.catalog_database_authentication_mechanism

# Inject search database
hostOverride(config["catalog"]["searchEngine"], args.catalog_search_hosts)

if args.catalog_search_user is not None:
config["catalog"]["searchEngine"]["user"] = args.catalog_search_user
config["catalog"]["searchEngine"]["password"] = args.catalog_search_password

# Inject execution settings
config["analysis"]["scratchDir"] = "/tmp/opencga_scratch"
if args.max_concurrent_jobs is not None:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
import subprocess
from shutil import copyfile
import sys
import unittest
import yaml
from io import StringIO
import sys
import os

from shutil import copyfile

os.chdir(sys.path[0])

Expand Down Expand Up @@ -40,9 +39,6 @@ def test_end_2_end(self):
"--catalog-database-hosts", "test-catalog-database-host1,test-catalog-database-host2,test-catalog-database-host3",
"--catalog-database-user", "test-catalog-database-user",
"--catalog-database-password", "test-catalog-database-password",
"--catalog-search-hosts", "test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user", "test-catalog-search-user",
"--catalog-search-password", "test-catalog-search-password",
"--rest-host", "test-rest-host",
"--grpc-host", "test-grpc-host",
"--max-concurrent-jobs", "25",
Expand Down Expand Up @@ -170,18 +166,6 @@ def test_end_2_end(self):
self.assertEqual(config["catalog"]["database"]["options"]["sslEnabled"], True)
self.assertEqual(config["catalog"]["database"]["options"]["sslInvalidCertificatesAllowed"], True)
self.assertEqual(config["catalog"]["database"]["options"]["authenticationDatabase"], "admin")
self.assertEqual(
config["catalog"]["searchEngine"]["hosts"][0], "test-catalog-search-host1"
)
self.assertEqual(
config["catalog"]["searchEngine"]["hosts"][1], "test-catalog-search-host2"
)
self.assertEqual(
config["catalog"]["searchEngine"]["user"], "test-catalog-search-user"
)
self.assertEqual(
config["catalog"]["searchEngine"]["password"], "test-catalog-search-password"
)
self.assertEqual(config["analysis"]["execution"]["id"], "test-analysis-execution-mode")
self.assertEqual(config["analysis"]["execution"]["maxConcurrentJobs"]["variant-index"], 25)
self.assertEqual(client_config["rest"]["hosts"][0]["url"], "test-rest-host")
Expand All @@ -200,9 +184,6 @@ def test_azure_batch_execution(self):
"--catalog-database-hosts", "test-catalog-database-host1,test-catalog-database-host2,test-catalog-database-host3",
"--catalog-database-user", "test-catalog-database-user",
"--catalog-database-password", "test-catalog-database-password",
"--catalog-search-hosts", "test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user", "test-catalog-search-user",
"--catalog-search-password", "test-catalog-search-password",
"--rest-host", "test-rest-host",
"--grpc-host", "test-grpc-host",
"--analysis-execution-mode", "AZURE",
Expand Down Expand Up @@ -273,9 +254,6 @@ def test_kubernetes_execution(self):
"--catalog-database-hosts", "test-catalog-database-host1,test-catalog-database-host2,test-catalog-database-host3",
"--catalog-database-user", "test-catalog-database-user",
"--catalog-database-password", "test-catalog-database-password",
"--catalog-search-hosts", "test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user", "test-catalog-search-user",
"--catalog-search-password", "test-catalog-search-password",
"--rest-host", "test-rest-host",
"--grpc-host", "test-grpc-host",
"--analysis-execution-mode", "k8s",
Expand Down Expand Up @@ -357,12 +335,6 @@ def test_cellbasedb_with_empty_hosts(self):
"test-catalog-database-user",
"--catalog-database-password",
"test-catalog-database-password",
"--catalog-search-hosts",
"test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user",
"test-catalog-search-user",
"--catalog-search-password",
"test-catalog-search-password",
"--rest-host",
"test-rest-host",
"--grpc-host",
Expand Down Expand Up @@ -437,12 +409,6 @@ def test_cellbasedb_with_no_db_hosts(self):
"test-catalog-database-user",
"--catalog-database-password",
"test-catalog-database-password",
"--catalog-search-hosts",
"test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user",
"test-catalog-search-user",
"--catalog-search-password",
"test-catalog-search-password",
"--rest-host",
"test-rest-host",
"--grpc-host",
Expand Down Expand Up @@ -519,12 +485,6 @@ def test_cellbase_rest_set(self):
"test-catalog-database-user",
"--catalog-database-password",
"test-catalog-database-password",
"--catalog-search-hosts",
"test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user",
"test-catalog-search-user",
"--catalog-search-password",
"test-catalog-search-password",
"--rest-host",
"test-rest-host",
"--grpc-host",
Expand Down Expand Up @@ -604,12 +564,6 @@ def test_cellbase_rest_empty_set(self):
"test-catalog-database-user",
"--catalog-database-password",
"test-catalog-database-password",
"--catalog-search-hosts",
"test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user",
"test-catalog-search-user",
"--catalog-search-password",
"test-catalog-search-password",
"--rest-host",
"test-rest-host",
"--grpc-host",
Expand Down Expand Up @@ -688,12 +642,6 @@ def test_cellbase_rest_not_set(self):
"test-catalog-database-user",
"--catalog-database-password",
"test-catalog-database-password",
"--catalog-search-hosts",
"test-catalog-search-host1,test-catalog-search-host2",
"--catalog-search-user",
"test-catalog-search-user",
"--catalog-search-password",
"test-catalog-search-password",
"--rest-host",
"test-rest-host",
"--grpc-host",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.opencb.opencga.app.cli.CommandExecutor;
import org.opencb.opencga.app.cli.admin.AdminCliOptionsParser;
import org.opencb.opencga.catalog.exceptions.CatalogException;
import org.opencb.opencga.core.config.Admin;

import java.util.Collections;

Expand Down Expand Up @@ -82,9 +81,6 @@ protected void setCatalogDatabaseCredentials(String host, String prefix, String
configuration.getCatalog().getDatabase().setUser(user);
}

if (configuration.getAdmin() == null) {
configuration.setAdmin(new Admin());
}
if (StringUtils.isNotEmpty(password)) {
configuration.getCatalog().getDatabase().setPassword(password);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@
import org.opencb.commons.datastore.core.QueryOptions;
import org.opencb.commons.datastore.mongodb.MongoDataStore;
import org.opencb.opencga.app.cli.admin.AdminCliOptionsParser;
import org.opencb.opencga.catalog.auth.authentication.JwtManager;
import org.opencb.opencga.catalog.db.mongodb.MongoDBAdaptorFactory;
import org.opencb.opencga.catalog.db.mongodb.MongoDBUtils;
import org.opencb.opencga.catalog.exceptions.CatalogException;
import org.opencb.opencga.catalog.managers.CatalogManager;
import org.opencb.opencga.core.common.JacksonUtils;
import org.opencb.opencga.core.common.PasswordUtils;
import org.opencb.opencga.master.monitor.MonitorService;

import javax.ws.rs.client.Client;
Expand Down Expand Up @@ -173,19 +171,12 @@ private void install() throws CatalogException {

validateConfiguration(commandOptions);

this.configuration.getAdmin().setAlgorithm("HS256");

this.configuration.getAdmin().setSecretKey(commandOptions.secretKey);
if (StringUtils.isEmpty(configuration.getAdmin().getSecretKey())) {
configuration.getAdmin().setSecretKey(PasswordUtils.getStrongRandomPassword(JwtManager.SECRET_KEY_MIN_LENGTH));
}

if (StringUtils.isEmpty(commandOptions.commonOptions.adminPassword)) {
throw new CatalogException("No admin password found. Please, insert your password.");
}

try (CatalogManager catalogManager = new CatalogManager(configuration)) {
catalogManager.installCatalogDB("HS256", configuration.getAdmin().getSecretKey(), commandOptions.commonOptions.adminPassword,
catalogManager.installCatalogDB("HS256", commandOptions.secretKey, commandOptions.commonOptions.adminPassword,
commandOptions.email, commandOptions.force);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public abstract class OpenCgaCompleter implements Completer {
.map(Candidate::new)
.collect(toList());

private List<Candidate> organizationsList = asList( "create","notes-create","notes-search","notes-delete","notes-update","configuration-update","info","update")
private List<Candidate> organizationsList = asList( "create","notes-create","notes-search","notes-delete","notes-update","update-status-user","user-update","configuration-update","info","update")
.stream()
.map(Candidate::new)
.collect(toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ public OpencgaCliOptionsParser() {
organizationsSubCommands.addCommand("notes-search", organizationsCommandOptions.searchNotesCommandOptions);
organizationsSubCommands.addCommand("notes-delete", organizationsCommandOptions.deleteNotesCommandOptions);
organizationsSubCommands.addCommand("notes-update", organizationsCommandOptions.updateNotesCommandOptions);
organizationsSubCommands.addCommand("update-status-user", organizationsCommandOptions.userUpdateStatusCommandOptions);
organizationsSubCommands.addCommand("user-update", organizationsCommandOptions.updateUserCommandOptions);
organizationsSubCommands.addCommand("configuration-update", organizationsCommandOptions.updateConfigurationCommandOptions);
organizationsSubCommands.addCommand("info", organizationsCommandOptions.infoCommandOptions);
organizationsSubCommands.addCommand("update", organizationsCommandOptions.updateCommandOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
import org.opencb.opencga.core.models.organizations.OrganizationCreateParams;
import org.opencb.opencga.core.models.organizations.OrganizationUpdateParams;
import org.opencb.opencga.core.models.organizations.TokenConfiguration;
import org.opencb.opencga.core.models.user.OrganizationUserUpdateParams;
import org.opencb.opencga.core.models.user.User;
import org.opencb.opencga.core.models.user.UserQuota;
import org.opencb.opencga.core.models.user.UserStatusUpdateParams;
import org.opencb.opencga.core.response.QueryType;
import org.opencb.opencga.core.response.RestResponse;

Expand Down Expand Up @@ -76,6 +80,12 @@ public void execute() throws Exception {
case "notes-update":
queryResponse = updateNotes();
break;
case "update-status-user":
queryResponse = userUpdateStatus();
break;
case "user-update":
queryResponse = updateUser();
break;
case "configuration-update":
queryResponse = updateConfiguration();
break;
Expand Down Expand Up @@ -120,6 +130,7 @@ private RestResponse<Organization> create() throws Exception {
putNestedIfNotEmpty(beanParams, "name",commandOptions.name, true);
putNestedIfNotEmpty(beanParams, "creationDate",commandOptions.creationDate, true);
putNestedIfNotEmpty(beanParams, "modificationDate",commandOptions.modificationDate, true);
putNestedIfNotEmpty(beanParams, "configuration.defaultUserExpirationDate",commandOptions.configurationDefaultUserExpirationDate, true);
putNestedIfNotNull(beanParams, "attributes",commandOptions.attributes, true);

organizationCreateParams = JacksonUtils.getDefaultObjectMapper().copy()
Expand Down Expand Up @@ -227,6 +238,77 @@ private RestResponse<Note> updateNotes() throws Exception {
return openCGAClient.getOrganizationClient().updateNotes(commandOptions.id, noteUpdateParams, queryParams);
}

private RestResponse<User> userUpdateStatus() throws Exception {
logger.debug("Executing userUpdateStatus in Organizations command line");

OrganizationsCommandOptions.UserUpdateStatusCommandOptions commandOptions = organizationsCommandOptions.userUpdateStatusCommandOptions;

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


UserStatusUpdateParams userStatusUpdateParams = null;
if (commandOptions.jsonDataModel) {
RestResponse<User> res = new RestResponse<>();
res.setType(QueryType.VOID);
PrintUtils.println(getObjectAsJSON(categoryName,"/{apiVersion}/organizations/user/{user}/status/update"));
return res;
} else if (commandOptions.jsonFile != null) {
userStatusUpdateParams = JacksonUtils.getDefaultObjectMapper()
.readValue(new java.io.File(commandOptions.jsonFile), UserStatusUpdateParams.class);
} else {
ObjectMap beanParams = new ObjectMap();
putNestedIfNotEmpty(beanParams, "status",commandOptions.status, true);

userStatusUpdateParams = JacksonUtils.getDefaultObjectMapper().copy()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
.readValue(beanParams.toJson(), UserStatusUpdateParams.class);
}
return openCGAClient.getOrganizationClient().userUpdateStatus(commandOptions.user, userStatusUpdateParams, queryParams);
}

private RestResponse<User> updateUser() throws Exception {
logger.debug("Executing updateUser in Organizations command line");

OrganizationsCommandOptions.UpdateUserCommandOptions commandOptions = organizationsCommandOptions.updateUserCommandOptions;

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


OrganizationUserUpdateParams organizationUserUpdateParams = null;
if (commandOptions.jsonDataModel) {
RestResponse<User> res = new RestResponse<>();
res.setType(QueryType.VOID);
PrintUtils.println(getObjectAsJSON(categoryName,"/{apiVersion}/organizations/user/{user}/update"));
return res;
} else if (commandOptions.jsonFile != null) {
organizationUserUpdateParams = JacksonUtils.getDefaultObjectMapper()
.readValue(new java.io.File(commandOptions.jsonFile), OrganizationUserUpdateParams.class);
} else {
ObjectMap beanParams = new ObjectMap();
putNestedIfNotEmpty(beanParams, "name",commandOptions.name, true);
putNestedIfNotEmpty(beanParams, "email",commandOptions.email, true);
putNestedIfNotNull(beanParams, "quota.diskUsage",commandOptions.quotaDiskUsage, true);
putNestedIfNotNull(beanParams, "quota.cpuUsage",commandOptions.quotaCpuUsage, true);
putNestedIfNotNull(beanParams, "quota.maxDisk",commandOptions.quotaMaxDisk, true);
putNestedIfNotNull(beanParams, "quota.maxCpu",commandOptions.quotaMaxCpu, true);
putNestedIfNotEmpty(beanParams, "account.expirationDate",commandOptions.accountExpirationDate, true);
putNestedIfNotNull(beanParams, "attributes",commandOptions.attributes, true);

organizationUserUpdateParams = JacksonUtils.getDefaultObjectMapper().copy()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
.readValue(beanParams.toJson(), OrganizationUserUpdateParams.class);
}
return openCGAClient.getOrganizationClient().updateUser(commandOptions.user, organizationUserUpdateParams, queryParams);
}

private RestResponse<OrganizationConfiguration> updateConfiguration() throws Exception {
logger.debug("Executing updateConfiguration in Organizations command line");

Expand All @@ -250,6 +332,7 @@ private RestResponse<OrganizationConfiguration> updateConfiguration() throws Exc
.readValue(new java.io.File(commandOptions.jsonFile), OrganizationConfiguration.class);
} else {
ObjectMap beanParams = new ObjectMap();
putNestedIfNotEmpty(beanParams, "defaultUserExpirationDate",commandOptions.defaultUserExpirationDate, true);
putNestedIfNotNull(beanParams, "optimizations.simplifyPermissions",commandOptions.optimizationsSimplifyPermissions, true);
putNestedIfNotEmpty(beanParams, "token.algorithm",commandOptions.tokenAlgorithm, true);
putNestedIfNotEmpty(beanParams, "token.secretKey",commandOptions.tokenSecretKey, true);
Expand Down
Loading
Loading