KmeliaComponentAuthorization.java

/*
 * Copyright (C) 2000 - 2024 Silverpeas
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the
 * GNU Affero General Public License as published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * As a special exception to the terms and conditions of version 3.0 of the GPL, you may
 * redistribute this Program in connection with Free/Libre Open Source Software ("FLOSS")
 * applications as described in Silverpeas's FLOSS exception. You should have received a copy of the
 * text describing the FLOSS exception, and it is also available here:
 * "https://www.silverpeas.org/legal/floss_exception.html"
 *
 * 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
 * Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program.
 * If not, see <https://www.gnu.org/licenses/>.
 */
package org.silverpeas.components.kmelia;

import org.silverpeas.core.contribution.publication.model.PublicationPK;
import org.silverpeas.core.node.model.NodePK;
import org.silverpeas.core.security.authorization.AccessControlContext;
import org.silverpeas.core.security.authorization.AccessControlOperation;
import org.silverpeas.core.security.authorization.ComponentAccessControl;
import org.silverpeas.core.security.authorization.ComponentAuthorization;
import org.silverpeas.core.security.authorization.NodeAccessControl;
import org.silverpeas.core.security.authorization.PublicationAccessControl;
import org.silverpeas.core.util.MapUtil;
import org.silverpeas.core.util.StringUtil;

import javax.inject.Named;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;

import static org.silverpeas.core.util.StringUtil.isDefined;

@Named
public class KmeliaComponentAuthorization implements ComponentAuthorization {

  private static final String PUBLICATION_TYPE = "Publication";
  private static final String NODE_TYPE = "Node";
  private static final String ATTACHMENT_TYPE = "Attachment";
  private static final String VERSION_TYPE = "Version";

  private KmeliaComponentAuthorization() {
    // Instantiated by IoC only.
  }

  @Override
  public boolean isRelatedTo(final String instanceId) {
    return instanceId.startsWith("kmelia");
  }

  @Override
  public <T> Stream<T> filter(final Collection<T> resources,
      final Function<T, ComponentResourceReference> converter, final String userId,
      final AccessControlOperation... operations) {
    final Map<PublicationPK, Set<ComponentResourceReference>> pubPks = new HashMap<>(resources.size());
    final Map<NodePK, Set<ComponentResourceReference>> nodePks = new HashMap<>(resources.size());
    final Map<String, Set<ComponentResourceReference>> instanceIds = new HashMap<>(resources.size());
    final Set<ComponentResourceReference> authorized = new HashSet<>(resources.size());
    resources.forEach(r -> {
      final ComponentResourceReference resourceRef = converter.apply(r);
      final String resourceType = resourceRef.getType();
        if (isHandledKmeliaResourceType(resourceType)) {
          if (StringUtil.isLong(resourceRef.getLocalId())) {
            MapUtil.putAddSet(pubPks,
                new PublicationPK(resourceRef.getLocalId(), resourceRef.getInstanceId()),
                resourceRef);
          }
        } else if (NODE_TYPE.equalsIgnoreCase(resourceType)) {
          MapUtil
              .putAddSet(nodePks, new NodePK(resourceRef.getLocalId(), resourceRef.getInstanceId()),
                  resourceRef);
        } else if (isDefined(resourceRef.getInstanceId())) {
          MapUtil.putAddSet(instanceIds, resourceRef.getInstanceId(), resourceRef);
        } else {
          authorized.add(resourceRef);
        }
    });
    PublicationAccessControl.get().filterAuthorizedByUser(pubPks.keySet(), userId, AccessControlContext
        .init().onOperationsOf(operations))
        .forEach(p -> authorized.addAll(pubPks.get(p)));
    NodeAccessControl.get().filterAuthorizedByUser(nodePks.keySet(), userId, AccessControlContext
        .init().onOperationsOf(operations))
        .forEach(p -> authorized.addAll(nodePks.get(p)));
    ComponentAccessControl.get().filterAuthorizedByUser(instanceIds.keySet(), userId, AccessControlContext
        .init().onOperationsOf(operations))
        .forEach(p -> authorized.addAll(instanceIds.get(p)));
    return resources.stream().filter(r -> authorized.contains(converter.apply(r)));
  }

  private boolean isHandledKmeliaResourceType(String objectType) {
    return objectType != null && (PUBLICATION_TYPE.equalsIgnoreCase(objectType)
        || objectType.startsWith(ATTACHMENT_TYPE) || objectType.startsWith(VERSION_TYPE));
  }
}