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