001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.ecm.webapp.security;
021
022import java.io.Serializable;
023import java.util.ArrayList;
024import java.util.HashMap;
025import java.util.Iterator;
026import java.util.List;
027import java.util.Map;
028
029import org.apache.commons.logging.Log;
030import org.apache.commons.logging.LogFactory;
031import org.nuxeo.common.utils.i18n.Labeler;
032import org.nuxeo.ecm.core.api.security.SecurityConstants;
033
034/**
035 * Holds the formatted security data, ready to be displayed. Holds the data on each map on the following structure: <br>
036 * <p>
037 * current doc grants: <br>
038 * user 1 - perm1, perm2 <br>
039 * user 2 - perm1, perm2 <br>
040 * user 3 - perm2 <br>
041 * current doc denies:<br>
042 * ... <br>
043 * parent doc grants:<br>
044 * ... <br>
045 * parent doc denies:<br>
046 * ...<br>
047 * <p>
048 * Also has methods that allow manipulation of the contained data, such as add/remove security privileges. The end
049 * result after add/remove has been called will be converted to a backend security DTO and then submitted on backend.
050 *
051 * @author Razvan Caraghin
052 */
053public class SecurityData implements Serializable {
054
055    protected static final Labeler labeler = new Labeler("label.security.permission");
056
057    private static final long serialVersionUID = -7958330304227141087L;
058
059    private static final Log log = LogFactory.getLog(SecurityData.class);
060
061    protected Map<String, List<String>> currentDocGrant = new HashMap<String, List<String>>();
062
063    protected Map<String, List<String>> currentDocDeny = new HashMap<String, List<String>>();
064
065    protected Map<String, List<String>> parentDocsGrant = new HashMap<String, List<String>>();
066
067    protected Map<String, List<String>> parentDocsDeny = new HashMap<String, List<String>>();
068
069    protected final List<String> currentDocumentUsers = new ArrayList<String>();
070
071    protected final List<String> parentDocumentsUsers = new ArrayList<String>();
072
073    protected String documentType = "";
074
075    protected boolean needSave = false;
076
077    public void setNeedSave(boolean needSave) {
078        this.needSave = needSave;
079    }
080
081    public boolean getNeedSave() {
082        return needSave;
083    }
084
085    public Map<String, List<String>> getCurrentDocDeny() {
086        return currentDocDeny;
087    }
088
089    public void setCurrentDocDeny(Map<String, List<String>> deny) {
090        currentDocDeny = deny;
091    }
092
093    public Map<String, List<String>> getCurrentDocGrant() {
094        return currentDocGrant;
095    }
096
097    public void setCurrentDocGrant(Map<String, List<String>> grant) {
098        currentDocGrant = grant;
099    }
100
101    public Map<String, List<String>> getParentDocsDenyLabels() {
102        return buildLabelMap(parentDocsDeny);
103    }
104
105    /**
106     * @since 6.0
107     */
108    public Map<String, List<String>> getCurrentDocDenyLabels() {
109        return buildLabelMap(currentDocDeny);
110    }
111
112    public Map<String, List<String>> getParentDocsDeny() {
113        return parentDocsDeny;
114    }
115
116    public void setParentDocsDeny(Map<String, List<String>> parentDocsDeny) {
117        this.parentDocsDeny = parentDocsDeny;
118    }
119
120    public Map<String, List<String>> getParentDocsGrant() {
121        return parentDocsGrant;
122    }
123
124    public Map<String, List<String>> getParentDocsGrantLabels() {
125        return buildLabelMap(parentDocsGrant);
126    }
127
128    /**
129     * @since 6.0
130     */
131    public Map<String, List<String>> getCurrentDocGrantLabels() {
132        return buildLabelMap(currentDocGrant);
133    }
134
135    public void setParentDocsGrant(Map<String, List<String>> parentDocsGrant) {
136        this.parentDocsGrant = parentDocsGrant;
137    }
138
139    public List<String> getCurrentDocumentUsers() {
140        return currentDocumentUsers;
141    }
142
143    public List<String> getParentDocumentsUsers() {
144        return parentDocumentsUsers;
145    }
146
147    protected Map<String, List<String>> buildLabelMap(Map<String, List<String>> permissions) {
148        Map<String, List<String>> labelMap = new HashMap<String, List<String>>();
149
150        for (String user : permissions.keySet()) {
151            List<String> labels = new ArrayList<String>();
152            for (String perm : permissions.get(user)) {
153                labels.add(labeler.makeLabel(perm));
154            }
155            labelMap.put(user, labels);
156        }
157        return labelMap;
158    }
159
160    public void rebuildUserLists() {
161        List<String> users = new ArrayList<String>();
162        users.addAll(currentDocGrant.keySet());
163        for (String user : currentDocDeny.keySet()) {
164            if (!users.contains(user)) {
165                users.add(user);
166            }
167        }
168
169        currentDocumentUsers.clear();
170        currentDocumentUsers.addAll(users);
171
172        users.clear();
173        users.addAll(parentDocsGrant.keySet());
174        for (String user : parentDocsDeny.keySet()) {
175            if (!users.contains(user)) {
176                users.add(user);
177            }
178        }
179
180        parentDocumentsUsers.clear();
181        parentDocumentsUsers.addAll(users);
182    }
183
184    /**
185     * Adds a privilege to the displayed list. This does not submit anything to the backend.
186     */
187    public void addModifiablePrivilege(String principalName, String permissionName, boolean grant) {
188        if (null == principalName || null == permissionName) {
189            log.error("Null params received, returning...");
190            return;
191        }
192
193        needSave = true;
194        if (grant) {
195            // if we already have the user stored with rights we dont add the
196            // user again, just update the list if needed
197            if (null != currentDocGrant.get(principalName)) {
198                // we already have the user - add the right to him
199                boolean shouldAddPermission = true;
200                for (String permission : currentDocGrant.get(principalName)) {
201                    // only add the right to list if the right is not already
202                    // there
203                    if (permission.equals(permissionName)) {
204                        shouldAddPermission = false;
205                        break;
206                    }
207                }
208
209                if (shouldAddPermission) {
210                    currentDocGrant.get(principalName).add(permissionName);
211                }
212            } else {
213                // add the user and create a new list of rights for him
214                List<String> permissions = new ArrayList<String>();
215                permissions.add(permissionName);
216                currentDocGrant.put(principalName, permissions);
217            }
218        } else {
219            // if we already have the user stored with rights we dont add the
220            // user again, just update the list if needed
221            if (null != currentDocDeny.get(principalName)) {
222                // we already have the user - add the right to him
223                boolean shouldAddPermission = true;
224                for (String permission : currentDocDeny.get(principalName)) {
225                    // only add the right to list if the right is not already
226                    // there
227                    if (permission.equals(permissionName)) {
228                        shouldAddPermission = false;
229                        break;
230                    }
231                }
232
233                if (shouldAddPermission) {
234                    currentDocDeny.get(principalName).add(permissionName);
235                }
236            } else {
237                // add the user and create a new list of rights for him
238                List<String> permissions = new ArrayList<String>();
239                permissions.add(permissionName);
240                currentDocDeny.put(principalName, permissions);
241            }
242        }
243
244        rebuildUserLists();
245    }
246
247    /**
248     * Removes a privilege from the displayed list. This does not submit anything to backend.
249     *
250     * @return true if a privilege was indeed removed
251     */
252    public boolean removeModifiablePrivilege(String principalName, String permissionName, boolean grant) {
253
254        if (null == principalName || null == permissionName) {
255            log.error("Null params received, returning...");
256            return false;
257        }
258
259        needSave = true;
260        boolean removed = false;
261        if (grant) {
262            if (null != currentDocGrant.get(principalName)) {
263                // we have the specified user, check if we have the right
264                Iterator<String> permissionIterator = currentDocGrant.get(principalName).iterator();
265                while (permissionIterator.hasNext()) {
266                    if (permissionIterator.next().equals(permissionName)) {
267                        permissionIterator.remove();
268                        removed = true;
269                        break;
270                    }
271                }
272            }
273        } else {
274            if (null != currentDocDeny.get(principalName)) {
275                // we have the specified user, check if we have the right
276                Iterator<String> permissionIterator = currentDocDeny.get(principalName).iterator();
277                while (permissionIterator.hasNext()) {
278                    if (permissionIterator.next().equals(permissionName)) {
279                        permissionIterator.remove();
280                        removed = true;
281                        break;
282                    }
283                }
284            }
285        }
286
287        rebuildUserLists();
288        return removed;
289    }
290
291    /**
292     * Removes all privileges for a given user. This does not edit the backend.
293     */
294    public void removeModifiablePrivilege(String principalName) {
295        if (null == principalName) {
296            log.error("Null principal received, returning...");
297            return;
298        }
299        currentDocGrant.remove(principalName);
300
301        // if user everyone had deny everything perm, then we have to
302        // keep this perm
303        if (principalName.equals(SecurityConstants.EVERYONE)) {
304
305            final List<String> deniedPerms = currentDocDeny.get(principalName);
306            boolean keepDenyAll = deniedPerms != null ? deniedPerms.contains(SecurityConstants.EVERYTHING) : false;
307
308            currentDocDeny.remove(principalName);
309
310            if (keepDenyAll) {
311                addModifiablePrivilege(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, false);
312            }
313        } else {
314            currentDocDeny.remove(principalName);
315        }
316
317        needSave = true;
318        rebuildUserLists();
319    }
320
321    /**
322     * Adds an unmodifiable privilege to the displayed list (these are related to the parent documents).
323     */
324    public void addUnModifiablePrivilege(String principalName, String permissionName, boolean grant) {
325        if (null == principalName || null == permissionName) {
326            log.error("Null params received, returning...");
327            return;
328        }
329
330        if (grant) {
331            // if we already have the user stored with rights we dont add the
332            // user again, just update the list if needed
333            if (null != parentDocsGrant.get(principalName)) {
334                // we already have the user - add the right to him
335                boolean shouldAddPermission = true;
336                for (String permission : parentDocsGrant.get(principalName)) {
337                    // only add the right to list if the right is not already
338                    // there
339                    if (permission.equals(permissionName)) {
340                        shouldAddPermission = false;
341                        break;
342                    }
343                }
344
345                if (shouldAddPermission) {
346                    parentDocsGrant.get(principalName).add(permissionName);
347                }
348            } else {
349                // add the user and create a new list of rights for him
350                List<String> permissions = new ArrayList<String>();
351                permissions.add(permissionName);
352                parentDocsGrant.put(principalName, permissions);
353            }
354        } else {
355            // if we already have the user stored with rights we dont add the
356            // user again, just update the list if needed
357            if (null != parentDocsDeny.get(principalName)) {
358                // we already have the user - add the right to him
359                boolean shouldAddPermission = true;
360                for (String permission : parentDocsDeny.get(principalName)) {
361                    // only add the right to list if the right is not already
362                    // there
363                    if (permission.equals(permissionName)) {
364                        shouldAddPermission = false;
365                        break;
366                    }
367                }
368
369                if (shouldAddPermission) {
370                    parentDocsDeny.get(principalName).add(permissionName);
371                }
372            } else {
373                // add the user and create a new list of rights for him
374                List<String> permissions = new ArrayList<String>();
375                permissions.add(permissionName);
376                parentDocsDeny.put(principalName, permissions);
377            }
378
379        }
380
381        rebuildUserLists();
382    }
383
384    public void clear() {
385        currentDocDeny.clear();
386        currentDocGrant.clear();
387        parentDocsDeny.clear();
388        parentDocsGrant.clear();
389
390        currentDocumentUsers.clear();
391        parentDocumentsUsers.clear();
392
393        log.debug("Cleared data...");
394        needSave = false;
395    }
396
397    public String getDocumentType() {
398        return documentType;
399    }
400
401    public void setDocumentType(String documentType) {
402        this.documentType = documentType;
403    }
404
405}