use of org.graylog.security.GrantDTO in project graylog2-server by Graylog2.
the class EntitySharesService method updateEntityShares.
/**
* Share / unshare an entity with one or more grantees.
* The grants in the request are created or, if they already exist, updated.
*
* @param ownedEntity the target entity for the updated grants
* @param request the request containing grantees and their capabilities
* @param sharingUser the user executing the request
*/
public EntityShareResponse updateEntityShares(GRN ownedEntity, EntityShareRequest request, User sharingUser) {
requireNonNull(ownedEntity, "ownedEntity cannot be null");
requireNonNull(request, "request cannot be null");
requireNonNull(sharingUser, "sharingUser cannot be null");
final ImmutableMap<GRN, Capability> selectedGranteeCapabilities = request.selectedGranteeCapabilities().orElse(ImmutableMap.of());
final String userName = sharingUser.getName();
final GRN sharingUserGRN = grnRegistry.ofUser(sharingUser);
final Set<Grantee> availableGrantees = granteeService.getAvailableGrantees(sharingUser);
final Set<GRN> availableGranteeGRNs = availableGrantees.stream().map(Grantee::grn).collect(Collectors.toSet());
final List<GrantDTO> existingGrants = grantService.getForTargetExcludingGrantee(ownedEntity, sharingUserGRN);
existingGrants.removeIf(grant -> !availableGranteeGRNs.contains(grant.grantee()));
final EntityShareResponse.Builder responseBuilder = EntityShareResponse.builder().entity(ownedEntity.toString()).sharingUser(sharingUserGRN).availableGrantees(availableGrantees).availableCapabilities(getAvailableCapabilities()).missingPermissionsOnDependencies(checkMissingPermissionsOnDependencies(ownedEntity, sharingUserGRN, ImmutableSet.of(), request));
final EntitySharesUpdateEvent.Builder updateEventBuilder = EntitySharesUpdateEvent.builder().user(sharingUser).entity(ownedEntity);
// Abort if validation fails, but try to return a complete EntityShareResponse
final ValidationResult validationResult = validateRequest(ownedEntity, request, sharingUser, availableGranteeGRNs);
if (validationResult.failed()) {
final ImmutableSet<ActiveShare> activeShares = getActiveShares(ownedEntity, sharingUser, availableGranteeGRNs);
return responseBuilder.activeShares(activeShares).selectedGranteeCapabilities(getSelectedGranteeCapabilities(activeShares, request)).validationResult(validationResult).build();
}
// Update capabilities of existing grants (for a grantee)
existingGrants.stream().filter(grantDTO -> request.grantees().contains(grantDTO.grantee())).forEach((g -> {
final Capability newCapability = selectedGranteeCapabilities.get(g.grantee());
if (!g.capability().equals(newCapability)) {
grantService.save(g.toBuilder().capability(newCapability).updatedBy(userName).updatedAt(ZonedDateTime.now(ZoneOffset.UTC)).build());
updateEventBuilder.addUpdates(g.grantee(), newCapability, g.capability());
}
}));
// Create newly added grants
// TODO Create multiple entries with one db query
selectedGranteeCapabilities.forEach((grantee, capability) -> {
if (existingGrants.stream().noneMatch(eg -> eg.grantee().equals(grantee))) {
grantService.create(GrantDTO.builder().grantee(grantee).capability(capability).target(ownedEntity).build(), sharingUser);
updateEventBuilder.addCreates(grantee, capability);
}
});
// remove grants that are not present anymore
// TODO delete multiple entries with one db query
existingGrants.forEach((g) -> {
if (!selectedGranteeCapabilities.containsKey(g.grantee())) {
grantService.delete(g.id());
updateEventBuilder.addDeletes(g.grantee(), g.capability());
}
});
postUpdateEvent(updateEventBuilder.build());
final ImmutableSet<ActiveShare> activeShares = getActiveShares(ownedEntity, sharingUser, availableGranteeGRNs);
return responseBuilder.activeShares(activeShares).selectedGranteeCapabilities(getSelectedGranteeCapabilities(activeShares, request)).build();
}
use of org.graylog.security.GrantDTO in project graylog2-server by Graylog2.
the class EntitySharesService method validateRequest.
private ValidationResult validateRequest(GRN ownedEntity, EntityShareRequest request, User sharingUser, Set<GRN> availableGranteeGRNs) {
final ValidationResult validationResult = new ValidationResult();
final List<GrantDTO> allEntityGrants = grantService.getForTarget(ownedEntity);
final List<GrantDTO> existingGrants = grantService.getForTargetExcludingGrantee(ownedEntity, grnRegistry.ofUser(sharingUser));
// The initial request doesn't submit a grantee selection. Just return.
if (!request.selectedGranteeCapabilities().isPresent()) {
return validationResult;
}
final ImmutableMap<GRN, Capability> selectedGranteeCapabilities = request.selectedGranteeCapabilities().get();
// If there is still an owner in the selection, everything is fine
if (selectedGranteeCapabilities.containsValue(Capability.OWN)) {
return validationResult;
}
// If this entity is already ownerless, things can't get any worse. Let this request pass.
if (allEntityGrants.stream().noneMatch(g -> g.capability().equals(Capability.OWN))) {
return validationResult;
}
// Iterate over all existing owner grants and find modifications
ArrayList<GRN> removedOwners = new ArrayList<>();
existingGrants.stream().filter(g -> g.capability().equals(Capability.OWN)).forEach((g) -> {
// owner got removed
if (!selectedGranteeCapabilities.containsKey(g.grantee())) {
// Ignore owners that were invisible to the requesting user
if (availableGranteeGRNs.contains(g.grantee())) {
removedOwners.add(g.grantee());
}
// owner capability got changed
} else if (!selectedGranteeCapabilities.get(g.grantee()).equals(Capability.OWN)) {
removedOwners.add(g.grantee());
}
});
// If all removedOwners are applied, is there still at least one owner left?
if (allEntityGrants.stream().filter(g -> g.capability().equals(Capability.OWN)).map(GrantDTO::grantee).anyMatch(grantee -> !removedOwners.contains(grantee))) {
return validationResult;
}
validationResult.addError(EntityShareRequest.SELECTED_GRANTEE_CAPABILITIES, String.format(Locale.US, "Removing the following owners <%s> will leave the entity ownerless.", removedOwners));
// Also return the grantees as list to be used by the frontend
validationResult.addContext(EntityShareRequest.SELECTED_GRANTEE_CAPABILITIES, removedOwners.stream().map(Objects::toString).collect(Collectors.toSet()));
return validationResult;
}
Aggregations