001/*
002 *  Copyright 2022 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.plugins.queriesdirectory.accesscontroller;
017
018import java.util.Collection;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Set;
023
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027import org.apache.commons.collections.MapUtils;
028
029import org.ametys.core.group.GroupIdentity;
030import org.ametys.core.right.AccessController;
031import org.ametys.core.right.AccessExplanation;
032import org.ametys.core.right.RightsException;
033import org.ametys.core.user.UserIdentity;
034import org.ametys.plugins.core.impl.right.AbstractRightBasedAccessController;
035import org.ametys.plugins.queriesdirectory.Query;
036import org.ametys.plugins.queriesdirectory.QueryDAO;
037import org.ametys.plugins.queriesdirectory.QueryFactory;
038import org.ametys.plugins.repository.AmetysObjectResolver;
039import org.ametys.plugins.repository.query.QueryHelper;
040import org.ametys.plugins.repository.query.expression.Expression.Operator;
041import org.ametys.plugins.repository.query.expression.UserExpression;
042import org.ametys.runtime.i18n.I18nizableText;
043
044/**
045 * {@link AccessController} to allow read access and handle for author of a query
046 *
047 */
048public class QueryAuthorAccessController extends AbstractRightBasedAccessController implements Serviceable
049{
050    private static final List<String> __CREATOR_RIGHTS = List.of(QueryDAO.QUERY_HANDLE_RIGHT_ID);
051    /** The ametys object resolver */
052    protected AmetysObjectResolver _resolver;
053    
054    public void service(ServiceManager manager) throws ServiceException
055    {
056        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
057    }
058    
059    public boolean isSupported(Object object)
060    {
061        return object instanceof Query;
062    }
063    
064    public AccessResult getPermission(UserIdentity user, Set<GroupIdentity> userGroups, String rightId, Object object)
065    {
066        if (((Query) object).getAuthor().equals(user))
067        {
068            return __CREATOR_RIGHTS.contains(rightId) ? AccessResult.USER_ALLOWED : AccessResult.UNKNOWN;
069        }
070        
071        return AccessResult.UNKNOWN;
072    }
073
074    public AccessResult getReadAccessPermission(UserIdentity user, Set<GroupIdentity> userGroups, Object object)
075    {
076        return ((Query) object).getAuthor().equals(user) ? AccessResult.USER_ALLOWED : AccessResult.UNKNOWN;
077    }
078
079    /**
080     * If creator, access to a list of rights
081     */
082    public Map<String, AccessResult> getPermissionByRight(UserIdentity user, Set<GroupIdentity> userGroups, Object object)
083    {
084        Map<String, AccessResult> permissionByRight = new HashMap<>();
085        
086        if (((Query) object).getAuthor().equals(user))
087        {
088            for (String rightId : __CREATOR_RIGHTS)
089            {
090                permissionByRight.put(rightId, AccessResult.USER_ALLOWED);
091            }
092        }
093        
094        return permissionByRight;
095    }
096
097    public AccessResult getPermissionForAnonymous(String rightId, Object object)
098    {
099        return AccessResult.UNKNOWN;
100    }
101
102    public AccessResult getReadAccessPermissionForAnonymous(Object object)
103    {
104        return AccessResult.UNKNOWN;
105    }
106
107    public AccessResult getPermissionForAnyConnectedUser(String rightId, Object object)
108    {
109        return AccessResult.UNKNOWN;
110    }
111
112    public AccessResult getReadAccessPermissionForAnyConnectedUser(Object object)
113    {
114        return AccessResult.UNKNOWN;
115    }
116
117    /**
118     * If right requested is in the list, the creator is added the list of USER_ALLOWED
119     */
120    public Map<UserIdentity, AccessResult> getPermissionByUser(String rightId, Object object)
121    {
122        Map<UserIdentity, AccessResult> permissionByUser = new HashMap<>();
123        
124        if (__CREATOR_RIGHTS.contains(rightId))
125        {
126            permissionByUser.put(((Query) object).getAuthor(), AccessResult.USER_ALLOWED);
127        }
128        return permissionByUser;
129    }
130
131    public Map<UserIdentity, AccessResult> getReadAccessPermissionByUser(Object object)
132    {
133        return MapUtils.EMPTY_MAP;
134    }
135
136    public Map<GroupIdentity, AccessResult> getPermissionByGroup(String rightId, Object object)
137    {
138        return MapUtils.EMPTY_MAP;
139    }
140
141    public Map<GroupIdentity, AccessResult> getReadAccessPermissionByGroup(Object object)
142    {
143        return MapUtils.EMPTY_MAP;
144    }
145
146    public boolean hasUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups, String rightId)
147    {
148        return false;
149    }
150
151    public boolean hasUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups)
152    {
153        return false;
154    }
155
156    public boolean hasAnonymousAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId)
157    {
158        return false;
159    }
160
161    public boolean hasAnonymousAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts)
162    {
163        return false;
164    }
165
166    public boolean hasAnyConnectedUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId)
167    {
168        return false;
169    }
170
171    public boolean hasAnyConnectedUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts)
172    {
173        return false;
174    }
175    
176    @Override
177    public AccessExplanation getStandardAccessExplanation(AccessResult permission, Object object)
178    {
179        switch (permission)
180        {
181            case USER_ALLOWED:
182            case UNKNOWN:
183                return new AccessExplanation(
184                        getId(),
185                        permission,
186                        new I18nizableText("plugin.queries-directory", "PLUGINS_QUERIESDIRECTORY_QUERY_AUTHOR_ACCESS_CONTROLLER_" + permission.name() + "_EXPLANATION",
187                                Map.of("title", getObjectLabel(object)))
188                        );
189            default:
190                return super.getStandardAccessExplanation(permission, object);
191        }
192    }
193    
194    @Override
195    protected Iterable< ? extends Object> getHandledObjects(UserIdentity identity, Set<GroupIdentity> groups)
196    {
197        String xPathQuery = QueryHelper.getXPathQuery(null, QueryFactory.QUERY_NODETYPE, new UserExpression(Query.AUTHOR, Operator.EQ, identity), null);
198        return _resolver.query(xPathQuery);
199    }
200    
201    @Override
202    protected Collection<String> getHandledRights(UserIdentity identity, Set<GroupIdentity> groups, Object object)
203    {
204        return __CREATOR_RIGHTS;
205    }
206    
207    @Override
208    public I18nizableText getObjectLabel(Object object)
209    {
210        if (object instanceof Query query)
211        {
212            return new I18nizableText(QueryAccessController.getQueryContainerParentPathLabel(query.getParent()) + query.getTitle());
213        }
214        throw new RightsException("Unsupported context: " + object.toString());
215    }
216    
217    @Override
218    public I18nizableText getObjectCategory(Object object)
219    {
220        return QueryAccessController.QUERIES_DIRECTORY_CONTEXT_CATEGORY;
221    }
222}