
org.apache.jackrabbit.api.security.JackrabbitAccessControlManager Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache 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://www.apache.org/licenses/LICENSE-2.0
*
* 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.apache.jackrabbit.api.security;
import javax.jcr.AccessDeniedException;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.PathNotFoundException;
import javax.jcr.security.AccessControlException;
import javax.jcr.security.AccessControlManager;
import javax.jcr.security.AccessControlPolicy;
import javax.jcr.security.Privilege;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.jackrabbit.api.security.authorization.PrivilegeCollection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.osgi.annotation.versioning.ProviderType;
/**
* JackrabbitAccessControlManager
provides extensions to the
* AccessControlManager
interface.
*/
@ProviderType
public interface JackrabbitAccessControlManager extends AccessControlManager {
/**
* Returns the applicable policies for the specified principal
* or an empty array if no additional policies can be applied.
*
* @param principal A principal known to the editing session.
* @return array of policies for the specified principal
. Note
* that the policy object returned must reveal the path of the node where
* they can be applied later on using {@link AccessControlManager#setPolicy(String, javax.jcr.security.AccessControlPolicy)}.
* @throws AccessDeniedException if the session lacks
* MODIFY_ACCESS_CONTROL
privilege.
* @throws AccessControlException if the specified principal does not exist
* or if another access control related exception occurs.
* @throws UnsupportedRepositoryOperationException if editing access control
* policies by principal is not supported.
* @throws RepositoryException if another error occurs.
* @see JackrabbitAccessControlPolicy#getPath()
*/
@NotNull
JackrabbitAccessControlPolicy[] getApplicablePolicies(@NotNull Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException;
/**
* Returns the AccessControlPolicy
objects that have been set
* for the given principal
or an empty array if no policy has
* been set. This method reflects the binding state, including transient
* policy modifications.
*
* @param principal A valid principal.
* @return The policies defined for the given principal or an empty array.
* @throws AccessDeniedException if the session lacks
* READ_ACCESS_CONTROL
privilege.
* @throws AccessControlException if the specified principal does not exist
* or if another access control related exception occurs.
* @throws UnsupportedRepositoryOperationException if editing access control
* policies by principal is not supported.
* @throws RepositoryException If another error occurs.
*/
@NotNull
JackrabbitAccessControlPolicy[] getPolicies(@NotNull Principal principal) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException;
/**
* Returns the AccessControlPolicy
objects that are in effect
* for the given Principal
s. This may be policies set through
* this API or some implementation specific (default) policies.
*
* @param principals A set of valid principals.
* @return The policies defined for the given principal or an empty array.
* @throws AccessDeniedException if the session lacks
* READ_ACCESS_CONTROL
privilege.
* @throws AccessControlException if the specified principal does not exist
* or if another access control related exception occurs.
* @throws UnsupportedRepositoryOperationException if editing access control
* policies by principal is not supported.
* @throws RepositoryException If another error occurs.
*/
@NotNull
AccessControlPolicy[] getEffectivePolicies(@NotNull Set principals) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException;
/**
* Returns the {@code AccessControlPolicy} objects that are in effect
* for the given {@code Principal}s at the specified absolute paths. This may be policies set through
* this API or some implementation specific (default) policies.
*
* Note, that this method will make a best effort approach to reflect the effects of the existing access control setup.
* For backwards compatibility this new method comes with a default implementation that calls {@link #getEffectivePolicies(Set)}
* followed by a best effort approach to determine effect on any of specified paths, which does not take the
* effect of restrictions into account.
*
* @param principals A set of valid principals for which the effective policies should be computed.
* @param absPaths The absolute paths for which the effective policies should be computed. In contrast to
* {@link #getEffectivePolicies(String)} this method does not mandate the paths to point to existing nodes.
* @return The policies defined for the given principal or an empty iterator.
* @throws AccessDeniedException if the session lacks {@code READ_ACCESS_CONTROL} privilege to retrieve the information
* for the given principals or paths.
* @throws AccessControlException if the specified principal does not exist or if another access control related
* exception occurs.
* @throws UnsupportedRepositoryOperationException if editing access control policies by principal or path is not
* supported or if this method is not implemented.
* @throws RepositoryException If another error occurs.
* @since Oak 1.52.0
*/
@NotNull
default Iterator getEffectivePolicies(@NotNull Set principals, @Nullable String... absPaths) throws AccessDeniedException, AccessControlException, UnsupportedRepositoryOperationException, RepositoryException {
return Arrays.stream(getEffectivePolicies(principals)).filter(policy -> {
if (policy instanceof JackrabbitAccessControlPolicy) {
String acPath = ((JackrabbitAccessControlPolicy) policy).getPath();
return Arrays.stream(absPaths).anyMatch(path -> {
if (path == null) {
return acPath == null;
} else {
return acPath != null && (acPath.equals(path) || path.startsWith(acPath+"/"));
}
});
}
// unable to determine path => include it in the result
return true;
}).iterator();
}
/**
* Returns whether the given set of Principal
s has the specified
* privileges for absolute path absPath
, which must be an
* existing node.
*
* Testing an aggregate privilege is equivalent to testing each non
* aggregate privilege among the set returned by calling
* Privilege.getAggregatePrivileges()
for that privilege.
*
* The results reported by the this method reflect the net effect of
* the currently applied control mechanisms. It does not reflect unsaved
* access control policies or unsaved access control entries. Changes to
* access control status caused by these mechanisms only take effect on
* Session.save()
and are only then reflected in the results of
* the privilege test methods.
*
* Since this method allows to view the privileges of principals other
* than included in the editing session, this method must throw
* AccessDeniedException
if the session lacks
* READ_ACCESS_CONTROL
privilege for the absPath
* node.
*
* @param absPath an absolute path.
* @param principals a set of Principal
s for which is the
* given privileges are tested.
* @param privileges an array of Privilege
s.
* @return true
if the session has the specified privileges;
* false
otherwise.
* @throws javax.jcr.PathNotFoundException if no node at absPath
exists
* or the session does not have sufficient access to retrieve a node at that location.
* @throws AccessDeniedException if the session lacks
* READ_ACCESS_CONTROL
privilege for the absPath
node.
* @throws RepositoryException if another error occurs.
*/
boolean hasPrivileges(@Nullable String absPath, @NotNull Set principals, @NotNull Privilege[] privileges)
throws PathNotFoundException, AccessDeniedException, RepositoryException;
/**
* Returns the privileges the given set of Principal
s has for
* absolute path absPath
, which must be an existing node.
*
* The returned privileges are those for which {@link #hasPrivileges} would
* return true
.
*
* The results reported by the this method reflect the net effect of
* the currently applied control mechanisms. It does not reflect unsaved
* access control policies or unsaved access control entries. Changes to
* access control status caused by these mechanisms only take effect on
* Session.save()
and are only then reflected in the results of
* the privilege test methods.
*
* Since this method allows to view the privileges of principals other
* than included in the editing session, this method must throw
* AccessDeniedException
if the session lacks
* READ_ACCESS_CONTROL
privilege for the absPath
* node.
*
* Note that this method does not resolve any group membership, as this is
* the job of the user manager. nor does it augment the set with the
* "everyone" principal.
*
* @param absPath an absolute path.
* @param principals a set of Principal
s for which is the
* privileges are retrieved.
* @return an array of Privilege
s.
* @throws PathNotFoundException if no node at absPath
exists
* or the session does not have sufficient access to retrieve a node at that
* location.
* @throws AccessDeniedException if the session lacks READ_ACCESS_CONTROL
* privilege for the absPath
node.
* @throws RepositoryException if another error occurs.
*/
@NotNull Privilege[] getPrivileges(@Nullable String absPath, @NotNull Set principals)
throws PathNotFoundException, AccessDeniedException, RepositoryException;
/**
* Returns the {@link PrivilegeCollection} for editing session at the given absolute path, which
* must be an existing node. This is equivalent to {@link #getPrivileges(String)} and
* {@link #hasPrivileges(String, Privilege[])} but allows for easy resolution of aggregated privileges
* (like e.g. jcr:all) and repeated evaluation if the editing session has privileges granted
* at the given target node.
*
* Note: For backwards compatibility this method comes with a default implementation that computes the {@link PrivilegeCollection}
* using regular JCR/Jackrabbit API, which might not be efficient. Implementations of {@link JackrabbitAccessControlManager}
* are therefore expected to overwrite the default.
*
* @param absPath An absolute path to an existing JCR node.
* @return A {@link PrivilegeCollection} wrapping around the privileges granted for the editing session at absPath.
* @throws PathNotFoundException if no node at absPath
exists or the session does not have sufficient
* access to retrieve a node at that location.
* @throws RepositoryException If another error occurs.
* @since Oak 1.42.0
*/
@NotNull
default PrivilegeCollection getPrivilegeCollection(@Nullable String absPath) throws RepositoryException {
return new PrivilegeCollection.Default(getPrivileges(absPath), this);
}
/**
* Returns the {@link PrivilegeCollection} for the given set of principals at the given absolute path, which
* must be an existing node. This is equivalent to {@link #getPrivileges(String,Set)} and
* {@link #hasPrivileges(String, Set, Privilege[])} but allows for easy resolution of aggregated privileges
* (like e.g. jcr:all) and repeated evaluation if the editing session has privileges granted
* at the given target node.
*
* Note: For backwards compatibility this method comes with a default implementation that computes the {@link PrivilegeCollection}
* using regular JCR/Jackrabbit API, which might not be efficient. Implementations of {@link JackrabbitAccessControlManager}
* are therefore expected to overwrite the default.
*
* @param absPath An absolute path to an existing JCR node.
* @param principals A set of principals for which the {@link PrivilegeCollection} should be created.
* @return A {@link PrivilegeCollection} wrapping around the privileges granted for the editing session at absPath.
* @throws PathNotFoundException if no node at absPath
exists or the session does not have sufficient
* access to retrieve a node at that location.
* @throws AccessDeniedException if the session lacks READ_ACCESS_CONTROL
privilege for the absPath
node.
* @throws RepositoryException If another error occurs.
* @since Oak 1.42.0
*/
@NotNull
default PrivilegeCollection getPrivilegeCollection(@Nullable String absPath, @NotNull Set principals) throws RepositoryException {
return new PrivilegeCollection.Default(getPrivileges(absPath, principals), this);
}
/**
* Returns the {@link PrivilegeCollection} for the specified privilegeNames
.
* Since the privilege names are JCR names, they may be passed in either
* qualified or expanded form (see specification for details on JCR names).
*
* Note: For backwards compatibility this method comes with a default implementation that computes the {@link PrivilegeCollection}
* using regular JCR/Jackrabbit API, which might not be efficient. Implementations of {@link JackrabbitAccessControlManager}
* are therefore expected to overwrite the default.
*
* @param privilegeNames the names of existing privilege.
* @return the PrivilegeCollection
representing the specified privilegeNames
.
* @throws AccessControlException if no privilege with any of the specified names exists.
* @throws RepositoryException If another error occurs.
* @since Oak 1.42.0
*/
@NotNull
default PrivilegeCollection privilegeCollectionFromNames(@NotNull String... privilegeNames) throws RepositoryException {
List privileges = new ArrayList<>();
for (String privilegeName : privilegeNames) {
privileges.add(privilegeFromName(privilegeName));
}
return new PrivilegeCollection.Default(privileges.toArray(new Privilege[0]), this);
}
}