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