001/* 002 * Copyright 2017 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.editionfo; 017 018import java.util.Collections; 019import java.util.HashMap; 020import java.util.HashSet; 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.slf4j.Logger; 028 029import org.ametys.core.group.GroupIdentity; 030import org.ametys.core.right.AccessController; 031import org.ametys.core.right.AccessControllerExtensionPoint; 032import org.ametys.core.user.UserIdentity; 033import org.ametys.plugins.explorer.resources.ResourceCollection; 034import org.ametys.plugins.explorer.rights.ResourceAccessController; 035import org.ametys.plugins.frontedition.AmetysFrontEditionHelper; 036import org.ametys.plugins.workspaces.project.ProjectManager; 037import org.ametys.plugins.workspaces.project.modules.WorkspaceModule; 038import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint; 039import org.ametys.plugins.workspaces.project.objects.Project; 040import org.ametys.runtime.plugin.component.LogEnabled; 041import org.ametys.web.repository.page.Page; 042import org.ametys.web.repository.page.PagesContainer; 043 044/** 045 * This controller will grant the right "Front_Edition_Access_Right" on the "/cms/{site}" context to any user that have the Edition fo rights on the project corresponding to this site 046 * Beware that this controller works with ResourceAccessController... that should be enabled (and if another AccessController can give rights to resources... that's too bad) 047 */ 048public class EditionFOAccessController implements AccessController, Serviceable, LogEnabled 049{ 050 private ProjectManager _projectManager; 051 private WorkspaceModuleExtensionPoint _workspaceModuleExtensionPoint; 052 private Logger _logger; 053 private AccessControllerExtensionPoint _accessControllerExtensionPoint; 054 private AccessController _accessController; 055 056 public void service(ServiceManager manager) throws ServiceException 057 { 058 _projectManager = (ProjectManager) manager.lookup(ProjectManager.ROLE); 059 _workspaceModuleExtensionPoint = (WorkspaceModuleExtensionPoint) manager.lookup(WorkspaceModuleExtensionPoint.ROLE); 060 _accessControllerExtensionPoint = (AccessControllerExtensionPoint) manager.lookup(AccessControllerExtensionPoint.ROLE); 061 } 062 063 public void setLogger(Logger logger) 064 { 065 _logger = logger; 066 } 067 068 private AccessController _getAccessController() 069 { 070 if (_accessController == null) 071 { 072 _accessController = _accessControllerExtensionPoint.getExtension(ResourceAccessController.class.getName()); 073 } 074 return _accessController; 075 } 076 077 private ResourceCollection _getEditionFOModuleRootFromContext(Object object) 078 { 079 String siteName = _getSiteFromContext(object); 080 for (String projectName : _projectManager.getProjectsForSite(siteName)) 081 { 082 Project project = _projectManager.getProject(projectName); 083 if (project == null) 084 { 085 _logger.warn("Cannot find project '{}' associated to the site '{}'.", projectName, siteName); 086 continue; 087 } 088 089 WorkspaceModule editionFOWorkspaceModule = _workspaceModuleExtensionPoint.getExtension(EditionFOWorkspaceModule.EDITIONFO_MODULE_ID); 090 091 if (!_isPageInProjectWiki(editionFOWorkspaceModule, project, object)) 092 { 093 return null; 094 } 095 096 return editionFOWorkspaceModule.getModuleRoot(project, false); 097 } 098 099 return null; 100 } 101 102 private String _getSiteFromContext(Object context) 103 { 104 if (context instanceof PagesContainer) 105 { 106 return ((PagesContainer) context).getSiteName(); 107 } 108 return null; 109 } 110 111 private boolean _isPageInProjectWiki(WorkspaceModule editionFOWorkspaceModule, Project project, Object object) 112 { 113 if (!(object instanceof PagesContainer)) 114 { 115 return false; 116 } 117 PagesContainer page = (PagesContainer) object; 118 String pagePath = page.getPath(); 119 120 return editionFOWorkspaceModule.getModulePages(project, page.getSitemapName()) 121 .stream() 122 .anyMatch(wikiPage -> pagePath.equals(wikiPage.getPath()) || pagePath.contains(wikiPage.getPath() + "/")); 123 } 124 125 public AccessResult getPermission(UserIdentity user, Set<GroupIdentity> userGroups, String rightId, Object object) 126 { 127 if (AmetysFrontEditionHelper.FRONT_EDITION_RIGHT_ID.equals(rightId) || object instanceof Page) 128 { 129 Set<AccessResult> results = new HashSet<>(); 130 131 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 132 if (moduleRoot != null) 133 { 134 AccessResult permission = _getAccessController().getPermission(user, userGroups, rightId, moduleRoot); 135 results.add(permission); 136 } 137 138 return AccessResult.merge(results); 139 } 140 else 141 { 142 return AccessResult.UNKNOWN; 143 } 144 } 145 146 public AccessResult getReadAccessPermission(UserIdentity user, Set<GroupIdentity> userGroups, Object object) 147 { 148 if (object instanceof Page) 149 { 150 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 151 if (moduleRoot != null) 152 { 153 return _getAccessController().getReadAccessPermission(user, userGroups, moduleRoot); 154 } 155 } 156 157 return AccessResult.UNKNOWN; 158 } 159 160 public Map<String, AccessResult> getPermissionByRight(UserIdentity user, Set<GroupIdentity> userGroups, Object object) 161 { 162 AccessResult accessResult = getPermission(user, userGroups, AmetysFrontEditionHelper.FRONT_EDITION_RIGHT_ID, object); 163 if (accessResult == AccessResult.UNKNOWN) 164 { 165 return Collections.EMPTY_MAP; 166 } 167 else 168 { 169 Map<String, AccessResult> permissions = new HashMap<>(); 170 permissions.put(AmetysFrontEditionHelper.FRONT_EDITION_RIGHT_ID, accessResult); 171 return permissions; 172 } 173 } 174 175 public AccessResult getPermissionForAnonymous(String rightId, Object object) 176 { 177 if (AmetysFrontEditionHelper.FRONT_EDITION_RIGHT_ID.equals(rightId) || object instanceof Page) 178 { 179 Set<AccessResult> results = new HashSet<>(); 180 181 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 182 if (moduleRoot != null) 183 { 184 AccessResult permission = _getAccessController().getPermissionForAnonymous(rightId, moduleRoot); 185 results.add(permission); 186 } 187 188 return AccessResult.merge(results); 189 } 190 else 191 { 192 return AccessResult.UNKNOWN; 193 } 194 } 195 196 public AccessResult getReadAccessPermissionForAnonymous(Object object) 197 { 198 if (object instanceof Page) 199 { 200 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 201 if (moduleRoot != null) 202 { 203 return _getAccessController().getReadAccessPermissionForAnonymous(moduleRoot); 204 } 205 } 206 207 return AccessResult.UNKNOWN; 208 } 209 210 public AccessResult getPermissionForAnyConnectedUser(String rightId, Object object) 211 { 212 if (AmetysFrontEditionHelper.FRONT_EDITION_RIGHT_ID.equals(rightId) || object instanceof Page) 213 { 214 Set<AccessResult> results = new HashSet<>(); 215 216 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 217 if (moduleRoot != null) 218 { 219 AccessResult permission = _getAccessController().getPermissionForAnyConnectedUser(rightId, moduleRoot); 220 results.add(permission); 221 } 222 223 return AccessResult.merge(results); 224 } 225 else 226 { 227 return AccessResult.UNKNOWN; 228 } 229 } 230 231 public AccessResult getReadAccessPermissionForAnyConnectedUser(Object object) 232 { 233 if (object instanceof Page) 234 { 235 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 236 if (moduleRoot != null) 237 { 238 return _getAccessController().getReadAccessPermissionForAnyConnectedUser(moduleRoot); 239 } 240 } 241 242 return AccessResult.UNKNOWN; 243 } 244 245 public Map<UserIdentity, AccessResult> getPermissionByUser(String rightId, Object object) 246 { 247 if (AmetysFrontEditionHelper.FRONT_EDITION_RIGHT_ID.equals(rightId) || object instanceof Page) 248 { 249 Map<UserIdentity, AccessResult> permissionsByUser = new HashMap<>(); 250 251 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 252 if (moduleRoot != null) 253 { 254 Map<UserIdentity, AccessResult> permissionByUser = _getAccessController().getPermissionByUser(rightId, moduleRoot); 255 for (UserIdentity userIdentity : permissionByUser.keySet()) 256 { 257 if (permissionsByUser.containsKey(userIdentity)) 258 { 259 permissionsByUser.put(userIdentity, AccessResult.merge(permissionsByUser.get(userIdentity), permissionByUser.get(userIdentity))); 260 } 261 else 262 { 263 permissionsByUser.put(userIdentity, permissionByUser.get(userIdentity)); 264 } 265 } 266 } 267 268 return permissionsByUser; 269 } 270 else 271 { 272 return Collections.EMPTY_MAP; 273 } 274 } 275 276 public Map<UserIdentity, AccessResult> getReadAccessPermissionByUser(Object object) 277 { 278 if (object instanceof Page) 279 { 280 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 281 if (moduleRoot != null) 282 { 283 return _getAccessController().getReadAccessPermissionByUser(moduleRoot); 284 } 285 } 286 287 return Collections.EMPTY_MAP; 288 } 289 290 public Map<GroupIdentity, AccessResult> getPermissionByGroup(String rightId, Object object) 291 { 292 if (AmetysFrontEditionHelper.FRONT_EDITION_RIGHT_ID.equals(rightId) || object instanceof Page) 293 { 294 Map<GroupIdentity, AccessResult> permissionsByGroup = new HashMap<>(); 295 296 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 297 if (moduleRoot != null) 298 { 299 Map<GroupIdentity, AccessResult> permissionByGroup = _getAccessController().getPermissionByGroup(rightId, moduleRoot); 300 for (GroupIdentity groupIdentity : permissionByGroup.keySet()) 301 { 302 if (permissionsByGroup.containsKey(groupIdentity)) 303 { 304 permissionsByGroup.put(groupIdentity, AccessResult.merge(permissionsByGroup.get(groupIdentity), permissionByGroup.get(groupIdentity))); 305 } 306 else 307 { 308 permissionsByGroup.put(groupIdentity, permissionByGroup.get(groupIdentity)); 309 } 310 } 311 } 312 313 return permissionsByGroup; 314 } 315 else 316 { 317 return Collections.EMPTY_MAP; 318 } 319 } 320 321 public Map<GroupIdentity, AccessResult> getReadAccessPermissionByGroup(Object object) 322 { 323 if (object instanceof Page) 324 { 325 ResourceCollection moduleRoot = _getEditionFOModuleRootFromContext(object); 326 if (moduleRoot != null) 327 { 328 return _getAccessController().getReadAccessPermissionByGroup(moduleRoot); 329 } 330 } 331 332 return Collections.EMPTY_MAP; 333 } 334 335 public boolean hasUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups, String rightId) 336 { 337 // We do not want that this accesscontroller give access to the backoffice (even if #isSupported would not match in this case) 338 return false; 339 } 340 341 public boolean hasUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts, UserIdentity user, Set<GroupIdentity> userGroups) 342 { 343 return false; 344 } 345 346 public boolean hasAnonymousAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId) 347 { 348 // We do not want that this accesscontroller give access to the backoffice (even if #isSupported would not match in this case) 349 return false; 350 } 351 352 public boolean hasAnonymousAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts) 353 { 354 return false; 355 } 356 357 public boolean hasAnyConnectedUserAnyPermissionOnWorkspace(Set<Object> workspacesContexts, String rightId) 358 { 359 // We do not want that this accesscontroller give access to the backoffice (even if #isSupported would not match in this case) 360 return false; 361 } 362 363 public boolean hasAnyConnectedUserAnyReadAccessPermissionOnWorkspace(Set<Object> workspacesContexts) 364 { 365 return false; 366 } 367 368 public boolean isSupported(Object object) 369 { 370 return object instanceof PagesContainer; 371 } 372 373}