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, 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.ade.contenteditor;
029
030import org.opencms.ade.contenteditor.CmsWidgetUtil.WidgetInfo;
031import org.opencms.file.CmsGroup;
032import org.opencms.file.CmsObject;
033import org.opencms.json.JSONObject;
034import org.opencms.main.CmsLog;
035import org.opencms.main.OpenCms;
036import org.opencms.security.CmsRole;
037import org.opencms.util.CmsFileUtil;
038import org.opencms.util.CmsStringUtil;
039import org.opencms.widgets.CmsAccessRestrictionWidget;
040import org.opencms.xml.CmsXmlContentDefinition;
041import org.opencms.xml.types.CmsXmlAccessRestrictionValue;
042import org.opencms.xml.types.CmsXmlNestedContentDefinition;
043import org.opencms.xml.types.I_CmsXmlSchemaType;
044
045import java.util.HashMap;
046import java.util.Map;
047
048import org.apache.commons.logging.Log;
049
050/**
051 * Class for representing information about a 'restriction' field defined in a schema.
052 */
053public class CmsAccessRestrictionInfo {
054
055    /** The role that can ignore group membership for manipulating the 'restricted' status. */
056    public static final CmsRole ROLE_CAN_IGNORE_GROUP = CmsRole.ROOT_ADMIN;
057
058    /** Log instance for this class. */
059    private static final Log LOG = CmsLog.getLog(CmsAccessRestrictionInfo.class);
060
061    /** The restriction group. */
062    private CmsGroup m_group;
063
064    /** The xpath for the restriction field in the schema. */
065    private String m_path;
066
067    /**
068     * Creates a new instance.
069     *
070     * @param path the xpath for the restriction field in the schema
071     * @param group the restriction group
072     */
073    public CmsAccessRestrictionInfo(String path, CmsGroup group) {
074
075        super();
076        m_path = path;
077        m_group = group;
078    }
079
080    /**
081     * Helper method for collecting all nested schema types of a content definition in a map.
082     *
083     * <p>The map keys in the resulting map will be the xpaths corresponding to the schema types.
084     *
085     * @param definition a content definition
086     * @param path the path to start with
087     * @param typesByPath the map in which the schema types should be stored
088     */
089    public static void collectTypesByPath(
090        CmsXmlContentDefinition definition,
091        String path,
092        Map<String, I_CmsXmlSchemaType> typesByPath) {
093
094        for (I_CmsXmlSchemaType schemaType : definition.getTypeSequence()) {
095            String name = schemaType.getName();
096            String subPath = path + "/" + name;
097            typesByPath.put(CmsFileUtil.removeLeadingSeparator(subPath), schemaType);
098            if (schemaType instanceof CmsXmlNestedContentDefinition) {
099                CmsXmlContentDefinition nestedDef = ((CmsXmlNestedContentDefinition)schemaType).getNestedContentDefinition();
100                if (nestedDef != null) {
101                    collectTypesByPath(nestedDef, subPath, typesByPath);
102                }
103            }
104        }
105    }
106
107    /**
108     * Gets the restriction info for the current user and content definition.
109     *
110     * <p>This will only return a non-null value if the is restriction field defined in the content definition <em>and</em> the current user is in the group configured as the restriction group for that field.
111     *
112     * @param cms the current CMS context
113     * @param contentDef the content definition
114     *
115     * @return the restriction information
116     */
117    public static CmsAccessRestrictionInfo getRestrictionInfo(CmsObject cms, CmsXmlContentDefinition contentDef) {
118
119        Map<String, I_CmsXmlSchemaType> typesByPath = new HashMap<>();
120        collectTypesByPath(contentDef, "", typesByPath);
121        for (Map.Entry<String, I_CmsXmlSchemaType> entry : typesByPath.entrySet()) {
122            I_CmsXmlSchemaType type = entry.getValue();
123            try {
124                if (type instanceof CmsXmlAccessRestrictionValue) {
125                    WidgetInfo widgetInfo = CmsWidgetUtil.collectWidgetInfo(cms, contentDef, entry.getKey(), null, null);
126                    String widgetConfig = widgetInfo.getWidget().getConfiguration();
127                    if (widgetConfig != null) {
128                        JSONObject json = new JSONObject(widgetConfig);
129                        String groupName = json.optString(CmsAccessRestrictionWidget.ATTR_GROUP);
130                        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(groupName)) {
131                            groupName = groupName.trim();
132                            if (OpenCms.getRoleManager().hasRole(cms, ROLE_CAN_IGNORE_GROUP)
133                                || cms.userInGroup(cms.getRequestContext().getCurrentUser().getName(), groupName)) {
134                                return new CmsAccessRestrictionInfo(entry.getKey(), cms.readGroup(groupName));
135                            }
136                        }
137                    }
138                    break;
139                }
140            } catch (Exception e) {
141                LOG.error(e.getLocalizedMessage(), e);
142            }
143        }
144        return null;
145
146    }
147
148    /**
149     * Gets the restriction group.
150     *
151     * @return the restriction group
152     */
153    public CmsGroup getGroup() {
154
155        return m_group;
156    }
157
158    /**
159     * Gets the xpath of the restriction field.
160     *
161     * @return the xpath of the restriction field
162     */
163    public String getPath() {
164
165        return m_path;
166    }
167
168}