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.util.ArrayList; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.LinkedList; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025import java.util.stream.Collectors; 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.apache.commons.lang3.StringUtils; 032import org.slf4j.LoggerFactory; 033 034import org.ametys.cms.FilterNameHelper; 035import org.ametys.core.group.GroupIdentity; 036import org.ametys.core.ui.Callable; 037import org.ametys.core.user.CurrentUserProvider; 038import org.ametys.core.user.UserIdentity; 039import org.ametys.core.user.UserManager; 040import org.ametys.plugins.cart.Cart.CartElementType; 041import org.ametys.plugins.cart.Cart.CartProfile; 042import org.ametys.plugins.cart.Cart.Visibility; 043import org.ametys.plugins.core.user.UserHelper; 044import org.ametys.plugins.repository.AmetysObjectResolver; 045import org.ametys.plugins.repository.AmetysRepositoryException; 046import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 047import org.ametys.plugins.repository.UnknownAmetysObjectException; 048 049/** 050 * DAO for manipulating carts 051 */ 052public class CartsDAO implements Serviceable, Component 053{ 054 /** The Avalon role */ 055 public static final String ROLE = CartsDAO.class.getName(); 056 057 /** The user manager */ 058 protected UserManager _userManager; 059 060 /** The current user provider */ 061 private CurrentUserProvider _userProvider; 062 063 /** The Ametys object resolver */ 064 private AmetysObjectResolver _resolver; 065 066 private UserHelper _userHelper; 067 068 @Override 069 public void service(ServiceManager serviceManager) throws ServiceException 070 { 071 _userProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE); 072 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 073 _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE); 074 _userHelper = (UserHelper) serviceManager.lookup(UserHelper.ROLE); 075 } 076 077 /** 078 * Gets carts information. 079 * @param cartIds The ids of the carts to retrieve. 080 * @return The carts information 081 */ 082 @Callable 083 public Map<String, Object> getCartsInformation (List<String> cartIds) 084 { 085 Map<String, Object> result = new HashMap<>(); 086 087 List<Map<String, Object>> carts = new LinkedList<>(); 088 List<Map<String, Object>> notAllowedCarts = new LinkedList<>(); 089 Set<String> unknownCarts = new HashSet<>(); 090 091 for (String id : cartIds) 092 { 093 Cart cart = getCart(id); 094 095 if (cart != null && _hasRight(cart)) 096 { 097 if (_hasRight(cart)) 098 { 099 carts.add(getCartProperties(cart)); 100 } 101 else 102 { 103 notAllowedCarts.add(getCartProperties(cart)); 104 } 105 106 } 107 else 108 { 109 unknownCarts.add(id); 110 } 111 } 112 113 result.put("carts", carts); 114 result.put("unknownCarts", unknownCarts); 115 result.put("notAllowedCarts", unknownCarts); 116 117 return result; 118 } 119 120 /** 121 * Creates a cart. 122 * @param title The title 123 * @param description The description 124 * @return The id of the created cart 125 */ 126 @Callable 127 public Map<String, String> createCart (String title, String description) 128 { 129 Map<String, String> result = new HashMap<>(); 130 131 ModifiableTraversableAmetysObject cartsNode = CartHelper.getCartsNode(_resolver); 132 133 String name = FilterNameHelper.filterName(title); 134 135 // Find unique name 136 int index = 1; 137 String originalName = name; 138 while (cartsNode.hasChild(name)) 139 { 140 name = originalName + "_" + (++index); 141 } 142 143 // title might be modified to handle project with same title. 144 String realTitle = title + (index > 1 ? " (" + index + ")" : ""); 145 146 Cart cart = cartsNode.createChild(name, CartFactory.CART_NODETYPE); 147 cart.setTitle(realTitle); 148 cart.setDescription(description); 149 cart.setAuthor(_userProvider.getUser()); 150 151 cart.setVisibility(Visibility.PRIVATE); 152 153 cartsNode.saveChanges(); 154 155 result.put("id", cart.getId()); 156 157 return result; 158 } 159 160 /** 161 * Updates a cart. 162 * @param id The id of the cart to update 163 * @param title The title 164 * @param description The description 165 * @return The id of the updated cart 166 */ 167 @Callable 168 public Map<String, String> updateCart (String id, String title, String description) 169 { 170 Map<String, String> result = new HashMap<>(); 171 172 Cart cart = _resolver.resolveById(id); 173 UserIdentity author = cart.getAuthor(); 174 175 if (author != null && author.equals(_userProvider.getUser())) 176 { 177 cart.setTitle(title); 178 cart.setDescription(description); 179 cart.saveChanges(); 180 } 181 else 182 { 183 result.put("message", "not-allowed"); 184 } 185 186 result.put("id", cart.getId()); 187 188 return result; 189 } 190 191 /** 192 * Deletes some carts. 193 * @param ids The ids of the carts to delete 194 * @return The ids of the deleted carts 195 */ 196 @Callable 197 public Map<String, Object> deleteCarts (List<String> ids) 198 { 199 Map<String, Object> result = new HashMap<>(); 200 201 List<String> deletedCarts = new ArrayList<>(); 202 List<String> unknownCarts = new ArrayList<>(); 203 List<String> notallowedCarts = new ArrayList<>(); 204 205 for (String id : ids) 206 { 207 try 208 { 209 Cart cart = _resolver.resolveById(id); 210 if (cart.getAuthor().equals(_userProvider.getUser())) 211 { 212 cart.remove(); 213 cart.saveChanges(); 214 deletedCarts.add(id); 215 } 216 else 217 { 218 notallowedCarts.add(cart.getTitle()); 219 } 220 } 221 catch (UnknownAmetysObjectException e) 222 { 223 unknownCarts.add(id); 224 LoggerFactory.getLogger(getClass()).error("Unable to delete cart. The cart of id '" + id + " doesn't exist", e); 225 } 226 } 227 228 result.put("deletedCarts", deletedCarts); 229 result.put("notallowedCarts", notallowedCarts); 230 result.put("unknownCarts", unknownCarts); 231 232 return result; 233 } 234 235 /** 236 * Add elements to a cart. 237 * @param cartId The cart id. 238 * @param type The type of element. 239 * @param elementParams The parameters of the element. 240 * @return The id of the cart or an error 241 */ 242 @Callable 243 public Map<String, Object> addElements (String cartId, String type, Map<String, Object> elementParams) 244 { 245 Map<String, Object> result = new HashMap<>(); 246 247 UserIdentity user = _userProvider.getUser(); 248 249 Cart cart = _resolver.resolveById(cartId); 250 251 if (!cart.canWrite(user)) 252 { 253 LoggerFactory.getLogger(getClass()).error("User '{}' try to add elements to a cart without convenient privileges", user); 254 result.put("msg", "not-allowed"); 255 return result; 256 } 257 258 switch (CartElementType.valueOf(type.toUpperCase())) 259 { 260 case CONTENT: 261 @SuppressWarnings("unchecked") 262 List<String> contentIds = (List<String>) elementParams.get("ids"); 263 for (String contentId : contentIds) 264 { 265 cart.addContent(contentId); 266 } 267 break; 268 269 case RESOURCE: 270 @SuppressWarnings("unchecked") 271 List<String> resourceIds = (List<String>) elementParams.get("ids"); 272 for (String resourceId : resourceIds) 273 { 274 cart.addResource(resourceId); 275 } 276 break; 277 278 case CARTQUERY: 279 String title = (String) elementParams.get("title"); 280 String description = (String) elementParams.get("description"); 281 282 cart.addQuery(user, title, description); 283 break; 284 285 default: 286 throw new IllegalArgumentException("Unknown cart element type"); 287 } 288 289 cart.saveChanges(); 290 291 result.put("id", cart.getId()); 292 293 return result; 294 } 295 296 /** 297 * Deletes elements of a cart. 298 * @param cartId The cart id. 299 * @param cartElements The elements to delete. 300 * @return The id of the cart or an error 301 */ 302 @Callable 303 public Map<String, Object> deleteElements (String cartId, List<Map<String, String>> cartElements) 304 { 305 Map<String, Object> result = new HashMap<>(); 306 307 Cart cart = _resolver.resolveById(cartId); 308 309 UserIdentity user = _userProvider.getUser(); 310 311 if (!cart.canWrite(user)) 312 { 313 LoggerFactory.getLogger(getClass()).error("User '{}' try to add elements to a cart without convenient privileges", user); 314 result.put("msg", "not-allowed"); 315 return result; 316 } 317 318 for (Map<String, String> cartElement : cartElements) 319 { 320 CartElementType type = CartElementType.valueOf(cartElement.get("type").toUpperCase()); 321 cart.removeElement(cartElement.get("id"), type); 322 } 323 324 cart.saveChanges(); 325 326 result.put("id", cartId); 327 328 return result; 329 } 330 331 /** 332 * Changes the visibility of a cart. 333 * @param cartId The cart id. 334 * @param visibilityStr The visibility to set. 335 * @return An empty map, or an error message. 336 */ 337 @Callable 338 public Map<String, Object> changeVisibility (String cartId, String visibilityStr) 339 { 340 Map<String, Object> result = new HashMap<>(); 341 342 // Parameter checks. 343 Cart cart = null; 344 if (StringUtils.isNotEmpty(cartId)) 345 { 346 cart = _resolver.resolveById(cartId); 347 } 348 else 349 { 350 throw new IllegalArgumentException("Mandatory cart id parameter is missing."); 351 } 352 353 Visibility visibility = Visibility.valueOf(visibilityStr.toUpperCase()); 354 355 UserIdentity author = cart.getAuthor(); 356 if (author != null && author.equals(_userProvider.getUser())) 357 { 358 cart.setVisibility(visibility); 359 cart.saveChanges(); 360 } 361 else 362 { 363 result.put("message", "not-allowed"); 364 } 365 366 return result; 367 } 368 369 /** 370 * Adds users or groups to a cart profile. 371 * @param cartId The cart id. 372 * @param profileId The profile id. 373 * @param entries The users (or groups) entries. 374 * @param type The type of the entries to add: 'users' or 'groups' 375 * @return An empty map, or an error. 376 */ 377 @Callable 378 public Map<String, Object> assignRights (String cartId, String profileId, List<Map<String, String>> entries, String type) 379 { 380 Map<String, Object> result = new HashMap<>(); 381 382 // Parameter checks. 383 Cart cart = null; 384 if (StringUtils.isNotEmpty(cartId)) 385 { 386 cart = _resolver.resolveById(cartId); 387 } 388 else 389 { 390 throw new IllegalArgumentException("Mandatory cart id parameter is missing."); 391 } 392 393 if (!"users".equals(type) && !"groups".equals(type)) 394 { 395 throw new IllegalArgumentException("Unexpected type parameter : " + type); 396 } 397 398 if (!"read_access".equals(profileId) && !"write_access".equals(profileId)) 399 { 400 throw new IllegalArgumentException("Unexpected profile identifier : " + profileId); 401 } 402 403 UserIdentity author = cart.getAuthor(); 404 if (author != null && author.equals(_userProvider.getUser())) 405 { 406 CartProfile profile = CartProfile.valueOf(profileId.toUpperCase()); 407 408 // Add the entries to the profile 409 410 411 // Set new values 412 if ("users".equals(type)) 413 { 414 Set<UserIdentity> allEntries = cart.getGrantedUsers(profile); 415 416 for (Map<String, String> user : entries) 417 { 418 UserIdentity identity = new UserIdentity(user.get("login"), user.get("populationId")); 419 if (!allEntries.contains(identity)) 420 { 421 allEntries.add(identity); 422 } 423 } 424 cart.setGrantedUsers(profile, allEntries); 425 } 426 else 427 { 428 Set<GroupIdentity> allEntries = cart.getGrantedGroups(profile); 429 430 for (Map<String, String> group : entries) 431 { 432 GroupIdentity identity = new GroupIdentity(group.get("id"), group.get("groupDirectory")); 433 if (!allEntries.contains(identity)) 434 { 435 allEntries.add(identity); 436 } 437 } 438 cart.setGrantedGroups(profile, allEntries); 439 } 440 441 // Save 442 cart.saveChanges(); 443 } 444 else 445 { 446 result.put("message", "not-allowed"); 447 } 448 449 return result; 450 } 451 452 /** 453 * Deletes users or groups to a cart profile. 454 * @param cartId The cart id. 455 * @param profileId The profile id. 456 * @param users The users to delete. 457 * @param groups The groups to delete; 458 * @return An empty map, or an error. 459 */ 460 @Callable 461 public Map<String, Object> removeAssignment (String cartId, String profileId, List<Map<String, String>> users, List<Map<String, String>> groups) 462 { 463 Map<String, Object> result = new HashMap<>(); 464 465 // Parameter checks. 466 Cart cart = null; 467 if (StringUtils.isNotEmpty(cartId)) 468 { 469 cart = _resolver.resolveById(cartId); 470 } 471 else 472 { 473 throw new IllegalArgumentException("Mandatory cart id parameter is missing."); 474 } 475 476 if (!"read_access".equals(profileId) && !"write_access".equals(profileId)) 477 { 478 throw new IllegalArgumentException("Unexpected profile identifier : " + profileId); 479 } 480 481 UserIdentity author = cart.getAuthor(); 482 if (author != null && author.equals(_userProvider.getUser())) 483 { 484 CartProfile profile = CartProfile.valueOf(profileId.toUpperCase()); 485 486 if (!users.isEmpty()) 487 { 488 Set<UserIdentity> grantedUsers = cart.getGrantedUsers(profile); 489 grantedUsers.removeAll(users.stream().map(userAsMap -> new UserIdentity(userAsMap.get("login"), userAsMap.get("populationId"))).collect(Collectors.toList())); 490 491 cart.setGrantedUsers(profile, grantedUsers); 492 } 493 494 if (!groups.isEmpty()) 495 { 496 Set<GroupIdentity> grantedGroups = cart.getGrantedGroups(profile); 497 grantedGroups.removeAll(groups.stream().map(groupAsMap -> new GroupIdentity(groupAsMap.get("id"), groupAsMap.get("groupDirectory"))).collect(Collectors.toList())); 498 499 cart.setGrantedGroups(profile, grantedGroups); 500 } 501 502 // Save 503 cart.saveChanges(); 504 } 505 else 506 { 507 result.put("message", "not-allowed"); 508 } 509 510 return result; 511 } 512 513 /** 514 * Get the cart with given id 515 * @param cartId The cart id 516 * @return The retrieved cart or null. 517 */ 518 protected Cart getCart(String cartId) 519 { 520 try 521 { 522 return _resolver.resolveById(cartId); 523 } 524 catch (AmetysRepositoryException e) 525 { 526 if (LoggerFactory.getLogger(getClass()).isWarnEnabled()) 527 { 528 LoggerFactory.getLogger(getClass()).warn("Failed to retrieves the cart with id : " + cartId, e); 529 } 530 531 return null; 532 } 533 } 534 535 /** 536 * Get the cart type properties 537 * @param cart The cart 538 * @return The cart type properties 539 */ 540 public Map<String, Object> getCartProperties (Cart cart) 541 { 542 Map<String, Object> infos = new HashMap<>(); 543 544 infos.put("id", cart.getId()); 545 infos.put("title", cart.getTitle()); 546 infos.put("description", cart.getDescription()); 547 infos.put("author", _userHelper.user2json(cart.getAuthor())); 548 infos.put("visibility", cart.getVisibility().toString()); 549 550 UserIdentity currentUser = _userProvider.getUser(); 551 infos.put("canRead", cart.canRead(currentUser)); 552 infos.put("canWrite", cart.canWrite(currentUser)); 553 554 return infos; 555 } 556 557 /** 558 * Test if the current user has the right needed by the content type to view this cart. 559 * @param cart The cart 560 * @return true if the user has the right needed, false otherwise. 561 */ 562 protected boolean _hasRight(Cart cart) 563 { 564 UserIdentity user = _userProvider.getUser(); 565 return cart.canRead(user) || cart.canWrite(user); 566 } 567 568}