001/*
002 * (C) Copyright 2006-2013 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Anahide Tchertchian
018 *     Florent Guillaume
019 */
020
021package org.nuxeo.ecm.core.security;
022
023import java.security.Principal;
024
025import org.nuxeo.ecm.core.api.security.ACP;
026import org.nuxeo.ecm.core.api.security.Access;
027import org.nuxeo.ecm.core.model.Document;
028import org.nuxeo.ecm.core.query.sql.model.SQLQuery.Transformer;
029
030/**
031 * Interface for pluggable core security policy.
032 *
033 * @author Anahide Tchertchian
034 * @author Florent Guillaume
035 */
036public interface SecurityPolicy {
037
038    /**
039     * Checks given permission for doc and principal.
040     * <p>
041     * Note that for the {@code Browse} permission, which is also implemented in SQL using {@link #getQueryTransformer},
042     * a security policy must never bypass standard ACL access, it must only return DENY or UNKNOWN. Failing to do this
043     * would make direct access and queries behave differently.
044     *
045     * @param doc the document to check
046     * @param mergedAcp merged ACP resolved for this document
047     * @param principal principal to check
048     * @param permission permission to check
049     * @param resolvedPermissions permissions or groups of permissions containing permission
050     * @param additionalPrincipals
051     * @return access: GRANT, DENY, or UNKNOWN. When UNKNOWN is returned, following policies or default core security
052     *         are applied.
053     */
054    Access checkPermission(Document doc, ACP mergedAcp, Principal principal, String permission,
055            String[] resolvedPermissions, String[] additionalPrincipals);
056
057    /**
058     * Checks if this policy is restricting the given permission.
059     * <p>
060     * Queries check the BROWSE permission.
061     *
062     * @param permission the permission to check for
063     * @return {@code true} if the policy restricts the permission
064     */
065    boolean isRestrictingPermission(String permission);
066
067    /**
068     * Checks if this policy can be expressed in a query for given repository.
069     * <p>
070     * If not, then any query made will have to be post-filtered.
071     *
072     * @param repositoryName the target repository name.
073     * @return {@code true} if the policy can be expressed in a query
074     */
075    boolean isExpressibleInQuery(String repositoryName);
076
077    /**
078     * Checks if this policy can be expressed in a string-based query for given repository.
079     * <p>
080     * If not, then any query made will have to be post-filtered, if possible, otherwise denied.
081     *
082     * @param repositoryName the target repository name.
083     * @return {@code true} if the policy can be expressed in a string-based query
084     * @since 5.7.2
085     */
086    boolean isExpressibleInQuery(String repositoryName, String queryLanguage);
087
088    /**
089     * Get the transformer to use to apply this policy to a query.
090     * <p>
091     * Called only when {@link #isExpressibleInQuery()} returned {@code true}
092     *
093     * @param repositoryName the target repository name.
094     * @return the transformer
095     */
096    Transformer getQueryTransformer(String repositoryName);
097
098    /**
099     * Get the string-based transformer to use to apply this policy to a query.
100     * <p>
101     * Called only when {@link #isExpressibleInQuery(String, String)} returned {@code true}
102     *
103     * @param repositoryName the target repository name.
104     * @return the transformer
105     * @since 5.7.2
106     */
107    QueryTransformer getQueryTransformer(String repositoryName, String queryLanguage);
108
109    /**
110     * Interface for a class that can transform a string-based query into another. Not used for NXQL.
111     *
112     * @since 5.7.2
113     */
114    interface QueryTransformer {
115
116        /**
117         * Query transformer that does nothing.
118         */
119        QueryTransformer IDENTITY = new IdentityQueryTransformer();
120
121        /**
122         * Transforms a query into another query that has the security policy applied.
123         *
124         * @param principal the principal making the query
125         * @param query the query
126         * @return the query with security policy applied
127         * @since 5.7.2
128         */
129        String transform(Principal principal, String query);
130    }
131
132    /**
133     * Query transformer that does nothing. Use {@link QueryTransformer#IDENTITY} instead of instantiating this class.
134     *
135     * @since 5.7.2
136     */
137    class IdentityQueryTransformer implements QueryTransformer {
138        @Override
139        public String transform(Principal principal, String query) {
140            return query;
141        }
142    }
143
144}