001/*
002 *  Copyright 2023 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.forms.workflow;
017
018import java.util.Arrays;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Optional;
023import java.util.Set;
024import java.util.stream.Collectors;
025import java.util.stream.Stream;
026
027import org.apache.avalon.framework.logger.AbstractLogEnabled;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.avalon.framework.service.Serviceable;
031import org.apache.commons.lang3.StringUtils;
032
033import org.ametys.cms.workflow.AmetysObjectCheckRightsCondition;
034import org.ametys.core.right.RightManager.RightResult;
035import org.ametys.core.user.CurrentUserProvider;
036import org.ametys.core.user.UserIdentity;
037import org.ametys.core.user.UserManager;
038import org.ametys.plugins.forms.repository.FormEntry;
039import org.ametys.plugins.workflow.EnhancedCondition;
040import org.ametys.plugins.workflow.component.WorkflowArgument;
041import org.ametys.plugins.workflow.support.WorkflowElementDefinitionHelper;
042import org.ametys.plugins.workflow.support.WorkflowHelper.WorkflowVisibility;
043import org.ametys.runtime.i18n.I18nizableText;
044import org.ametys.runtime.model.type.ModelItemTypeConstants;
045
046import com.opensymphony.module.propertyset.PropertySet;
047import com.opensymphony.workflow.WorkflowException;
048
049/**
050 * Worklow condition for checking if current user is the same user as an user defined in a question 
051 */
052public class IsUserCondition extends AbstractLogEnabled implements EnhancedCondition, FormEntryCondition, Serviceable
053{
054    /** The question name argument */
055    public static final String QUESTION_NAME = "question-name";
056    
057    /** The user manager */
058    protected UserManager _userManager;
059    
060    /** The current user provider */
061    protected CurrentUserProvider _currentUserProvider;
062    
063    @Override
064    public void service(ServiceManager manager) throws ServiceException
065    {
066        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
067        _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
068    }
069
070    @Override
071    public boolean passesCondition(Map transientVars, Map args, PropertySet ps) throws WorkflowException
072    {
073        FormEntry formEntry = (FormEntry) transientVars.get(AmetysObjectCheckRightsCondition.AMETYS_OBJECT_KEY);
074        return getUsersFromEntry(formEntry, args).contains(_currentUserProvider.getUser());
075    }
076    
077    @Override
078    public List<WorkflowArgument> getArguments()
079    {
080        WorkflowArgument questionName = WorkflowElementDefinitionHelper.getElementDefinition(
081            QUESTION_NAME,
082            new I18nizableText("plugin.forms", "PLUGINS_FORMS_IS_USER_ARGUMENT_QUESTION_NAME_LABEL"),
083            new I18nizableText("plugin.forms", "PLUGINS_FORMS_IS_USER_ARGUMENT_QUESTION_NAME_DESCRIPTION"),
084            true,
085            false
086        );
087        
088        return List.of(questionName);
089    }
090
091    public I18nizableText getLabel()
092    {
093        return new I18nizableText("plugin.forms", "PLUGINS_FORMS_IS_USER_CONDITION_LABEL");
094    }
095    
096    @Override
097    public I18nizableText getFullLabel(Map<String, String> argumentsValues)
098    {
099        String questionName = argumentsValues.get(QUESTION_NAME);
100        return new I18nizableText("plugin.forms", "PLUGINS_FORMS_IS_USER_CONDITION_DESCRIPTION", List.of(questionName));
101    }
102    
103    @Override
104    public List<WorkflowVisibility> getVisibilities()
105    {
106        List<WorkflowVisibility> visibilities = EnhancedCondition.super.getVisibilities();
107        visibilities.add(WorkflowVisibility.USER);
108        return visibilities;
109    }
110    
111    public Map<UserIdentity, RightResult> getWorkflowActorsPermissions(FormEntry entry, Map args)
112    {
113        Map<UserIdentity, RightResult> permissions = new HashMap<>();
114        for (UserIdentity user : getUsersFromEntry(entry, args))
115        {
116            permissions.put(user, RightResult.RIGHT_ALLOW);
117        }
118        return permissions;
119    }
120    
121    /**
122     * Get the set of users defined in the given question of the form entry
123     * @param formEntry the form entry to get the users from
124     * @param args the condition arguments containing the question name
125     * @return the set of users defined in the given question of the form entry, or an empty set if the question is not valid
126     */
127    protected Set<UserIdentity> getUsersFromEntry(FormEntry formEntry, Map args)
128    {
129        String questionName = (String) args.get(QUESTION_NAME);
130        if (StringUtils.isBlank(questionName) || !formEntry.hasDefinition(questionName) || !formEntry.getType(questionName).getId().equals(ModelItemTypeConstants.USER_ELEMENT_TYPE_ID))
131        {
132            getLogger().warn("Given argument '" + questionName + "' for condition is not an user form question");
133            return Set.of();
134        }
135        
136        if (formEntry.isMultiple(questionName)) 
137        {
138            UserIdentity[] userIds = formEntry.getValue(questionName);
139            return Optional.ofNullable(userIds)
140                           .map(Arrays::stream)
141                           .orElse(Stream.of())
142                           .collect(Collectors.toSet());
143        }
144        else
145        {
146            UserIdentity userId = formEntry.getValue(questionName);
147            if (userId == null)
148            {
149                return Set.of(userId);
150            }
151        }
152        
153        return Set.of();
154    }
155}