001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008 Sun Microsystems, Inc.
015 * Portions Copyright 2013-2015 ForgeRock AS.
016 */
017package org.opends.server.authorization.dseecompat;
018
019import static org.opends.messages.AccessControlMessages.*;
020import static org.opends.server.authorization.dseecompat.Aci.*;
021
022import java.util.Iterator;
023import java.util.Set;
024import java.util.regex.Pattern;
025
026import org.forgerock.i18n.LocalizableMessage;
027
028/**
029 * A class representing the permissions of an bind rule. The permissions
030 * of an ACI look like deny(search, write).
031 */
032public class Permission {
033
034    /**
035     *  The access type (allow,deny) corresponding to the ACI permission value.
036     */
037    private EnumAccessType accessType;
038
039    /**
040     * The rights (search, add, delete, ...) corresponding to the ACI rights
041     * value.
042     */
043    private int rights;
044
045    /**
046     * Regular expression token representing the separator.
047     */
048    private static final String separatorToken = ",";
049
050    /**
051     * Regular expression used to match the ACI rights string.
052     */
053    private static final String rightsRegex = ZERO_OR_MORE_WHITESPACE +
054            WORD_GROUP + ZERO_OR_MORE_WHITESPACE +
055            "(," + ZERO_OR_MORE_WHITESPACE + WORD_GROUP +
056            ZERO_OR_MORE_WHITESPACE +  ")*";
057
058    /**
059     * Constructor creating a class representing a permission part of an bind
060     * rule.
061     * @param accessType A string representing access type.
062     * @param rights  A string representing the rights.
063     * @throws AciException If the access type string or rights string
064     * is invalid.
065     */
066    private Permission(String accessType, String rights)
067    throws AciException {
068        this.accessType = EnumAccessType.decode(accessType);
069        if (this.accessType == null){
070            LocalizableMessage message =
071                WARN_ACI_SYNTAX_INVALID_ACCESS_TYPE_VERSION.get(accessType);
072            throw new AciException(message);
073        }
074        if (!Pattern.matches(rightsRegex, rights)){
075            LocalizableMessage message = WARN_ACI_SYNTAX_INVALID_RIGHTS_SYNTAX.get(rights);
076            throw new AciException(message);
077        }
078        else {
079            Pattern separatorPattern = Pattern.compile(separatorToken);
080            String[] rightsStr =
081                separatorPattern.split(rights.replaceAll("\\s", ""));
082            for (String r : rightsStr) {
083                EnumRight right = EnumRight.decode(r);
084                if (right != null) {
085                  this.rights|= EnumRight.getMask(right);
086                } else {
087                    LocalizableMessage message =
088                        WARN_ACI_SYNTAX_INVALID_RIGHTS_KEYWORD.get(rights);
089                    throw new AciException(message);
090                }
091            }
092        }
093    }
094
095    /**
096     * Decode an string representation of bind rule permission into a Permission
097     * class.
098     * @param accessType  A string representing the access type.
099     * @param rights   A string representing the rights.
100     * @return  A Permission class representing the permissions of the bind
101     * rule.
102     * @throws AciException  If the accesstype or rights strings are invalid.
103     */
104    public static Permission decode (String accessType, String rights)
105            throws AciException {
106        return new Permission(accessType, rights);
107    }
108
109    /**
110     * Checks if a given access type enumeration is equal to this classes
111     * access type.
112     * @param accessType An enumeration representing an access type.
113     * @return True if the access types are equal.
114     */
115    public boolean hasAccessType(EnumAccessType accessType) {
116        return this.accessType == accessType;
117    }
118
119    /**
120     * Checks if the permission's rights has the specified rights.
121     * @param  rights The rights to check for.
122     * @return True if the permission's rights has the specified rights.
123     */
124    public boolean hasRights(int rights) {
125        return (this.rights & rights) != 0;
126    }
127
128    /** {@inheritDoc} */
129    @Override
130    public String toString() {
131        final StringBuilder sb = new StringBuilder();
132        toString(sb);
133        return sb.toString();
134    }
135
136    /**
137     * Appends a string representation of this object to the provided buffer.
138     *
139     * @param buffer
140     *          The buffer into which a string representation of this object
141     *          should be appended.
142     */
143    public final void toString(StringBuilder buffer) {
144        if (this.accessType != null) {
145            buffer.append(accessType.toString().toLowerCase());
146            Set<EnumRight> enumRights = EnumRight.getEnumRight(rights);
147            if (enumRights != null) {
148                buffer.append("(");
149                for (Iterator<EnumRight> iter = enumRights.iterator(); iter
150                        .hasNext();) {
151                    buffer.append(iter.next().getRight());
152                    if (iter.hasNext()) {
153                        buffer.append(",");
154                    }
155                }
156                buffer.append(")");
157            } else {
158                buffer.append("(all)");
159            }
160        }
161    }
162}