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