001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.kernel.impl.services;
019
020import static org.fcrepo.kernel.api.RdfLexicon.FEDORA_WEBAC_ACL_URI;
021import static org.fcrepo.kernel.api.rdf.DefaultRdfStream.fromModel;
022
023import java.util.Optional;
024
025import javax.inject.Inject;
026
027import org.fcrepo.kernel.api.RdfStream;
028import org.fcrepo.kernel.api.Transaction;
029import org.fcrepo.kernel.api.auth.ACLHandle;
030import org.fcrepo.kernel.api.exception.PathNotFoundException;
031import org.fcrepo.kernel.api.exception.PathNotFoundRuntimeException;
032import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
033import org.fcrepo.kernel.api.identifiers.FedoraId;
034import org.fcrepo.kernel.api.models.ResourceFactory;
035import org.fcrepo.kernel.api.models.WebacAcl;
036import org.fcrepo.kernel.api.operations.RdfSourceOperation;
037import org.fcrepo.kernel.api.operations.RdfSourceOperationFactory;
038import org.fcrepo.kernel.api.services.WebacAclService;
039import org.fcrepo.kernel.impl.models.WebacAclImpl;
040import org.fcrepo.persistence.api.PersistentStorageSession;
041import org.fcrepo.persistence.api.PersistentStorageSessionManager;
042import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
043import org.springframework.stereotype.Component;
044
045import org.apache.jena.rdf.model.Model;
046
047import com.github.benmanes.caffeine.cache.Cache;
048
049/**
050 * Implementation of {@link WebacAclService}
051 *
052 * @author dbernstein
053 */
054@Component
055public class WebacAclServiceImpl extends AbstractService implements WebacAclService {
056
057    @Inject
058    private PersistentStorageSessionManager psManager;
059
060    @Inject
061    private ResourceFactory resourceFactory;
062
063    @Inject
064    private RdfSourceOperationFactory rdfSourceOperationFactory;
065
066    @Inject
067    private Cache<String, Optional<ACLHandle>> authHandleCache;
068
069    @Override
070    public WebacAcl find(final Transaction transaction, final FedoraId fedoraId) {
071        try {
072            return resourceFactory.getResource(transaction, fedoraId, WebacAclImpl.class);
073        } catch (final PathNotFoundException exc) {
074            throw new PathNotFoundRuntimeException(exc.getMessage(), exc);
075        }
076    }
077
078    @Override
079    public void create(final Transaction transaction, final FedoraId fedoraId, final String userPrincipal,
080                                 final Model model) {
081        final PersistentStorageSession pSession = this.psManager.getSession(transaction);
082
083        ensureValidACLAuthorization(model);
084
085        final RdfStream stream = fromModel(model.getResource(fedoraId.getFullId()).asNode(), model);
086
087        final RdfSourceOperation createOp = rdfSourceOperationFactory
088                .createBuilder(transaction, fedoraId, FEDORA_WEBAC_ACL_URI,
089                        fedoraPropsConfig.getServerManagedPropsMode())
090                .parentId(fedoraId.asBaseId())
091                .triples(stream)
092                .relaxedProperties(model)
093                .userPrincipal(userPrincipal)
094                .build();
095
096        lockArchivalGroupResourceFromParent(transaction, pSession, fedoraId.asBaseId());
097        transaction.lockResource(fedoraId);
098
099        try {
100            pSession.persist(createOp);
101            recordEvent(transaction, fedoraId, createOp);
102            // Flush ACL cache on any ACL creation/update/deletion.
103            authHandleCache.invalidateAll();
104        } catch (final PersistentStorageException exc) {
105            throw new RepositoryRuntimeException(String.format("failed to create resource %s", fedoraId), exc);
106        }
107    }
108
109}