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;
025
026import org.apache.avalon.framework.component.Component;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.avalon.framework.service.Serviceable;
030import org.slf4j.LoggerFactory;
031
032import org.ametys.cms.FilterNameHelper;
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.plugins.cart.Cart.CartElementType;
040import org.ametys.plugins.core.user.UserHelper;
041import org.ametys.plugins.repository.AmetysObjectResolver;
042import org.ametys.plugins.repository.AmetysRepositoryException;
043import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
044import org.ametys.plugins.repository.UnknownAmetysObjectException;
045
046/**
047 * DAO for manipulating carts
048 */
049public class CartsDAO implements Serviceable, Component
050{
051    /** The Avalon role */
052    public static final String ROLE = CartsDAO.class.getName();
053    
054    /** The user manager */
055    protected UserManager _userManager;
056    
057    /** The current user provider */
058    private CurrentUserProvider _userProvider;
059    
060    /** The Ametys object resolver */
061    private AmetysObjectResolver _resolver;
062
063    private UserHelper _userHelper;
064
065    private RightManager _rightManager;
066    
067    @Override
068    public void service(ServiceManager serviceManager) throws ServiceException
069    {
070        _userProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE);
071        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
072        _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE);
073        _userHelper = (UserHelper) serviceManager.lookup(UserHelper.ROLE);
074        _rightManager = (RightManager) serviceManager.lookup(RightManager.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)
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        cartsNode.saveChanges();
152        
153        result.put("id", cart.getId());
154        
155        return result;
156    }
157    
158    /**
159     * Updates a cart.
160     * @param id The id of the cart to update
161     * @param title The title
162     * @param description The description
163     * @return The id of the updated cart
164     */
165    @Callable
166    public Map<String, String> updateCart (String id, String title, String description)
167    {
168        Map<String, String> result = new HashMap<>();
169        
170        Cart cart = _resolver.resolveById(id);
171        
172        if (hasWriteRightOnCart(_userProvider.getUser(), cart))
173        {
174            cart.setTitle(title);
175            cart.setDescription(description);
176            cart.saveChanges();
177        }
178        else
179        {
180            result.put("message", "not-allowed");
181        }
182        
183        result.put("id", cart.getId());
184        
185        return result;
186    }
187    
188    /**
189     * Deletes some carts.
190     * @param ids The ids of the carts to delete
191     * @return The ids of the deleted carts
192     */
193    @Callable
194    public Map<String, Object> deleteCarts (List<String> ids)
195    {
196        Map<String, Object> result = new HashMap<>();
197        
198        List<String> deletedCarts = new ArrayList<>();
199        List<String> unknownCarts = new ArrayList<>();
200        List<String> notallowedCarts = new ArrayList<>();
201        
202        for (String id : ids)
203        {
204            try
205            {
206                Cart cart = _resolver.resolveById(id);
207                if (hasWriteRightOnCart(_userProvider.getUser(), cart))
208                {
209                    cart.remove();
210                    cart.saveChanges();
211                    deletedCarts.add(id);
212                }
213                else
214                {
215                    notallowedCarts.add(cart.getTitle());
216                }
217            }
218            catch (UnknownAmetysObjectException e)
219            {
220                unknownCarts.add(id);
221                LoggerFactory.getLogger(getClass()).error("Unable to delete cart. The cart of id '" + id + " doesn't exist", e);
222            }
223        }
224        
225        result.put("deletedCarts", deletedCarts);
226        result.put("notallowedCarts", notallowedCarts);
227        result.put("unknownCarts", unknownCarts);
228        
229        return result;
230    }
231    
232    /**
233     * Add elements to a cart.
234     * @param cartId The cart id.
235     * @param type The type of element.
236     * @param elementParams The parameters of the element.
237     * @return The id of the cart or an error
238     */
239    @Callable
240    public Map<String, Object> addElements (String cartId, String type, Map<String, Object> elementParams)
241    {
242        Map<String, Object> result = new HashMap<>();
243        
244        UserIdentity user = _userProvider.getUser();
245        
246        Cart cart = _resolver.resolveById(cartId);
247        
248        if (!hasWriteRightOnCart(user, cart))
249        {
250            LoggerFactory.getLogger(getClass()).error("User '{}' try to add elements to a cart without convenient privileges", user);
251            result.put("msg", "not-allowed");
252            return result;
253        }
254        
255        switch (CartElementType.valueOf(type.toUpperCase()))
256        {
257            case CONTENT:
258                @SuppressWarnings("unchecked")
259                List<String> contentIds = (List<String>) elementParams.get("ids");
260                for (String contentId : contentIds)
261                {
262                    cart.addContent(contentId);
263                }
264                break;
265
266            case RESOURCE:
267                @SuppressWarnings("unchecked")
268                List<String> resourceIds = (List<String>) elementParams.get("ids");
269                for (String resourceId : resourceIds)
270                {
271                    cart.addResource(resourceId);
272                }
273                break;
274                
275            case CARTQUERY:
276                String title = (String) elementParams.get("title");
277                String description = (String) elementParams.get("description");
278                
279                cart.addQuery(user, title, description);
280                break;
281            
282            case CARTQUERYFROMDIRECTORY:
283                @SuppressWarnings("unchecked")
284                List<String> queryIds = (List<String>) elementParams.get("queryIds");
285                for (String queryId : queryIds)
286                {
287                    cart.addQueryFormDirectory(queryId);
288                }
289                break;
290                
291            default:
292                throw new IllegalArgumentException("Unknown cart element type");
293        }
294        
295        cart.saveChanges();
296        
297        result.put("id", cart.getId());
298        
299        return result;
300    }
301    
302    /**
303     * Deletes elements of a cart.
304     * @param cartId The cart id.
305     * @param cartElements The elements to delete.
306     * @return The id of the cart or an error
307     */
308    @Callable
309    public Map<String, Object> deleteElements (String cartId, List<Map<String, String>> cartElements)
310    {
311        Map<String, Object> result = new HashMap<>();
312        
313        Cart cart = _resolver.resolveById(cartId);
314        
315        UserIdentity user = _userProvider.getUser();
316        
317        if (!hasWriteRightOnCart(user, cart))
318        {
319            LoggerFactory.getLogger(getClass()).error("User '{}' try to add elements to a cart without convenient privileges", user);
320            result.put("msg", "not-allowed");
321            return result;
322        }
323        
324        for (Map<String, String> cartElement : cartElements)
325        {
326            CartElementType type = CartElementType.valueOf(cartElement.get("type").toUpperCase());
327            cart.removeElement(cartElement.get("id"), type);
328        }
329        
330        cart.saveChanges();
331       
332        result.put("id", cartId);
333        
334        return result;
335    }
336    
337    /**
338     * Get the cart with given id
339     * @param cartId The cart id
340     * @return The retrieved cart or null.
341     */
342    public Cart getCart(String cartId)
343    {
344        try
345        {
346            return _resolver.resolveById(cartId);
347        }
348        catch (AmetysRepositoryException e)
349        {
350            if (LoggerFactory.getLogger(getClass()).isWarnEnabled())
351            {
352                LoggerFactory.getLogger(getClass()).warn("Failed to retrieves the cart with id : " +  cartId, e);
353            }
354            
355            return null;
356        }
357    }
358    
359    /**
360     * Get the cart type properties
361     * @param cart The cart
362     * @return The cart type properties
363     */
364    public Map<String, Object> getCartProperties (Cart cart)
365    {
366        Map<String, Object> infos = new HashMap<>();
367        
368        infos.put("id", cart.getId());
369        infos.put("title", cart.getTitle());
370        infos.put("description", cart.getDescription());
371        infos.put("author", _userHelper.user2json(cart.getAuthor()));
372        
373        UserIdentity currentUser = _userProvider.getUser();
374        infos.put("canRead", hasReadRightOnCart(currentUser, cart));
375        infos.put("canWrite", hasWriteRightOnCart(currentUser, cart));
376        infos.put("canEditRight", hasRightAffectationRightOnCart(currentUser, cart));
377        
378        return infos;
379    }
380    
381    /**
382     * Test if the current user has the right needed by the content type to view this cart.
383     * @param cart The cart
384     * @return true if the user has the right needed, false otherwise.
385     */
386    protected boolean _hasRight(Cart cart)
387    {
388        UserIdentity user = _userProvider.getUser();
389        return hasReadRightOnCart(user, cart) || hasWriteRightOnCart(user, cart);
390    }
391    
392    /**
393     * Check if a user have read rights on a cart
394     * @param userIdentity the user
395     * @param cart the cart
396     * @return true if the user have read rights on a cart
397     */
398    public boolean hasReadRightOnCart(UserIdentity userIdentity, Cart cart)
399    {
400        return cart != null && (userIdentity.equals(cart.getAuthor()) || _rightManager.hasReadAccess(userIdentity, cart));
401    }
402
403    /**
404     * Check if a user have write rights on a cart
405     * @param userIdentity the user
406     * @param cart the cart
407     * @return true if the user have write rights on a cart
408     */
409    public boolean hasWriteRightOnCart(UserIdentity userIdentity, Cart cart)
410    {
411        return cart != null && (userIdentity.equals(cart.getAuthor()) || _rightManager.hasRight(userIdentity, "Cart_Rights_Admin", cart) == RightResult.RIGHT_ALLOW);
412    }
413
414    /**
415     * Check if a user have rights to edit rights on a cart
416     * @param userIdentity the user
417     * @param cart the cart
418     * @return true if the user have write rights to edit rights on a cart
419     */
420    public boolean hasRightAffectationRightOnCart(UserIdentity userIdentity, Cart cart)
421    {
422        return hasWriteRightOnCart(userIdentity, cart) || _rightManager.hasRight(userIdentity, "Runtime_Rights_Rights_Handle", "/cms") == RightResult.RIGHT_ALLOW;
423    }
424
425}