001/*
002 *  Copyright 2016 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.authentication;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.parameters.Parameters;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.cocoon.acting.ServiceableAction;
027import org.apache.cocoon.environment.ObjectModelHelper;
028import org.apache.cocoon.environment.Redirector;
029import org.apache.cocoon.environment.Request;
030import org.apache.cocoon.environment.SourceResolver;
031import org.apache.commons.lang3.StringUtils;
032
033import org.ametys.core.cocoon.ActionResultGenerator;
034import org.ametys.core.user.directory.UserDirectory;
035import org.ametys.core.user.directory.UserDirectoryFactory;
036import org.ametys.core.user.directory.UserDirectoryModel;
037import org.ametys.core.user.population.UserPopulation;
038import org.ametys.core.user.population.UserPopulationDAO;
039import org.ametys.core.util.JSONUtils;
040import org.ametys.runtime.model.checker.ItemChecker;
041import org.ametys.runtime.model.checker.ItemCheckerDescriptor;
042import org.ametys.runtime.model.type.ElementType;
043import org.ametys.runtime.model.type.ModelItemTypeConstants;
044
045/**
046 * This action checks the validity of a user directory
047 */
048public class CheckUserDirectoryAction extends ServiceableAction
049{
050    /** Helper component gathering utility methods for the management of JSON entities */
051    private JSONUtils _jsonUtils;
052    
053    /** The user directory factory */
054    private UserDirectoryFactory _userDirectoryFactory;
055
056    private UserPopulationDAO _userPopulationDAO;
057    
058    @Override
059    public void service(ServiceManager smanager) throws ServiceException
060    {
061        _jsonUtils = (JSONUtils) smanager.lookup(JSONUtils.ROLE);
062        _userDirectoryFactory = (UserDirectoryFactory) smanager.lookup(UserDirectoryFactory.ROLE);
063        _userPopulationDAO = (UserPopulationDAO) smanager.lookup(UserPopulationDAO.ROLE);
064        super.service(smanager);
065    }
066    
067    @SuppressWarnings("unchecked")
068    @Override
069    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
070    {
071        Map<String, String> result = new HashMap<>();
072        Request request = ObjectModelHelper.getRequest(objectModel);
073        
074        // Prepare the values for the test
075        String fieldCheckersInfoJSON = request.getParameter("fieldCheckersInfo");
076        Map<String, Object> fieldCheckersInfo = _jsonUtils.convertJsonToMap(fieldCheckersInfoJSON);
077        Map<String, Object> valuesByParameterChecker = _getValuesByParamCheckerId(fieldCheckersInfo);
078
079        // Dispatch the requests
080        for (String fieldCheckerId : valuesByParameterChecker.keySet())
081        {
082            ItemChecker fieldChecker = (ItemChecker) ((Map<String, Object>) valuesByParameterChecker.get(fieldCheckerId)).get("checker");
083            List<String> values = (List<String>) ((Map<String, Object>) valuesByParameterChecker.get(fieldCheckerId)).get("values");
084            try 
085            {
086                fieldChecker.check(values); 
087            }
088            catch (Throwable t)
089            {
090                getLogger().error("The test '" + fieldCheckerId + "' failed : \n" + t.getMessage(), t);
091                String msg = t.getMessage() != null ? t.getMessage() : "Unknown error";
092                result.put(fieldCheckerId, msg);
093            }
094        }
095        
096        request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
097        return result;
098    }
099    
100    @SuppressWarnings("unchecked")
101    private Map<String, Object> _getValuesByParamCheckerId(Map<String, Object> paramCheckersInfo)
102    {
103        Map<String, Object> result = new HashMap<> ();
104        
105        String populationId = (String) paramCheckersInfo.get("_user_population_id");
106        paramCheckersInfo.remove("_user_population_id");
107        UserPopulation userPopulation = null;
108        
109        for (String paramCheckerId : paramCheckersInfo.keySet())
110        {
111            Map<String, Object> valuesByParamCheckerId = new HashMap<> (); 
112            
113            // Check the ids of the parameter checkers and build the parameter checkers' list
114            ItemCheckerDescriptor parameterCheckerDescriptor = null;
115            UserDirectoryModel udModel = null;
116            for (String userDirectoryModelId : _userDirectoryFactory.getExtensionsIds())
117            {
118                if (parameterCheckerDescriptor != null)
119                {
120                    break; // param checker was found
121                }
122                udModel = _userDirectoryFactory.getExtension(userDirectoryModelId);
123                for (String localCheckerId : udModel.getParameterCheckers().keySet())
124                {
125                    if (localCheckerId.equals(paramCheckerId))
126                    {
127                        parameterCheckerDescriptor = udModel.getParameterCheckers().get(localCheckerId);
128                        break;
129                    }
130                }
131            }
132            if (udModel == null || parameterCheckerDescriptor == null)
133            {
134                throw new IllegalArgumentException("The parameter checker '" + paramCheckerId + "' was not found.");
135            }
136            
137            ItemChecker parameterChecker  = parameterCheckerDescriptor.getParameterChecker();
138            
139            valuesByParamCheckerId.put("checker", parameterChecker);
140            
141            List<String> paramNames = (List<String>) ((Map<String, Object>) paramCheckersInfo.get(paramCheckerId)).get("testParamsNames");
142            List<String> paramRawValues = (List<String>) ((Map<String, Object>) paramCheckersInfo.get(paramCheckerId)).get("rawTestValues");
143            
144            List<String> values = new ArrayList<> ();
145            
146            // Compute the proper values for the test
147            String udId = paramRawValues.get(paramRawValues.size() - 1);
148            for (int i = 0; i < paramNames.size() - 1; i++)
149            {
150                String paramName = StringUtils.substringAfter(paramNames.get(i), "$");
151                ElementType type = udModel.getParameters().get(paramName).getType();
152                String untypedValue = type.toString(paramRawValues.get(i));
153                
154                // Handle password field
155                if (untypedValue == null && ModelItemTypeConstants.PASSWORD_ELEMENT_TYPE_ID.equals(type.getId()))
156                {
157                    // The password is null => it means we use the existing password
158                    
159                    if (userPopulation == null)
160                    {
161                        userPopulation = _userPopulationDAO.getUserPopulation(populationId);
162                    }
163                    UserDirectory ud = userPopulation.getUserDirectory(udId);
164                    values.add((String) ud.getParameterValues().get(paramName));
165                }
166                else
167                {
168                    values.add(untypedValue);
169                }
170            }
171            
172            valuesByParamCheckerId.put("values", values);
173            
174            result.put(paramCheckerId, valuesByParamCheckerId);
175        }
176        
177        return result;
178    }
179
180}