001/*
002 *  Copyright 2020 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.workspaces.project.rights.accesscontroller;
017
018import java.util.List;
019import java.util.Map;
020import java.util.Set;
021import java.util.stream.Collectors;
022import java.util.stream.Stream;
023
024import org.apache.avalon.framework.context.Context;
025import org.apache.avalon.framework.context.ContextException;
026import org.apache.avalon.framework.context.Contextualizable;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.avalon.framework.service.Serviceable;
030import org.apache.cocoon.components.ContextHelper;
031import org.apache.cocoon.environment.Request;
032import org.apache.commons.lang3.StringUtils;
033
034import org.ametys.core.group.GroupIdentity;
035import org.ametys.core.right.AccessController;
036import org.ametys.core.right.RightProfilesDAO;
037import org.ametys.core.user.UserIdentity;
038import org.ametys.plugins.workspaces.project.ProjectManager;
039import org.ametys.plugins.workspaces.project.objects.Project;
040import org.ametys.runtime.config.Config;
041import org.ametys.web.WebHelper;
042import org.ametys.web.repository.page.PagesContainer;
043import org.ametys.web.repository.site.Site;
044import org.ametys.web.repository.site.SiteManager;
045
046import com.google.common.collect.Iterables;
047
048/**
049 * Automatically grand access to CMS on site related to a project where the user is manager.
050 * Grants the right on general context and sitemap context with the default admin profjle
051 */
052public class BackOfficeAccessController implements AccessController, Serviceable, Contextualizable
053{
054    private String _adminProfileIdentifier;
055    private RightProfilesDAO _rightProfileDAO;
056    private Context _context;
057    private SiteManager _siteManager;
058    private ProjectManager _projectManager;
059    
060    public void service(ServiceManager manager) throws ServiceException
061    {
062        _rightProfileDAO = (RightProfilesDAO) manager.lookup(RightProfilesDAO.ROLE);
063        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
064        _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE);
065    }
066    
067    public void contextualize(Context context) throws ContextException
068    {
069        _context = context;
070    }
071    
072    public boolean isSupported(Object object)
073    {
074        return object instanceof String && ((String) object).startsWith("/cms")
075                || object instanceof PagesContainer;
076    }
077    
078    private Project _getProject(Object object)
079    {
080        Site site = null;
081        
082        if (object instanceof PagesContainer)
083        {
084            site = ((PagesContainer) object).getSite();
085        }
086        else 
087        {
088            Request request = ContextHelper.getRequest(_context);
089            String siteName = WebHelper.getSiteName(request);
090            if (StringUtils.isNotBlank(siteName))
091            {
092                site = _siteManager.getSite(siteName);
093            }
094        }
095        
096        if (site != null)
097        {
098            List<Project> projectsForSite = _projectManager.getProjectsForSite(site);
099            Project project = Iterables.getFirst(projectsForSite, null);
100            return project;
101        }
102        else
103        {
104            return null;
105        }
106    }
107    
108    private boolean _isRightInAdminProfile(String rightId)
109    {
110        if (rightId == null)
111        {
112            return true; // READER profile
113        }
114        
115        return _getRightsInAdminProfile().contains(rightId);
116    }
117    private synchronized List<String> _getRightsInAdminProfile()
118    {
119        if (_adminProfileIdentifier == null)
120        {
121            _adminProfileIdentifier = Config.getInstance().getValue("workspaces.profile.managerdefault");
122        }
123        
124        return _rightProfileDAO.getRights(_adminProfileIdentifier);
125    }
126
127    public AccessResult getPermission(UserIdentity user, Set<GroupIdentity> userGroups, String rightId, Object object)
128    {
129        if (_isRightInAdminProfile(rightId))
130        {
131            Project project = _getProject(object);
132            if (project != null && _projectManager.isManager(project, user))
133            {
134                return AccessResult.USER_ALLOWED;
135            }
136        }
137        
138        return AccessResult.UNKNOWN;
139    }
140
141    public AccessResult getReadAccessPermission(UserIdentity user, Set<GroupIdentity> userGroups, Object object)
142    {
143        return getPermission(user, userGroups, null, object);
144    }
145
146    public Map<String, AccessResult> getPermissionByRight(UserIdentity user, Set<GroupIdentity> userGroups, Object object)
147    {
148        Project project = _getProject(object);
149        if (project != null && _projectManager.isManager(project, user))
150        {
151            return _getRightsInAdminProfile().stream().collect(Collectors.toMap(rightId -> rightId, rightId -> AccessResult.USER_ALLOWED));
152        }
153        else
154        {
155            return Map.of();
156        }
157    }
158
159    public AccessResult getPermissionForAnonymous(String rightId, Object object)
160    {
161        return AccessResult.UNKNOWN;
162    }
163
164    public AccessResult getReadAccessPermissionForAnonymous(Object object)
165    {
166        return AccessResult.UNKNOWN;
167    }
168
169    public AccessResult getPermissionForAnyConnectedUser(String rightId, Object object)
170    {
171        return AccessResult.UNKNOWN;
172    }
173
174    public AccessResult getReadAccessPermissionForAnyConnectedUser(Object object)
175    {
176        return AccessResult.UNKNOWN;
177    }
178
179    public Map<UserIdentity, AccessResult> getPermissionByUser(String rightId, Object object)
180    {
181        if (_isRightInAdminProfile(rightId))
182        {
183            Project project = _getProject(object);
184            if (project != null)
185            {
186                return Stream.of(project.getManagers()).distinct().collect(Collectors.toMap(user -> user, user -> AccessResult.USER_ALLOWED));
187            }
188        }
189        
190        return Map.of();
191    }
192
193    public Map<UserIdentity, AccessResult> getReadAccessPermissionByUser(Object object)
194    {
195        return getPermissionByUser(null, object);
196    }
197
198    public Map<GroupIdentity, AccessResult> getPermissionByGroup(String rightId, Object object)
199    {
200        return Map.of();
201    }
202
203    public Map<GroupIdentity, AccessResult> getReadAccessPermissionByGroup(Object object)
204    {
205        return Map.of();
206    }
207
208    public boolean hasUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups, String rightId)
209    {
210        if (_isRightInAdminProfile(rightId) && workspacesContexts.contains("/cms"))
211        {
212            Project project = _getProject("/cms");
213            if (project != null && _projectManager.isManager(project, user))
214            {
215                return true; // Assume that admin profile is not empty
216            }
217        }
218
219        return false;
220    }
221
222    public boolean hasUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups)
223    {
224        return hasUserAnyPermissionOnWorkspace(workspacesContexts, user, userGroups, null);
225    }
226
227    public boolean hasAnonymousAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId)
228    {
229        return false;
230    }
231
232    public boolean hasAnonymousAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts)
233    {
234        return false;
235    }
236
237    public boolean hasAnyConnectedUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId)
238    {
239        return false;
240    }
241
242    public boolean hasAnyConnectedUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts)
243    {
244        return false;
245    }
246}