CollectionService.java
package de.dlr.shepard.context.collection.services;
import de.dlr.shepard.auth.permission.io.PermissionsIO;
import de.dlr.shepard.auth.permission.model.Permissions;
import de.dlr.shepard.auth.permission.model.Roles;
import de.dlr.shepard.auth.permission.services.PermissionsService;
import de.dlr.shepard.auth.security.AuthenticationContext;
import de.dlr.shepard.auth.users.services.UserService;
import de.dlr.shepard.common.exceptions.InvalidAuthException;
import de.dlr.shepard.common.exceptions.InvalidPathException;
import de.dlr.shepard.common.exceptions.InvalidRequestException;
import de.dlr.shepard.common.util.AccessType;
import de.dlr.shepard.common.util.Constants;
import de.dlr.shepard.common.util.DateHelper;
import de.dlr.shepard.common.util.PermissionType;
import de.dlr.shepard.common.util.QueryParamHelper;
import de.dlr.shepard.context.collection.daos.CollectionDAO;
import de.dlr.shepard.context.collection.entities.Collection;
import de.dlr.shepard.context.collection.io.CollectionIO;
import de.dlr.shepard.context.version.daos.VersionDAO;
import de.dlr.shepard.context.version.entities.Version;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@RequestScoped
public class CollectionService {
@Inject
CollectionDAO collectionDAO;
@Inject
UserService userService;
@Inject
PermissionsService permissionsService;
@Inject
DateHelper dateHelper;
@Inject
VersionDAO versionDAO;
@Inject
AuthenticationContext authenticationContext;
/**
* Creates a Collection and stores it in Neo4J
*
* @param collection to be stored
* @return the created collection
*/
public Collection createCollection(CollectionIO collection) {
Date date = dateHelper.getDate();
var user = userService.getCurrentUser();
var toCreate = new Collection();
toCreate.setAttributes(collection.getAttributes());
toCreate.setCreatedBy(user);
toCreate.setCreatedAt(date);
toCreate.setDescription(collection.getDescription());
toCreate.setName(collection.getName());
var createdCollection = collectionDAO.createOrUpdate(toCreate);
Version nullVersion = new Version(Constants.HEAD, Constants.HEAD_VERSION, date, user);
Version savedNullVersion = versionDAO.createOrUpdate(nullVersion);
long collectionId = createdCollection.getId();
createdCollection.setShepardId(collectionId);
createdCollection.setVersion(savedNullVersion);
var updated = collectionDAO.createOrUpdate(createdCollection);
permissionsService.createPermissions(updated, user, PermissionType.Private);
return updated;
}
/**
* Searches the database for all Collections
*
* @param params encapsulates possible parameters
* @param username the name of the user
* @return a list of Collections
*/
public List<Collection> getAllCollections(QueryParamHelper params) {
List<Collection> queryResult = collectionDAO.findAllCollectionsByShepardId(
params,
authenticationContext.getCurrentUserName()
);
List<Collection> collections = queryResult.stream().map(this::cutDeleted).toList();
return collections;
}
/**
* Retrieves a collection by shepardId.
* The returned collection is in 'light' format, so dataobjects and incoming references are excluded.
*
* @param shepardId long
* @return Collection
* @throws InvalidPathException if no collection could be found by shepardId
* @throws InvalidAuthException if the user does not have permissions to read the collection
*/
public Collection getCollection(long shepardId) {
return getCollection(shepardId, null, true);
}
/**
* Retrieves a collection by shepardId and versionUID.
* The returned collection is in 'light' format, so dataobjects and incoming references are excluded.
*
* @param shepardId long
* @param versionUID UUID
* @return Collection
* @throws InvalidPathException if no collection (with specified version) could be found by shepardId
* @throws InvalidAuthException if the user does not have permissions to read the collection
*/
public Collection getCollection(long shepardId, UUID versionUID) {
return getCollection(shepardId, versionUID, true);
}
/**
* Fetches a collection including permissions, attributes, contained data objects and incoming references.
* @param shepardId shepardId of the desired collection
* @return Collection
* @throws InvalidPathException if no collection could be found by shepardId
* @throws InvalidAuthException if the user does not have permissions to read the collection
*/
public Collection getCollectionWithDataObjectsAndIncomingReferences(long shepardId) {
return getCollection(shepardId, null, false);
}
/**
* Fetches a collection including permissions, attributes, contained data objects and incoming references.
* @param shepardId shepardId of the desired collection
* @param versionUID ID of the version to retrieve
* @return Collection
* @throws InvalidPathException if no collection could be found by shepardId
* @throws InvalidAuthException if the user does not have permissions to read the collection
*/
public Collection getCollectionWithDataObjectsAndIncomingReferences(long shepardId, UUID versionUID) {
return getCollection(shepardId, versionUID, false);
}
/**
* Return collection by shepard Id or shepard id + versionUId.
*
* @return Collection
* @throws InvalidPathException if no collection could be found by shepardId
* @throws InvalidAuthException if the user does not have permissions to read the collection
*/
private Collection getCollection(long shepardId, UUID versionUID, boolean excludeDataObjectsAndIncomingReferences) {
Collection ret;
String errorMsg;
if (versionUID == null) {
ret = collectionDAO.findByShepardId(shepardId, excludeDataObjectsAndIncomingReferences);
errorMsg = String.format("Collection with id %s is null or deleted", shepardId);
} else {
ret = collectionDAO.findByShepardId(shepardId, versionUID, excludeDataObjectsAndIncomingReferences);
errorMsg = String.format("Collection with id %s and versionUID %s is null or deleted", shepardId, versionUID);
}
if (ret == null || ret.isDeleted()) {
throw new InvalidPathException("ID ERROR - " + errorMsg);
}
assertIsAllowedToReadCollection(shepardId);
cutDeleted(ret);
return ret;
}
/**
* Updates a Collection with new Attributes.
*
* @param shepardId collection's shepardID
* @param collection which contains the new Attributes
* @param username of the related user
* @return updated Collection
* @throws InvalidPathException if no collection could be found by shepardId
* @throws InvalidAuthException if the user does not have permissions to read or edit the collection
*/
public Collection updateCollectionByShepardId(long shepardId, CollectionIO collection) {
Collection old = getCollectionWithDataObjectsAndIncomingReferences(shepardId);
assertIsAllowedToEditCollection(shepardId);
old.setUpdatedBy(userService.getCurrentUser());
old.setUpdatedAt(dateHelper.getDate());
old.setAttributes(collection.getAttributes());
old.setDescription(collection.getDescription());
old.setName(collection.getName());
Collection updated = collectionDAO.createOrUpdate(old);
cutDeleted(updated);
return updated;
}
/**
* Deletes a Collection in Neo4j.
* Before a collection is deleted, a check is run to test if collection exists.
*
* @param shepardId identifies the Collection
* @param username of the related user
* @return a boolean to determine if Collection was successfully deleted
* @throws InvalidPathException if no collection could be found by shepardId
* @throws InvalidAuthException if the user does not have permissions to read or edit the collection
*/
public void deleteCollection(long shepardId) {
getCollection(shepardId);
assertIsAllowedToEditCollection(shepardId);
var date = dateHelper.getDate();
var user = userService.getCurrentUser();
if (!collectionDAO.deleteCollectionByShepardId(shepardId, user, date)) {
throw new InvalidRequestException(String.format("Could not delete Collection with ShepardId %s", shepardId));
}
}
/**
* Gets roles for collection specified by id
*
* @param collectionId
* @return Roles
* @throws InvalidPathException if collection with collectionId does not exist
* @throws InvalidAuthException if user has no read permissions on specified collection
*/
public Roles getCollectionRoles(long collectionId) {
getCollection(collectionId);
// We can use the collectionId as neo4jId here since permissions are global for all versions and shepardId and neo4jId are equal for the head version.
return permissionsService.getUserRolesOnEntity(collectionId, authenticationContext.getCurrentUserName());
}
/**
* Gets Permissions for collection specified by id
*
* @param collectionId
* @return Permissions
* @throws InvalidPathException if collection with collectionId does not exist
* @throws InvalidAuthException if user has no read permissions on specified collection, or is not allowed to manage permissions on collection
*/
public Permissions getCollectionPermissions(long collectionId) {
getCollection(collectionId);
assertIsAllowedToManageCollection(collectionId);
// We can use the collectionId as neo4jId here since permissions are global for all versions and shepardId and neo4jId are equal for the head version.
return permissionsService.getPermissionsOfEntity(collectionId);
}
/**
* Updates Permissions for collection specified by id
*
* @param collectionId
* @return Permissions
* @throws InvalidPathException if collection with collectionId does not exist
* @throws InvalidAuthException if user has no read permissions on specified collection, or is not allowed to manage permissions on collection
*/
public Permissions updateCollectionPermissions(PermissionsIO newPermissions, long collectionId) {
getCollection(collectionId);
assertIsAllowedToManageCollection(collectionId);
// We can use the collectionId as neo4jId here since permissions are global for all versions and shepardId and neo4jId are equal for the head version.
return permissionsService.updatePermissionsByNeo4jId(newPermissions, collectionId);
}
/**
* Checks if the user requested the Collection is allowed to read it
*
* @throws InvalidAuthException when user is not allowed to read the Collection
*/
public void assertIsAllowedToReadCollection(long collectionId) {
if (
!permissionsService.isAccessTypeAllowedForUser(
collectionId,
AccessType.Read,
authenticationContext.getCurrentUserName()
)
) {
throw new InvalidAuthException("The requested action is forbidden by the permission policies");
}
}
/**
* Checks if the user requested the Collection is allowed to edit it
*
* @throws InvalidAuthException when user is not allowed to edit the Collection
*/
public void assertIsAllowedToEditCollection(long collectionId) {
if (
!permissionsService.isAccessTypeAllowedForUser(
collectionId,
AccessType.Write,
authenticationContext.getCurrentUserName()
)
) {
throw new InvalidAuthException("The requested action is forbidden by the permission policies");
}
}
/**
* Checks if the user requested the Collection is allowed to manage it
*
* @throws InvalidAuthException when user is not allowed to manage the Collection
*/
public void assertIsAllowedToManageCollection(long collectionId) {
if (
!permissionsService.isAccessTypeAllowedForUser(
collectionId,
AccessType.Manage,
authenticationContext.getCurrentUserName()
)
) {
throw new InvalidAuthException("The requested action is forbidden by the permission policies");
}
}
private Collection cutDeleted(Collection collection) {
var dataObjects = collection.getDataObjects().stream().filter(d -> !d.isDeleted()).toList();
collection.setDataObjects(dataObjects);
return collection;
}
}