/** * Copyright (c) Codice Foundation * <p> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. */ package org.codice.ddf.catalog.security.policy.metacard; import static ddf.catalog.Constants.OPERATION_TRANSACTION_KEY; import java.io.Serializable; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddf.catalog.data.Attribute; import ddf.catalog.data.Metacard; import ddf.catalog.data.Result; import ddf.catalog.operation.OperationTransaction; import ddf.catalog.operation.Query; import ddf.catalog.operation.ResourceRequest; import ddf.catalog.operation.ResourceResponse; import ddf.catalog.plugin.PolicyPlugin; import ddf.catalog.plugin.PolicyResponse; import ddf.catalog.plugin.StopProcessingException; import ddf.catalog.plugin.impl.PolicyResponseImpl; import ddf.security.permission.Permissions; /** * Security-based plugin that adds a policy if the point-of-contact field changed on preUpdate. */ public class PointOfContactPolicyPlugin implements PolicyPlugin { private static final String[] PERMISSION_STRING = {"read-only=Cannot update the point-of-contact field"}; private static final Map<String, Set<String>> PERMISSION_MAP = Permissions.parsePermissionsFromString(PERMISSION_STRING); private static final Logger LOGGER = LoggerFactory.getLogger(PointOfContactPolicyPlugin.class); @Override public PolicyResponse processPreCreate(Metacard input, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPreUpdate(Metacard newMetacard, Map<String, Serializable> properties) throws StopProcessingException { //If it's not a resource metacard, don't apply the policy. if (!newMetacard.getTags().isEmpty() && !newMetacard.getTags().contains("resource")) { return new PolicyResponseImpl(); } List<Metacard> previousStateMetacards = ((OperationTransaction) properties.get( OPERATION_TRANSACTION_KEY)).getPreviousStateMetacards(); Metacard previous; try { previous = previousStateMetacards.stream() .filter((x) -> x.getId() .equals(newMetacard.getId())) .findFirst() .get(); } catch (NoSuchElementException e) { LOGGER.debug("Cannot locate metacard {} for update.", newMetacard.getId()); return new PolicyResponseImpl(); } return pointOfContactChanged(newMetacard, previous) ? new PolicyResponseImpl(null, PERMISSION_MAP) : new PolicyResponseImpl(); } private boolean pointOfContactChanged(Metacard newMetacard, Metacard previousMetacard) { Attribute newPointOfContact = newMetacard.getAttribute(Metacard.POINT_OF_CONTACT); Attribute oldPointOfContact = previousMetacard.getAttribute(Metacard.POINT_OF_CONTACT); if (newPointOfContact != null && oldPointOfContact != null) { return !newPointOfContact.getValue() .equals(oldPointOfContact.getValue()); } //Return true if only one of them is null return newPointOfContact != oldPointOfContact; } @Override public PolicyResponse processPreDelete(List<Metacard> metacards, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPostDelete(Metacard input, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPreQuery(Query query, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPostQuery(Result input, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPreResource(ResourceRequest resourceRequest) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPostResource(ResourceResponse resourceResponse, Metacard metacard) throws StopProcessingException { return new PolicyResponseImpl(); } }