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.actions; 017 018import java.util.HashMap; 019import java.util.List; 020import java.util.Map; 021import java.util.Optional; 022 023import org.apache.avalon.framework.parameters.Parameters; 024import org.apache.cocoon.environment.ObjectModelHelper; 025import org.apache.cocoon.environment.Redirector; 026import org.apache.cocoon.environment.Request; 027import org.apache.cocoon.environment.SourceResolver; 028import org.apache.commons.lang3.StringUtils; 029 030import org.ametys.core.right.RightManager.RightResult; 031import org.ametys.plugins.forms.dao.FormEntryDAO; 032import org.ametys.plugins.forms.dao.FormQuestionDAO.FormEntryValues; 033import org.ametys.plugins.forms.helper.FormWorkflowHelper; 034import org.ametys.plugins.forms.repository.Form; 035import org.ametys.plugins.forms.repository.FormEntry; 036import org.ametys.plugins.forms.repository.FormQuestion; 037import org.ametys.plugins.repository.RepositoryConstants; 038import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 039import org.ametys.runtime.i18n.I18nizableText; 040 041import com.google.common.collect.ArrayListMultimap; 042import com.google.common.collect.Multimap; 043 044/** 045 * Action to edit the given form entry 046 */ 047public class EditFormEntryAction extends AbstractProcessFormAction 048{ 049 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 050 { 051 Request request = ObjectModelHelper.getRequest(objectModel); 052 // Retrieve the current workspace. 053 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 054 try 055 { 056 // Force the workspace. 057 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, RepositoryConstants.DEFAULT_WORKSPACE); 058 059 String entryId = request.getParameter("entryId"); 060 if (entryId == null) 061 { 062 throw new IllegalStateException("Impossible to edit entry. No id provided."); 063 } 064 065 Multimap<String, I18nizableText> formErrors = ArrayListMultimap.create(); 066 FormEntry entry = _resolver.resolveById(entryId); 067 boolean canSubmitterEdit = _canSubmitterEdit(entry); 068 if (!canSubmitterEdit && !_canManagerEdit(entry)) 069 { 070 formErrors.put("form-access", new I18nizableText("plugin.forms", "PLUGINS_FORMS_EDIT_FORM_ENTRY_ERRORS")); 071 request.setAttribute("form", entry.getForm()); 072 request.setAttribute("form-errors", formErrors); 073 return null; 074 } 075 076 Optional<Long> currentStepId = Optional.of(_entryDAO.getCurrentStepId(entry)); 077 078 Map<String, Object> additionalParameters = new HashMap<>(); 079 additionalParameters.put("ignoreWriteRestriction", canSubmitterEdit); 080 formErrors.putAll(editFormEntryValues(request, entry, currentStepId, additionalParameters, false)); 081 082 if (!formErrors.isEmpty()) 083 { 084 request.setAttribute("form", entry.getForm()); 085 request.setAttribute("form-errors", formErrors); 086 return null; 087 } 088 } 089 finally 090 { 091 // Restore context 092 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 093 } 094 095 return EMPTY_MAP; 096 } 097 098 @Override 099 protected List<FormQuestion> _getRuleFilteredQuestions(Request request, Form form, FormEntryValues entryValues, Optional<Long> currentStepId) 100 { 101 String isSubmitterAsString = request.getParameter("isSubmitter"); 102 boolean isSubmitter = StringUtils.isNotBlank(isSubmitterAsString) ? Boolean.valueOf(isSubmitterAsString) : false; 103 104 boolean canSubmitterEdit = isSubmitter && _canSubmitterEdit(entryValues.entry()); 105 boolean onlyWritableQuestion = !canSubmitterEdit; // Get only writable questions if it's not the submitter 106 boolean onlyReadableQuestion = canSubmitterEdit; // Get only readable questions if it's the submitter 107 108 return _formQuestionDAO.getRuleFilteredQuestions(form, entryValues, currentStepId, onlyWritableQuestion, onlyReadableQuestion) 109 .stream() 110 .filter(q -> !canSubmitterEdit || _formQuestionDAO.canSubmitterEditSubmission(q)) // If the submitter is editing the entry, check is the question can be edited by the submitter 111 .toList(); 112 } 113 114 private boolean _canManagerEdit(FormEntry entry) 115 { 116 // Manager can edit if the edit action is available and he has the right to handle the entry 117 return _rightManager.currentUserHasRight(FormEntryDAO.HANDLE_FORMS_ENTRIES_RIGHT_ID, entry) == RightResult.RIGHT_ALLOW 118 && !_formWorkflowHelper.getAvailableActionsRestrictedToTypes(entry, List.of(FormWorkflowHelper.EDIT_ACTION)).isEmpty(); 119 } 120 121 private boolean _canSubmitterEdit(FormEntry entry) 122 { 123 // Submitter can edit if the edit-by-submitter action is available and he is the entry submitter 124 return _currentUserProvider.getUser().equals(entry.getUser()) 125 && !_formWorkflowHelper.getAvailableActionsRestrictedToTypes(entry, List.of(FormWorkflowHelper.EDIT_BY_SUBMITTER_ACTION)).isEmpty(); 126 } 127}