001/* 002 * Copyright 2024 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.odfweb.rights; 017 018import org.apache.avalon.framework.context.Context; 019import org.apache.avalon.framework.context.ContextException; 020import org.apache.avalon.framework.context.Contextualizable; 021import org.apache.avalon.framework.service.ServiceException; 022import org.apache.avalon.framework.service.ServiceManager; 023import org.apache.cocoon.components.ContextHelper; 024import org.apache.cocoon.environment.Request; 025import org.apache.commons.lang3.StringUtils; 026 027import org.ametys.core.cache.Cache; 028import org.ametys.core.user.UserIdentity; 029import org.ametys.odf.ODFHelper; 030import org.ametys.odf.ProgramItem; 031import org.ametys.odf.program.AbstractProgram; 032import org.ametys.odf.program.Container; 033import org.ametys.plugins.core.impl.cache.AbstractCacheKey; 034import org.ametys.plugins.odfweb.repository.OdfPageHandler; 035import org.ametys.plugins.odfweb.repository.OdfPageResolver; 036import org.ametys.plugins.repository.AmetysObjectIterable; 037import org.ametys.runtime.config.Config; 038import org.ametys.runtime.i18n.I18nizableText; 039import org.ametys.web.WebHelper; 040import org.ametys.web.repository.site.Site; 041import org.ametys.web.repository.site.SiteManager; 042 043/** 044 * Implementation of {@link ODFRoleAccessControllerHelper} that consider current site to get program items with user as role. 045 * 046 */ 047public class ODFRoleAccessControllerHelper extends org.ametys.odf.rights.ODFRoleAccessControllerHelper implements Contextualizable 048{ 049 private static final String __CACHE_BY_SITE_ID = ODFRoleAccessControllerHelper.class.getName() + "$cacheBySite"; 050 051 private SiteManager _siteManager; 052 private OdfPageHandler _odfPageHandler; 053 private OdfPageResolver _odfPageResolver; 054 private ODFHelper _odfHelper; 055 056 private Context _context; 057 058 public void contextualize(Context context) throws ContextException 059 { 060 _context = context; 061 } 062 063 @Override 064 public void service(ServiceManager smanager) throws ServiceException 065 { 066 super.service(smanager); 067 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 068 _odfPageHandler = (OdfPageHandler) smanager.lookup(OdfPageHandler.ROLE); 069 _odfPageResolver = (OdfPageResolver) smanager.lookup(OdfPageResolver.ROLE); 070 _odfHelper = (ODFHelper) smanager.lookup(ODFHelper.ROLE); 071 } 072 073 @Override 074 public void initialize() throws Exception 075 { 076 if (!_cacheManager.hasCache(__CACHE_BY_SITE_ID)) 077 { 078 _cacheManager.createRequestCache(__CACHE_BY_SITE_ID, 079 new I18nizableText("plugin.odf-web", "PLUGINS_ODF_WEB_CACHE_ROLE_ACCESS_CONTROLLER_LABEL"), 080 new I18nizableText("plugin.odf-web", "PLUGINS_ODF_WEB_CACHE_ROLE_ACCESS_CONTROLLER_DESCRIPTION"), 081 false 082 ); 083 } 084 } 085 086 static class CacheKey extends AbstractCacheKey 087 { 088 CacheKey(UserIdentity userIdentity, String siteName, String roleAttributePath) 089 { 090 super(userIdentity, siteName, roleAttributePath); 091 } 092 093 static CacheKey of(UserIdentity userIdentity, String siteName, String roleAttributePath) 094 { 095 return new CacheKey(userIdentity, siteName, roleAttributePath); 096 } 097 098 } 099 100 @Override 101 public boolean hasODFRoleOnAnyProgramItem(UserIdentity user, String attributePath) 102 { 103 Cache<CacheKey, Boolean> cache = _getCacheBySite(); 104 105 Request request = ContextHelper.getRequest(_context); 106 String siteName = WebHelper.getSiteName(request); 107 108 CacheKey key = CacheKey.of(user, siteName, attributePath); 109 return cache.get(key, __ -> _hasODFRoleOnAnyProgramItem(user, siteName, attributePath)); 110 } 111 112 private boolean _hasODFRoleOnAnyProgramItem(UserIdentity user, String siteName, String attributePath) 113 { 114 AmetysObjectIterable<ProgramItem> programItems = _odfRightHelper.getProgramItemsWithUserAsRole(user, attributePath); 115 if (programItems.getSize() == 0) 116 { 117 // user has no ODF role on program items 118 return false; 119 } 120 121 if (StringUtils.isNotBlank(siteName)) 122 { 123 Site site = _siteManager.getSite(siteName); 124 125 String odfMainSite = Config.getInstance().getValue("odf.web.site.name"); 126 if (siteName.equals(odfMainSite)) 127 { 128 // Allow access to main ODF site for user with a ODF role 129 return true; 130 } 131 else if (_odfPageHandler.hasOdfRootPage(site)) 132 { 133 // Check if at least one program item is part of ODF sitemap tree of current site (taking into account ODF restrictions) 134 for (ProgramItem programItem : programItems) 135 { 136 if (programItem instanceof Container) 137 { 138 for (AbstractProgram abstractProgram : _odfHelper.getParentAbstractPrograms(programItem)) 139 { 140 if (!_odfPageResolver.getReferencingPages(abstractProgram, siteName, null).isEmpty()) 141 { 142 return true; 143 } 144 } 145 } 146 else if (!_odfPageResolver.getReferencingPages(programItem, siteName, null).isEmpty()) 147 { 148 return true; 149 } 150 } 151 152 // No find program item which is part of ODF tree on current site (there is no ODF root page, or ODF restrictions do not match program items) 153 return false; 154 } 155 else 156 { 157 // User has ONLY access to main ODF site 158 return false; 159 } 160 } 161 else 162 { 163 // user has ODF role on program items on no site context 164 return true; 165 } 166 } 167 168 private Cache<CacheKey, Boolean> _getCacheBySite() 169 { 170 return _cacheManager.get(__CACHE_BY_SITE_ID); 171 } 172}