001/*
002 *  Copyright 2016 Anyware Services
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 */
016package org.ametys.core.right;
017
018import java.util.Arrays;
019import java.util.Collection;
020import java.util.Comparator;
021import java.util.Map;
022import java.util.Set;
023
024import org.ametys.core.group.GroupIdentity;
025import org.ametys.core.right.RightManager.RightResult;
026import org.ametys.core.user.UserIdentity;
027
028/**
029 * This interface is for computing the rights a user has.
030 */
031public interface AccessController
032{
033    /**
034     * The access result when looking for a right
035     */
036    public enum AccessResult
037    {
038        /* Note: the order of the values are important ! */
039        
040        /** If the user is allowed because the right is allowed for any anonymous user */
041        ANONYMOUS_ALLOWED,
042        /** If the user is directly denied */
043        USER_DENIED,
044        /** If the user is directly allowed */
045        USER_ALLOWED,
046        /** If the user is denied through its groups and not directly */
047        GROUP_DENIED,
048        /** If the user is allowed through its groups and not directly */
049        GROUP_ALLOWED,
050        /** If the user is denied because the right is denied for any connected user */
051        ANY_CONNECTED_DENIED,
052        /** If the user is allowed because the right is allowed for any connected user */
053        ANY_CONNECTED_ALLOWED,
054        /** If the user is denied because the right is denied for any anonymous user */
055        ANONYMOUS_DENIED,
056        /** Cannot determine */
057        UNKNOWN;
058        
059        /**
060         * Convert the value to an access result
061         * @return denied enumerated will be converted to deny, allow to allow and unknown to unknown
062         */
063        public RightResult toRightResult()
064        {
065            switch (this)
066            {
067                case USER_DENIED:
068                case GROUP_DENIED:
069                case ANY_CONNECTED_DENIED:
070                case ANONYMOUS_DENIED:
071                    return RightResult.RIGHT_DENY;
072                case USER_ALLOWED:
073                case GROUP_ALLOWED:
074                case ANY_CONNECTED_ALLOWED:
075                case ANONYMOUS_ALLOWED:
076                    return RightResult.RIGHT_ALLOW;
077                case UNKNOWN:
078                default:
079                    return RightResult.RIGHT_UNKNOWN;
080            }
081        }
082        
083        /**
084         * Merge several access results to keep only the more important
085         * @param accessResults The access results to merge. Cannot be null but can be empty.
086         * @return The more important access result
087         */
088        public static AccessResult merge(Collection<AccessResult> accessResults)
089        {
090            return accessResults.stream().filter(r -> r != null).min(Comparator.naturalOrder()).orElse(AccessResult.UNKNOWN);
091        }
092        
093        /**
094         * Merge several access results to keep only the more important
095         * @param accessResults The access results to merge. Cannot be null but can be empty.
096         * @return The more important access result
097         */
098        public static AccessResult merge(AccessResult... accessResults)
099        {
100            return Arrays.stream(accessResults).filter(r -> r != null).min(Comparator.naturalOrder()).orElse(AccessResult.UNKNOWN);
101        }
102
103    }
104    
105    /**
106     * Gets the kind of access a user has on an object for a given right
107     * @param user The user. Cannot be null.
108     * @param userGroups The groups the user belongs to
109     * @param rightId The id of the right of the user
110     * @param object The context object to check the access
111     * @return the kind of access a user has on an object for a right
112     */
113    public AccessResult getPermission(UserIdentity user, Set<GroupIdentity> userGroups, String rightId, Object object);
114
115    /**
116     * Gets the kind of access a user has on an object for thye read access
117     * @param user The user. Cannot be null.
118     * @param userGroups The groups the user belongs to
119     * @param object The context object to check the access
120     * @return the kind of access a user has on an object for the read access
121     */
122    public AccessResult getReadAccessPermission(UserIdentity user, Set<GroupIdentity> userGroups, Object object);
123
124    /**
125     * Gets the kind of access a user has on an object for all rights
126     * @param user The user. Cannot be null.
127     * @param userGroups The groups the user belongs to
128     * @param object The context object to check the access
129     * @return the kind of access a user has on an object for all rights
130     */
131    public Map<String, AccessResult> getPermissionByRight(UserIdentity user, Set<GroupIdentity> userGroups, Object object);
132    
133    /**
134     * Gets the permission for Anonymous only on an object for a given right
135     * @param rightId The id of the right to check
136     * @param object The object
137     * @return the permission for Anonymous only on an object for a given right
138     */
139    public AccessResult getPermissionForAnonymous(String rightId, Object object);
140    
141    /**
142     * Gets the read access permission for Anonymous only on an object
143     * @param object The object
144     * @return the read access permission for Anonymous only on an object
145     */
146    public AccessResult getReadAccessPermissionForAnonymous(Object object);
147    
148    /**
149     * Gets the permission for any connected user only on an object for a given right
150     * @param rightId The id of the right to check
151     * @param object The object
152     * @return the permission for any connected user only on an object for a given right
153     */
154    public AccessResult getPermissionForAnyConnectedUser(String rightId, Object object);
155
156    /**
157     * Gets the read access permission for any connected user only on an object
158     * @param object The object
159     * @return the read access permission for any connected user only on an object
160     */
161    public AccessResult getReadAccessPermissionForAnyConnectedUser(Object object);
162
163    /**
164     * Gets the permission by user only on an object for the given right. It does not take account of the groups of the user, etc.
165     * @param rightId The id of the right to check
166     * @param object The object
167     * @return the permission by user only on an object for the given right
168     */
169    public Map<UserIdentity, AccessResult> getPermissionByUser(String rightId, Object object);
170
171    /**
172     * Gets the read access permission by user only on an object. It does not take account of the groups of the user, etc.
173     * @param object The object
174     * @return the read access permission by user only on an object
175     */
176    public Map<UserIdentity, AccessResult> getReadAccessPermissionByUser(Object object);
177    
178    /**
179     * Gets the permission by group only on an object for the given right.
180     * @param rightId The id of the right to check
181     * @param object The object
182     * @return the permission by group only on an object for the given right
183     */
184    public Map<GroupIdentity, AccessResult> getPermissionByGroup(String rightId, Object object);
185    
186    /**
187     * Gets the read access permission by group only on an object.
188     * @param object The object
189     * @return the read access permission by group only on an object
190     */
191    public Map<GroupIdentity, AccessResult> getReadAccessPermissionByGroup(Object object);
192    
193    /**
194     * Returns true if the user has a permission on at least one object, directly or though groups, for a given rights and if the object is attached to the given context that is /${WorkspaceName} and its conversions.<br>
195     * @param workspacesContexts The contexts to tests such as {"/${WorkspaceName}", "/repository", "/admin"}
196     * @param user The user
197     * @param userGroups The groups
198     * @param rightId The id of the right to check
199     * @return true if the user has a permission on at least one object, directly or though groups, for a given right
200     */
201    public boolean hasUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups, String rightId);
202    
203    /**
204     * Returns true if the user has a read access permission on at least one object, directly or though groups, for a given rights and if the object is attached to the given context that is /${WorkspaceName} and its conversions.<br>
205     * @param workspacesContexts The contexts to tests such as {"/${WorkspaceName}", "/repository", "/admin"}
206     * @param user The user
207     * @param userGroups The groups
208     * @return true if the user has a permission on at least one object, directly or though groups, for a given right
209     */
210    public boolean hasUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups);
211    
212    /**
213     * Returns true if anonymous has a permission on at least one object, directly or though groups, for a given rights and if the object is attached to the given context that is /${WorkspaceName} and its conversions.<br>
214     * @param workspacesContexts The contexts to tests such as {"/${WorkspaceName}", "/repository", "/admin"}
215     * @param rightId The id of the right to check
216     * @return true if anonymous has a permission on at least one object, directly or though groups, for a given right
217     */
218    public boolean hasAnonymousAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId);
219    
220    /**
221     * Returns true if anonymous has a read access permission on at least one object, directly or though groups, for a given rights and if the object is attached to the given context that is /${WorkspaceName} and its conversions.<br>
222     * @param workspacesContexts The contexts to tests such as {"/${WorkspaceName}", "/repository", "/admin"}
223     * @return true if anonymous has a permission on at least one object, directly or though groups, for a given right
224     */
225    public boolean hasAnonymousAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts);
226    
227    /**
228     * Returns true if any connected user has a permission on at least one object, directly or though groups, for a given rights and if the object is attached to the given context that is /${WorkspaceName} and its conversions.<br>
229     * @param workspacesContexts The contexts to tests such as {"/${WorkspaceName}", "/repository", "/admin"}
230     * @param rightId The id of the right to check
231     * @return true if any connected user has a permission on at least one object, directly or though groups, for a given right
232     */
233    public boolean hasAnyConnectedUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId);
234    
235    /**
236     * Returns true if any connected user has a read access permission on at least one object, directly or though groups, for a given rights and if the object is attached to the given context that is /${WorkspaceName} and its conversions.<br>
237     * @param workspacesContexts The contexts to tests such as {"/${WorkspaceName}", "/repository", "/admin"}
238     * @return true if any connected user has a permission on at least one object, directly or though groups, for a given right
239     */
240    public boolean hasAnyConnectedUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts);
241    
242    /**
243     * Returns true if this access controller supports the given object
244     * @param object The object to test
245     * @return true if this accessc controller supports the given object
246     */
247    public boolean isSupported(Object object);
248}