This is an automated email from the ASF dual-hosted git repository. dyankiv pushed a commit to branch DATALAB-2995 in repository https://gitbox.apache.org/repos/asf/incubator-datalab.git
commit 2b4480cd29e3d2b054b3ccfa534be30c0046123e Author: Denys Yankiv <[email protected]> AuthorDate: Wed Sep 7 12:55:17 2022 +0300 move image sharing to images collection --- .../main/java/com/epam/datalab/dto/SharedWith.java | 15 +++++ .../com/epam/datalab/model/exploratory/Image.java | 2 + .../backendapi/dao/ImageExploratoryDAO.java | 3 + .../backendapi/dao/ImageExploratoryDAOImpl.java | 10 +++ .../backendapi/resources/dto/ImageInfoRecord.java | 2 + .../resources/dto/ImageProjectGroupsShareDTO.java | 2 + .../service/impl/ImageExploratoryServiceImpl.java | 72 ++++++---------------- 7 files changed, 52 insertions(+), 54 deletions(-) diff --git a/services/datalab-model/src/main/java/com/epam/datalab/dto/SharedWith.java b/services/datalab-model/src/main/java/com/epam/datalab/dto/SharedWith.java new file mode 100644 index 000000000..c9d4da861 --- /dev/null +++ b/services/datalab-model/src/main/java/com/epam/datalab/dto/SharedWith.java @@ -0,0 +1,15 @@ +package com.epam.datalab.dto; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.HashSet; +import java.util.Set; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class SharedWith { + private Set<String> users=new HashSet<>(); + private Set<String> groups=new HashSet<>(); +} diff --git a/services/datalab-model/src/main/java/com/epam/datalab/model/exploratory/Image.java b/services/datalab-model/src/main/java/com/epam/datalab/model/exploratory/Image.java index ba338d92c..3fd928b37 100644 --- a/services/datalab-model/src/main/java/com/epam/datalab/model/exploratory/Image.java +++ b/services/datalab-model/src/main/java/com/epam/datalab/model/exploratory/Image.java @@ -19,6 +19,7 @@ package com.epam.datalab.model.exploratory; +import com.epam.datalab.dto.SharedWith; import com.epam.datalab.dto.aws.computational.ClusterConfig; import com.epam.datalab.dto.exploratory.ImageStatus; import com.epam.datalab.model.library.Library; @@ -45,6 +46,7 @@ public class Image { private final String instanceName; private final String cloudProvider; private final String dockerImage; + private final SharedWith sharedWith; private final List<ClusterConfig> clusterConfig; private final List<Library> libraries; private final Map<String, List<Library>> computationalLibraries; diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAO.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAO.java index 65ab9755a..94f6e3202 100644 --- a/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAO.java +++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAO.java @@ -20,6 +20,7 @@ package com.epam.datalab.backendapi.dao; import com.epam.datalab.backendapi.resources.dto.ImageInfoRecord; +import com.epam.datalab.dto.SharedWith; import com.epam.datalab.dto.exploratory.ImageStatus; import com.epam.datalab.dto.exploratory.LibStatus; import com.epam.datalab.model.exploratory.Image; @@ -51,4 +52,6 @@ public interface ImageExploratoryDAO { Optional<ImageInfoRecord> getImage(String user, String name, String project, String endpoint); List<Library> getLibraries(String imageName, String project, String endpoint, LibStatus status); + + void updateSharing(SharedWith sharedWith, String imageName, String project, String endpoint); } diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAOImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAOImpl.java index 688a02f17..a48b6a4b5 100644 --- a/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAOImpl.java +++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/dao/ImageExploratoryDAOImpl.java @@ -20,6 +20,7 @@ package com.epam.datalab.backendapi.dao; import com.epam.datalab.backendapi.resources.dto.ImageInfoRecord; +import com.epam.datalab.dto.SharedWith; import com.epam.datalab.dto.exploratory.ImageStatus; import com.epam.datalab.dto.exploratory.LibStatus; import com.epam.datalab.model.exploratory.Image; @@ -35,6 +36,7 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; +import static com.epam.datalab.backendapi.dao.ExploratoryDAO.COMPUTATIONAL_RESOURCES; import static com.mongodb.client.model.Filters.and; import static com.mongodb.client.model.Filters.eq; import static com.mongodb.client.model.Filters.in; @@ -42,6 +44,7 @@ import static com.mongodb.client.model.Projections.elemMatch; import static com.mongodb.client.model.Projections.excludeId; import static com.mongodb.client.model.Projections.fields; import static com.mongodb.client.model.Projections.include; +import static com.mongodb.client.model.Updates.push; import static com.mongodb.client.model.Updates.set; @Singleton @@ -56,6 +59,8 @@ public class ImageExploratoryDAOImpl extends BaseDAO implements ImageExploratory private static final String PROJECT = "project"; private static final String ENDPOINT = "endpoint"; + private static final String SHARED_WITH = "sharedWith"; + @Override public boolean exist(String image, String project) { return findOne(MongoCollections.IMAGES, imageProjectCondition(image, project)).isPresent(); @@ -131,6 +136,11 @@ public class ImageExploratoryDAOImpl extends BaseDAO implements ImageExploratory .collect(Collectors.toList()); } + @Override + public void updateSharing(SharedWith sharedWith, String imageName, String project, String endpoint) { + updateOne(MongoCollections.IMAGES, and(eq(IMAGE_NAME,imageName),eq(PROJECT,project),eq(ENDPOINT,endpoint)), set(SHARED_WITH, convertToBson(sharedWith))); + } + private Optional<Document> libDocument(String imageName, String project, String endpoint, LibStatus status) { return findOne(MongoCollections.IMAGES, diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageInfoRecord.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageInfoRecord.java index 4b9786194..ca51fe771 100644 --- a/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageInfoRecord.java +++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageInfoRecord.java @@ -20,6 +20,7 @@ package com.epam.datalab.backendapi.resources.dto; import com.epam.datalab.cloud.CloudProvider; +import com.epam.datalab.dto.SharedWith; import com.epam.datalab.dto.aws.computational.ClusterConfig; import com.epam.datalab.dto.exploratory.ImageSharingStatus; import com.epam.datalab.dto.exploratory.ImageStatus; @@ -49,6 +50,7 @@ public class ImageInfoRecord { private final ImageStatus status; private ImageSharingStatus sharingStatus; private ImageUserPermissions imageUserPermissions; + private final SharedWith sharedWith; private final List<ClusterConfig> clusterConfig; private final String exploratoryURL; private final List<Library> libraries; diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageProjectGroupsShareDTO.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageProjectGroupsShareDTO.java index 17613954c..b1e682ab5 100644 --- a/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageProjectGroupsShareDTO.java +++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/resources/dto/ImageProjectGroupsShareDTO.java @@ -19,6 +19,7 @@ package com.epam.datalab.backendapi.resources.dto; +import com.epam.datalab.dto.SharedWith; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; @@ -28,4 +29,5 @@ public class ImageProjectGroupsShareDTO { private final String imageName; private final String projectName; private final String endpoint; + private final SharedWith sharedWith; } diff --git a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ImageExploratoryServiceImpl.java b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ImageExploratoryServiceImpl.java index fe0af1fb4..302a555aa 100644 --- a/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ImageExploratoryServiceImpl.java +++ b/services/self-service/src/main/java/com/epam/datalab/backendapi/service/impl/ImageExploratoryServiceImpl.java @@ -36,6 +36,7 @@ import com.epam.datalab.backendapi.service.ImageExploratoryService; import com.epam.datalab.backendapi.service.ProjectService; import com.epam.datalab.backendapi.util.RequestBuilder; import com.epam.datalab.constants.ServiceConsts; +import com.epam.datalab.dto.SharedWith; import com.epam.datalab.dto.UserInstanceDTO; import com.epam.datalab.dto.UserInstanceStatus; import com.epam.datalab.dto.exploratory.ExploratoryStatusDTO; @@ -72,14 +73,7 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService { private static final String SHARE_OWN_IMAGES_PAGE = "/api/image/share"; private static final String TERMINATE_OWN_IMAGES_PAGE = "/api/image/terminate"; private static final String SHARE_RECEIVED_IMAGES_PAGE = "/api/image/shareReceived"; - private static final String IMAGE_ROLE = "img_%s_%s_%s_%s"; - private static final String IMAGE_ROLE_DESCRIPTION = "Create Notebook from image %s"; - - /** - * projectName-endpointName-exploratoryName-imageName - */ - private static final String IMAGE_MONIKER = "%s_%s_%s_%s"; @Inject private ExploratoryDAO exploratoryDAO; @Inject @@ -121,6 +115,7 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService { .description(imageDescription) .status(ImageStatus.CREATING) .user(user.getName()) + .sharedWith(new SharedWith()) .libraries(fetchExploratoryLibs(libraries)) .computationalLibraries(fetchComputationalLibs(libraries)) .clusterConfig(userInstance.getClusterConfig()) @@ -180,8 +175,6 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService { imageExploratoryDao.updateImageFields(image); log.debug("Image {}", image); - // Create image roles - createImageRole(image, exploratoryName); if (newNotebookIp != null) { log.debug("Changing exploratory ip with name {} for user {} to {}", exploratoryName, image.getUser(), @@ -290,13 +283,18 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService { public void shareImageWithProjectGroups(UserInfo user, String imageName, String projectName, String endpoint) { Set<String> projectGroups = projectService.get(projectName).getGroups(); Optional<ImageInfoRecord> image = imageExploratoryDao.getImage(user.getName(),imageName,projectName,endpoint); - if(image.isPresent()){ - String exploratoryName = image.get().getInstanceName(); - userRoleDAO.addGroupToRole(projectGroups, - Collections.singleton(String.format(IMAGE_ROLE, - projectName, endpoint, exploratoryName ,imageName))); - } + image.ifPresent(img -> { + log.info("image {}", img); + SharedWith sharedWith = img.getSharedWith(); + sharedWith.getGroups().addAll(projectGroups); + imageExploratoryDao.updateSharing(sharedWith, img.getName() ,img.getProject(), img.getEndpoint()); + }); + } + public boolean hasAccess(String userName, SharedWith sharedWith){ + boolean accessByUserName = sharedWith.getUsers().contains(userName); + boolean accessByGroup = sharedWith.getGroups().stream().anyMatch(groupName -> userGroupDAO.getUsers(groupName).contains(userName)); + return accessByUserName || accessByGroup; } private Map<String, List<Library>> fetchComputationalLibs(List<Library> libraries) { @@ -323,10 +321,7 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService { public List<ImageInfoRecord> getSharedImages(UserInfo userInfo) { List<ImageInfoRecord> sharedImages = imageExploratoryDao.getAllImages().stream() .filter(img -> !img.getUser().equals(userInfo.getName())) - .filter(img -> - UserRoles.checkAccess(userInfo, RoleType.IMAGE, - String.format(IMAGE_MONIKER, img.getProject(), img.getEndpoint(), img.getInstanceName(), img.getName()), - userInfo.getRoles())) + .filter(img -> hasAccess(userInfo.getName(),img.getSharedWith())) .collect(Collectors.toList()); sharedImages.forEach(img -> img.setSharingStatus(getImageSharingStatus(userInfo.getName(),img))); log.info("Shared with user {} images : {}", userInfo.getName(), sharedImages); @@ -338,9 +333,7 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService { .filter(img -> img.getStatus().equals(ImageStatus.ACTIVE)) .filter(img -> !img.getUser().equals(userInfo.getName())) .filter(img -> img.getDockerImage().equals(dockerImage) && img.getProject().equals(project) && img.getEndpoint().equals(endpoint)) - .filter(img -> UserRoles.checkAccess(userInfo, RoleType.IMAGE, - String.format(IMAGE_MONIKER, img.getProject(), img.getEndpoint(), img.getInstanceName(), img.getName()), - userInfo.getRoles())) + .filter(img -> hasAccess(userInfo.getName(),img.getSharedWith())) .collect(Collectors.toList()); sharedImages.forEach(img -> img.setSharingStatus(getImageSharingStatus(userInfo.getName(),img))); log.info("Found shared with user {} images {}", userInfo.getName(), sharedImages); @@ -366,44 +359,15 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService { } private ImageSharingStatus getImageSharingStatus(String username, ImageInfoRecord image){ - String anyUser = "$anyuser"; - UserRoleDTO role = getImageRole(image); - if (role==null){ + boolean notShared = image.getSharedWith().getUsers().isEmpty() && image.getSharedWith().getGroups().isEmpty(); + if(notShared && image.getUser().equals(username)){ return ImageSharingStatus.PRIVATE; - } - boolean roleHasGroups = (role.getGroups().contains(anyUser) && role.getGroups().size() >= 2) - || (!role.getGroups().contains(anyUser) && !role.getGroups().isEmpty()); - if(!roleHasGroups && image.getUser().equals(username)){ - return ImageSharingStatus.PRIVATE; - } else if (roleHasGroups && image.getUser().equals(username)){ + } else if (!notShared && image.getUser().equals(username)){ return ImageSharingStatus.SHARED; } return ImageSharingStatus.RECEIVED ; } - private UserRoleDTO getImageRole(ImageInfoRecord image){ - String imageId = String.format(IMAGE_ROLE, - image.getProject(), image.getEndpoint(), image.getInstanceName(),image.getName()); - return userRoleDAO.findById(imageId); - } - - private String getImageMoniker(String project, String endpoint, String exploratoryName, String imageName){ - return String.format(IMAGE_MONIKER, project, endpoint, exploratoryName, imageName); - } - - private void createImageRole(Image image, String exploratoryName){ - if (image.getStatus().equals(ImageStatus.ACTIVE)){ - UserRoleDTO role = new UserRoleDTO(); - role.setId(String.format(IMAGE_ROLE, image.getProject(), image.getEndpoint(), exploratoryName ,image.getName())); - role.setDescription(String.format(IMAGE_ROLE_DESCRIPTION, getImageMoniker(image.getProject(), image.getEndpoint(), exploratoryName, image.getName()).replaceAll("_","-"))); - role.setCloud(endpointService.get(image.getEndpoint()).getCloudProvider()); - role.setImages(new HashSet<>(Collections.singletonList(getImageMoniker(image.getProject(), image.getEndpoint(), exploratoryName, image.getName())))); - role.setType(UserRoleDTO.Type.NOTEBOOK); - role.setGroups(Collections.emptySet()); - userRoleDAO.insert(role); - } - } - private List<ImageInfoRecord> filterImages(List<ImageInfoRecord> images, ImageFilter filter){ return images.stream() .filter(img -> img.getName().toLowerCase().contains(filter.getImageName().toLowerCase())) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
