LifeCycleServiceImpl.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.lifecyclemanagement.impl;
import static org.opencastproject.security.api.SecurityConstants.GLOBAL_ADMIN_ROLE;
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.EventIndexSchema;
import org.opencastproject.elasticsearch.index.objects.event.EventSearchQuery;
import org.opencastproject.elasticsearch.index.objects.event.EventSearchQueryField;
import org.opencastproject.elasticsearch.index.objects.series.Series;
import org.opencastproject.elasticsearch.index.objects.series.SeriesIndexSchema;
import org.opencastproject.elasticsearch.index.objects.series.SeriesSearchQuery;
import org.opencastproject.index.service.api.IndexService;
import org.opencastproject.index.service.util.RestUtils;
import org.opencastproject.lifecyclemanagement.api.Action;
import org.opencastproject.lifecyclemanagement.api.LifeCycleDatabaseException;
import org.opencastproject.lifecyclemanagement.api.LifeCycleDatabaseService;
import org.opencastproject.lifecyclemanagement.api.LifeCyclePolicy;
import org.opencastproject.lifecyclemanagement.api.LifeCyclePolicyAccessControlEntry;
import org.opencastproject.lifecyclemanagement.api.LifeCycleService;
import org.opencastproject.lifecyclemanagement.api.LifeCycleServiceException;
import org.opencastproject.lifecyclemanagement.api.LifeCycleTask;
import org.opencastproject.lifecyclemanagement.api.StartWorkflowParameters;
import org.opencastproject.lifecyclemanagement.api.Status;
import org.opencastproject.lifecyclemanagement.api.Timing;
import org.opencastproject.metadata.dublincore.EventCatalogUIAdapter;
import org.opencastproject.metadata.dublincore.SeriesCatalogUIAdapter;
import org.opencastproject.security.api.AccessControlEntry;
import org.opencastproject.security.api.AccessControlList;
import org.opencastproject.security.api.AuthorizationService;
import org.opencastproject.security.api.Organization;
import org.opencastproject.security.api.Permissions;
import org.opencastproject.security.api.SecurityService;
import org.opencastproject.security.api.UnauthorizedException;
import org.opencastproject.security.api.User;
import org.opencastproject.util.NotFoundException;
import org.opencastproject.util.data.Tuple;
import org.opencastproject.util.requests.SortCriterion;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Component(
property = {
"service.description=LifeCycle Service",
"service.pid=org.opencastproject.lifecyclemanagement.LifeCycleService"
},
immediate = true,
service = LifeCycleService.class
)
public class LifeCycleServiceImpl implements LifeCycleService {
/** Logging facility */
private static final Logger logger = LoggerFactory.getLogger(LifeCycleServiceImpl.class);
private static final Gson gson = new Gson();
/** Max number of events to fetch at a time in {@link #filterForEvents(Map)} */
private static final int EVENT_QUERY_LIMIT = 1000;
/** Persistent storage */
protected LifeCycleDatabaseService persistence;
/** The security service */
protected SecurityService securityService;
/** The authorization service */
protected AuthorizationService authorizationService = null;
protected ElasticsearchIndex index;
protected IndexService indexService;
@Reference
public void setPersistence(LifeCycleDatabaseService persistence) {
this.persistence = persistence;
}
@Reference
public void setSecurityService(SecurityService securityService) {
this.securityService = securityService;
}
@Reference
public void setAuthorizationService(AuthorizationService authorizationService) {
this.authorizationService = authorizationService;
}
@Reference
public void setElasticSearchIndex(ElasticsearchIndex index) {
this.index = index;
}
@Reference
public void setIndexService(IndexService indexService) {
this.indexService = indexService;
}
@Activate
public void activate(ComponentContext cc) throws Exception {
logger.info("Activating LifeCycle Management Service");
}
/**
* {@inheritDoc}
* @see LifeCycleService#getLifeCyclePolicyById(String)
*/
@Override
public LifeCyclePolicy getLifeCyclePolicyById(String id)
throws NotFoundException, LifeCycleServiceException, UnauthorizedException {
try {
LifeCyclePolicy policy = persistence.getLifeCyclePolicy(id);
if (!checkPermission(policy, Permissions.Action.READ)) {
throw new UnauthorizedException("User does not have read permissions");
}
return policy;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#getLifeCyclePolicyById(String)
*/
@Override
public LifeCyclePolicy getLifeCyclePolicyById(String id, String orgId)
throws NotFoundException, LifeCycleServiceException, UnauthorizedException {
try {
LifeCyclePolicy policy = persistence.getLifeCyclePolicy(id, orgId);
if (!checkPermission(policy, Permissions.Action.READ)) {
throw new UnauthorizedException("User does not have read permissions");
}
return policy;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#getLifeCyclePoliciesTotal()
*/
@Override
public long getLifeCyclePoliciesTotal() throws LifeCycleServiceException {
try {
return persistence.getLifeCyclePoliciesTotal(securityService.getOrganization().getId());
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#getLifeCyclePolicies(int, int, SortCriterion)
*/
@Override
public List<LifeCyclePolicy> getLifeCyclePolicies(int limit, int offset, SortCriterion sortCriterion)
throws LifeCycleServiceException {
try {
List<LifeCyclePolicy> policies = persistence.getLifeCyclePolicies(limit, offset, sortCriterion);
policies.removeIf(policy -> !checkPermission(policy, Permissions.Action.READ));
return policies;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#getActiveLifeCyclePolicies
*/
@Override
public List<LifeCyclePolicy> getActiveLifeCyclePolicies() throws LifeCycleServiceException {
try {
String orgId = securityService.getOrganization().getId();
List<LifeCyclePolicy> policies = persistence.getActiveLifeCyclePolicies(orgId);
policies.removeIf(policy -> !checkPermission(policy, Permissions.Action.READ));
return policies;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#createLifeCyclePolicy(LifeCyclePolicy)
*/
@Override
public LifeCyclePolicy createLifeCyclePolicy(LifeCyclePolicy policy)
throws LifeCycleServiceException, UnauthorizedException {
try {
if (policy.getOrganization() != null) {
policy = persistence.createLifeCyclePolicy(policy, policy.getOrganization());
} else {
policy = persistence.createLifeCyclePolicy(policy, securityService.getOrganization().getId());
}
return policy;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#updateLifeCyclePolicy(LifeCyclePolicy)
*/
@Override
public boolean updateLifeCyclePolicy(LifeCyclePolicy policy)
throws NotFoundException, LifeCycleServiceException, UnauthorizedException, IllegalArgumentException {
LifeCyclePolicy existingPolicy;
try {
existingPolicy = persistence.getLifeCyclePolicy(policy.getId());
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException("Could not get policy from database with id " + policy.getId(), e);
}
if (!checkPermission(existingPolicy, Permissions.Action.WRITE)) {
throw new UnauthorizedException("User does not have write permissions");
}
if (policy.getOrganization() == null) {
policy.setOrganization(securityService.getOrganization().getId());
}
try {
return persistence.updateLifeCyclePolicy(policy, securityService.getOrganization().getId());
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#deleteLifeCyclePolicy(String)
*/
@Override
public boolean deleteLifeCyclePolicy(String id)
throws NotFoundException, LifeCycleServiceException, UnauthorizedException {
try {
LifeCyclePolicy policy = persistence.getLifeCyclePolicy(id);
if (!checkPermission(policy, Permissions.Action.WRITE)) {
throw new UnauthorizedException("User does not have write permissions");
}
return persistence.deleteLifeCyclePolicy(policy, securityService.getOrganization().getId());
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException("Could not delete policy from database with id " + id, e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#deleteLifeCyclePolicy(String)
*/
public void deleteAllLifeCyclePoliciesCreatedByConfig(String orgId)
throws LifeCycleServiceException {
try {
persistence.deleteAllLifeCyclePoliciesCreatedByConfig(orgId);
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException("Could not delete policies created from config from database. ", e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#getLifeCycleTaskById(String)
*/
@Override
public LifeCycleTask getLifeCycleTaskById(String id)
throws NotFoundException, LifeCycleServiceException {
try {
LifeCycleTask task = persistence.getLifeCycleTask(id);
return task;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#getLifeCycleTaskByTargetId(String)
*/
@Override
public LifeCycleTask getLifeCycleTaskByTargetId(String targetId)
throws NotFoundException, LifeCycleServiceException {
try {
LifeCycleTask task = persistence.getLifeCycleTaskByTargetId(targetId);
return task;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#getLifeCycleTasksWithStatus(Status)
*/
@Override
public List<LifeCycleTask> getLifeCycleTasksWithStatus(Status status) throws LifeCycleServiceException {
try {
String orgId = securityService.getOrganization().getId();
List<LifeCycleTask> tasks = persistence.getLifeCycleTasksWithStatus(status, orgId);
return tasks;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#createLifeCycleTask(LifeCycleTask)
*/
@Override
public LifeCycleTask createLifeCycleTask(LifeCycleTask task) throws LifeCycleServiceException {
try {
task = persistence.createLifeCycleTask(task, securityService.getOrganization().getId());
return task;
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#updateLifeCycleTask(LifeCycleTask)
*/
@Override
public boolean updateLifeCycleTask(LifeCycleTask task)
throws NotFoundException, LifeCycleServiceException, IllegalArgumentException {
try {
persistence.getLifeCycleTask(task.getId());
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException("Could not get task from database with id " + task.getId(), e);
}
if (task.getOrganization() == null) {
task.setOrganization(securityService.getOrganization().getId());
}
try {
return persistence.updateLifeCycleTask(task, securityService.getOrganization().getId());
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException(e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#deleteLifeCycleTask(String)
*/
@Override
public boolean deleteLifeCycleTask(String id)
throws NotFoundException, LifeCycleServiceException {
try {
LifeCycleTask task = persistence.getLifeCycleTask(id);
return persistence.deleteLifeCycleTask(task, securityService.getOrganization().getId());
} catch (LifeCycleDatabaseException e) {
throw new LifeCycleServiceException("Could not delete task from database with id " + id, e);
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#checkValidity(LifeCyclePolicy)
*/
public boolean checkValidity(LifeCyclePolicy policy) {
if (policy.getTitle() == null || policy.getTitle().isEmpty()) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. Missing title.");
return false;
}
if (policy.getTargetType() == null) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. Missing target type.");
return false;
}
if (policy.getAction() == null) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. Missing action.");
return false;
}
if (policy.getTiming() == null) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. Missing timing.");
return false;
}
// Check if conditionally required fields are present
if (policy.getTiming() == Timing.SPECIFIC_DATE) {
if (policy.getActionDate() == null) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. A policy with the timing"
+ Timing.SPECIFIC_DATE + " must have an action date.");
return false;
}
}
if (policy.getTiming() == Timing.REPEATING) {
if (policy.getCronTrigger() == null || policy.getCronTrigger().isEmpty()) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. A policy with the timing"
+ Timing.REPEATING + " must have an cron trigger.");
return false;
}
}
// Check if cron string is valid
if (policy.getCronTrigger() != null && !policy.getCronTrigger().isEmpty()) {
if (!org.quartz.CronExpression.isValidExpression(policy.getCronTrigger())) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. Cron trigger "
+ policy.getCronTrigger() + " is not valid.");
return false;
}
}
// Check if action parameters are well formed
try {
if (policy.getAction() == Action.START_WORKFLOW) {
StartWorkflowParameters actionParametersParsed = gson.fromJson(policy.getActionParameters(),
StartWorkflowParameters.class);
if (actionParametersParsed.getWorkflowId() == null) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. Action parameters for the action"
+ Action.START_WORKFLOW + " must include workflowId.");
return false;
}
}
} catch (JsonSyntaxException e) {
logger.warn("LifeCyclePolicy with id " + policy.getId() + " is not valid. Action parameters are not well formed"
+ ".");
return false;
}
if (policy.getAccessControlEntries() == null || policy.getAccessControlEntries().isEmpty()) {
policy.setAccessControlEntries(new ArrayList<>());
}
return true;
}
/**
* {@inheritDoc}
* @see LifeCycleService#filterForEvents(Map, int, int)
*/
public List<Event> filterForEvents(Map<String, Map<String, EventSearchQueryField<String>>> filters, int limit,
int offset)
throws SearchIndexException, NotFoundException {
try {
SearchResult<Event> results = null;
List<Event> eventsList = new ArrayList<>();
final Organization organization = securityService.getOrganization();
final User user = securityService.getUser();
EventSearchQuery query = new EventSearchQuery(organization.getId(), user);
query.sortByUID(SortCriterion.Order.Ascending); // Ensure order
List<EventCatalogUIAdapter> extendedCatalogUIAdapters = indexService.getExtendedEventCatalogUIAdapters();
EventCatalogUIAdapter commonCatalogUIAdapter = indexService.getCommonEventCatalogUIAdapter();
boolean isFilterPresent = false;
// Get filtered series if applicable
List<Series> series = filterForSeries(filters);
if (!series.isEmpty()) {
isFilterPresent = true;
series.forEach(s -> query.withSeriesId(s.getIdentifier()));
}
// Apply limit and offset
query.withOffset(offset);
if (limit > 0) {
query.withLimit(limit);
}
// Add filters to query
for (String flavor: filters.keySet()) {
// Common metadata filter
if (commonCatalogUIAdapter.getFlavor().eq(flavor)) {
addFiltersToQuery(query, filters.get(flavor));
isFilterPresent = true;
continue;
}
// Extended metadata filter
Optional<EventCatalogUIAdapter> extendedOpt = extendedCatalogUIAdapters.stream()
.filter(f -> f.getFlavor().eq(flavor))
.findFirst();
if (!extendedOpt.isPresent()) {
continue;
}
for (String name: filters.get(flavor).keySet()) {
EventSearchQueryField<String> field = filters.get(flavor).get(name);
query.withExtendedMetadata(flavor, name, field.getValue());
isFilterPresent = true;
}
}
// Only query if there actually are applicable filters
if (!isFilterPresent) {
return eventsList;
}
// Run query
results = index.getByQuery(query);
for (SearchResultItem<Event> item : results.getItems()) {
Event source = item.getSource();
eventsList.add(source);
}
return eventsList;
} catch (SearchIndexException e) {
logger.error("The Search Index was not able to get the events list:", e);
throw e;
}
}
/**
* {@inheritDoc}
* @see LifeCycleService#filterForEvents(Map)
*/
public List<Event> filterForEvents(Map<String, Map<String, EventSearchQueryField<String>>> filters)
throws SearchIndexException, NotFoundException {
List<Event> allEvents = new ArrayList<>();
List<Event> page;
int offset = 0;
do {
page = filterForEvents(filters, EVENT_QUERY_LIMIT, offset);
allEvents.addAll(page);
offset += EVENT_QUERY_LIMIT;
} while (page.size() >= EVENT_QUERY_LIMIT);
return allEvents;
}
/**
* Add arguments to a query for the index
* @param query The query the arguments should be added to
* @param filters The arguments that should be added to the query
*/
private void addFiltersToQuery(EventSearchQuery query, Map<String, EventSearchQueryField<String>> filters) {
for (String name : filters.keySet()) {
switch (name) {
case EventIndexSchema.UID -> query.withIdentifier(filters.get(name).getValue());
case EventIndexSchema.TITLE -> query.withTitle(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.DESCRIPTION -> query.withDescription(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.PRESENTER -> query.withPresenter(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.CONTRIBUTOR-> query.withContributor(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.SUBJECT -> query.withSubject(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.LOCATION -> query.withLocation(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case "isPartOf" -> query.withSeriesId(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.SERIES_NAME -> query.withSeriesName(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.LANGUAGE -> query.withLanguage(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.SOURCE -> query.withSource(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.CREATED -> query.withCreated(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.CREATOR -> query.withCreator(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.PUBLISHER -> query.withPublisher(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.LICENSE -> query.withLicense(
filters.get(name).getValue(), filters.get(name).getType(), filters.get(name).isMust());
case EventIndexSchema.RIGHTS -> query.withRights(filters.get(name).getValue());
case EventIndexSchema.START_DATE -> query.withStartDate(
filters.get(name).getValue(), filters.get(name).getType());
case "start_date_range" -> {
Tuple<Date, Date> fromAndToCreationRange = RestUtils.getFromAndToDateRange(filters.get(name).getValue());
query.withStartFrom(fromAndToCreationRange.getA());
query.withStartTo(fromAndToCreationRange.getB());
}
case "start_date_relative" -> {
Period period = Period.parse(filters.get(name).getValue());
LocalDateTime now = LocalDateTime.now();
LocalDateTime relative = now.plus(period);
query.withStartDate(relative.atZone(ZoneId.systemDefault()).toInstant().toString(),
filters.get(name).getType());
}
case EventIndexSchema.END_DATE -> query.withEndDate(
filters.get(name).getValue(), filters.get(name).getType());
default -> logger.warn("Filter " + name + " is not supported");
}
}
}
private List<Series> filterForSeries(Map<String, Map<String, EventSearchQueryField<String>>> filters)
throws SearchIndexException, NotFoundException {
List<Series> seriesList = new ArrayList<>();
final Organization organization = securityService.getOrganization();
final User user = securityService.getUser();
SeriesSearchQuery query = new SeriesSearchQuery(organization.getId(), user);
List<SeriesCatalogUIAdapter> extendedCatalogUIAdapters = indexService.getExtendedSeriesCatalogUIAdapters();
SeriesCatalogUIAdapter commonCatalogUIAdapter = indexService.getCommonSeriesCatalogUIAdapter();
boolean isFilterPresent = false;
// Add filters to query
for (String flavor: filters.keySet()) {
// Common metadata filter
if (commonCatalogUIAdapter.getFlavor().eq(flavor)) {
addFiltersToSeriesQuery(query, filters.get(flavor));
isFilterPresent = true;
continue;
}
// Extended metadata filter
Optional<SeriesCatalogUIAdapter> extendedOpt = extendedCatalogUIAdapters.stream()
.filter(f -> f.getFlavor().eq(flavor))
.findFirst();
if (!extendedOpt.isPresent()) {
continue;
}
for (String name: filters.get(flavor).keySet()) {
EventSearchQueryField<String> field = filters.get(flavor).get(name);
String type = flavor.split("/")[0];
query.withExtendedMetadata(type, name, field.getValue());
isFilterPresent = true;
}
}
// Only query if there actually are applicable filters
if (!isFilterPresent) {
return seriesList;
}
// Run query
SearchResult<Series> results = index.getByQuery(query);
for (SearchResultItem<Series> item : results.getItems()) {
Series source = item.getSource();
seriesList.add(source);
}
return seriesList;
}
private void addFiltersToSeriesQuery(SeriesSearchQuery query, Map<String, EventSearchQueryField<String>> filters) {
for (String name : filters.keySet()) {
switch (name) {
case SeriesIndexSchema.UID -> query.withIdentifier(filters.get(name).getValue());
case SeriesIndexSchema.TITLE -> query.withTitle(filters.get(name).getValue());
case SeriesIndexSchema.DESCRIPTION -> query.withDescription(filters.get(name).getValue());
case SeriesIndexSchema.SUBJECT -> query.withSubject(filters.get(name).getValue());
case SeriesIndexSchema.LANGUAGE -> query.withLanguage(filters.get(name).getValue());
case SeriesIndexSchema.CREATOR -> query.withCreator(filters.get(name).getValue());
case SeriesIndexSchema.LICENSE -> query.withLicense(filters.get(name).getValue());
case SeriesIndexSchema.ORGANIZERS -> query.withOrganizer(filters.get(name).getValue());
case SeriesIndexSchema.CONTRIBUTORS -> query.withContributor(filters.get(name).getValue());
case SeriesIndexSchema.PUBLISHERS -> query.withPublisher(filters.get(name).getValue());
case SeriesIndexSchema.RIGHTS_HOLDER -> query.withRightsHolder(filters.get(name).getValue());
default -> logger.warn("Filter " + name + " is not supported");
}
}
}
/**
* Runs a permission check on the given policy for the given action
* @param policy {@link LifeCyclePolicy} to check permission for
* @param action Action to check permission for
* @return True if action is permitted on the {@link LifeCyclePolicy}, else false
*/
private boolean checkPermission(LifeCyclePolicy policy, Permissions.Action action) {
User currentUser = securityService.getUser();
Organization currentOrg = securityService.getOrganization();
String currentOrgAdminRole = currentOrg.getAdminRole();
String currentOrgId = currentOrg.getId();
// Restrict permission to admins until to do is fixed
// TODO: Figure out better permission management
// Allowing non-admins to create policies would allow them to affect entities that they may not have
// write rights on. That is not okay.
return currentUser.hasRole(GLOBAL_ADMIN_ROLE)
|| (currentUser.hasRole(currentOrgAdminRole) && currentOrgId.equals(policy.getOrganization()));
// return currentUser.hasRole(GLOBAL_ADMIN_ROLE)
// || (currentUser.hasRole(currentOrgAdminRole) && currentOrgId.equals(policy.getOrganization()))
// || authorizationService.hasPermission(getAccessControlList(policy), action.toString())
// && currentOrgId.equals(policy.getOrganization());
}
/**
* Parse the access information for a policy from its database format into an {@link AccessControlList}
* @param policy The {@link LifeCyclePolicy} to get the {@link AccessControlList} for
* @return The {@link AccessControlList} for the given {@link LifeCyclePolicy}
*/
private AccessControlList getAccessControlList(LifeCyclePolicy policy) {
List<AccessControlEntry> accessControlEntries = new ArrayList<>();
for (LifeCyclePolicyAccessControlEntry entry : policy.getAccessControlEntries()) {
accessControlEntries.add(entry.toAccessControlEntry());
}
return new AccessControlList(accessControlEntries);
}
}