001/*
002 *  Copyright 2019 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.linkdirectory;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021
022import javax.xml.transform.TransformerFactory;
023import javax.xml.transform.dom.DOMResult;
024import javax.xml.transform.sax.SAXTransformerFactory;
025import javax.xml.transform.sax.TransformerHandler;
026
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.cocoon.xml.XMLUtils;
030import org.w3c.dom.Node;
031import org.w3c.dom.NodeList;
032
033import org.ametys.core.user.UserIdentity;
034import org.ametys.core.util.dom.AmetysNodeList;
035import org.ametys.core.util.dom.MapElement;
036import org.ametys.plugins.linkdirectory.repository.DefaultLink;
037import org.ametys.web.repository.site.Site;
038import org.ametys.web.repository.site.SiteManager;
039import org.ametys.web.transformation.xslt.AmetysXSLTHelper;
040
041/**
042 * XSLT Helper with link directory specificity
043 */
044public class LinkDirectoryXSLTHelper extends AmetysXSLTHelper
045{
046    private static LinkDirectoryColorsComponent _linkDirectoryColorsComponent;
047    private static DirectoryHelper _directoryHelper;
048    private static SiteManager _siteManager;
049
050    @Override
051    public void service(ServiceManager manager) throws ServiceException
052    {
053        super.service(manager);
054        _linkDirectoryColorsComponent = (LinkDirectoryColorsComponent) manager.lookup(LinkDirectoryColorsComponent.ROLE);
055        _directoryHelper = (DirectoryHelper) manager.lookup(DirectoryHelper.ROLE);
056        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
057    }
058    
059    /**
060     * Get all the colors for the current site
061     * @return all colors available for the current site
062     */
063    public static MapElement getColors()
064    {
065        String siteName = site();
066        return getColors(siteName);
067    }
068    
069    /**
070     * Get all the colors for a site
071     * @param siteName site to check
072     * @return all colors available for this site
073     */
074    public static MapElement getColors(String siteName)
075    {
076        Map<String, Map<String, String>> colors = _linkDirectoryColorsComponent.getColors(siteName);
077        
078        return new MapElement("colors", colors);
079    }
080    
081    /**
082     * Get the default color index for the current site
083     * @return the default color index for the current site
084     */
085    public static String getDefaultColorIndex()
086    {
087        String siteName = site();
088        return getDefaultColorIndex(siteName);
089    }
090    
091    /**
092     * Get the default color index for a site
093     * @param siteName site to check
094     * @return the default color index for this site
095     */
096    public static String getDefaultColorIndex(String siteName)
097    {
098        return _linkDirectoryColorsComponent.getDefaultKey(siteName);
099    }
100    
101    /**
102     * Get the links that belong to a given theme. Only links allowed to anonymous access are returned !
103     * Internal URL are ignored.
104     * @param siteName the site name
105     * @param lang the language
106     * @param themeName the key of the theme
107     * @return the links as a {@link Node}.
108     */
109    public static NodeList getLinks(String siteName, String lang, String themeName)
110    {
111        return _getLinks(siteName, lang, themeName, null, false);
112    }
113    
114    /**
115     * Get the links that belong to a given theme for a given user.<br>
116     * Only user access is check. The user personal links are not retrieved and none user preferences is take into account to order or hide links !
117     * If IP restriction is configured, user authorization on IP is checked.
118     * DO NOT CALL THIS METHOD ON A CACHEABLE PAGE !
119     * @param siteName the site name
120     * @param lang the language
121     * @param themeName the key of the theme
122     * @return the links as a {@link Node}.
123     */
124    public static NodeList getLinksForCurrentUser(String siteName, String lang, String themeName)
125    {
126        return _getLinks(siteName, lang, themeName, _currentUserProvider.getUser(), true);
127    }
128    
129    /**
130     * Determines if the user IP matches the configured internal IP range for current site
131     * DO NOT CALL THIS METHOD ON A CACHEABLE PAGE !
132     * @return true if the user IP is an authorized IP for internal links or if no IP restriction is configured
133     */
134    public static boolean isInternalIP()
135    {
136        String siteName = site();
137        Site site = _siteManager.getSite(siteName);
138        return site != null ? _directoryHelper.isInternalIP(site) : false;
139    }
140    
141    private static NodeList _getLinks(String siteName, String lang, String themeName, UserIdentity user, boolean checkIPAuthorization)
142    {
143        try
144        {
145            Site site = _siteManager.getSite(siteName);
146            
147            boolean hasIPRestriction = _directoryHelper.hasIPRestriction(site);
148            boolean isIPAuthorized = checkIPAuthorization ? _directoryHelper.isInternalIP(site) : false;
149            
150            List<DefaultLink> links = _directoryHelper.getLinks(List.of(themeName), siteName, lang);
151            
152            SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
153            TransformerHandler th = saxTransformerFactory.newTransformerHandler();
154            
155            DOMResult result = new DOMResult();
156            th.setResult(result);
157            
158            th.startDocument();
159            XMLUtils.startElement(th, "links");
160            
161            for (DefaultLink link : links)
162            {
163                if (_rightManager.hasReadAccess(user, link))
164                {
165                    _directoryHelper.saxLink(siteName, th, link, false, hasIPRestriction, isIPAuthorized, false, false);
166                }
167            }
168            
169            XMLUtils.endElement(th, "links");
170            th.endDocument();
171            
172            List<Node> linkNodes = new ArrayList<>();
173            
174            NodeList childNodes = result.getNode().getChildNodes(); 
175            for (int i = 0; i < childNodes.getLength(); i++)
176            {
177                Node n = childNodes.item(i);
178                linkNodes.add(n);
179            }
180            
181            return new AmetysNodeList(linkNodes);
182        }
183        catch (Exception e) 
184        {
185            _logger.error("Unable to sax links directory for theme '" + themeName + " 'and site name '" + siteName + "'", e);
186        }
187        
188        return null;
189    }
190
191}