001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.security;
029
030import java.io.Serializable;
031import java.util.Collections;
032import java.util.LinkedHashMap;
033import java.util.Map;
034import java.util.Set;
035
036/**
037 * An immutable permission set that contains both allowed and denied permissions as bitsets.<p>
038 *
039 * Currently supported permissions are:<ul>
040 * <li><code>{@link CmsPermissionSet#PERMISSION_READ}</code> (r) the right to read the contents of a resource</li>
041 * <li><code>{@link CmsPermissionSet#PERMISSION_WRITE}</code> (w) the right to write the contents of a resource</li>
042 * <li><code>{@link CmsPermissionSet#PERMISSION_VIEW}</code> (v) the right to see a resource in listings (workplace)</li>
043 * <li><code>{@link CmsPermissionSet#PERMISSION_CONTROL}</code> (c) the right to set permissions of a resource</li>
044 * <li><code>{@link CmsPermissionSet#PERMISSION_DIRECT_PUBLISH}</code> (d) the right direct publish a resource even without publish project permissions</li></ul><p>
045 *
046 * @since 6.0.0
047 */
048public class CmsPermissionSet implements Serializable {
049
050    /** Permission set to check control access. */
051    public static final CmsPermissionSet ACCESS_CONTROL = new CmsPermissionSet(CmsPermissionSet.PERMISSION_CONTROL);
052
053    /** Permission set to check direct publish permissions. */
054    public static final CmsPermissionSet ACCESS_DIRECT_PUBLISH = new CmsPermissionSet(
055        CmsPermissionSet.PERMISSION_DIRECT_PUBLISH);
056
057    /** Permission set to check read access. */
058    public static final CmsPermissionSet ACCESS_READ = new CmsPermissionSet(CmsPermissionSet.PERMISSION_READ);
059
060    /** Permission set to check view access. */
061    public static final CmsPermissionSet ACCESS_VIEW = new CmsPermissionSet(CmsPermissionSet.PERMISSION_VIEW);
062
063    /** Permission set to check write access. */
064    public static final CmsPermissionSet ACCESS_WRITE = new CmsPermissionSet(CmsPermissionSet.PERMISSION_WRITE);
065
066    /** The permission to control a resource. */
067    public static final int PERMISSION_CONTROL = 8;
068
069    /** The permission to direct publish a resource. */
070    public static final int PERMISSION_DIRECT_PUBLISH = 16;
071
072    /** No permissions for a resource (used especially for denied permissions). */
073    public static final int PERMISSION_EMPTY = 0;
074
075    /** All allowed permissions for a resource. */
076    public static final int PERMISSION_FULL = CmsPermissionSet.PERMISSION_READ
077        + CmsPermissionSet.PERMISSION_WRITE
078        + CmsPermissionSet.PERMISSION_VIEW
079        + CmsPermissionSet.PERMISSION_CONTROL
080        + CmsPermissionSet.PERMISSION_DIRECT_PUBLISH;
081
082    /** The permission to read a resource. */
083    public static final int PERMISSION_READ = 1;
084
085    /**  The permission to view a resource. */
086    public static final int PERMISSION_VIEW = 4;
087
088    /** The permission to write a resource. */
089    public static final int PERMISSION_WRITE = 2;
090
091    /** HashMap of all available permissions. */
092    private static Map<String, Integer> m_permissions;
093
094    /** The serial version id. */
095    private static final long serialVersionUID = -8374511370934922020L;
096
097    /** The set of allowed permissions. */
098    protected int m_allowed;
099
100    /** The set of denied permissions. */
101    protected int m_denied;
102
103    /**
104     * Constructor to create a permission set with preset allowed and denied permissions.<p>
105     *
106     * @param allowedPermissions the set of permissions to allow
107     * @param deniedPermissions the set of permissions to deny
108     */
109    public CmsPermissionSet(int allowedPermissions, int deniedPermissions) {
110
111        m_allowed = allowedPermissions;
112        m_denied = deniedPermissions;
113    }
114
115    /**
116     * Constructor to create an empty permission set.<p>
117     */
118    protected CmsPermissionSet() {
119
120        // noop
121    }
122
123    /**
124     * Constructor to create a permission set with preset allowed permissions.<p>
125     *
126     * @param allowedPermissions bitset of allowed permissions
127     */
128    protected CmsPermissionSet(int allowedPermissions) {
129
130        m_allowed = allowedPermissions;
131        m_denied = 0;
132    }
133
134    /**
135     * Returns the message keys of each permission known in the system.<p>
136     *
137     * @return Enumeration of message keys
138     */
139    public static Set<String> getPermissionKeys() {
140
141        return permissions().keySet();
142    }
143
144    /**
145     * Returns the value of a single permission.<p>
146     *
147     * @param key the key of the permission
148     * @return the value of the given permission
149     */
150    public static int getPermissionValue(String key) {
151
152        return (permissions().get(key)).intValue();
153    }
154
155    /**
156     * Initializes and returns the linked hash map of all permissions known in the system.<p>
157     *
158     * @return a linked hash map with permission keys and values
159     */
160    private static Map<String, Integer> permissions() {
161
162        if (m_permissions == null) {
163            LinkedHashMap<String, Integer> permissions = new LinkedHashMap<String, Integer>();
164            permissions.put("GUI_PERMISSION_TYPE_READ_0", Integer.valueOf(CmsPermissionSet.PERMISSION_READ));
165            permissions.put("GUI_PERMISSION_TYPE_WRITE_0", Integer.valueOf(CmsPermissionSet.PERMISSION_WRITE));
166            permissions.put("GUI_PERMISSION_TYPE_VIEW_0", Integer.valueOf(CmsPermissionSet.PERMISSION_VIEW));
167            permissions.put("GUI_PERMISSION_TYPE_CONTROL_0", Integer.valueOf(CmsPermissionSet.PERMISSION_CONTROL));
168            permissions.put(
169                "GUI_PERMISSION_TYPE_DIRECT_PUBLISH_0",
170                Integer.valueOf(CmsPermissionSet.PERMISSION_DIRECT_PUBLISH));
171            m_permissions = Collections.unmodifiableMap(permissions);
172        }
173        return m_permissions;
174    }
175
176    /**
177     * @see java.lang.Object#equals(java.lang.Object)
178     */
179    @Override
180    public boolean equals(Object obj) {
181
182        if (obj == this) {
183            return true;
184        }
185        if (obj instanceof CmsPermissionSet) {
186            CmsPermissionSet other = (CmsPermissionSet)obj;
187            return (other.m_allowed == m_allowed) && (other.m_denied == m_denied);
188        }
189        return false;
190    }
191
192    /**
193     * Returns the currently allowed permissions of ths permission set.<p>
194     *
195     * @return the allowed permissions as bitset
196     */
197    public int getAllowedPermissions() {
198
199        return m_allowed;
200    }
201
202    /**
203     * Returns the currently denied permissions of this permission set.<p>
204     *
205     * @return the denied permissions as bitset.
206     */
207    public int getDeniedPermissions() {
208
209        return m_denied;
210    }
211
212    /**
213     * Returns the permissions calculated from this permission set.<p>
214     * These are all permissions allowed but not denied.
215     *
216     * @return the resulting permission set
217     */
218    public int getPermissions() {
219
220        return m_allowed & ~m_denied;
221    }
222
223    /**
224     * Returns the string representation of the current permissions in this permission set.<p>
225     *
226     * @return string of the format {{+|-}{r|w|v|c|d}}*
227     */
228    public String getPermissionString() {
229
230        StringBuffer p = new StringBuffer("");
231
232        if ((m_denied & CmsPermissionSet.PERMISSION_READ) > 0) {
233            p.append("-r");
234        } else if (requiresReadPermission()) {
235            p.append("+r");
236        }
237
238        if ((m_denied & CmsPermissionSet.PERMISSION_WRITE) > 0) {
239            p.append("-w");
240        } else if (requiresWritePermission()) {
241            p.append("+w");
242        }
243
244        if ((m_denied & CmsPermissionSet.PERMISSION_VIEW) > 0) {
245            p.append("-v");
246        } else if (requiresViewPermission()) {
247            p.append("+v");
248        }
249
250        if ((m_denied & CmsPermissionSet.PERMISSION_CONTROL) > 0) {
251            p.append("-c");
252        } else if (requiresControlPermission()) {
253            p.append("+c");
254        }
255
256        if ((m_denied & CmsPermissionSet.PERMISSION_DIRECT_PUBLISH) > 0) {
257            p.append("-d");
258        } else if (requiresDirectPublishPermission()) {
259            p.append("+d");
260        }
261
262        return p.toString();
263    }
264
265    /**
266     * @see java.lang.Object#hashCode()
267     */
268    @Override
269    public int hashCode() {
270
271        return m_allowed * m_denied;
272    }
273
274    /**
275     * Returns true if control permissions (+c) are required by this permission set.<p>
276     *
277     * @return true if control permissions (+c) are required by this permission set
278     */
279    public boolean requiresControlPermission() {
280
281        return 0 < (m_allowed & CmsPermissionSet.PERMISSION_CONTROL);
282    }
283
284    /**
285     * Returns true if direct publish permissions (+d) are required by this permission set.<p>
286     *
287     * @return true if direct publish permissions (+d) are required by this permission set
288     */
289    public boolean requiresDirectPublishPermission() {
290
291        return 0 < (m_allowed & CmsPermissionSet.PERMISSION_DIRECT_PUBLISH);
292    }
293
294    /**
295     * Returns true if read permissions (+r) are required by this permission set.<p>
296     *
297     * @return true if read permissions (+r) are required by this permission set
298     */
299    public boolean requiresReadPermission() {
300
301        return 0 < (m_allowed & CmsPermissionSet.PERMISSION_READ);
302    }
303
304    /**
305     * Returns true if view permissions (+v) are required by this permission set.<p>
306     *
307     * @return true if view permissions (+v) are required by this permission set
308     */
309    public boolean requiresViewPermission() {
310
311        return 0 < (m_allowed & CmsPermissionSet.PERMISSION_VIEW);
312    }
313
314    /**
315     * Returns true if write permissions (+w) are required by this permission set.<p>
316     *
317     * @return true if write permissions (+w) are required by this permission set
318     */
319    public boolean requiresWritePermission() {
320
321        return 0 < (m_allowed & CmsPermissionSet.PERMISSION_WRITE);
322    }
323
324    /**
325     * Returns the String representation of this permission set object.<p>
326     *
327     * @see java.lang.Object#toString()
328     */
329    @Override
330    public String toString() {
331
332        return "[PermissionSet:] " + getPermissionString();
333    }
334}