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