001/* 002 * Copyright 2014 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.cms.lock; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.avalon.framework.component.Component; 024import org.apache.avalon.framework.logger.AbstractLogEnabled; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.avalon.framework.service.Serviceable; 028import org.apache.commons.lang.StringUtils; 029 030import org.ametys.cms.content.ContentHelper; 031import org.ametys.cms.repository.Content; 032import org.ametys.core.right.RightManager; 033import org.ametys.core.right.RightManager.RightResult; 034import org.ametys.core.ui.Callable; 035import org.ametys.core.user.CurrentUserProvider; 036import org.ametys.core.user.UserIdentity; 037import org.ametys.plugins.repository.AmetysObjectResolver; 038import org.ametys.plugins.repository.AmetysRepositoryException; 039import org.ametys.plugins.repository.lock.LockAwareAmetysObject; 040import org.ametys.plugins.repository.lock.LockHelper; 041import org.ametys.plugins.repository.lock.LockableAmetysObject; 042 043 044/** 045 * Unlock or lock one or several content(s) 046 */ 047public class LockContentManager extends AbstractLogEnabled implements Serviceable, Component 048{ 049 050 /** The component role. */ 051 public static final String ROLE = LockContentManager.class.getName(); 052 053 /** The "unlock all" right ID. */ 054 public static final String UNLOCK_ALL_RIGHT = "CMS_Rights_UnlockAll"; 055 056 /** The rights manager */ 057 protected RightManager _rightManager; 058 /** The Ametys object resolver */ 059 protected AmetysObjectResolver _resolver; 060 /** The current user provider.*/ 061 protected CurrentUserProvider _currentUserProvider; 062 /** The content helper */ 063 protected ContentHelper _contentHelper; 064 065 @Override 066 public void service(ServiceManager smanager) throws ServiceException 067 { 068 _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 069 _rightManager = (RightManager) smanager.lookup(RightManager.ROLE); 070 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 071 _contentHelper = (ContentHelper) smanager.lookup(ContentHelper.ROLE); 072 } 073 074 /** 075 * Test if the current user can unlock the given locked object.<br> 076 * A user can unlock a locked object if he is the lock owner, or if he has the right to unlock all objects. 077 * @param object the locked object to test. 078 * @return true if the current user can unlock the given locked object, false otherwise. 079 */ 080 public boolean canUnlock(LockAwareAmetysObject object) 081 { 082 return canUnlock(object, _currentUserProvider.getUser()); 083 } 084 085 /** 086 * Test if a specific user can unlock the given locked object.<br> 087 * A user can unlock a locked object if he is the lock owner, or if he has the right to unlock all objects. 088 * @param object the locked object to test. 089 * @param user the user. 090 * @return true if the current user can unlock the given locked object, false otherwise. 091 */ 092 public boolean canUnlock(LockAwareAmetysObject object, UserIdentity user) 093 { 094 return LockHelper.isLockOwner(object, user) || canUnlockAll(user); 095 } 096 097 /** 098 * Test if the current user has the right to unlock all contents. 099 * @return true if the current user has the right to unlock all contents, false otherwise. 100 */ 101 public boolean canUnlockAll() 102 { 103 return canUnlockAll(_currentUserProvider.getUser()); 104 } 105 106 /** 107 * Test if a specific user has the right to unlock all contents. 108 * @param user the user. 109 * @return true if the user has the right to unlock all contents, false otherwise. 110 */ 111 public boolean canUnlockAll(UserIdentity user) 112 { 113 return _rightManager.hasRight(_currentUserProvider.getUser(), UNLOCK_ALL_RIGHT, "/cms") == RightResult.RIGHT_ALLOW; 114 } 115 116 /** 117 * Unlock or lock contents 118 * @param contents the contents to unlock or lock 119 * @param mode the mode ('lock' or 'unlock') 120 * @return the result JSON map 121 */ 122 @Callable 123 public Map<String, Object> unlockOrLock(List<String> contents, String mode) 124 { 125 Map<String, Object> result = new HashMap<>(); 126 127 if ("unlock".equals(mode)) 128 { 129 result = unlock(contents); 130 } 131 else 132 { 133 result = lock(contents); 134 } 135 136 result.put("mode", mode); 137 return result; 138 } 139 140 /** 141 * Unlock contents 142 * @param contents The ids of contents to unlock 143 * @return the result JSON map 144 */ 145 protected Map<String, Object> unlock(List<String> contents) 146 { 147 UserIdentity currentUser = _currentUserProvider.getUser(); 148 boolean canDelockAll = _rightManager.hasRight(currentUser, "CMS_Rights_UnlockAll", "/cms") == RightResult.RIGHT_ALLOW; 149 150 List<String> unlockContentsId = new ArrayList<>(); 151 String unlockedContents = ""; 152 String stillLockedContents = ""; 153 String failLockedContents = ""; 154 155 for (String contentId : contents) 156 { 157 LockableAmetysObject lockableContent = (LockableAmetysObject) _resolver.resolveById(contentId); 158 if (!lockableContent.isLocked()) 159 { 160 getLogger().warn("The content '" + contentId + "' is not locked anymore."); 161 } 162 else if (!LockHelper.isLockOwner(lockableContent, currentUser) && !canDelockAll) 163 { 164 getLogger().warn("The user '" + currentUser + "' try to unlock content '" + contentId + "' but he is not the lock owner"); 165 166 if (stillLockedContents.length() > 0) 167 { 168 stillLockedContents += ", "; 169 } 170 stillLockedContents += _contentHelper.getTitle((Content) lockableContent); 171 } 172 else 173 { 174 try 175 { 176 lockableContent.unlock(); 177 178 unlockContentsId.add(contentId); 179 if (unlockedContents.length() > 0) 180 { 181 unlockedContents += ", "; 182 } 183 unlockedContents += _contentHelper.getTitle((Content) lockableContent); 184 if (getLogger().isDebugEnabled()) 185 { 186 getLogger().debug("The user was unlocked content '" + contentId + "'"); 187 } 188 189 } 190 catch (AmetysRepositoryException e) 191 { 192 getLogger().error("Unable to unlock content '" + contentId + "'", e); 193 194 if (failLockedContents.length() > 0) 195 { 196 failLockedContents += ", "; 197 } 198 failLockedContents += _contentHelper.getTitle((Content) lockableContent); 199 } 200 } 201 } 202 203 Map<String, Object> result = new HashMap<>(); 204 205 result.put("unlocked-contents-id", StringUtils.join(unlockContentsId, ",")); 206 result.put("unlocked-contents", unlockedContents); 207 result.put("still-locked-contents", stillLockedContents); 208 result.put("fail-unlocked-contents", failLockedContents); 209 210 return result; 211 } 212 213 /** 214 * Lock contents 215 * @param contents The ids of contents to lock 216 * @return the result JSON map 217 */ 218 protected Map<String, Object> lock (List<String> contents) 219 { 220 List<String> lockContentsId = new ArrayList<>(); 221 String lockedContents = ""; 222 String alreadyLockedContents = ""; 223 String failUnlockedContents = ""; 224 225 for (String contentId : contents) 226 { 227 LockableAmetysObject lockableContent = (LockableAmetysObject) _resolver.resolveById(contentId); 228 if (lockableContent.isLocked() && !LockHelper.isLockOwner(lockableContent, _currentUserProvider.getUser())) 229 { 230 getLogger().warn("The content '" + contentId + "' is already locked."); 231 if (alreadyLockedContents.length() > 0) 232 { 233 alreadyLockedContents += ", "; 234 } 235 alreadyLockedContents += _contentHelper.getTitle((Content) lockableContent); 236 } 237 else if (!lockableContent.isLocked()) 238 { 239 try 240 { 241 lockableContent.lock(); 242 lockContentsId.add(contentId); 243 if (lockedContents.length() > 0) 244 { 245 lockedContents += ", "; 246 } 247 lockedContents += _contentHelper.getTitle((Content) lockableContent); 248 } 249 catch (AmetysRepositoryException e) 250 { 251 getLogger().error("Unable to lock content '" + contentId + "'", e); 252 if (failUnlockedContents.length() > 0) 253 { 254 failUnlockedContents += ", "; 255 } 256 failUnlockedContents += _contentHelper.getTitle((Content) lockableContent); 257 } 258 } 259 } 260 261 Map<String, Object> result = new HashMap<>(); 262 263 result.put("locked-contents-id", StringUtils.join(lockContentsId, ",")); 264 result.put("locked-contents", lockedContents); 265 result.put("already-locked-contents", alreadyLockedContents); 266 result.put("fail-locked-contents", failUnlockedContents); 267 268 return result; 269 } 270}