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.userdirectory; 017 018import java.util.Collections; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022import java.util.Set; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.commons.lang3.StringUtils; 027import org.apache.commons.lang3.tuple.Pair; 028import org.slf4j.Logger; 029 030import org.ametys.cms.content.ContentHelper; 031import org.ametys.cms.repository.Content; 032import org.ametys.cms.repository.WorkflowAwareContent; 033import org.ametys.cms.workflow.ContentWorkflowHelper; 034import org.ametys.cms.workflow.EditContentFunction; 035import org.ametys.core.util.I18nUtils; 036import org.ametys.plugins.repository.data.holder.impl.DataHolderHelper; 037import org.ametys.plugins.repository.data.holder.values.SynchronizableRepeater; 038import org.ametys.plugins.workflow.AbstractWorkflowComponent; 039import org.ametys.runtime.i18n.I18nizableText; 040import org.ametys.runtime.model.ModelItem; 041 042import com.opensymphony.workflow.InvalidActionException; 043import com.opensymphony.workflow.WorkflowException; 044 045/** 046 * Delete user component 047 */ 048public class DeleteUserComponent extends AbstractDeleteUDContentComponent 049{ 050 /** The avalon role. */ 051 public static final String ROLE = DeleteUserComponent.class.getName(); 052 053 /** The user directory helper */ 054 protected UserDirectoryHelper _udHelper; 055 056 /** The content helper */ 057 protected ContentHelper _contentHelper; 058 059 /** The content workflow helper */ 060 protected ContentWorkflowHelper _contentWorkflowHelper; 061 062 /** The i18n utils */ 063 protected I18nUtils _i18nUtils; 064 065 @Override 066 public void service(ServiceManager smanager) throws ServiceException 067 { 068 super.service(smanager); 069 _udHelper = (UserDirectoryHelper) smanager.lookup(UserDirectoryHelper.ROLE); 070 _contentHelper = (ContentHelper) smanager.lookup(ContentHelper.ROLE); 071 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 072 _contentWorkflowHelper = (ContentWorkflowHelper) smanager.lookup(ContentWorkflowHelper.ROLE); 073 } 074 075 @Override 076 public boolean isContentReferenced(Content content, Logger logger) 077 { 078 return _contentHelper.hasReferencingContents(content, Collections.singletonList(UserDirectoryHelper.ORGUNIT_CONTENT_TYPE), true); 079 } 080 081 @Override 082 protected boolean _checkBeforeDeletion(Content content, Map<String, String> rights, Map<String, Object> results, Logger logger) 083 { 084 // Check right and lock on content it self 085 boolean allRight = _canDeleteContent(content, rights, results); 086 087 // Check lock on orgunits contents 088 allRight = _checkOrgUnitsBeforeDeletion(content, results) && allRight; 089 090 return allRight; 091 } 092 093 /** 094 * True if the parent content is not locked 095 * @param content the parent content 096 * @param results the results map 097 * @return true if the parent content is not locked 098 */ 099 protected boolean _checkOrgUnitsBeforeDeletion(Content content, Map<String, Object> results) 100 { 101 boolean allRight = true; 102 103 // Check if parents are not locked 104 List<Content> orgUnits = _udHelper.getOrgUnits(content); 105 for (Content orgUnit : orgUnits) 106 { 107 if (_isLocked(orgUnit)) 108 { 109 @SuppressWarnings("unchecked") 110 List<Content> lockedContents = (List<Content>) results.get("locked-contents"); 111 lockedContents.add(orgUnit); 112 113 allRight = false; 114 } 115 } 116 117 return allRight; 118 } 119 120 @Override 121 protected boolean _removeRelations(Content content, Map<String, Object> parameters, Logger logger) 122 { 123 boolean success = true; 124 125 // Delete relation to orgunits 126 List<Pair<String, Content>> incomingReferences = _contentHelper.getReferencingContents(content); 127 for (Pair<String, Content> reference : incomingReferences) 128 { 129 String valuePath = reference.getLeft(); 130 Content orgUnit = reference.getRight(); 131 132 try 133 { 134 I18nizableText commentText = new I18nizableText("plugin.user-directory", "PLUGINS_USER_DIRECTORY_WORKFLOW_ACTION_REMOVE_USER_REFERENCE_MSG"); 135 String comment = _i18nUtils.translate(commentText, orgUnit.getLanguage()); 136 137 _removeRelation((WorkflowAwareContent) orgUnit, valuePath, comment); 138 } 139 catch (WorkflowException | InvalidActionException e) 140 { 141 logger.error("Unable to remove relation to content \"{}\" ({}) for referencing content \"{}\" ({}) ", content.getTitle(), content.getId(), orgUnit.getTitle(), orgUnit.getId(), e); 142 success = false; 143 } 144 } 145 146 return success; 147 } 148 149 private void _removeRelation(WorkflowAwareContent orgUnit, String valuePath, String comment) throws WorkflowException 150 { 151 // The valuePath is like users[1]/user 152 String entryPath = StringUtils.substringBeforeLast(valuePath, ModelItem.ITEM_PATH_SEPARATOR); 153 154 int position = DataHolderHelper.getRepeaterNameAndEntryPosition(entryPath).getRight(); 155 156 SynchronizableRepeater repeater = SynchronizableRepeater.appendOrRemove(List.of(), Set.of(position)); 157 Map<String, Object> values = Map.of("users", repeater); 158 159 Map<String, Object> inputs = new HashMap<>(); 160 if (StringUtils.isNotEmpty(comment)) 161 { 162 inputs.put("comment", comment); 163 } 164 165 Map<String, Object> parameters = new HashMap<>(); 166 167 parameters.put(EditContentFunction.VALUES_KEY, values); 168 parameters.put(EditContentFunction.QUIT, true); 169 inputs.put(AbstractWorkflowComponent.CONTEXT_PARAMETERS_KEY, parameters); 170 171 _contentWorkflowHelper.doAction(orgUnit, _removeReferenceActionId, inputs); 172 } 173 174 @Override 175 protected Set<String> _getContentIdsToDelete(Content content, Map<String, Object> parameters, Map<String, String> rights, Map<String, Object> results, Logger logger) 176 { 177 return Collections.singleton(content.getId()); 178 } 179}