/*
* Copyright 2015-2016 OpenCB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.opencb.opencga.catalog.auth.authorization;
import org.apache.commons.lang3.StringUtils;
import org.opencb.commons.datastore.core.Query;
import org.opencb.commons.datastore.core.QueryOptions;
import org.opencb.commons.datastore.core.QueryResult;
import org.opencb.opencga.catalog.audit.AuditManager;
import org.opencb.opencga.catalog.db.DBAdaptorFactory;
import org.opencb.opencga.catalog.db.api.AclDBAdaptor;
import org.opencb.opencga.catalog.db.api.*;
import org.opencb.opencga.catalog.exceptions.CatalogAuthorizationException;
import org.opencb.opencga.catalog.exceptions.CatalogDBException;
import org.opencb.opencga.catalog.exceptions.CatalogException;
import org.opencb.opencga.catalog.managers.AbstractManager;
import org.opencb.opencga.catalog.models.*;
import org.opencb.opencga.catalog.models.acls.permissions.*;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.opencb.opencga.catalog.utils.CatalogMemberValidator.checkMembers;
/**
* Created by pfurio on 12/05/16.
*/
public class CatalogAuthorizationManager implements AuthorizationManager {
private static final QueryOptions FILE_INCLUDE_QUERY_OPTIONS = new QueryOptions(QueryOptions.INCLUDE,
Arrays.asList(FILTER_ROUTE_FILES + FileDBAdaptor.QueryParams.ID.key(),
FILTER_ROUTE_FILES + FileDBAdaptor.QueryParams.PATH.key(),
FILTER_ROUTE_FILES + FileDBAdaptor.QueryParams.ACL.key()
));
private final DBAdaptorFactory dbAdaptorFactory;
private final UserDBAdaptor userDBAdaptor;
private final ProjectDBAdaptor projectDBAdaptor;
private final StudyDBAdaptor studyDBAdaptor;
private final FileDBAdaptor fileDBAdaptor;
private final JobDBAdaptor jobDBAdaptor;
private final SampleDBAdaptor sampleDBAdaptor;
private final IndividualDBAdaptor individualDBAdaptor;
private final CohortDBAdaptor cohortDBAdaptor;
private final DatasetDBAdaptor datasetDBAdaptor;
private final PanelDBAdaptor panelDBAdaptor;
private final MetaDBAdaptor metaDBAdaptor;
private final AuditManager auditManager;
private final String ADMIN = "admin";
private final String ANONYMOUS = "anonymous";
public CatalogAuthorizationManager(DBAdaptorFactory catalogDBAdaptorFactory, AuditManager auditManager) {
this.auditManager = auditManager;
this.dbAdaptorFactory = catalogDBAdaptorFactory;
userDBAdaptor = catalogDBAdaptorFactory.getCatalogUserDBAdaptor();
projectDBAdaptor = catalogDBAdaptorFactory.getCatalogProjectDbAdaptor();
studyDBAdaptor = catalogDBAdaptorFactory.getCatalogStudyDBAdaptor();
fileDBAdaptor = catalogDBAdaptorFactory.getCatalogFileDBAdaptor();
jobDBAdaptor = catalogDBAdaptorFactory.getCatalogJobDBAdaptor();
sampleDBAdaptor = catalogDBAdaptorFactory.getCatalogSampleDBAdaptor();
individualDBAdaptor = catalogDBAdaptorFactory.getCatalogIndividualDBAdaptor();
cohortDBAdaptor = catalogDBAdaptorFactory.getCatalogCohortDBAdaptor();
datasetDBAdaptor = catalogDBAdaptorFactory.getCatalogDatasetDBAdaptor();
panelDBAdaptor = catalogDBAdaptorFactory.getCatalogPanelDBAdaptor();
metaDBAdaptor = catalogDBAdaptorFactory.getCatalogMetaDBAdaptor();
}
@Override
public void checkProjectPermission(long projectId, String userId, StudyAclEntry.StudyPermissions permission) throws CatalogException {
if (projectDBAdaptor.getOwnerId(projectId).equals(userId)) {
return;
}
if (permission.equals(StudyAclEntry.StudyPermissions.VIEW_STUDY)) {
final Query query = new Query(StudyDBAdaptor.QueryParams.PROJECT_ID.key(), projectId);
final QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE,
FILTER_ROUTE_STUDIES + StudyDBAdaptor.QueryParams.ID.key());
for (Study study : studyDBAdaptor.get(query, queryOptions).getResult()) {
try {
checkStudyPermission(study.getId(), userId, StudyAclEntry.StudyPermissions.VIEW_STUDY);
return; //Return if can read some study
} catch (CatalogException e) {
e.printStackTrace();
}
}
}
throw CatalogAuthorizationException.deny(userId, permission.toString(), "Project", projectId, null);
}
@Override
public void checkStudyPermission(long studyId, String userId, StudyAclEntry.StudyPermissions permission) throws CatalogException {
checkStudyPermission(studyId, userId, permission, permission.toString());
}
@Override
public void checkStudyPermission(long studyId, String userId, StudyAclEntry.StudyPermissions permission, String message)
throws CatalogException {
if (isStudyOwner(studyId, userId)) {
return;
}
StudyAclEntry studyAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
studyAcl = studyAclQueryResult.first();
}
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
studyAcl = getStudyAclBelonging(studyId, userId, groupId);
}
if (studyAcl == null) {
throw CatalogAuthorizationException.deny(userId, message, "Study", studyId, null);
}
if (studyAcl.getPermissions().contains(permission)) {
return;
}
throw CatalogAuthorizationException.deny(userId, message, "Study", studyId, null);
}
@Override
public void checkFilePermission(long fileId, String userId, FileAclEntry.FilePermissions permission) throws CatalogException {
long studyId = fileDBAdaptor.getStudyIdByFileId(fileId);
if (isStudyOwner(studyId, userId)) {
return;
}
FileAclEntry fileAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
fileAcl = transformStudyAclToFileAcl(studyAclQueryResult.first());
}
} else {
fileAcl = resolveFilePermissions(studyId, fileId, userId);
}
if (!fileAcl.getPermissions().contains(permission)) {
throw CatalogAuthorizationException.deny(userId, permission.toString(), "File", fileId, null);
}
}
private FileAclEntry resolveFilePermissions(long studyId, File file, String userId) throws CatalogException {
if (file.getAcl() == null) {
return resolveFilePermissions(studyId, file.getId(), userId);
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
Map<String, FileAclEntry> userAclMap = new HashMap<>();
for (FileAclEntry fileAcl : file.getAcl()) {
userAclMap.put(fileAcl.getMember(), fileAcl);
}
return resolveFilePermissions(studyId, userId, groupId, userAclMap);
}
}
private FileAclEntry resolveFilePermissions(long studyId, long fileId, String userId) throws CatalogException {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
List<String> userIds = (groupId == null)
? Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS);
List<FileAclEntry> fileAclEntryList = fileDBAdaptor.getAcl(fileId, userIds).getResult();
Map<String, FileAclEntry> userAclMap = new HashMap<>();
for (FileAclEntry fileAclEntry : fileAclEntryList) {
userAclMap.put(fileAclEntry.getMember(), fileAclEntry);
}
return resolveFilePermissions(studyId, userId, groupId, userAclMap);
}
private FileAclEntry resolveFilePermissions(long studyId, String userId, String groupId, Map<String, FileAclEntry> userAclMap)
throws CatalogException {
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
} else {
return transformStudyAclToFileAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
// Registered user
EnumSet<FileAclEntry.FilePermissions> permissions = EnumSet.noneOf(FileAclEntry.FilePermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new FileAclEntry(userId, permissions);
} else {
return transformStudyAclToFileAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
@Override
public void checkSamplePermission(long sampleId, String userId, SampleAclEntry.SamplePermissions permission) throws CatalogException {
long studyId = sampleDBAdaptor.getStudyId(sampleId);
if (isStudyOwner(studyId, userId)) {
return;
}
SampleAclEntry sampleAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
sampleAcl = transformStudyAclToSampleAcl(studyAclQueryResult.first());
}
} else {
sampleAcl = resolveSamplePermissions(studyId, sampleId, userId);
}
if (!sampleAcl.getPermissions().contains(permission)) {
throw CatalogAuthorizationException.deny(userId, permission.toString(), "Sample", sampleId, null);
}
}
/**
* Resolves the permissions between a sample and a user.
* Returns the most specific matching ACL following the next sequence:
* user > group > others > study
*
* @param studyId Study id.
* @param sample Sample.
* @param userId User id.
* @return
* @throws CatalogException
*/
private SampleAclEntry resolveSamplePermissions(long studyId, Sample sample, String userId) throws CatalogException {
if (sample.getAcl() == null) {
return resolveSamplePermissions(studyId, sample.getId(), userId);
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
Map<String, SampleAclEntry> userAclMap = new HashMap<>();
for (SampleAclEntry sampleAcl : sample.getAcl()) {
userAclMap.put(sampleAcl.getMember(), sampleAcl);
}
return resolveSamplePermissions(studyId, userId, groupId, userAclMap);
}
}
private SampleAclEntry resolveSamplePermissions(long studyId, long sampleId, String userId) throws CatalogException {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
List<String> userIds = (groupId == null)
? Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS);
List<SampleAclEntry> sampleAclList = sampleDBAdaptor.getAcl(sampleId, userIds).getResult();
Map<String, SampleAclEntry> userAclMap = new HashMap<>();
for (SampleAclEntry sampleAcl : sampleAclList) {
userAclMap.put(sampleAcl.getMember(), sampleAcl);
}
return resolveSamplePermissions(studyId, userId, groupId, userAclMap);
}
private SampleAclEntry resolveSamplePermissions(long studyId, String userId, String groupId, Map<String, SampleAclEntry> userAclMap)
throws CatalogException {
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
} else {
return transformStudyAclToSampleAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
// Registered user
EnumSet<SampleAclEntry.SamplePermissions> permissions = EnumSet.noneOf(SampleAclEntry.SamplePermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new SampleAclEntry(userId, permissions);
} else {
return transformStudyAclToSampleAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
@Override
public void checkIndividualPermission(long individualId, String userId, IndividualAclEntry.IndividualPermissions permission)
throws CatalogException {
long studyId = individualDBAdaptor.getStudyId(individualId);
if (isStudyOwner(studyId, userId)) {
return;
}
IndividualAclEntry individualAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
individualAcl = transformStudyAclToIndividualAcl(studyAclQueryResult.first());
}
} else {
individualAcl = resolveIndividualPermissions(studyId, individualId, userId);
}
if (!individualAcl.getPermissions().contains(permission)) {
throw CatalogAuthorizationException.deny(userId, permission.toString(), "Individual", individualId, null);
}
}
private IndividualAclEntry resolveIndividualPermissions(long studyId, Individual individual, String userId) throws CatalogException {
if (individual.getAcl() == null) {
return resolveIndividualPermissions(studyId, individual.getId(), userId);
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
Map<String, IndividualAclEntry> userAclMap = new HashMap<>();
for (IndividualAclEntry individualAcl : individual.getAcl()) {
userAclMap.put(individualAcl.getMember(), individualAcl);
}
return resolveIndividualPermissions(studyId, userId, groupId, userAclMap);
}
}
private IndividualAclEntry resolveIndividualPermissions(long studyId, long individualId, String userId) throws CatalogException {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
List<String> userIds = (groupId == null)
? Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS);
List<IndividualAclEntry> individualAcls = individualDBAdaptor.getAcl(individualId, userIds).getResult();
Map<String, IndividualAclEntry> userAclMap = new HashMap<>();
for (IndividualAclEntry individualAcl : individualAcls) {
userAclMap.put(individualAcl.getMember(), individualAcl);
}
return resolveIndividualPermissions(studyId, userId, groupId, userAclMap);
}
private IndividualAclEntry resolveIndividualPermissions(long studyId, String userId, String groupId, Map<String,
IndividualAclEntry> userAclMap) throws CatalogException {
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
} else {
return transformStudyAclToIndividualAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
// Registered user
EnumSet<IndividualAclEntry.IndividualPermissions> permissions = EnumSet.noneOf(IndividualAclEntry.IndividualPermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new IndividualAclEntry(userId, permissions);
} else {
return transformStudyAclToIndividualAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
@Override
public void checkJobPermission(long jobId, String userId, JobAclEntry.JobPermissions permission) throws CatalogException {
long studyId = jobDBAdaptor.getStudyId(jobId);
if (isStudyOwner(studyId, userId)) {
return;
}
JobAclEntry jobAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
jobAcl = transformStudyAclToJobAcl(studyAclQueryResult.first());
}
} else {
jobAcl = resolveJobPermissions(studyId, jobId, userId);
}
if (!jobAcl.getPermissions().contains(permission)) {
throw CatalogAuthorizationException.deny(userId, permission.toString(), "Job", jobId, null);
}
}
private JobAclEntry resolveJobPermissions(long studyId, Job job, String userId) throws CatalogException {
if (job.getAcl() == null) {
return resolveJobPermissions(studyId, job.getId(), userId);
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
Map<String, JobAclEntry> userAclMap = new HashMap<>();
for (JobAclEntry jobAcl : job.getAcl()) {
userAclMap.put(jobAcl.getMember(), jobAcl);
}
return resolveJobPermissions(studyId, userId, groupId, userAclMap);
}
}
private JobAclEntry resolveJobPermissions(long studyId, long jobId, String userId) throws CatalogException {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
List<String> userIds = (groupId == null)
? Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS);
List<JobAclEntry> jobAcls = jobDBAdaptor.getAcl(jobId, userIds).getResult();
Map<String, JobAclEntry> userAclMap = new HashMap<>();
for (JobAclEntry jobAcl : jobAcls) {
userAclMap.put(jobAcl.getMember(), jobAcl);
}
return resolveJobPermissions(studyId, userId, groupId, userAclMap);
}
private JobAclEntry resolveJobPermissions(long studyId, String userId, String groupId, Map<String, JobAclEntry> userAclMap)
throws CatalogException {
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
} else {
return transformStudyAclToJobAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
// Registered user
EnumSet<JobAclEntry.JobPermissions> permissions = EnumSet.noneOf(JobAclEntry.JobPermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new JobAclEntry(userId, permissions);
} else {
return transformStudyAclToJobAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
@Override
public void checkCohortPermission(long cohortId, String userId, CohortAclEntry.CohortPermissions permission) throws CatalogException {
long studyId = cohortDBAdaptor.getStudyId(cohortId);
if (isStudyOwner(studyId, userId)) {
return;
}
CohortAclEntry cohortAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
cohortAcl = transformStudyAclToCohortAcl(studyAclQueryResult.first());
}
} else {
cohortAcl = resolveCohortPermissions(studyId, cohortId, userId);
}
if (!cohortAcl.getPermissions().contains(permission)) {
throw CatalogAuthorizationException.deny(userId, permission.toString(), "Cohort", cohortId, null);
}
}
private CohortAclEntry resolveCohortPermissions(long studyId, Cohort cohort, String userId) throws CatalogException {
if (cohort.getAcl() == null) {
return resolveCohortPermissions(studyId, cohort.getId(), userId);
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
Map<String, CohortAclEntry> userAclMap = new HashMap<>();
for (CohortAclEntry cohortAcl : cohort.getAcl()) {
userAclMap.put(cohortAcl.getMember(), cohortAcl);
}
return resolveCohortPermissions(studyId, userId, groupId, userAclMap);
}
}
private CohortAclEntry resolveCohortPermissions(long studyId, long cohortId, String userId) throws CatalogException {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
List<String> userIds = (groupId == null)
? Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS);
List<CohortAclEntry> cohortAcls = cohortDBAdaptor.getAcl(cohortId, userIds).getResult();
Map<String, CohortAclEntry> userAclMap = new HashMap<>();
for (CohortAclEntry cohortAcl : cohortAcls) {
userAclMap.put(cohortAcl.getMember(), cohortAcl);
}
return resolveCohortPermissions(studyId, userId, groupId, userAclMap);
}
private CohortAclEntry resolveCohortPermissions(long studyId, String userId, String groupId, Map<String, CohortAclEntry> userAclMap)
throws CatalogException {
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
} else {
return transformStudyAclToCohortAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
// Registered user
EnumSet<CohortAclEntry.CohortPermissions> permissions = EnumSet.noneOf(CohortAclEntry.CohortPermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new CohortAclEntry(userId, permissions);
} else {
return transformStudyAclToCohortAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
@Override
public void checkDatasetPermission(long datasetId, String userId, DatasetAclEntry.DatasetPermissions permission)
throws CatalogException {
long studyId = datasetDBAdaptor.getStudyIdByDatasetId(datasetId);
if (isStudyOwner(studyId, userId)) {
return;
}
DatasetAclEntry datasetAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
datasetAcl = transformStudyAclToDatasetAcl(studyAclQueryResult.first());
}
} else {
datasetAcl = resolveDatasetPermissions(studyId, datasetId, userId);
}
if (!datasetAcl.getPermissions().contains(permission)) {
throw CatalogAuthorizationException.deny(userId, permission.toString(), "Dataset", datasetId, null);
}
}
private DatasetAclEntry resolveDatasetPermissions(long studyId, Dataset dataset, String userId) throws CatalogException {
if (dataset.getAcl() == null) {
return resolveDatasetPermissions(studyId, dataset.getId(), userId);
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
Map<String, DatasetAclEntry> userAclMap = new HashMap<>();
for (DatasetAclEntry datasetAcl : dataset.getAcl()) {
userAclMap.put(datasetAcl.getMember(), datasetAcl);
}
return resolveDatasetPermissions(studyId, userId, groupId, userAclMap);
}
}
private DatasetAclEntry resolveDatasetPermissions(long studyId, long datasetId, String userId) throws CatalogException {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
List<String> userIds = (groupId == null)
? Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS);
List<DatasetAclEntry> datasetAcls = datasetDBAdaptor.getAcl(datasetId, userIds).getResult();
Map<String, DatasetAclEntry> userAclMap = new HashMap<>();
for (DatasetAclEntry datasetAcl : datasetAcls) {
userAclMap.put(datasetAcl.getMember(), datasetAcl);
}
return resolveDatasetPermissions(studyId, userId, groupId, userAclMap);
}
private DatasetAclEntry resolveDatasetPermissions(long studyId, String userId, String groupId, Map<String, DatasetAclEntry> userAclMap)
throws CatalogException {
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
} else {
return transformStudyAclToDatasetAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
// Registered user
EnumSet<DatasetAclEntry.DatasetPermissions> permissions = EnumSet.noneOf(DatasetAclEntry.DatasetPermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new DatasetAclEntry(userId, permissions);
} else {
return transformStudyAclToDatasetAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
@Override
public void checkDiseasePanelPermission(long panelId, String userId, DiseasePanelAclEntry.DiseasePanelPermissions permission)
throws CatalogException {
long studyId = panelDBAdaptor.getStudyId(panelId);
if (isStudyOwner(studyId, userId)) {
return;
}
DiseasePanelAclEntry panelAcl = null;
if (userId.equals(ADMIN)) {
QueryResult<StudyAclEntry> studyAclQueryResult = metaDBAdaptor.getDaemonAcl(Arrays.asList(ADMIN));
if (studyAclQueryResult.getNumResults() == 1) {
panelAcl = transformStudyAclToDiseasePanelAcl(studyAclQueryResult.first());
}
} else {
panelAcl = resolveDiseasePanelPermissions(studyId, panelId, userId);
}
if (!panelAcl.getPermissions().contains(permission)) {
throw CatalogAuthorizationException.deny(userId, permission.toString(), "DiseasePanel", panelId, null);
}
}
private DiseasePanelAclEntry resolveDiseasePanelPermissions(long studyId, DiseasePanel panel, String userId) throws CatalogException {
if (panel.getAcl() == null) {
return resolveDiseasePanelPermissions(studyId, panel.getId(), userId);
} else {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
Map<String, DiseasePanelAclEntry> userAclMap = new HashMap<>();
for (DiseasePanelAclEntry panelAcl : panel.getAcl()) {
userAclMap.put(panelAcl.getMember(), panelAcl);
}
return resolveDiseasePanelPermissions(studyId, userId, groupId, userAclMap);
}
}
private DiseasePanelAclEntry resolveDiseasePanelPermissions(long studyId, long panelId, String userId) throws CatalogException {
String groupId = null;
if (!userId.equalsIgnoreCase(ANONYMOUS)) {
QueryResult<Group> group = getGroupBelonging(studyId, userId);
groupId = group.getNumResults() == 1 ? group.first().getName() : null;
}
List<String> userIds = (groupId == null)
? Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS);
List<DiseasePanelAclEntry> panelAcls = panelDBAdaptor.getAcl(panelId, userIds).getResult();
Map<String, DiseasePanelAclEntry> userAclMap = new HashMap<>();
for (DiseasePanelAclEntry panelAcl : panelAcls) {
userAclMap.put(panelAcl.getMember(), panelAcl);
}
return resolveDiseasePanelPermissions(studyId, userId, groupId, userAclMap);
}
private DiseasePanelAclEntry resolveDiseasePanelPermissions(long studyId, String userId, String groupId,
Map<String, DiseasePanelAclEntry> userAclMap) throws CatalogException {
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
} else {
return transformStudyAclToDiseasePanelAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
// Registered user
EnumSet<DiseasePanelAclEntry.DiseasePanelPermissions> permissions =
EnumSet.noneOf(DiseasePanelAclEntry.DiseasePanelPermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new DiseasePanelAclEntry(userId, permissions);
} else {
return transformStudyAclToDiseasePanelAcl(getStudyAclBelonging(studyId, userId, groupId));
}
}
@Override
public void filterProjects(String userId, List<Project> projects) throws CatalogException {
if (projects == null || projects.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
Iterator<Project> projectIt = projects.iterator();
while (projectIt.hasNext()) {
Project p = projectIt.next();
try {
checkProjectPermission(p.getId(), userId, StudyAclEntry.StudyPermissions.VIEW_STUDY);
} catch (CatalogAuthorizationException e) {
projectIt.remove();
continue;
}
filterStudies(userId, p.getStudies());
}
}
@Override
public void filterStudies(String userId, List<Study> studies) throws CatalogException {
if (studies == null || studies.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
Iterator<Study> studyIt = studies.iterator();
while (studyIt.hasNext()) {
Study study = studyIt.next();
try {
checkStudyPermission(study.getId(), userId, StudyAclEntry.StudyPermissions.VIEW_STUDY);
} catch (CatalogAuthorizationException e) {
studyIt.remove();
continue;
}
filterFiles(userId, study.getId(), study.getFiles());
filterSamples(userId, study.getId(), study.getSamples());
filterJobs(userId, study.getId(), study.getJobs());
filterCohorts(userId, study.getId(), study.getCohorts());
filterIndividuals(userId, study.getId(), study.getIndividuals());
filterDatasets(userId, study.getId(), study.getDatasets());
}
}
@Override
public void filterFiles(String userId, long studyId, List<File> files) throws CatalogException {
if (files == null || files.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
if (isStudyOwner(studyId, userId)) {
return;
}
Iterator<File> fileIt = files.iterator();
while (fileIt.hasNext()) {
File file = fileIt.next();
FileAclEntry fileAcl = resolveFilePermissions(studyId, file, userId);
if (!fileAcl.getPermissions().contains(FileAclEntry.FilePermissions.VIEW)) {
fileIt.remove();
}
}
}
@Override
public void filterSamples(String userId, long studyId, List<Sample> samples) throws CatalogException {
if (samples == null || samples.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
if (isStudyOwner(studyId, userId)) {
return;
}
Iterator<Sample> sampleIterator = samples.iterator();
while (sampleIterator.hasNext()) {
Sample sample = sampleIterator.next();
SampleAclEntry sampleACL = resolveSamplePermissions(studyId, sample, userId);
if (!sampleACL.getPermissions().contains(SampleAclEntry.SamplePermissions.VIEW)) {
sampleIterator.remove();
continue;
}
if (!sampleACL.getPermissions().contains(SampleAclEntry.SamplePermissions.VIEW_ANNOTATIONS)) {
sample.setAnnotationSets(new ArrayList<>());
}
}
}
@Override
public void filterIndividuals(String userId, long studyId, List<Individual> individuals) throws CatalogException {
if (individuals == null || individuals.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
if (isStudyOwner(studyId, userId)) {
return;
}
Iterator<Individual> individualIterator = individuals.iterator();
while (individualIterator.hasNext()) {
Individual individual = individualIterator.next();
IndividualAclEntry individualAcl = resolveIndividualPermissions(studyId, individual, userId);
if (!individualAcl.getPermissions().contains(IndividualAclEntry.IndividualPermissions.VIEW)) {
individualIterator.remove();
continue;
}
if (!individualAcl.getPermissions().contains(IndividualAclEntry.IndividualPermissions.VIEW_ANNOTATIONS)) {
individual.setAnnotationSets(new ArrayList<>());
}
}
}
@Override
public void filterCohorts(String userId, long studyId, List<Cohort> cohorts) throws CatalogException {
if (cohorts == null || cohorts.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
if (isStudyOwner(studyId, userId)) {
return;
}
Iterator<Cohort> cohortIterator = cohorts.iterator();
while (cohortIterator.hasNext()) {
Cohort cohort = cohortIterator.next();
CohortAclEntry cohortAcl = resolveCohortPermissions(studyId, cohort, userId);
if (!cohortAcl.getPermissions().contains(CohortAclEntry.CohortPermissions.VIEW)) {
cohortIterator.remove();
continue;
}
if (!cohortAcl.getPermissions().contains(CohortAclEntry.CohortPermissions.VIEW_ANNOTATIONS)) {
cohort.setAnnotationSets(new ArrayList<>());
}
}
}
@Override
public void filterJobs(String userId, long studyId, List<Job> jobs) throws CatalogException {
if (jobs == null || jobs.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
if (isStudyOwner(studyId, userId)) {
return;
}
Iterator<Job> jobIterator = jobs.iterator();
while (jobIterator.hasNext()) {
Job job = jobIterator.next();
JobAclEntry jobAcl = resolveJobPermissions(studyId, job, userId);
if (!jobAcl.getPermissions().contains(JobAclEntry.JobPermissions.VIEW)) {
jobIterator.remove();
}
}
}
@Override
public void filterDatasets(String userId, long studyId, List<Dataset> datasets) throws CatalogException {
if (datasets == null || datasets.isEmpty()) {
return;
}
if (userId.equals(ADMIN)) {
return;
}
if (isStudyOwner(studyId, userId)) {
return;
}
Iterator<Dataset> datasetIterator = datasets.iterator();
while (datasetIterator.hasNext()) {
Dataset dataset = datasetIterator.next();
DatasetAclEntry datasetAcl = resolveDatasetPermissions(studyId, dataset, userId);
if (!datasetAcl.getPermissions().contains(DatasetAclEntry.DatasetPermissions.VIEW)) {
datasetIterator.remove();
}
}
}
@Override
public QueryResult<StudyAclEntry> createStudyAcls(String userId, long studyId, List<String> members, List<String> permissions,
String template) throws CatalogException {
studyDBAdaptor.checkId(studyId);
checkMembers(dbAdaptorFactory, studyId, members);
checkStudyPermission(studyId, userId, StudyAclEntry.StudyPermissions.SHARE_STUDY);
// We obtain the permissions present in the demanded template (if present)
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = AuthorizationManager.getLockedAcls();
if (template != null && !template.isEmpty()) {
if (template.equals(AuthorizationManager.ROLE_ADMIN)) {
studyPermissions = AuthorizationManager.getAdminAcls();
} else if (template.equals(AuthorizationManager.ROLE_ANALYST)) {
studyPermissions = AuthorizationManager.getAnalystAcls();
} else if (template.equals(AuthorizationManager.ROLE_VIEW_ONLY)) {
studyPermissions = AuthorizationManager.getViewOnlyAcls();
}
}
// Add the permissions present in permissions
studyPermissions.addAll(permissions.stream().map(StudyAclEntry.StudyPermissions::valueOf).collect(Collectors.toList()));
// If the user already has permissions set, we cannot create a new set of permissions
List<StudyAclEntry> studyAclList = new ArrayList<>(members.size());
for (String member : members) {
if (memberExists(studyId, member)) {
throw new CatalogException("The member " + member + " already has some permissions set in study. Please, remove those"
+ " permissions or add, remove or set new permissions.");
}
}
int timeSpent = 0;
for (String member : members) {
StudyAclEntry studyAcl = new StudyAclEntry(member, studyPermissions);
QueryResult<StudyAclEntry> studyAclQueryResult = studyDBAdaptor.createAcl(studyId, studyAcl);
timeSpent += studyAclQueryResult.getDbTime();
studyAclList.add(studyAclQueryResult.first());
}
return new QueryResult<>("create study Acls", timeSpent, studyAclList.size(), studyAclList.size(), "", "", studyAclList);
}
private boolean memberExists(long studyId, String member) throws CatalogDBException {
QueryResult<StudyAclEntry> acl = studyDBAdaptor.getAcl(studyId, Arrays.asList(member));
return acl.getNumResults() > 0;
}
@Override
public QueryResult<StudyAclEntry> getAllStudyAcls(String userId, long studyId) throws CatalogException {
studyDBAdaptor.checkId(studyId);
// checkStudyPermission(studyId, userId, StudyAclEntry.StudyPermissions.SHARE_STUDY);
Query query = new Query(StudyDBAdaptor.QueryParams.ID.key(), studyId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, StudyDBAdaptor.QueryParams.ACL.key());
QueryResult<Study> studyQueryResult = studyDBAdaptor.get(query, queryOptions);
List<StudyAclEntry> studyAclList;
if (studyQueryResult == null || studyQueryResult.getNumResults() == 0) {
studyAclList = Collections.emptyList();
} else {
studyAclList = studyQueryResult.first().getAcl();
}
return new QueryResult<>("Get all study Acls", studyQueryResult.getDbTime(), studyAclList.size(), studyAclList.size(),
studyQueryResult.getWarningMsg(), studyQueryResult.getErrorMsg(), studyAclList);
}
@Override
public QueryResult<StudyAclEntry> getStudyAcl(String userId, long studyId, String member) throws CatalogException {
studyDBAdaptor.checkId(studyId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkStudyPermission(studyId, userId, StudyAclEntry.StudyPermissions.SHARE_STUDY);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return studyDBAdaptor.getAcl(studyId, members);
}
@Override
public QueryResult<StudyAclEntry> removeStudyAcl(String userId, long studyId, String member) throws CatalogException {
studyDBAdaptor.checkId(studyId);
checkStudyPermission(studyId, userId, StudyAclEntry.StudyPermissions.SHARE_STUDY);
// Cannot remove permissions for the owner of the study
String studyOwnerId = studyDBAdaptor.getOwnerId(studyId);
if (member.equals(studyOwnerId)) {
throw new CatalogException("Error: It is not allowed removing the permissions to the owner of the study.");
}
// Obtain the ACLs the member had
QueryResult<StudyAclEntry> studyAcl = studyDBAdaptor.getAcl(studyId, Arrays.asList(member));
if (studyAcl == null || studyAcl.getNumResults() == 0) {
throw new CatalogException("Could not remove the ACLs for " + member + ". It seems " + member + " did not have any ACLs "
+ "defined");
}
studyDBAdaptor.removeAcl(studyId, member);
studyAcl.setId("Remove study ACLs");
return studyAcl;
}
@Override
public QueryResult<StudyAclEntry> updateStudyAcl(String userId, long studyId, String member, @Nullable String addPermissions,
@Nullable String removePermissions, @Nullable String setPermissions)
throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
studyDBAdaptor.checkId(studyId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
checkStudyPermission(studyId, userId, StudyAclEntry.StudyPermissions.SHARE_STUDY);
// Check that the member has permissions
Query query = new Query()
.append(StudyDBAdaptor.QueryParams.ID.key(), studyId)
.append(StudyDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = studyDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any permissions set "
+ "yet.");
}
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(setPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, StudyAclEntry.StudyPermissions::valueOf);
studyDBAdaptor.setAclsToMember(studyId, member, permissions);
} else {
if (addPermissions != null) {
permissions = Arrays.asList(addPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, StudyAclEntry.StudyPermissions::valueOf);
studyDBAdaptor.addAclsToMember(studyId, member, permissions);
}
if (removePermissions != null) {
permissions = Arrays.asList(removePermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, StudyAclEntry.StudyPermissions::valueOf);
studyDBAdaptor.removeAclsFromMember(studyId, member, permissions);
}
}
return studyDBAdaptor.getAcl(studyId, Arrays.asList(member));
}
@Override
public QueryResult<SampleAclEntry> createSampleAcls(String userId, long sampleId, List<String> members, List<String> permissions)
throws CatalogException {
sampleDBAdaptor.checkId(sampleId);
// Check if the userId has proper permissions for all the samples.
checkSamplePermission(sampleId, userId, SampleAclEntry.SamplePermissions.SHARE);
// Check if all the members have a permission already set at the study level.
long studyId = sampleDBAdaptor.getStudyId(sampleId);
for (String member : members) {
if (!member.equals("*") && !member.equals("anonymous") && !memberExists(studyId, member)) {
throw new CatalogException("Cannot create ACL for " + member + ". First, a general study permission must be "
+ "defined for that member.");
}
}
// Check all the members exist in all the possible different studies
checkMembers(dbAdaptorFactory, studyId, members);
// Check if any of the members already have permissions set in the sample
if (anyMemberHasPermissions(studyId, sampleId, members, sampleDBAdaptor)) {
throw new CatalogException("Cannot create ACL. At least one of the members already have some permissions set for this "
+ "particular sample. Please, use update instead.");
}
// Set the permissions
int timeSpent = 0;
List<SampleAclEntry> sampleAclList = new ArrayList<>(members.size());
for (String member : members) {
SampleAclEntry sampleAcl = new SampleAclEntry(member, permissions);
QueryResult<SampleAclEntry> sampleAclQueryResult = sampleDBAdaptor.createAcl(sampleId, sampleAcl);
timeSpent += sampleAclQueryResult.getDbTime();
sampleAclList.add(sampleAclQueryResult.first());
}
return new QueryResult<>("create sample acl", timeSpent, sampleAclList.size(), sampleAclList.size(), "", "", sampleAclList);
}
@Override
public QueryResult<SampleAclEntry> getAllSampleAcls(String userId, long sampleId) throws CatalogException {
sampleDBAdaptor.checkId(sampleId);
// Check if the userId has proper permissions for all the samples.
// checkSamplePermission(sampleId, userId, SampleAclEntry.SamplePermissions.SHARE);
// Obtain the Acls
Query query = new Query(SampleDBAdaptor.QueryParams.ID.key(), sampleId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, SampleDBAdaptor.QueryParams.ACL.key());
QueryResult<Sample> queryResult = sampleDBAdaptor.get(query, queryOptions);
List<SampleAclEntry> aclList;
if (queryResult != null && queryResult.getNumResults() == 1) {
aclList = queryResult.first().getAcl();
} else {
aclList = Collections.emptyList();
}
return new QueryResult<>("get sample acl", queryResult.getDbTime(), aclList.size(), aclList.size(), queryResult.getWarningMsg(),
queryResult.getErrorMsg(), aclList);
}
@Override
public QueryResult<SampleAclEntry> getSampleAcl(String userId, long sampleId, String member) throws CatalogException {
sampleDBAdaptor.checkId(sampleId);
long studyId = sampleDBAdaptor.getStudyId(sampleId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkSamplePermission(sampleId, userId, SampleAclEntry.SamplePermissions.SHARE);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return sampleDBAdaptor.getAcl(sampleId, members);
}
@Override
public QueryResult<SampleAclEntry> removeSampleAcl(String userId, long sampleId, String member) throws CatalogException {
sampleDBAdaptor.checkId(sampleId);
checkSamplePermission(sampleId, userId, SampleAclEntry.SamplePermissions.SHARE);
long studyId = sampleDBAdaptor.getStudyId(sampleId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Obtain the ACLs the member had
QueryResult<SampleAclEntry> sampleAcl = sampleDBAdaptor.getAcl(sampleId, Arrays.asList(member));
if (sampleAcl == null || sampleAcl.getNumResults() == 0) {
throw new CatalogException("Could not remove the ACLs for " + member + ". It seems " + member + " did not have any ACLs "
+ "defined");
}
sampleDBAdaptor.removeAcl(sampleId, member);
sampleAcl.setId("Remove sample ACLs");
return sampleAcl;
}
@Override
public QueryResult<SampleAclEntry> updateSampleAcl(String userId, long sampleId, String member, @Nullable String addPermissions,
@Nullable String removePermissions, @Nullable String setPermissions)
throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
sampleDBAdaptor.checkId(sampleId);
checkSamplePermission(sampleId, userId, SampleAclEntry.SamplePermissions.SHARE);
long studyId = sampleDBAdaptor.getStudyId(sampleId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Check that the member has permissions
Query query = new Query()
.append(SampleDBAdaptor.QueryParams.ID.key(), sampleId)
.append(SampleDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = sampleDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any permissions set "
+ "yet.");
}
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(setPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, SampleAclEntry.SamplePermissions::valueOf);
sampleDBAdaptor.setAclsToMember(sampleId, member, permissions);
} else {
if (addPermissions != null) {
permissions = Arrays.asList(addPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, SampleAclEntry.SamplePermissions::valueOf);
sampleDBAdaptor.addAclsToMember(sampleId, member, permissions);
}
if (removePermissions != null) {
permissions = Arrays.asList(removePermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, SampleAclEntry.SamplePermissions::valueOf);
sampleDBAdaptor.removeAclsFromMember(sampleId, member, permissions);
}
}
return sampleDBAdaptor.getAcl(sampleId, Arrays.asList(member));
}
@Override
public List<QueryResult<FileAclEntry>> createFileAcls(AbstractManager.MyResourceIds resourceIds, List<String> members,
List<String> permissions) throws CatalogException {
checkPermissions(permissions, FileAclEntry.FilePermissions::valueOf);
String userId = resourceIds.getUser();
long studyId = resourceIds.getStudyId();
// Check all the members are valid members
checkMembers(dbAdaptorFactory, studyId, members);
// Check that all the members have permissions defined at the study level
for (String member : members) {
if (!member.equals("*") && !member.equals("anonymous") && !memberExists(studyId, member)) {
throw new CatalogException("Cannot create ACL for " + member + ". First, a general study permission must be "
+ "defined for that member.");
}
}
List<QueryResult<FileAclEntry>> retQueryResultList = new ArrayList<>(resourceIds.getResourceIds().size());
// We create the list of permissions
List<FileAclEntry> fileAclEntryList = new ArrayList<>(permissions.size());
for (String member : members) {
fileAclEntryList.add(new FileAclEntry(member, permissions));
}
for (Long fileId : resourceIds.getResourceIds()) {
try {
// Check if the userId has proper permissions for all the files.
checkFilePermission(fileId, userId, FileAclEntry.FilePermissions.SHARE);
// Check if any of the members already have permissions set in the file
if (anyMemberHasPermissions(studyId, fileId, members, fileDBAdaptor)) {
throw new CatalogException("Cannot create ACL. At least one of the members already have some permissions set for this "
+ "particular file. Please, use update instead.");
}
QueryResult<File> fileQueryResult = fileDBAdaptor.get(fileId, new QueryOptions(QueryOptions.INCLUDE,
Arrays.asList(FileDBAdaptor.QueryParams.PATH.key(), FileDBAdaptor.QueryParams.TYPE.key())));
if (fileQueryResult.getNumResults() != 1) {
throw new CatalogException("An unexpected error occured. File " + fileId + " not found when trying to create new ACLs");
}
// We create those ACLs for the whole path contained (propagate the acls in case of a directory)
Query query = new Query(FileDBAdaptor.QueryParams.STUDY_ID.key(), studyId);
if (fileQueryResult.first().getType().equals(File.Type.FILE)) {
query.append(FileDBAdaptor.QueryParams.ID.key(), fileId);
} else {
query.append(FileDBAdaptor.QueryParams.PATH.key(), "~^" + fileQueryResult.first().getPath());
}
fileDBAdaptor.createAcl(query, fileAclEntryList);
QueryResult<FileAclEntry> aclEntryQueryResult = fileDBAdaptor.getAcl(fileId, members);
aclEntryQueryResult.setId("Create file ACLs");
retQueryResultList.add(aclEntryQueryResult);
} catch (CatalogException e) {
QueryResult<FileAclEntry> queryResult = new QueryResult<>();
queryResult.setErrorMsg(e.getMessage());
queryResult.setId("Create file ACLs");
retQueryResultList.add(queryResult);
}
}
return retQueryResultList;
}
@Override
public QueryResult<FileAclEntry> getAllFileAcls(String userId, long fileId) throws CatalogException {
fileDBAdaptor.checkId(fileId);
// Check if the userId has proper permissions for all the samples.
// checkFilePermission(fileId, userId, FileAclEntry.FilePermissions.SHARE);
// Obtain the Acls
Query query = new Query(FileDBAdaptor.QueryParams.ID.key(), fileId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, FileDBAdaptor.QueryParams.ACL.key());
QueryResult<File> queryResult = fileDBAdaptor.get(query, queryOptions);
List<FileAclEntry> aclList;
if (queryResult != null && queryResult.getNumResults() == 1) {
aclList = queryResult.first().getAcl();
} else {
aclList = Collections.emptyList();
}
return new QueryResult<>("get file acl", queryResult.getDbTime(), aclList.size(), aclList.size(), queryResult.getWarningMsg(),
queryResult.getErrorMsg(), aclList);
}
@Override
public QueryResult<FileAclEntry> getFileAcl(String userId, long fileId, String member) throws CatalogException {
fileDBAdaptor.checkId(fileId);
long studyId = fileDBAdaptor.getStudyIdByFileId(fileId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkFilePermission(fileId, userId, FileAclEntry.FilePermissions.SHARE);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return fileDBAdaptor.getAcl(fileId, members);
}
@Override
public List<QueryResult<FileAclEntry>> removeFileAcls(AbstractManager.MyResourceIds resources, List<String> members)
throws CatalogException {
// Check the member is valid
checkMembers(dbAdaptorFactory, resources.getStudyId(), members);
List<QueryResult<FileAclEntry>> retQueryResultList = new ArrayList<>(resources.getResourceIds().size());
for (Long fileId : resources.getResourceIds()) {
try {
// Check if the userId has proper permissions for all the files.
checkFilePermission(fileId, resources.getUser(), FileAclEntry.FilePermissions.SHARE);
QueryResult<FileAclEntry> aclEntryQueryResult = fileDBAdaptor.getAcl(fileId, members);
QueryResult<File> fileQueryResult = fileDBAdaptor.get(fileId, new QueryOptions(QueryOptions.INCLUDE,
Arrays.asList(FileDBAdaptor.QueryParams.PATH.key(), FileDBAdaptor.QueryParams.TYPE.key())));
if (fileQueryResult.getNumResults() != 1) {
throw new CatalogException("An unexpected error occured. File " + fileId + " not found when trying to delete the ACLs");
}
// We delete those ACLs for the whole path contained (propagate the acls in case of a directory)
Query query = new Query(FileDBAdaptor.QueryParams.STUDY_ID.key(), resources.getStudyId());
if (fileQueryResult.first().getType().equals(File.Type.FILE)) {
query.append(FileDBAdaptor.QueryParams.ID.key(), fileId);
} else {
query.append(FileDBAdaptor.QueryParams.PATH.key(), "~^" + fileQueryResult.first().getPath());
}
fileDBAdaptor.removeAclsFromMember(query, members, null);
aclEntryQueryResult.setId("Remove file ACLs");
retQueryResultList.add(aclEntryQueryResult);
} catch (CatalogException e) {
QueryResult<FileAclEntry> queryResult = new QueryResult<>();
queryResult.setErrorMsg(e.getMessage());
queryResult.setId("Remove file ACLs");
retQueryResultList.add(queryResult);
}
}
return retQueryResultList;
}
@Override
public List<QueryResult<FileAclEntry>> updateFileAcl(AbstractManager.MyResourceIds resources, String member,
@Nullable String addPermissions, @Nullable String removePermissions,
@Nullable String setPermissions) throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
// Check the member is valid
checkMembers(dbAdaptorFactory, resources.getStudyId(), Arrays.asList(member));
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(StringUtils.split(setPermissions, ","));
// Check if the permissions are correct
checkPermissions(permissions, FileAclEntry.FilePermissions::valueOf);
} else {
if (addPermissions != null) {
permissions = Arrays.asList(StringUtils.split(addPermissions, ","));
// Check if the permissions are correct
checkPermissions(permissions, FileAclEntry.FilePermissions::valueOf);
} else if (removePermissions != null) {
permissions = Arrays.asList(StringUtils.split(removePermissions, ","));
// Check if the permissions are correct
checkPermissions(permissions, FileAclEntry.FilePermissions::valueOf);
} else {
throw new CatalogException("No permissions given to be added, removed or set");
}
}
List<QueryResult<FileAclEntry>> retQueryResultList = new ArrayList<>(resources.getResourceIds().size());
for (Long fileId : resources.getResourceIds()) {
try {
checkFilePermission(fileId, resources.getUser(), FileAclEntry.FilePermissions.SHARE);
// Check that the member has permissions in the file
Query query = new Query()
.append(FileDBAdaptor.QueryParams.ID.key(), fileId)
.append(FileDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = fileDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any "
+ "permissions set yet.");
}
// We create the query to update just the file acl in case of a file or all the files and folders within the folder in other
// case
QueryResult<File> fileQueryResult = fileDBAdaptor.get(fileId, new QueryOptions(QueryOptions.INCLUDE,
Arrays.asList(FileDBAdaptor.QueryParams.PATH.key(), FileDBAdaptor.QueryParams.TYPE.key())));
if (fileQueryResult.getNumResults() != 1) {
throw new CatalogException("An unexpected error occured. File " + fileId + " not found when trying to create new ACLs");
}
// We create those ACLs for the whole path contained (propagate the acls in case of a directory)
query = new Query(FileDBAdaptor.QueryParams.STUDY_ID.key(), resources.getStudyId());
if (fileQueryResult.first().getType().equals(File.Type.FILE)) {
query.append(FileDBAdaptor.QueryParams.ID.key(), fileId);
} else {
query.append(FileDBAdaptor.QueryParams.PATH.key(), "~^" + fileQueryResult.first().getPath());
}
// Update
if (setPermissions != null) {
FileAclEntry fileAclEntry = new FileAclEntry(member, permissions);
fileDBAdaptor.createAcl(query, Arrays.asList(fileAclEntry));
} else if (addPermissions != null) {
fileDBAdaptor.addAclsToMember(query, Arrays.asList(member), permissions);
} else {
fileDBAdaptor.removeAclsFromMember(query, Arrays.asList(member), permissions);
}
QueryResult<FileAclEntry> aclEntryQueryResult = fileDBAdaptor.getAcl(fileId, member);
aclEntryQueryResult.setId("Update file ACLs");
retQueryResultList.add(aclEntryQueryResult);
} catch (CatalogException e) {
QueryResult<FileAclEntry> queryResult = new QueryResult<>();
queryResult.setErrorMsg(e.getMessage());
queryResult.setId("Update file ACLs");
retQueryResultList.add(queryResult);
}
}
return retQueryResultList;
}
@Override
public List<QueryResult<IndividualAclEntry>> createIndividualAcls(AbstractManager.MyResourceIds resourceIds, List<String> members,
List<String> permissions) throws CatalogException {
checkPermissions(permissions, IndividualAclEntry.IndividualPermissions::valueOf);
String userId = resourceIds.getUser();
long studyId = resourceIds.getStudyId();
// Check all the members are valid members
checkMembers(dbAdaptorFactory, studyId, members);
// Check that all the members have permissions defined at the study level
for (String member : members) {
if (!member.equals("*") && !member.equals("anonymous") && !memberExists(studyId, member)) {
throw new CatalogException("Cannot create ACL for " + member + ". First, a general study permission must be "
+ "defined for that member.");
}
}
List<QueryResult<IndividualAclEntry>> retQueryResultList = new ArrayList<>(resourceIds.getResourceIds().size());
// We create the list of permissions
List<IndividualAclEntry> individualAclEntryList = new ArrayList<>(permissions.size());
List<SampleAclEntry> sampleAclEntryList = new ArrayList<>(permissions.size());
for (String member : members) {
individualAclEntryList.add(new IndividualAclEntry(member, permissions));
sampleAclEntryList.add(new SampleAclEntry(member, permissions));
}
for (Long individualId : resourceIds.getResourceIds()) {
try {
// Check if the userId has proper permissions for all the files.
checkIndividualPermission(individualId, userId, IndividualAclEntry.IndividualPermissions.SHARE);
// Check if any of the members already have permissions set in the file
if (anyMemberHasPermissions(studyId, individualId, members, individualDBAdaptor)) {
throw new CatalogException("Cannot create ACL. At least one of the members already have some permissions set for this "
+ "particular cohort. Please, use update instead.");
}
Query query = new Query()
.append(CohortDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(CohortDBAdaptor.QueryParams.ID.key(), individualId);
individualDBAdaptor.createAcl(query, individualAclEntryList);
// Look for all the samples belonging to the individual
query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.INDIVIDUAL_ID.key(), individualId);
QueryResult<Sample> sampleQueryResult =
sampleDBAdaptor.get(query, new QueryOptions(QueryOptions.INCLUDE, SampleDBAdaptor.QueryParams.ID.key()));
// If the individual contains samples, we propagate the permissions to all the samples
if (sampleQueryResult != null && sampleQueryResult.getResult() != null && sampleQueryResult.getNumResults() > 0) {
List<Long> sampleIds = sampleQueryResult.getResult().stream().map(Sample::getId).collect(Collectors.toList());
query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.ID.key(), sampleIds);
sampleDBAdaptor.createAcl(query, sampleAclEntryList);
}
QueryResult<IndividualAclEntry> aclEntryQueryResult = individualDBAdaptor.getAcl(individualId, members);
aclEntryQueryResult.setId("Create individual ACLs");
retQueryResultList.add(aclEntryQueryResult);
} catch (CatalogException e) {
QueryResult<IndividualAclEntry> queryResult = new QueryResult<>();
queryResult.setErrorMsg(e.getMessage());
queryResult.setId("Create individual ACLs");
retQueryResultList.add(queryResult);
}
}
return retQueryResultList;
}
@Override
public QueryResult<IndividualAclEntry> getAllIndividualAcls(String userId, long individualId) throws CatalogException {
individualDBAdaptor.checkId(individualId);
// Check if the userId has proper permissions for all the individuals.
// checkIndividualPermission(individualId, userId, IndividualAclEntry.IndividualPermissions.SHARE);
// Obtain the Acls
Query query = new Query(IndividualDBAdaptor.QueryParams.ID.key(), individualId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, IndividualDBAdaptor.QueryParams.ACL.key());
QueryResult<Individual> queryResult = individualDBAdaptor.get(query, queryOptions);
List<IndividualAclEntry> aclList;
if (queryResult != null && queryResult.getNumResults() == 1) {
aclList = queryResult.first().getAcl();
} else {
aclList = Collections.emptyList();
}
return new QueryResult<>("get individual acl", queryResult.getDbTime(), aclList.size(), aclList.size(),
queryResult.getWarningMsg(), queryResult.getErrorMsg(), aclList);
}
@Override
public QueryResult<IndividualAclEntry> getIndividualAcl(String userId, long individualId, String member) throws CatalogException {
individualDBAdaptor.checkId(individualId);
long studyId = individualDBAdaptor.getStudyId(individualId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkIndividualPermission(individualId, userId, IndividualAclEntry.IndividualPermissions.SHARE);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return individualDBAdaptor.getAcl(individualId, members);
}
@Override
public QueryResult<IndividualAclEntry> removeIndividualAcl(String userId, long individualId, String member) throws CatalogException {
individualDBAdaptor.checkId(individualId);
checkIndividualPermission(individualId, userId, IndividualAclEntry.IndividualPermissions.SHARE);
long studyId = individualDBAdaptor.getStudyId(individualId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Obtain the ACLs the member had
QueryResult<IndividualAclEntry> individualDBAdaptorAcl = individualDBAdaptor.getAcl(individualId, Arrays.asList(member));
if (individualDBAdaptorAcl == null || individualDBAdaptorAcl.getNumResults() == 0) {
throw new CatalogException("Could not remove the ACLs for " + member + ". It seems " + member + " did not have any ACLs "
+ "defined");
}
individualDBAdaptor.removeAcl(individualId, member);
// Look for all the samples belonging to the individual
Query query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.INDIVIDUAL_ID.key(), individualId);
QueryResult<Sample> sampleQueryResult =
sampleDBAdaptor.get(query, new QueryOptions(QueryOptions.INCLUDE, SampleDBAdaptor.QueryParams.ID.key()));
// If the individual contains samples, we propagate the permissions to all the samples
if (sampleQueryResult != null && sampleQueryResult.getResult() != null && sampleQueryResult.getNumResults() > 0) {
List<Long> sampleIds = sampleQueryResult.getResult().stream().map(Sample::getId).collect(Collectors.toList());
query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.ID.key(), sampleIds);
sampleDBAdaptor.removeAclsFromMember(query, Arrays.asList(member), null);
}
individualDBAdaptorAcl.setId("Remove individual ACLs");
return individualDBAdaptorAcl;
}
@Override
public QueryResult<IndividualAclEntry> updateIndividualAcl(String userId, long individualId, String member,
@Nullable String addPermissions, @Nullable String removePermissions,
@Nullable String setPermissions) throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
individualDBAdaptor.checkId(individualId);
checkIndividualPermission(individualId, userId, IndividualAclEntry.IndividualPermissions.SHARE);
long studyId = individualDBAdaptor.getStudyId(individualId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Check that the member has permissions
Query query = new Query()
.append(IndividualDBAdaptor.QueryParams.ID.key(), individualId)
.append(IndividualDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = individualDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any permissions set "
+ "yet.");
}
// Look for all the samples belonging to the individual
query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.INDIVIDUAL_ID.key(), individualId);
QueryResult<Sample> sampleQueryResult =
sampleDBAdaptor.get(query, new QueryOptions(QueryOptions.INCLUDE, SampleDBAdaptor.QueryParams.ID.key()));
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(setPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, IndividualAclEntry.IndividualPermissions::valueOf);
individualDBAdaptor.setAclsToMember(individualId, member, permissions);
// If the individual contains samples, we propagate the permissions to all the samples
if (sampleQueryResult != null && sampleQueryResult.getResult() != null && sampleQueryResult.getNumResults() > 0) {
List<Long> sampleIds = sampleQueryResult.getResult().stream().map(Sample::getId).collect(Collectors.toList());
query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.ID.key(), sampleIds);
SampleAclEntry aclEntry = new SampleAclEntry(member, permissions);
sampleDBAdaptor.createAcl(query, Arrays.asList(aclEntry));
}
} else {
if (addPermissions != null) {
permissions = Arrays.asList(addPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, IndividualAclEntry.IndividualPermissions::valueOf);
individualDBAdaptor.addAclsToMember(individualId, member, permissions);
// If the individual contains samples, we propagate the permissions to all the samples
if (sampleQueryResult != null && sampleQueryResult.getResult() != null && sampleQueryResult.getNumResults() > 0) {
List<Long> sampleIds = sampleQueryResult.getResult().stream().map(Sample::getId).collect(Collectors.toList());
query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.ID.key(), sampleIds);
sampleDBAdaptor.addAclsToMember(query, Arrays.asList(member), permissions);
}
}
if (removePermissions != null) {
permissions = Arrays.asList(removePermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, IndividualAclEntry.IndividualPermissions::valueOf);
individualDBAdaptor.removeAclsFromMember(individualId, member, permissions);
// If the individual contains samples, we propagate the permissions to all the samples
if (sampleQueryResult != null && sampleQueryResult.getResult() != null && sampleQueryResult.getNumResults() > 0) {
List<Long> sampleIds = sampleQueryResult.getResult().stream().map(Sample::getId).collect(Collectors.toList());
query = new Query()
.append(SampleDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(SampleDBAdaptor.QueryParams.ID.key(), sampleIds);
sampleDBAdaptor.removeAclsFromMember(query, Arrays.asList(member), permissions);
}
}
}
return individualDBAdaptor.getAcl(individualId, Arrays.asList(member));
}
@Override
public List<QueryResult<CohortAclEntry>> createCohortAcls(AbstractManager.MyResourceIds resourceIds, List<String> members,
List<String> permissions) throws CatalogException {
checkPermissions(permissions, CohortAclEntry.CohortPermissions::valueOf);
String userId = resourceIds.getUser();
long studyId = resourceIds.getStudyId();
// Check all the members are valid members
checkMembers(dbAdaptorFactory, studyId, members);
// Check that all the members have permissions defined at the study level
for (String member : members) {
if (!member.equals("*") && !member.equals("anonymous") && !memberExists(studyId, member)) {
throw new CatalogException("Cannot create ACL for " + member + ". First, a general study permission must be "
+ "defined for that member.");
}
}
List<QueryResult<CohortAclEntry>> retQueryResultList = new ArrayList<>(resourceIds.getResourceIds().size());
// We create the list of permissions
List<CohortAclEntry> cohortAclEntryList = new ArrayList<>(permissions.size());
for (String member : members) {
cohortAclEntryList.add(new CohortAclEntry(member, permissions));
}
for (Long cohortId : resourceIds.getResourceIds()) {
try {
// Check if the userId has proper permissions for all the files.
checkCohortPermission(cohortId, userId, CohortAclEntry.CohortPermissions.SHARE);
// Check if any of the members already have permissions set in the file
if (anyMemberHasPermissions(studyId, cohortId, members, cohortDBAdaptor)) {
throw new CatalogException("Cannot create ACL. At least one of the members already have some permissions set for this "
+ "particular cohort. Please, use update instead.");
}
Query query = new Query()
.append(CohortDBAdaptor.QueryParams.STUDY_ID.key(), studyId)
.append(CohortDBAdaptor.QueryParams.ID.key(), cohortId);
cohortDBAdaptor.createAcl(query, cohortAclEntryList);
QueryResult<CohortAclEntry> aclEntryQueryResult = cohortDBAdaptor.getAcl(cohortId, members);
aclEntryQueryResult.setId("Create cohort ACLs");
retQueryResultList.add(aclEntryQueryResult);
} catch (CatalogException e) {
QueryResult<CohortAclEntry> queryResult = new QueryResult<>();
queryResult.setErrorMsg(e.getMessage());
queryResult.setId("Create cohort ACLs");
retQueryResultList.add(queryResult);
}
}
return retQueryResultList;
}
@Override
public QueryResult<CohortAclEntry> getAllCohortAcls(String userId, long cohortId) throws CatalogException {
cohortDBAdaptor.checkId(cohortId);
// Check if the userId has proper permissions for all the cohorts.
// checkCohortPermission(cohortId, userId, CohortAclEntry.CohortPermissions.SHARE);
// Obtain the Acls
Query query = new Query(CohortDBAdaptor.QueryParams.ID.key(), cohortId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, CohortDBAdaptor.QueryParams.ACL.key());
QueryResult<Cohort> queryResult = cohortDBAdaptor.get(query, queryOptions);
List<CohortAclEntry> aclList;
if (queryResult != null && queryResult.getNumResults() == 1) {
aclList = queryResult.first().getAcl();
} else {
aclList = Collections.emptyList();
}
return new QueryResult<>("get cohort acl", queryResult.getDbTime(), aclList.size(), aclList.size(),
queryResult.getWarningMsg(), queryResult.getErrorMsg(), aclList);
}
@Override
public QueryResult<CohortAclEntry> getCohortAcl(String userId, long cohortId, String member) throws CatalogException {
cohortDBAdaptor.checkId(cohortId);
long studyId = cohortDBAdaptor.getStudyId(cohortId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkCohortPermission(cohortId, userId, CohortAclEntry.CohortPermissions.SHARE);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return cohortDBAdaptor.getAcl(cohortId, members);
}
@Override
public QueryResult<CohortAclEntry> removeCohortAcl(String userId, long cohortId, String member) throws CatalogException {
cohortDBAdaptor.checkId(cohortId);
checkCohortPermission(cohortId, userId, CohortAclEntry.CohortPermissions.SHARE);
long studyId = cohortDBAdaptor.getStudyId(cohortId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Obtain the ACLs the member had
QueryResult<CohortAclEntry> cohortDBAdaptorAcl = cohortDBAdaptor.getAcl(cohortId, Arrays.asList(member));
if (cohortDBAdaptorAcl == null || cohortDBAdaptorAcl.getNumResults() == 0) {
throw new CatalogException("Could not remove the ACLs for " + member + ". It seems " + member + " did not have any ACLs "
+ "defined");
}
cohortDBAdaptor.removeAcl(cohortId, member);
cohortDBAdaptorAcl.setId("Remove cohort ACLs");
return cohortDBAdaptorAcl;
}
@Override
public QueryResult<CohortAclEntry> updateCohortAcl(String userId, long cohortId, String member, @Nullable String addPermissions,
@Nullable String removePermissions, @Nullable String setPermissions)
throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
cohortDBAdaptor.checkId(cohortId);
checkCohortPermission(cohortId, userId, CohortAclEntry.CohortPermissions.SHARE);
long studyId = cohortDBAdaptor.getStudyId(cohortId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Check that the member has permissions
Query query = new Query()
.append(CohortDBAdaptor.QueryParams.ID.key(), cohortId)
.append(CohortDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = cohortDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any permissions set "
+ "yet.");
}
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(setPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, CohortAclEntry.CohortPermissions::valueOf);
cohortDBAdaptor.setAclsToMember(cohortId, member, permissions);
} else {
if (addPermissions != null) {
permissions = Arrays.asList(addPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, CohortAclEntry.CohortPermissions::valueOf);
cohortDBAdaptor.addAclsToMember(cohortId, member, permissions);
}
if (removePermissions != null) {
permissions = Arrays.asList(removePermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, CohortAclEntry.CohortPermissions::valueOf);
cohortDBAdaptor.removeAclsFromMember(cohortId, member, permissions);
}
}
return cohortDBAdaptor.getAcl(cohortId, Arrays.asList(member));
}
private void checkUpdateParams(@Nullable String addPermissions, @Nullable String removePermissions, @Nullable String setPermissions)
throws CatalogException {
int cont = 0;
cont += addPermissions != null ? 1 : 0;
cont += removePermissions != null ? 1 : 0;
cont += setPermissions != null ? 1 : 0;
if (cont == 0) {
throw new CatalogException("No permissions to be added, removed or set");
} else if (cont > 1) {
throw new CatalogException("More than one action to be performed found. Please, select just one.");
}
}
@Override
public QueryResult<DatasetAclEntry> createDatasetAcls(String userId, long datasetId, List<String> members, List<String> permissions)
throws CatalogException {
datasetDBAdaptor.checkId(datasetId);
// Check if the userId has proper permissions for all the datasets.
checkDatasetPermission(datasetId, userId, DatasetAclEntry.DatasetPermissions.SHARE);
// Check if all the members have a permission already set at the study level.
long studyId = datasetDBAdaptor.getStudyIdByDatasetId(datasetId);
for (String member : members) {
if (!member.equals("*") && !member.equals("anonymous") && !memberExists(studyId, member)) {
throw new CatalogException("Cannot create ACL for " + member + ". First, a general study permission must be "
+ "defined for that member.");
}
}
// Check all the members exist in all the possible different studies
checkMembers(dbAdaptorFactory, studyId, members);
// Check if any of the members already have permissions set in the file
if (anyMemberHasPermissions(studyId, datasetId, members, datasetDBAdaptor)) {
throw new CatalogException("Cannot create ACL. At least one of the members already have some permissions set for this "
+ "particular dataset. Please, use update instead.");
}
// Set the permissions
int timeSpent = 0;
List<DatasetAclEntry> datasetAclList = new ArrayList<>(members.size());
for (String member : members) {
DatasetAclEntry datasetAcl = new DatasetAclEntry(member, permissions);
QueryResult<DatasetAclEntry> datasetAclQueryResult = datasetDBAdaptor.createAcl(datasetId, datasetAcl);
timeSpent += datasetAclQueryResult.getDbTime();
datasetAclList.add(datasetAclQueryResult.first());
}
return new QueryResult<>("create dataset acl", timeSpent, datasetAclList.size(), datasetAclList.size(), "", "",
datasetAclList);
}
@Override
public QueryResult<DatasetAclEntry> getAllDatasetAcls(String userId, long datasetId) throws CatalogException {
datasetDBAdaptor.checkId(datasetId);
// Check if the userId has proper permissions for all the datasets.
// checkDatasetPermission(datasetId, userId, DatasetAclEntry.DatasetPermissions.SHARE);
// Obtain the Acls
Query query = new Query(DatasetDBAdaptor.QueryParams.ID.key(), datasetId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, DatasetDBAdaptor.QueryParams.ACL.key());
QueryResult<Dataset> queryResult = datasetDBAdaptor.get(query, queryOptions);
List<DatasetAclEntry> aclList;
if (queryResult != null && queryResult.getNumResults() == 1) {
aclList = queryResult.first().getAcl();
} else {
aclList = Collections.emptyList();
}
return new QueryResult<>("get dataset acl", queryResult.getDbTime(), aclList.size(), aclList.size(),
queryResult.getWarningMsg(), queryResult.getErrorMsg(), aclList);
}
@Override
public QueryResult<DatasetAclEntry> getDatasetAcl(String userId, long datasetId, String member) throws CatalogException {
datasetDBAdaptor.checkId(datasetId);
long studyId = datasetDBAdaptor.getStudyIdByDatasetId(datasetId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkDatasetPermission(datasetId, userId, DatasetAclEntry.DatasetPermissions.SHARE);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return datasetDBAdaptor.getAcl(datasetId, members);
}
@Override
public QueryResult<DatasetAclEntry> removeDatasetAcl(String userId, long datasetId, String member) throws CatalogException {
datasetDBAdaptor.checkId(datasetId);
checkDatasetPermission(datasetId, userId, DatasetAclEntry.DatasetPermissions.SHARE);
long studyId = datasetDBAdaptor.getStudyIdByDatasetId(datasetId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Obtain the ACLs the member had
QueryResult<DatasetAclEntry> datasetDBAdaptorAcl = datasetDBAdaptor.getAcl(datasetId, Arrays.asList(member));
if (datasetDBAdaptorAcl == null || datasetDBAdaptorAcl.getNumResults() == 0) {
throw new CatalogException("Could not remove the ACLs for " + member + ". It seems " + member + " did not have any ACLs "
+ "defined");
}
datasetDBAdaptor.removeAcl(datasetId, member);
datasetDBAdaptorAcl.setId("Remove dataset ACLs");
return datasetDBAdaptorAcl;
}
@Override
public QueryResult<DatasetAclEntry> updateDatasetAcl(String userId, long datasetId, String member, @Nullable String addPermissions,
@Nullable String removePermissions, @Nullable String setPermissions)
throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
datasetDBAdaptor.checkId(datasetId);
checkDatasetPermission(datasetId, userId, DatasetAclEntry.DatasetPermissions.SHARE);
long studyId = datasetDBAdaptor.getStudyIdByDatasetId(datasetId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Check that the member has permissions
Query query = new Query()
.append(DatasetDBAdaptor.QueryParams.ID.key(), datasetId)
.append(DatasetDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = datasetDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any permissions set "
+ "yet.");
}
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(setPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, DatasetAclEntry.DatasetPermissions::valueOf);
datasetDBAdaptor.setAclsToMember(datasetId, member, permissions);
} else {
if (addPermissions != null) {
permissions = Arrays.asList(addPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, DatasetAclEntry.DatasetPermissions::valueOf);
datasetDBAdaptor.addAclsToMember(datasetId, member, permissions);
}
if (removePermissions != null) {
permissions = Arrays.asList(removePermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, DatasetAclEntry.DatasetPermissions::valueOf);
datasetDBAdaptor.removeAclsFromMember(datasetId, member, permissions);
}
}
return datasetDBAdaptor.getAcl(datasetId, Arrays.asList(member));
}
@Override
public QueryResult<JobAclEntry> createJobAcls(String userId, long jobId, List<String> members, List<String> permissions)
throws CatalogException {
jobDBAdaptor.checkId(jobId);
// Check if the userId has proper permissions for all the jobs.
checkJobPermission(jobId, userId, JobAclEntry.JobPermissions.SHARE);
// Check if all the members have a permission already set at the study level.
long studyId = jobDBAdaptor.getStudyId(jobId);
for (String member : members) {
if (!member.equals("*") && !member.equals("anonymous") && !memberExists(studyId, member)) {
throw new CatalogException("Cannot create ACL for " + member + ". First, a general study permission must be "
+ "defined for that member.");
}
}
// Check all the members exist in all the possible different studies
checkMembers(dbAdaptorFactory, studyId, members);
// Check if any of the members already have permissions set in the job
if (anyMemberHasPermissions(studyId, jobId, members, jobDBAdaptor)) {
throw new CatalogException("Cannot create ACL. At least one of the members already have some permissions set for this "
+ "particular job. Please, use update instead.");
}
// Set the permissions
int timeSpent = 0;
List<JobAclEntry> jobAclList = new ArrayList<>(members.size());
for (String member : members) {
JobAclEntry jobAcl = new JobAclEntry(member, permissions);
QueryResult<JobAclEntry> jobAclQueryResult = jobDBAdaptor.createAcl(jobId, jobAcl);
timeSpent += jobAclQueryResult.getDbTime();
jobAclList.add(jobAclQueryResult.first());
}
return new QueryResult<>("create job acl", timeSpent, jobAclList.size(), jobAclList.size(), "", "", jobAclList);
}
@Override
public QueryResult<JobAclEntry> getAllJobAcls(String userId, long jobId) throws CatalogException {
jobDBAdaptor.checkId(jobId);
// Check if the userId has proper permissions for all the jobs.
// checkJobPermission(jobId, userId, JobAclEntry.JobPermissions.SHARE);
// Obtain the Acls
Query query = new Query(JobDBAdaptor.QueryParams.ID.key(), jobId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, JobDBAdaptor.QueryParams.ACL.key());
QueryResult<Job> queryResult = jobDBAdaptor.get(query, queryOptions);
List<JobAclEntry> aclList;
if (queryResult != null && queryResult.getNumResults() == 1) {
aclList = queryResult.first().getAcl();
} else {
aclList = Collections.emptyList();
}
return new QueryResult<>("get job acl", queryResult.getDbTime(), aclList.size(), aclList.size(),
queryResult.getWarningMsg(), queryResult.getErrorMsg(), aclList);
}
@Override
public QueryResult<JobAclEntry> getJobAcl(String userId, long jobId, String member) throws CatalogException {
jobDBAdaptor.checkId(jobId);
long studyId = jobDBAdaptor.getStudyId(jobId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkJobPermission(jobId, userId, JobAclEntry.JobPermissions.SHARE);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return jobDBAdaptor.getAcl(jobId, members);
}
@Override
public QueryResult<JobAclEntry> removeJobAcl(String userId, long jobId, String member) throws CatalogException {
jobDBAdaptor.checkId(jobId);
checkJobPermission(jobId, userId, JobAclEntry.JobPermissions.SHARE);
long studyId = jobDBAdaptor.getStudyId(jobId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Obtain the ACLs the member had
QueryResult<JobAclEntry> jobDBAdaptorAcl = jobDBAdaptor.getAcl(jobId, Arrays.asList(member));
if (jobDBAdaptorAcl == null || jobDBAdaptorAcl.getNumResults() == 0) {
throw new CatalogException("Could not remove the ACLs for " + member + ". It seems " + member + " did not have any ACLs "
+ "defined");
}
jobDBAdaptor.removeAcl(jobId, member);
jobDBAdaptorAcl.setId("Remove job ACLs");
return jobDBAdaptorAcl;
}
@Override
public QueryResult<JobAclEntry> updateJobAcl(String userId, long jobId, String member, @Nullable String addPermissions,
@Nullable String removePermissions, @Nullable String setPermissions)
throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
jobDBAdaptor.checkId(jobId);
checkJobPermission(jobId, userId, JobAclEntry.JobPermissions.SHARE);
long studyId = jobDBAdaptor.getStudyId(jobId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Check that the member has permissions
Query query = new Query()
.append(JobDBAdaptor.QueryParams.ID.key(), jobId)
.append(JobDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = jobDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any permissions set "
+ "yet.");
}
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(setPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, JobAclEntry.JobPermissions::valueOf);
jobDBAdaptor.setAclsToMember(jobId, member, permissions);
} else {
if (addPermissions != null) {
permissions = Arrays.asList(addPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, JobAclEntry.JobPermissions::valueOf);
jobDBAdaptor.addAclsToMember(jobId, member, permissions);
}
if (removePermissions != null) {
permissions = Arrays.asList(removePermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, JobAclEntry.JobPermissions::valueOf);
jobDBAdaptor.removeAclsFromMember(jobId, member, permissions);
}
}
return jobDBAdaptor.getAcl(jobId, Arrays.asList(member));
}
@Override
public QueryResult<DiseasePanelAclEntry> createPanelAcls(String userId, long panelId, List<String> members, List<String> permissions)
throws CatalogException {
panelDBAdaptor.checkId(panelId);
// Check if the userId has proper permissions for all the panels.
checkDiseasePanelPermission(panelId, userId, DiseasePanelAclEntry.DiseasePanelPermissions.SHARE);
// Check if all the members have a permission already set at the study level.
Set<Long> studySet = new HashSet<>();
long studyId = panelDBAdaptor.getStudyId(panelId);
studySet.add(studyId);
for (String member : members) {
if (!member.equals("*") && !member.equals("anonymous") && !memberExists(studyId, member)) {
throw new CatalogException("Cannot create ACL for " + member + ". First, a general study permission must be "
+ "defined for that member.");
}
}
// Check all the members exist in all the possible different studies
checkMembers(dbAdaptorFactory, studyId, members);
// Check if any of the members already have permissions set in the panel
if (anyMemberHasPermissions(studyId, panelId, members, panelDBAdaptor)) {
throw new CatalogException("Cannot create ACL. At least one of the members already have some permissions set for this "
+ "particular panel. Please, use update instead.");
}
// Set the permissions
int timeSpent = 0;
List<DiseasePanelAclEntry> panelAclList = new ArrayList<>(members.size());
for (String member : members) {
DiseasePanelAclEntry panelAcl = new DiseasePanelAclEntry(member, permissions);
QueryResult<DiseasePanelAclEntry> panelAclQueryResult = panelDBAdaptor.createAcl(panelId, panelAcl);
timeSpent += panelAclQueryResult.getDbTime();
panelAclList.add(panelAclQueryResult.first());
}
return new QueryResult<>("create panel acl", timeSpent, panelAclList.size(), panelAclList.size(), "", "",
panelAclList);
}
@Override
public QueryResult<DiseasePanelAclEntry> getAllPanelAcls(String userId, long panelId) throws CatalogException {
panelDBAdaptor.checkId(panelId);
// Check if the userId has proper permissions for all the panels.
// checkDiseasePanelPermission(panelId, userId, DiseasePanelAclEntry.DiseasePanelPermissions.SHARE);
// Obtain the Acls
Query query = new Query(PanelDBAdaptor.QueryParams.ID.key(), panelId);
QueryOptions queryOptions = new QueryOptions(QueryOptions.INCLUDE, PanelDBAdaptor.QueryParams.ACL.key());
QueryResult<DiseasePanel> queryResult = panelDBAdaptor.get(query, queryOptions);
List<DiseasePanelAclEntry> aclList;
if (queryResult != null && queryResult.getNumResults() == 1) {
aclList = queryResult.first().getAcl();
} else {
aclList = Collections.emptyList();
}
return new QueryResult<>("get panel acl", queryResult.getDbTime(), aclList.size(), aclList.size(),
queryResult.getWarningMsg(), queryResult.getErrorMsg(), aclList);
}
@Override
public QueryResult<DiseasePanelAclEntry> getPanelAcl(String userId, long panelId, String member) throws CatalogException {
panelDBAdaptor.checkId(panelId);
long studyId = panelDBAdaptor.getStudyId(panelId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
try {
checkDiseasePanelPermission(panelId, userId, DiseasePanelAclEntry.DiseasePanelPermissions.SHARE);
} catch (CatalogException e) {
// It will be OK if the userId asking for the ACLs wants to see its own permissions
if (member.startsWith("@")) { //group
// If the userId does not belong to the group...
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, userId);
if (groupBelonging.getNumResults() != 1 || !groupBelonging.first().getName().equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
} else {
// If the userId asking to see the permissions is not asking to see their own permissions
if (!userId.equals(member)) {
throw new CatalogAuthorizationException("The user " + userId + " does not have permissions to see the ACLs of "
+ member);
}
}
}
List<String> members = new ArrayList<>(2);
members.add(member);
if (!member.startsWith("@") && !member.equalsIgnoreCase("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
members.add(groupBelonging.first().getName());
}
}
return panelDBAdaptor.getAcl(panelId, members);
}
@Override
public QueryResult<DiseasePanelAclEntry> removePanelAcl(String userId, long panelId, String member) throws CatalogException {
panelDBAdaptor.checkId(panelId);
checkDiseasePanelPermission(panelId, userId, DiseasePanelAclEntry.DiseasePanelPermissions.SHARE);
long studyId = panelDBAdaptor.getStudyId(panelId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Obtain the ACLs the member had
QueryResult<DiseasePanelAclEntry> panelDBAdaptorAcl = panelDBAdaptor.getAcl(panelId, Arrays.asList(member));
if (panelDBAdaptorAcl == null || panelDBAdaptorAcl.getNumResults() == 0) {
throw new CatalogException("Could not remove the ACLs for " + member + ". It seems " + member + " did not have any ACLs "
+ "defined");
}
panelDBAdaptor.removeAcl(panelId, member);
panelDBAdaptorAcl.setId("Remove panel ACLs");
return panelDBAdaptorAcl;
}
@Override
public QueryResult<DiseasePanelAclEntry> updatePanelAcl(String userId, long panelId, String member, @Nullable String addPermissions,
@Nullable String removePermissions, @Nullable String setPermissions)
throws CatalogException {
checkUpdateParams(addPermissions, removePermissions, setPermissions);
panelDBAdaptor.checkId(panelId);
checkDiseasePanelPermission(panelId, userId, DiseasePanelAclEntry.DiseasePanelPermissions.SHARE);
long studyId = panelDBAdaptor.getStudyId(panelId);
checkMembers(dbAdaptorFactory, studyId, Arrays.asList(member));
// Check that the member has permissions
Query query = new Query()
.append(PanelDBAdaptor.QueryParams.ID.key(), panelId)
.append(PanelDBAdaptor.QueryParams.ACL_MEMBER.key(), member);
QueryResult<Long> count = panelDBAdaptor.count(query);
if (count == null || count.first() == 0) {
throw new CatalogException("Could not update ACLs for " + member + ". It seems the member does not have any permissions set "
+ "yet.");
}
List<String> permissions;
if (setPermissions != null) {
permissions = Arrays.asList(setPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, DiseasePanelAclEntry.DiseasePanelPermissions::valueOf);
panelDBAdaptor.setAclsToMember(panelId, member, permissions);
} else {
if (addPermissions != null) {
permissions = Arrays.asList(addPermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, DiseasePanelAclEntry.DiseasePanelPermissions::valueOf);
panelDBAdaptor.addAclsToMember(panelId, member, permissions);
}
if (removePermissions != null) {
permissions = Arrays.asList(removePermissions.split(","));
// Check if the permissions are correct
checkPermissions(permissions, DiseasePanelAclEntry.DiseasePanelPermissions::valueOf);
panelDBAdaptor.removeAclsFromMember(panelId, member, permissions);
}
}
return panelDBAdaptor.getAcl(panelId, Arrays.asList(member));
}
@Override
public boolean anyMemberHasPermissions(long studyId, long id, List<String> members, AclDBAdaptor dbAdaptor)
throws CatalogException {
List<String> allMembers = new ArrayList<>(members.size());
allMembers.addAll(members);
for (String member : members) {
if (member.startsWith("@")) { // It's a group
// Obtain the users of the group
QueryResult<Group> group = studyDBAdaptor.getGroup(studyId, member, Collections.emptyList());
if (group != null && group.getNumResults() == 1) {
allMembers.addAll(group.first().getUserIds());
}
} else if (!member.equalsIgnoreCase("anonymous") && !member.equals("*")) { // It's a user id
// Get the group where the user might belong to
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging != null && groupBelonging.getNumResults() == 1) {
allMembers.add(groupBelonging.first().getName());
}
}
}
return dbAdaptor.getAcl(id, allMembers).getNumResults() > 0;
}
@Override
public boolean memberHasPermissionsInStudy(long studyId, String member) throws CatalogException {
String userId = member;
String groupId = null;
if (!member.startsWith("@")) { // User
if (member.equals(ADMIN) || isStudyOwner(studyId, member)) {
return true;
}
if (!member.equals("anonymous") && !member.equals("*")) {
QueryResult<Group> groupBelonging = getGroupBelonging(studyId, member);
if (groupBelonging.getNumResults() > 0) {
groupId = groupBelonging.first().getName();
}
}
}
StudyAclEntry studyAcl = getStudyAclBelonging(studyId, userId, groupId);
return studyAcl != null;
}
private boolean isStudyOwner(long studyId, String userId) throws CatalogDBException {
return studyDBAdaptor.getOwnerId(studyId).equals(userId);
}
/*
====================================
Auxiliar methods
====================================
*/
/**
* Retrieves the groupId where the members belongs to.
*
* @param studyId study id.
* @param members List of user ids.
* @return the group id of the user. Null if the user does not take part of any group.
* @throws CatalogException when there is any database error.
*/
QueryResult<Group> getGroupBelonging(long studyId, List<String> members) throws CatalogException {
return studyDBAdaptor.getGroup(studyId, null, members);
}
QueryResult<Group> getGroupBelonging(long studyId, String members) throws CatalogException {
return getGroupBelonging(studyId, Arrays.asList(members.split(",")));
}
/**
* Retrieves the StudyAcl where the user/group belongs to.
*
* @param studyId study id.
* @param userId user id.
* @param groupId group id. This can be null.
* @return the studyAcl where the user/group belongs to.
* @throws CatalogException when there is any database error.
*/
StudyAclEntry getStudyAclBelonging(long studyId, String userId, @Nullable String groupId) throws CatalogException {
List<String> members = (groupId != null)
? Arrays.asList(userId, groupId, OTHER_USERS_ID, ANONYMOUS)
: Arrays.asList(userId, OTHER_USERS_ID, ANONYMOUS);
QueryResult<StudyAclEntry> studyQueryResult = studyDBAdaptor.getAcl(studyId, members);
Map<String, StudyAclEntry> userAclMap = studyQueryResult.getResult().stream().collect(Collectors.toMap(StudyAclEntry::getMember,
Function.identity()));
if (userId.equals(ANONYMOUS)) {
if (userAclMap.containsKey(userId)) {
return userAclMap.get(userId);
}
return null;
}
// Registered user
EnumSet<StudyAclEntry.StudyPermissions> permissions = EnumSet.noneOf(StudyAclEntry.StudyPermissions.class);
boolean flagPermissionFound = false;
if (userAclMap.containsKey(userId)) {
permissions.addAll(userAclMap.get(userId).getPermissions());
flagPermissionFound = true;
}
if (StringUtils.isNotEmpty(groupId) && userAclMap.containsKey(groupId)) {
permissions.addAll(userAclMap.get(groupId).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(ANONYMOUS)) {
permissions.addAll(userAclMap.get(ANONYMOUS).getPermissions());
flagPermissionFound = true;
}
if (userAclMap.containsKey(OTHER_USERS_ID)) {
permissions.addAll(userAclMap.get(OTHER_USERS_ID).getPermissions());
flagPermissionFound = true;
}
if (flagPermissionFound) {
return new StudyAclEntry(userId, permissions);
}
return null;
}
public static void checkPermissions(List<String> permissions, Function<String, Enum> getValue) throws CatalogException {
for (String permission : permissions) {
try {
getValue.apply(permission);
} catch (IllegalArgumentException e) {
throw new CatalogException("The permission " + permission + " is not a correct permission.");
}
}
}
/*
====================================
ACL transformation methods
====================================
*/
private FileAclEntry transformStudyAclToFileAcl(StudyAclEntry studyAcl) {
FileAclEntry fileAcl = new FileAclEntry(null, Collections.emptyList());
if (studyAcl == null) {
return fileAcl;
}
fileAcl.setMember(studyAcl.getMember());
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = studyAcl.getPermissions();
EnumSet<FileAclEntry.FilePermissions> filePermissions = EnumSet.noneOf(FileAclEntry.FilePermissions.class);
for (StudyAclEntry.StudyPermissions studyPermission : studyPermissions) {
FileAclEntry.FilePermissions aux = studyPermission.getFilePermission();
if (aux != null) {
filePermissions.add(aux);
}
}
fileAcl.setPermissions(filePermissions);
return fileAcl;
}
private SampleAclEntry transformStudyAclToSampleAcl(StudyAclEntry studyAcl) {
SampleAclEntry sampleAcl = new SampleAclEntry(null, Collections.emptyList());
if (studyAcl == null) {
return sampleAcl;
}
sampleAcl.setMember(studyAcl.getMember());
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = studyAcl.getPermissions();
EnumSet<SampleAclEntry.SamplePermissions> samplePermission = EnumSet.noneOf(SampleAclEntry.SamplePermissions.class);
for (StudyAclEntry.StudyPermissions studyPermission : studyPermissions) {
SampleAclEntry.SamplePermissions aux = studyPermission.getSamplePermission();
if (aux != null) {
samplePermission.add(aux);
}
}
sampleAcl.setPermissions(samplePermission);
return sampleAcl;
}
private IndividualAclEntry transformStudyAclToIndividualAcl(StudyAclEntry studyAcl) {
IndividualAclEntry individualAcl = new IndividualAclEntry(null, Collections.emptyList());
if (studyAcl == null) {
return individualAcl;
}
individualAcl.setMember(studyAcl.getMember());
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = studyAcl.getPermissions();
EnumSet<IndividualAclEntry.IndividualPermissions> individualPermissions =
EnumSet.noneOf(IndividualAclEntry.IndividualPermissions.class);
for (StudyAclEntry.StudyPermissions studyPermission : studyPermissions) {
IndividualAclEntry.IndividualPermissions aux = studyPermission.getIndividualPermission();
if (aux != null) {
individualPermissions.add(aux);
}
}
individualAcl.setPermissions(individualPermissions);
return individualAcl;
}
private JobAclEntry transformStudyAclToJobAcl(StudyAclEntry studyAcl) {
JobAclEntry jobAcl = new JobAclEntry(null, Collections.emptyList());
if (studyAcl == null) {
return jobAcl;
}
jobAcl.setMember(studyAcl.getMember());
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = studyAcl.getPermissions();
EnumSet<JobAclEntry.JobPermissions> jobPermissions = EnumSet.noneOf(JobAclEntry.JobPermissions.class);
for (StudyAclEntry.StudyPermissions studyPermission : studyPermissions) {
JobAclEntry.JobPermissions aux = studyPermission.getJobPermission();
if (aux != null) {
jobPermissions.add(aux);
}
}
jobAcl.setPermissions(jobPermissions);
return jobAcl;
}
private CohortAclEntry transformStudyAclToCohortAcl(StudyAclEntry studyAcl) {
CohortAclEntry cohortAcl = new CohortAclEntry(null, Collections.emptyList());
if (studyAcl == null) {
return cohortAcl;
}
cohortAcl.setMember(studyAcl.getMember());
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = studyAcl.getPermissions();
EnumSet<CohortAclEntry.CohortPermissions> cohortPermissions = EnumSet.noneOf(CohortAclEntry.CohortPermissions.class);
for (StudyAclEntry.StudyPermissions studyPermission : studyPermissions) {
CohortAclEntry.CohortPermissions aux = studyPermission.getCohortPermission();
if (aux != null) {
cohortPermissions.add(aux);
}
}
cohortAcl.setPermissions(cohortPermissions);
return cohortAcl;
}
private DatasetAclEntry transformStudyAclToDatasetAcl(StudyAclEntry studyAcl) {
DatasetAclEntry datasetAcl = new DatasetAclEntry(null, Collections.emptyList());
if (studyAcl == null) {
return datasetAcl;
}
datasetAcl.setMember(studyAcl.getMember());
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = studyAcl.getPermissions();
EnumSet<DatasetAclEntry.DatasetPermissions> datasetPermissions = EnumSet.noneOf(DatasetAclEntry.DatasetPermissions.class);
for (StudyAclEntry.StudyPermissions studyPermission : studyPermissions) {
DatasetAclEntry.DatasetPermissions aux = studyPermission.getDatasetPermission();
if (aux != null) {
datasetPermissions.add(aux);
}
}
datasetAcl.setPermissions(datasetPermissions);
return datasetAcl;
}
private DiseasePanelAclEntry transformStudyAclToDiseasePanelAcl(StudyAclEntry studyAcl) {
DiseasePanelAclEntry panelAcl = new DiseasePanelAclEntry(null, Collections.emptyList());
if (studyAcl == null) {
return panelAcl;
}
panelAcl.setMember(studyAcl.getMember());
EnumSet<StudyAclEntry.StudyPermissions> studyPermissions = studyAcl.getPermissions();
EnumSet<DiseasePanelAclEntry.DiseasePanelPermissions> datasetPermissions =
EnumSet.noneOf(DiseasePanelAclEntry.DiseasePanelPermissions.class);
for (StudyAclEntry.StudyPermissions studyPermission : studyPermissions) {
DiseasePanelAclEntry.DiseasePanelPermissions aux = studyPermission.getDiseasePanelPermission();
if (aux != null) {
datasetPermissions.add(aux);
}
}
panelAcl.setPermissions(datasetPermissions);
return panelAcl;
}
}