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.thesaurus.right; 017 018import java.util.Map; 019import java.util.Set; 020 021import org.apache.avalon.framework.context.Context; 022import org.apache.avalon.framework.context.ContextException; 023import org.apache.avalon.framework.context.Contextualizable; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.components.ContextHelper; 027import org.apache.cocoon.environment.Request; 028import org.apache.commons.collections.MapUtils; 029import org.apache.commons.lang3.StringUtils; 030 031import org.ametys.cms.content.archive.ArchiveConstants; 032import org.ametys.cms.contenttype.ContentTypesHelper; 033import org.ametys.cms.repository.Content; 034import org.ametys.cms.rights.ContentTypeAccessController; 035import org.ametys.core.group.GroupIdentity; 036import org.ametys.core.right.AccessController; 037import org.ametys.core.right.AccessController.Permission.PermissionType; 038import org.ametys.core.right.AccessExplanation; 039import org.ametys.core.right.Profile; 040import org.ametys.core.right.RightsException; 041import org.ametys.core.right.RightsExtensionPoint; 042import org.ametys.core.user.UserIdentity; 043import org.ametys.plugins.core.impl.right.AbstractProfileStorageBasedAccessController; 044import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 045import org.ametys.plugins.thesaurus.ThesaurusDAO; 046import org.ametys.runtime.i18n.I18nizableText; 047import org.ametys.runtime.i18n.I18nizableTextParameter; 048 049/** 050 * {@link AccessController} for a thesaurus objects. The rights are checked on '/cms' context. 051 * Read access is allowed to any connected user. 052 */ 053public class ThesaurusAccessController extends AbstractProfileStorageBasedAccessController implements Contextualizable 054{ 055 /** Right to edit thesaurus term */ 056 public static final String THESAURUS_RIGHTS_EDIT_TERM = "Thesaurus_Rights_EditTerm"; 057 058 /** The right context for thesaurus */ 059 private static final String __APPLICATION_RIGHT_CONTEXT = "/cms"; 060 061 /** The right extension point */ 062 protected RightsExtensionPoint _rightEP; 063 064 private ContentTypesHelper _contentTypeHelper; 065 066 private Context _context; 067 068 @Override 069 public void service(ServiceManager manager) throws ServiceException 070 { 071 super.service(manager); 072 _contentTypeHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 073 _rightEP = (RightsExtensionPoint) manager.lookup(RightsExtensionPoint.ROLE); 074 } 075 076 public void contextualize(Context context) throws ContextException 077 { 078 _context = context; 079 } 080 081 public boolean supports(Object object) 082 { 083 Request request = ContextHelper.getRequest(_context); 084 String currentWorkspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 085 086 if (ArchiveConstants.ARCHIVE_WORKSPACE.equals(currentWorkspace)) 087 { 088 return false; 089 } 090 091 return object instanceof Content && _contentTypeHelper.isInstanceOf((Content) object, ThesaurusDAO.MICROTHESAURUS_ABSTRACT_CONTENT_TYPE); 092 } 093 094 @Override 095 protected Object _convertContext(Object initialContext) 096 { 097 String siteName = _getSiteName(); 098 return __APPLICATION_RIGHT_CONTEXT + (StringUtils.isNoneEmpty(siteName) ? "/" + siteName : ""); 099 } 100 101 /** 102 * Convert the asked right id to the real right to check 103 * @param rightId The asked right id 104 * @return the right to check 105 */ 106 protected String _convertRightId(String rightId) 107 { 108 return THESAURUS_RIGHTS_EDIT_TERM; 109 } 110 111 @Override 112 public AccessResult getPermission(UserIdentity user, Set<GroupIdentity> userGroups, String rightId, Object object) 113 { 114 return super.getPermission(user, userGroups, _convertRightId(rightId), object); 115 } 116 117 @Override 118 public AccessExplanation explainPermission(UserIdentity user, Set<GroupIdentity> groups, String rightId, Object object) 119 { 120 return super.explainPermission(user, groups, _convertRightId(rightId), object); 121 } 122 123 @Override 124 protected I18nizableText _getExplanationI18nText(PermissionDetails details) 125 { 126 return new I18nizableText("plugin.thesaurus", _getAccessExplanationI18nKey("PLUGINS_THESAURUS_ACCESS_CONTROLLER_", details), _getExplanationI18nParams(details)); 127 } 128 129 @Override 130 protected Map<String, I18nizableTextParameter> _getExplanationI18nParams(PermissionDetails details) 131 { 132 Map<String, I18nizableTextParameter> i18nParams = super._getExplanationI18nParams(details); 133 i18nParams.put("right", _rightEP.getExtension(_convertRightId(null)).getLabel()); 134 return i18nParams; 135 } 136 137 @Override 138 protected I18nizableText getObjectLabelForExplanation(Object object) throws RightsException 139 { 140 return new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_ACCESS_CONTROLLER_EXPLANATION_CONTEXT_LABEL"); 141 } 142 143 @Override 144 public AccessResult getReadAccessPermission(UserIdentity user, Set<GroupIdentity> userGroups, Object object) 145 { 146 return AccessResult.ANY_CONNECTED_ALLOWED; 147 } 148 149 @Override 150 public AccessExplanation explainReadAccessPermission(UserIdentity user, Set<GroupIdentity> groups, Object object) 151 { 152 return new AccessExplanation( 153 getId(), 154 getReadAccessPermission(user, groups, object), 155 new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_ACCESS_CONTROLLER_READ_ACCESS_EXPLANATION", Map.of("title", new I18nizableText(((Content) object).getTitle()))) 156 ); 157 } 158 159 @Override 160 public Map<String, AccessResult> getPermissionByRight(UserIdentity user, Set<GroupIdentity> userGroups, Object object) 161 { 162 return MapUtils.EMPTY_MAP; 163 } 164 165 @Override 166 public AccessResult getPermissionForAnonymous(String rightId, Object object) 167 { 168 return AccessResult.ANONYMOUS_DENIED; 169 } 170 171 @Override 172 public AccessExplanation explainPermissionForAnonymous(String rightId, Object object) 173 { 174 return new AccessExplanation( 175 getId(), 176 getPermissionForAnonymous(rightId, object), 177 new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_ACCESS_CONTROLLER_ANONYMOUS_PERMISSION_EXPLANATION", Map.of("title", new I18nizableText(((Content) object).getTitle()))) 178 ); 179 } 180 181 @Override 182 public AccessResult getReadAccessPermissionForAnonymous(Object object) 183 { 184 return AccessResult.ANONYMOUS_DENIED; 185 } 186 187 @Override 188 public AccessExplanation explainReadAccessPermissionForAnonymous(Object object) 189 { 190 return new AccessExplanation( 191 getId(), 192 getReadAccessPermissionForAnonymous(object), 193 new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_ACCESS_CONTROLLER_ANONYMOUS_PERMISSION_EXPLANATION", Map.of("title", new I18nizableText(((Content) object).getTitle()))) 194 ); 195 } 196 197 @Override 198 public AccessResult getPermissionForAnyConnectedUser(String rightId, Object object) 199 { 200 return AccessResult.ANY_CONNECTED_DENIED; 201 } 202 203 @Override 204 public AccessExplanation explainPermissionForAnyConnectedUser(String rightId, Object object) 205 { 206 return new AccessExplanation( 207 getId(), 208 getPermissionForAnyConnectedUser(rightId, object), 209 new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_ACCESS_CONTROLLER_ANY_CONNECTED_PERMISSION_EXPLANATION") 210 ); 211 } 212 213 @Override 214 public AccessResult getReadAccessPermissionForAnyConnectedUser(Object object) 215 { 216 return AccessResult.ANY_CONNECTED_ALLOWED; 217 } 218 219 @Override 220 public AccessExplanation explainReadAccessPermissionForAnyConnectedUser(Object object) 221 { 222 return new AccessExplanation( 223 getId(), 224 getReadAccessPermissionForAnyConnectedUser(object), 225 new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_ACCESS_CONTROLLER_READ_ACCESS_EXPLANATION") 226 ); 227 } 228 229 @Override 230 public Map<UserIdentity, AccessResult> getPermissionByUser(String rightId, Object object) 231 { 232 return MapUtils.EMPTY_MAP; 233 } 234 235 @Override 236 public Map<GroupIdentity, AccessResult> getReadAccessPermissionByGroup(Object object) 237 { 238 return MapUtils.EMPTY_MAP; 239 } 240 241 @Override 242 public Map<UserIdentity, AccessResult> getReadAccessPermissionByUser(Object object) 243 { 244 return MapUtils.EMPTY_MAP; 245 } 246 247 @Override 248 public Map<GroupIdentity, AccessResult> getPermissionByGroup(String rightId, Object object) 249 { 250 return MapUtils.EMPTY_MAP; 251 } 252 253 @Override 254 protected boolean ignoreOnHasAnyPermission() 255 { 256 return true; 257 } 258 259 @Override 260 protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts) 261 { 262 if (workspacesContexts.contains("/cms")) 263 { 264 // the implementation of _convertContext doesn't depends on the context 265 return Set.of(_convertContext(null)); 266 } 267 return null; 268 } 269 270 // FIXME To remove https://issues.ametys.org/browse/THES-86 271 private String _getSiteName() 272 { 273 Request request = ContextHelper.getRequest(_context); 274 String siteName = request.getParameter("siteName"); 275 276 if (siteName == null) 277 { 278 siteName = (String) request.getAttribute("siteName"); 279 } 280 return siteName; 281 } 282 283 @Override 284 public Map<ExplanationObject, Map<Permission, AccessExplanation>> explainAllPermissions(UserIdentity identity, Set<GroupIdentity> groups, Set<Object> workspacesContexts) 285 { 286 AccessExplanation explanation = explainPermission(identity, groups, null, null); 287 if (explanation.accessResult() != AccessResult.UNKNOWN) 288 { 289 return Map.of( 290 getExplanationObject("thesaurus"), 291 Map.of(new Permission(PermissionType.ALL_RIGHTS, null), explanation) 292 ); 293 } 294 return Map.of(); 295 } 296 297 public I18nizableText getObjectLabel(Object object) throws RightsException 298 { 299 return new I18nizableText("plugin.thesaurus", "PLUGINS_THESAURUS_ACCESS_CONTROLLER_ALL_CONTEXT"); 300 } 301 302 public I18nizableText getObjectCategory(Object object) 303 { 304 return ContentTypeAccessController.REFERENCE_TABLE_CONTEXT_CATEGORY; 305 } 306 307 public int getObjectPriority(Object object) 308 { 309 // after root but before the content type 310 return 5; 311 } 312 313 @Override 314 public Map<ExplanationObject, AccessExplanation> explainAllProfileUsesForAnonymousOnWorkspaces(String profileId, Set<Object> workspacesContexts) 315 { 316 Profile profile = _rightProfileDAO.getProfile(profileId); 317 if (profile != null 318 && _rightProfileDAO.getRights(profile).contains(THESAURUS_RIGHTS_EDIT_TERM)) 319 { 320 return super.explainAllProfileUsesForAnonymousOnWorkspaces(profileId, workspacesContexts); 321 } 322 return Map.of(); 323 } 324 325 @Override 326 public Map<ExplanationObject, AccessExplanation> explainAllProfileUsesForAnyConnectedOnWorkspaces(String profileId, Set<Object> workspacesContexts) 327 { 328 Profile profile = _rightProfileDAO.getProfile(profileId); 329 if (profile != null 330 && _rightProfileDAO.getRights(profile).contains(THESAURUS_RIGHTS_EDIT_TERM)) 331 { 332 return super.explainAllProfileUsesForAnyConnectedOnWorkspaces(profileId, workspacesContexts); 333 } 334 return Map.of(); 335 } 336 337 @Override 338 public Map<ExplanationObject, Map<GroupIdentity, AccessExplanation>> explainAllProfileUsesOnWorkspacesByGroups(String profileId, Set<Object> workspacesContexts) 339 { 340 Profile profile = _rightProfileDAO.getProfile(profileId); 341 if (profile != null 342 && _rightProfileDAO.getRights(profile).contains(THESAURUS_RIGHTS_EDIT_TERM)) 343 { 344 return super.explainAllProfileUsesOnWorkspacesByGroups(profileId, workspacesContexts); 345 } 346 return Map.of(); 347 } 348 349 @Override 350 public Map<ExplanationObject, Map<UserIdentity, AccessExplanation>> explainAllProfileUsesOnWorkspacesByUser(String profileId, Set<Object> workspacesContexts) 351 { 352 Profile profile = _rightProfileDAO.getProfile(profileId); 353 if (profile != null 354 && _rightProfileDAO.getRights(profile).contains(THESAURUS_RIGHTS_EDIT_TERM)) 355 { 356 return super.explainAllProfileUsesOnWorkspacesByUser(profileId, workspacesContexts); 357 } 358 return Map.of(); 359 } 360}