AclServiceImpl.java
/*
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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.opencastproject.authorization.xacml.manager.impl;
import org.opencastproject.authorization.xacml.manager.api.AclService;
import org.opencastproject.authorization.xacml.manager.api.AclServiceException;
import org.opencastproject.authorization.xacml.manager.api.ManagedAcl;
import org.opencastproject.elasticsearch.api.SearchIndexException;
import org.opencastproject.elasticsearch.api.SearchResult;
import org.opencastproject.elasticsearch.api.SearchResultItem;
import org.opencastproject.elasticsearch.index.ElasticsearchIndex;
import org.opencastproject.elasticsearch.index.objects.event.Event;
import org.opencastproject.elasticsearch.index.objects.event.EventSearchQuery;
import org.opencastproject.elasticsearch.index.objects.series.Series;
import org.opencastproject.elasticsearch.index.objects.series.SeriesSearchQuery;
import org.opencastproject.security.api.AccessControlList;
import org.opencastproject.security.api.Organization;
import org.opencastproject.security.api.SecurityService;
import org.opencastproject.security.api.User;
import org.opencastproject.util.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
/** Organization bound impl. */
public final class AclServiceImpl implements AclService {
/** Logging utility */
private static final Logger logger = LoggerFactory.getLogger(AclServiceImpl.class);
/** Context */
private final Organization organization;
/** Service dependencies */
private final AclDb aclDb;
private final SecurityService securityService;
/** The Elasticsearch indices */
protected ElasticsearchIndex index;
public AclServiceImpl(Organization organization, AclDb aclDb, ElasticsearchIndex index,
SecurityService securityService) {
this.organization = organization;
this.aclDb = aclDb;
this.index = index;
this.securityService = securityService;
}
@Override
public List<ManagedAcl> getAcls() {
return aclDb.getAcls(organization);
}
@Override
public Optional<ManagedAcl> getAcl(long id) {
return aclDb.getAcl(organization, id);
}
@Override
public boolean updateAcl(ManagedAcl acl) {
Optional<ManagedAcl> oldName = getAcl(acl.getId());
boolean updateAcl = aclDb.updateAcl(acl);
if (updateAcl) {
if (oldName.isPresent() && !(oldName.get().getName().equals(acl.getName()))) {
User user = securityService.getUser();
updateAclInIndex(oldName.get().getName(), acl.getName(), index, organization.getId(), user);
}
}
return updateAcl;
}
@Override
public Optional<ManagedAcl> createAcl(AccessControlList acl, String name) {
// we don't need to update the Elasticsearch indices in this case
return aclDb.createAcl(organization, acl, name);
}
@Override
public boolean deleteAcl(long id) throws AclServiceException, NotFoundException {
Optional<ManagedAcl> deletedAcl = getAcl(id);
if (aclDb.deleteAcl(organization, id)) {
if (deletedAcl.isPresent()) {
User user = securityService.getUser();
removeAclFromIndex(deletedAcl.get().getName(), index, organization.getId(), user);
}
return true;
}
throw new NotFoundException("Managed acl with id " + id + " not found.");
}
/**
* Update the Managed ACL in the events and series in the Elasticsearch index.
*
* @param currentAclName
* the current name of the managed acl
* @param newAclName
* the new name of the managed acl
* @param index
* the index to update
* @param orgId
* the organization the managed acl belongs to
* @param user
* the current user
*/
private void updateAclInIndex(String currentAclName, String newAclName, ElasticsearchIndex index, String orgId,
User user) {
logger.debug("Update the events to change the managed acl name from '{}' to '{}'.", currentAclName, newAclName);
updateManagedAclForEvents(currentAclName, Optional.of(newAclName), index, orgId, user);
logger.debug("Update the series to change the managed acl name from '{}' to '{}'.", currentAclName, newAclName);
updateManagedAclForSeries(currentAclName, Optional.of(newAclName), index, orgId, user);
}
/**
* Remove the Managed ACL from the events and series in the Elasticsearch index.
*
* @param currentAclName
* the current name of the managed acl
* @param index
* the index to update
* @param orgId
* the organization the managed acl belongs to
* @param user
* the current user
*/
private void removeAclFromIndex(String currentAclName, ElasticsearchIndex index, String orgId,
User user) {
logger.debug("Update the events to remove the managed acl name '{}'.", currentAclName);
updateManagedAclForEvents(currentAclName, Optional.empty(), index, orgId, user);
logger.debug("Update the series to remove the managed acl name '{}'.", currentAclName);
updateManagedAclForSeries(currentAclName, Optional.empty(), index, orgId, user);
}
/**
* Update or remove the Managed Acl for the series in the Elasticsearch index.
*
* @param currentAclName
* the current name of the managed acl
* @param newAclNameOpt
* @param index
* the index to update
* @param orgId
* the organization the managed acl belongs to
* @param user
* the current user
*/
private void updateManagedAclForSeries(String currentAclName, Optional<String> newAclNameOpt,
ElasticsearchIndex index, String orgId, User user) {
SearchResult<Series> result;
try {
result = index.getByQuery(new SeriesSearchQuery(orgId, user).withoutActions()
.withManagedAcl(currentAclName));
} catch (SearchIndexException e) {
logger.error("Unable to find the series in org '{}' with current managed acl name '{}'", orgId, currentAclName,
e);
return;
}
for (SearchResultItem<Series> seriesItem : result.getItems()) {
String seriesId = seriesItem.getSource().getIdentifier();
Function<Optional<Series>, Optional<Series>> updateFunction = (Optional<Series> seriesOpt) -> {
if (seriesOpt.isPresent() && seriesOpt.get().getManagedAcl().equals(currentAclName)) {
Series series = seriesOpt.get();
series.setManagedAcl(newAclNameOpt.orElse(null));
return Optional.of(series);
}
return Optional.empty();
};
try {
index.addOrUpdateSeries(seriesId, updateFunction, orgId, user);
} catch (SearchIndexException e) {
if (newAclNameOpt.isPresent()) {
logger.warn("Unable to update series'{}' from current managed acl '{}' to new managed acl name '{}'",
seriesId, currentAclName, newAclNameOpt.get(), e);
} else {
logger.warn("Unable to update series '{}' to remove managed acl '{}'", seriesId, currentAclName, e);
}
}
}
}
/**
* Update or remove the Managed Acl for the events in the Elasticsearch index.
*
* @param currentAclName
* the current name of the managed acl
* @param newAclNameOpt
* @param index
* the index to update
* @param orgId
* the organization the managed acl belongs to
* @param user
* the current user
*/
private void updateManagedAclForEvents(String currentAclName, Optional<String> newAclNameOpt,
ElasticsearchIndex index, String orgId, User user) {
SearchResult<Event> result;
try {
result = index.getByQuery(new EventSearchQuery(orgId, user).withoutActions()
.withManagedAcl(currentAclName));
} catch (SearchIndexException e) {
logger.error("Unable to find the events in org '{}' with current managed acl name '{}' for event",
orgId, currentAclName, e);
return;
}
for (SearchResultItem<Event> eventItem : result.getItems()) {
String eventId = eventItem.getSource().getIdentifier();
Function<Optional<Event>, Optional<Event>> updateFunction = (Optional<Event> eventOpt) -> {
if (eventOpt.isPresent() && eventOpt.get().getManagedAcl().equals(currentAclName)) {
Event event = eventOpt.get();
event.setManagedAcl(newAclNameOpt.orElse(null));
return Optional.of(event);
}
return Optional.empty();
};
try {
index.addOrUpdateEvent(eventId, updateFunction, orgId, user);
} catch (SearchIndexException e) {
if (newAclNameOpt.isPresent()) {
logger.warn(
"Unable to update event '{}' from current managed acl '{}' to new managed acl name '{}'",
eventId, currentAclName, newAclNameOpt.get(), e);
} else {
logger.warn("Unable to update event '{}' to remove managed acl '{}'", eventId, currentAclName, e);
}
}
}
}
}