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.core.ui.parameter.files;
017
018import java.io.IOException;
019import java.util.Map;
020
021import org.apache.avalon.framework.service.ServiceException;
022import org.apache.avalon.framework.service.ServiceManager;
023import org.apache.excalibur.source.SourceResolver;
024import org.apache.excalibur.source.impl.FileSource;
025
026import org.ametys.core.file.FileHelper;
027import org.ametys.core.right.RightManager.RightResult;
028import org.ametys.core.ui.Callable;
029import org.ametys.core.ui.StaticClientSideElement;
030import org.ametys.core.user.UserIdentity;
031import org.ametys.runtime.plugin.PluginsManager;
032
033/**
034 * Component for operations on parameters files and folders
035 */
036public class ParametersClientSideElement extends StaticClientSideElement
037{
038    private static final String _ROOT_PARAMETERS_DIRECTORY_URI = "context://WEB-INF/param";
039    
040    private FileHelper _fileHelper;
041    private SourceResolver _srcResolver;
042    
043    @Override
044    public void service(ServiceManager serviceManager) throws ServiceException
045    {
046        super.service(serviceManager);
047        _fileHelper = (FileHelper) serviceManager.lookup(FileHelper.ROLE);
048        _srcResolver = (org.apache.excalibur.source.SourceResolver) serviceManager.lookup(org.apache.excalibur.source.SourceResolver.ROLE);        
049    }
050
051    /**
052     * Saves parameters file.
053     * @param relPath the relative file's path from parameters files root directory
054     * @param text the UTF-8 file content to save
055     * @return The result map
056     * @throws IOException If an error occurred while saving 
057     */
058    @Callable
059    public Map<String, Object> saveParameters(String relPath, String text) throws IOException 
060    {
061        String fileURI = _ROOT_PARAMETERS_DIRECTORY_URI + (relPath.length() > 0 ? "/" + relPath : "");
062        return _fileHelper.saveFile(fileURI, text);
063    }
064    
065    /**
066     * Add a new folder
067     * @param parentRelPath the relative parent file's path from parameters files root directory
068     * @param name The name of folder to create
069     * @return a map containing the name of the created folder, its path and the path of its parent
070     * @throws IOException If an error occurred while creating folder
071     */
072    @Callable
073    public Map<String, Object> addFolder(String parentRelPath, String name) throws IOException 
074    {
075        // Check user can access this feature
076        _checkUserRight("CORE_Rights_EditParameterFile", "/${WorkspaceName}");
077        _checkNotSafeMode();
078        
079        FileSource rootDir = (FileSource) _srcResolver.resolveURI(_ROOT_PARAMETERS_DIRECTORY_URI);
080        
081        String parentURI = _ROOT_PARAMETERS_DIRECTORY_URI + (parentRelPath.length() > 0 ? "/" + parentRelPath : "");
082        
083        Map<String, Object> result = _fileHelper.addFolder(parentURI, name, true);
084        
085        if (result.containsKey("uri"))
086        {
087            String folderUri = (String) result.get("uri");
088            String path = folderUri.substring(rootDir.getURI().length());
089            result.put("path", path.endsWith("/") ? path.substring(0, path.length() - 1) : path);
090            result.put("parentPath", parentRelPath.endsWith("/") ? parentRelPath.substring(0, parentRelPath.length() - 1) : parentRelPath);
091        }
092
093        return result;
094    }
095    
096    /**
097    * Remove a folder or a file
098    * @param relPath the relative file's path from parameters files root directory
099    * @return the result map
100    * @throws IOException If an error occurs while removing the folder
101    */
102    @Callable
103    public Map<String, Object> deleteFile(String relPath) throws IOException
104    {
105        // Check user can access this feature
106        _checkUserRight("CORE_Rights_EditParameterFile", "/${WorkspaceName}");
107        _checkNotSafeMode();
108       
109        String fileUri = _ROOT_PARAMETERS_DIRECTORY_URI + (relPath.length() > 0 ? "/" + relPath : "");
110        return _fileHelper.deleteFile(fileUri);
111    }
112    
113    /**
114    * Rename a file or a folder 
115    * @param relPath the relative file's path from parameters files root directory
116    * @param name the new name of the file/folder
117    * @return the result map
118    * @throws IOException if an error occurs while renaming the file/folder
119    */
120    @Callable
121    public Map<String, Object> renameFile(String relPath, String name) throws IOException 
122    {
123        // Check user can access this feature
124        _checkUserRight("CORE_Rights_EditParameterFile", "/${WorkspaceName}");
125        _checkNotSafeMode();
126        
127        FileSource rootDir = (FileSource) _srcResolver.resolveURI(_ROOT_PARAMETERS_DIRECTORY_URI);
128        
129        String fileUri = _ROOT_PARAMETERS_DIRECTORY_URI + (relPath.length() > 0 ? "/" + relPath : "");
130        Map<String, Object> result = _fileHelper.renameFile(fileUri, name);
131        
132        if (result.containsKey("uri"))
133        {
134            String newURI = (String) result.get("uri");
135            String path = newURI.substring(rootDir.getURI().length());
136            result.put("path", path);
137        }
138        return result;
139    }
140    
141    /**
142    * Check if a file with same name already exist
143    * @param parentRelPath the path where the file will be added
144    * @param name the name of the file 
145    * @return result the server's response in JSON
146    * @throws Exception if an error occurred
147    */
148    @Callable
149    public boolean fileExists(String parentRelPath, String name) throws Exception
150    {
151        String parentUri = _ROOT_PARAMETERS_DIRECTORY_URI + (parentRelPath.length() > 0 ? "/" + parentRelPath : "");
152        return _fileHelper.hasChild(parentUri, name);
153    }
154    
155    /**
156     * Check if the user right to access the feature
157     * @param rightId The right id
158     * @param context The right context
159     * @throws IllegalStateException if the user has no right
160     */
161    protected void _checkUserRight(String rightId, String context) throws IllegalStateException
162    {
163        UserIdentity user = _currentUserProvider.getUser();
164        if (_rightManager.hasRight(user, rightId, context) != RightResult.RIGHT_ALLOW)
165        {
166            getLogger().error("User '" + user + "' tried to access a privileged feature without convenient right. Should have right '" + rightId + "' on context '" + context + "'");
167            throw new IllegalStateException("You have no right to access this feature.");
168        }
169    }
170    
171    /**
172     * Check if application is in normal mode, otherwise throw an exception.
173     */
174    protected void _checkNotSafeMode()
175    {
176        if (PluginsManager.getInstance().isSafeMode())
177        {
178            throw new IllegalStateException("This feature is not available in safe mode.");
179        }
180    }
181    
182}