001/* 002 * Copyright 2015 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.cart; 017 018import java.time.ZonedDateTime; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.LinkedList; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026 027import org.apache.avalon.framework.component.Component; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031import org.slf4j.LoggerFactory; 032 033import org.ametys.core.right.RightManager; 034import org.ametys.core.right.RightManager.RightResult; 035import org.ametys.core.ui.Callable; 036import org.ametys.core.user.CurrentUserProvider; 037import org.ametys.core.user.UserIdentity; 038import org.ametys.core.user.UserManager; 039import org.ametys.core.util.DateUtils; 040import org.ametys.plugins.cart.Cart.CartElementType; 041import org.ametys.plugins.core.user.UserHelper; 042import org.ametys.plugins.repository.AmetysObjectResolver; 043import org.ametys.plugins.repository.AmetysRepositoryException; 044import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 045import org.ametys.plugins.repository.UnknownAmetysObjectException; 046import org.ametys.plugins.repository.jcr.NameHelper; 047 048/** 049 * DAO for manipulating carts 050 */ 051public class CartsDAO implements Serviceable, Component 052{ 053 /** The Avalon role */ 054 public static final String ROLE = CartsDAO.class.getName(); 055 056 /** The user manager */ 057 protected UserManager _userManager; 058 059 /** The current user provider */ 060 private CurrentUserProvider _userProvider; 061 062 /** The Ametys object resolver */ 063 private AmetysObjectResolver _resolver; 064 065 private UserHelper _userHelper; 066 067 private RightManager _rightManager; 068 069 @Override 070 public void service(ServiceManager serviceManager) throws ServiceException 071 { 072 _userProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE); 073 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 074 _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE); 075 _userHelper = (UserHelper) serviceManager.lookup(UserHelper.ROLE); 076 _rightManager = (RightManager) serviceManager.lookup(RightManager.ROLE); 077 } 078 079 /** 080 * Gets carts information. 081 * @param cartIds The ids of the carts to retrieve. 082 * @return The carts information 083 */ 084 @Callable(rights = Callable.SKIP_BUILTIN_CHECK) 085 public Map<String, Object> getCartsInformation (List<String> cartIds) 086 { 087 Map<String, Object> result = new HashMap<>(); 088 089 List<Map<String, Object>> carts = new LinkedList<>(); 090 List<Map<String, Object>> notAllowedCarts = new LinkedList<>(); 091 Set<String> unknownCarts = new HashSet<>(); 092 093 for (String id : cartIds) 094 { 095 Cart cart = getCart(id); 096 097 if (cart != null) 098 { 099 if (_hasRight(cart)) 100 { 101 carts.add(getCartProperties(cart)); 102 } 103 else 104 { 105 notAllowedCarts.add(getCartProperties(cart)); 106 } 107 108 } 109 else 110 { 111 unknownCarts.add(id); 112 } 113 } 114 115 result.put("carts", carts); 116 result.put("unknownCarts", unknownCarts); 117 result.put("notAllowedCarts", notAllowedCarts); 118 119 return result; 120 } 121 122 /** 123 * Creates a cart. 124 * @param title The title 125 * @param description The description 126 * @param documentation The documentation of the cart 127 * @return The id of the created cart 128 */ 129 @Callable(rights = "Plugin_Cart_Rights_Create") 130 public Map<String, String> createCart (String title, String description, String documentation) 131 { 132 Map<String, String> result = new HashMap<>(); 133 134 ModifiableTraversableAmetysObject cartsNode = CartHelper.getCartsNode(_resolver); 135 136 String name = NameHelper.filterName(title); 137 138 // Find unique name 139 int index = 1; 140 String originalName = name; 141 while (cartsNode.hasChild(name)) 142 { 143 name = originalName + "_" + (++index); 144 } 145 146 // title might be modified to handle project with same title. 147 String realTitle = title + (index > 1 ? " (" + index + ")" : ""); 148 149 Cart cart = cartsNode.createChild(name, CartFactory.CART_NODETYPE); 150 cart.setTitle(realTitle); 151 cart.setDescription(description); 152 cart.setDocumentation(documentation); 153 cart.setAuthor(_userProvider.getUser()); 154 cart.setContributor(_userProvider.getUser()); 155 cart.setCreationDate(ZonedDateTime.now()); 156 cart.setLastModificationDate(ZonedDateTime.now()); 157 158 cartsNode.saveChanges(); 159 160 result.put("id", cart.getId()); 161 162 return result; 163 } 164 165 /** 166 * Updates a cart. 167 * @param id The id of the cart to update 168 * @param title The title 169 * @param description The description 170 * @param documentation The documentation of the cart 171 * @return The id of the updated cart 172 */ 173 @Callable(rights = Callable.SKIP_BUILTIN_CHECK) 174 public Map<String, String> updateCart (String id, String title, String description, String documentation) 175 { 176 Map<String, String> result = new HashMap<>(); 177 178 Cart cart = _resolver.resolveById(id); 179 180 if (canWrite(_userProvider.getUser(), cart)) 181 { 182 cart.setTitle(title); 183 cart.setDescription(description); 184 cart.setDocumentation(documentation); 185 cart.setContributor(_userProvider.getUser()); 186 cart.setLastModificationDate(ZonedDateTime.now()); 187 cart.saveChanges(); 188 } 189 else 190 { 191 result.put("message", "not-allowed"); 192 } 193 194 result.put("id", cart.getId()); 195 196 return result; 197 } 198 199 /** 200 * Deletes some carts. 201 * @param ids The ids of the carts to delete 202 * @return The ids of the deleted carts 203 */ 204 @Callable(rights = Callable.SKIP_BUILTIN_CHECK) 205 public Map<String, Object> deleteCarts (List<String> ids) 206 { 207 Map<String, Object> result = new HashMap<>(); 208 209 List<String> deletedCarts = new ArrayList<>(); 210 List<String> unknownCarts = new ArrayList<>(); 211 List<String> notallowedCarts = new ArrayList<>(); 212 213 for (String id : ids) 214 { 215 try 216 { 217 Cart cart = _resolver.resolveById(id); 218 if (canWrite(_userProvider.getUser(), cart)) 219 { 220 cart.remove(); 221 cart.saveChanges(); 222 deletedCarts.add(id); 223 } 224 else 225 { 226 notallowedCarts.add(cart.getTitle()); 227 } 228 } 229 catch (UnknownAmetysObjectException e) 230 { 231 unknownCarts.add(id); 232 LoggerFactory.getLogger(getClass()).error("Unable to delete cart. The cart of id '" + id + " doesn't exist", e); 233 } 234 } 235 236 result.put("deletedCarts", deletedCarts); 237 result.put("notallowedCarts", notallowedCarts); 238 result.put("unknownCarts", unknownCarts); 239 240 return result; 241 } 242 243 /** 244 * Add elements to a cart. 245 * @param cartId The cart id. 246 * @param type The type of element. 247 * @param elementParams The parameters of the element. 248 * @return The id of the cart or an error 249 */ 250 @Callable(rights = Callable.SKIP_BUILTIN_CHECK) 251 public Map<String, Object> addElements (String cartId, String type, Map<String, Object> elementParams) 252 { 253 Map<String, Object> result = new HashMap<>(); 254 255 UserIdentity user = _userProvider.getUser(); 256 257 Cart cart = _resolver.resolveById(cartId); 258 259 if (!canWrite(user, cart)) 260 { 261 LoggerFactory.getLogger(getClass()).error("User '{}' try to add elements to a cart without convenient privileges", user); 262 result.put("msg", "not-allowed"); 263 return result; 264 } 265 266 switch (CartElementType.valueOf(type.toUpperCase())) 267 { 268 case CONTENT: 269 @SuppressWarnings("unchecked") 270 List<String> contentIds = (List<String>) elementParams.get("ids"); 271 for (String contentId : contentIds) 272 { 273 cart.addContent(contentId); 274 } 275 break; 276 277 case RESOURCE: 278 @SuppressWarnings("unchecked") 279 List<String> resourceIds = (List<String>) elementParams.get("ids"); 280 for (String resourceId : resourceIds) 281 { 282 cart.addResource(resourceId); 283 } 284 break; 285 286 case CARTQUERY: 287 String title = (String) elementParams.get("title"); 288 String description = (String) elementParams.get("description"); 289 290 cart.addQuery(user, title, description); 291 break; 292 293 case CARTQUERYFROMDIRECTORY: 294 @SuppressWarnings("unchecked") 295 List<String> queryIds = (List<String>) elementParams.get("queryIds"); 296 for (String queryId : queryIds) 297 { 298 cart.addQueryFormDirectory(queryId); 299 } 300 break; 301 302 default: 303 throw new IllegalArgumentException("Unknown cart element type"); 304 } 305 306 cart.setContributor(_userProvider.getUser()); 307 cart.setLastModificationDate(ZonedDateTime.now()); 308 cart.saveChanges(); 309 310 result.put("id", cart.getId()); 311 312 return result; 313 } 314 315 /** 316 * Deletes elements of a cart. 317 * @param cartId The cart id. 318 * @param cartElements The elements to delete. 319 * @return The id of the cart or an error 320 */ 321 @Callable(rights = Callable.SKIP_BUILTIN_CHECK) 322 public Map<String, Object> deleteElements (String cartId, List<Map<String, String>> cartElements) 323 { 324 Map<String, Object> result = new HashMap<>(); 325 326 Cart cart = _resolver.resolveById(cartId); 327 328 UserIdentity user = _userProvider.getUser(); 329 330 if (!canWrite(user, cart)) 331 { 332 LoggerFactory.getLogger(getClass()).error("User '{}' try to add elements to a cart without convenient privileges", user); 333 result.put("msg", "not-allowed"); 334 return result; 335 } 336 337 for (Map<String, String> cartElement : cartElements) 338 { 339 CartElementType type = CartElementType.valueOf(cartElement.get("type").toUpperCase()); 340 cart.removeElement(cartElement.get("id"), type); 341 } 342 343 cart.setContributor(_userProvider.getUser()); 344 cart.setLastModificationDate(ZonedDateTime.now()); 345 cart.saveChanges(); 346 347 result.put("id", cartId); 348 349 return result; 350 } 351 352 /** 353 * Get the cart with given id 354 * @param cartId The cart id 355 * @return The retrieved cart or null. 356 */ 357 public Cart getCart(String cartId) 358 { 359 try 360 { 361 return _resolver.resolveById(cartId); 362 } 363 catch (AmetysRepositoryException e) 364 { 365 if (LoggerFactory.getLogger(getClass()).isWarnEnabled()) 366 { 367 LoggerFactory.getLogger(getClass()).warn("Failed to retrieves the cart with id : " + cartId, e); 368 } 369 370 return null; 371 } 372 } 373 374 /** 375 * Get the cart type properties 376 * @param cart The cart 377 * @return The cart type properties 378 */ 379 public Map<String, Object> getCartProperties (Cart cart) 380 { 381 Map<String, Object> infos = new HashMap<>(); 382 383 infos.put("id", cart.getId()); 384 infos.put("title", cart.getTitle()); 385 infos.put("description", cart.getDescription()); 386 infos.put("documentation", cart.getDocumentation()); 387 infos.put("author", _userHelper.user2json(cart.getAuthor())); 388 infos.put("contributor", _userHelper.user2json(cart.getContributor())); 389 infos.put("lastModificationDate", DateUtils.zonedDateTimeToString(cart.getLastModificationDate())); 390 infos.put("creationDate", DateUtils.zonedDateTimeToString(cart.getCreationDate())); 391 392 UserIdentity currentUser = _userProvider.getUser(); 393 infos.put("canRead", canRead(currentUser, cart)); 394 infos.put("canWrite", canWrite(currentUser, cart)); 395 infos.put("canAssignRights", canAssignRights(currentUser, cart)); 396 397 return infos; 398 } 399 400 /** 401 * Test if the current user has the right needed by the content type to view this cart. 402 * @param cart The cart 403 * @return true if the user has the right needed, false otherwise. 404 */ 405 protected boolean _hasRight(Cart cart) 406 { 407 UserIdentity user = _userProvider.getUser(); 408 return canRead(user, cart) || canWrite(user, cart); 409 } 410 411 /** 412 * Check if a user have read rights on a cart 413 * @param userIdentity the user 414 * @param cart the cart 415 * @return true if the user have read rights on a cart 416 */ 417 public boolean canRead(UserIdentity userIdentity, Cart cart) 418 { 419 return _rightManager.hasReadAccess(userIdentity, cart); 420 } 421 422 /** 423 * Check if a user have write rights on a cart 424 * @param userIdentity the user 425 * @param cart the cart 426 * @return true if the user have write rights on a cart 427 */ 428 public boolean canWrite(UserIdentity userIdentity, Cart cart) 429 { 430 return _rightManager.hasRight(userIdentity, "Cart_Rights_Admin", cart) == RightResult.RIGHT_ALLOW; 431 } 432 433 /** 434 * Check if a user have rights to edit rights on a cart 435 * @param userIdentity the user 436 * @param cart the cart 437 * @return true if the user have write rights to edit rights on a cart 438 */ 439 public boolean canAssignRights(UserIdentity userIdentity, Cart cart) 440 { 441 return canWrite(userIdentity, cart) || _rightManager.hasRight(userIdentity, "Runtime_Rights_Rights_Handle", "/cms") == RightResult.RIGHT_ALLOW; 442 } 443 444}