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