/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.framework.security.metadata; import com.esri.gpt.catalog.arcims.ImsMetadataAdminDao; import com.esri.gpt.framework.context.RequestContext; import com.esri.gpt.framework.security.identity.AuthenticationStatus; import com.esri.gpt.framework.security.identity.IdentityException; import com.esri.gpt.framework.security.principal.Group; import com.esri.gpt.framework.security.principal.Groups; import com.esri.gpt.framework.security.principal.User; import com.esri.gpt.framework.util.Val; import com.esri.gpt.framework.xml.DomUtil; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.logging.Logger; import javax.naming.NamingException; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** * This class is used to metadata build access control lists. */ public class MetadataAcl { /** class variables ========================================================= */ /** Logger */ private static Logger LOGGER = Logger.getLogger(MetadataAcl.class.getName()); /** instance variables ====================================================== */ private RequestContext _requestContext = null; /** * Constructor. * @param context the active request context */ public MetadataAcl(RequestContext context) { _requestContext = context; } /** methods ================================================================= */ /** * Build list of selected groups * @param groups groups * @param pickedGroups picked groups * @return acl */ public String buildAclGroups(Groups groups, ArrayList<String> pickedGroups) { // TODO: Transfer ownership of documents is an issue since // user might not be member of a group for acl is set for a document Collection<Group> grps = groups.values(); Groups selectedGroups = new Groups(); for (String o : pickedGroups) { for (Group group : grps) { if (group != null && group.getName().equals(o)) { selectedGroups.add(group); break; } } } if (selectedGroups.size() > 0) { } else { for (String o : pickedGroups) { Group group = groups.get(o); if (group != null) { selectedGroups.add(group); } } } StringBuffer sbAclXml = new StringBuffer(); if (selectedGroups != null && selectedGroups.isEmpty()) { return null; } sbAclXml.append("<acl>"); for (Group group : selectedGroups.values()) { sbAclXml.append("<principal type=\"groupDn\">"); sbAclXml.append(Val.escapeXml(group.getDistinguishedName())); sbAclXml.append("</principal>"); } sbAclXml.append("</acl>"); return sbAclXml.toString(); } /** * * @param xml * @return document ACL * @throws ParserConfigurationException * @throws SAXException * @throws IOException */ private HashMap<String, String> buildDocumentAcl(String xml) throws ParserConfigurationException, SAXException, IOException { Document document = null; HashMap<String, String> acls = new HashMap<String, String>(); if (xml != null && xml.trim().length() > 0) { document = DomUtil.makeDomFromString(xml, false); } if (document != null) { NodeList principalNodes = document.getElementsByTagName("principal"); if (principalNodes != null && principalNodes.getLength() > 0) { for (int i = 0; i < principalNodes.getLength(); i++) { Node principalNode = principalNodes.item(i); NamedNodeMap attributes = principalNode.getAttributes(); if (attributes.getNamedItem("type").getNodeValue().equalsIgnoreCase("groupDn")) { String acl = "g." + principalNode.getTextContent(); acl = acl.toUpperCase().trim(); acls.put(acl, acl); } } } } return acls; } /** * Indicates if the user has read access for the document with given UUID. * @param user the application user * @param uuid the document uuid * @return true if the user has read access * @throws IOException * @throws SAXException * @throws ParserConfigurationException * @throws SQLException */ public boolean hasReadAccess(User user, String uuid) throws SQLException, ParserConfigurationException, SAXException, IOException { AuthenticationStatus auth = user.getAuthenticationStatus(); boolean bAdmin = auth.getAuthenticatedRoles().hasRole("gptAdministrator"); if (bAdmin || isPolicyUnrestricted()) { return true; } else { if (uuid == null) { return true; } if (user == null) { return false; } HashMap<String, String> acls = makeDocumentAclFromUUID(uuid); if (acls != null && acls.size() > 0) { Groups groups = user.getGroups(); for (Group group : groups.values()) { String userAclKey = makeAclString(group); userAclKey = userAclKey.toUpperCase().trim(); if ((userAclKey.length() > 0) && acls.containsKey(userAclKey)) { return true; } } } else { return true; } } return false; } /** * Indicates if the application metadata access policy is unrestricted. * @return true if the policy is unrestricted */ public boolean isPolicyUnrestricted() { MetadataAccessPolicy cfg; cfg = _requestContext.getApplicationConfiguration().getMetadataAccessPolicy(); return cfg.isPolicyUnrestricted(); } /** * * @param group * @return ACL string */ private String makeAclString(Group group) { return "g." + group.getDistinguishedName(); } /** * Builds array of acl strings * @param xml xml string * @return document acl string array * @throws IOException * @throws SAXException * @throws ParserConfigurationException */ public String[] makeDocumentAcl(String xml) throws ParserConfigurationException, SAXException, IOException { return buildDocumentAcl(xml).values().toArray(new String[0]); } /** * Builds hashed map of acl values * @param uuid the document uuid * @return document acl HashMap * @throws SQLException * @throws IOException * @throws SAXException * @throws ParserConfigurationException */ private HashMap<String, String> makeDocumentAclFromUUID(String uuid) throws SQLException, ParserConfigurationException, SAXException, IOException { ImsMetadataAdminDao adminDao = new ImsMetadataAdminDao(_requestContext); String xml = adminDao.queryAclByUUID(uuid); return buildDocumentAcl(xml); } /** * Returns groups from acl xml string * @param groups group * @param xml xml * @return string representation of groups * @throws IOException * @throws SAXException * @throws ParserConfigurationException */ public String makeGroupsfromXml(Groups groups, String xml) throws ParserConfigurationException, SAXException, IOException { StringBuffer selectedGroups = new StringBuffer(); Document document = null; if (xml != null && xml.trim().length() > 0) { document = DomUtil.makeDomFromString(xml, true); } else { return null; } if (document != null) { NodeList principalNodes = document.getElementsByTagName("principal"); if (principalNodes != null && principalNodes.getLength() > 0) { for (int i = 0; i < principalNodes.getLength(); i++) { Node principalNode = principalNodes.item(i); NamedNodeMap attributes = principalNode.getAttributes(); if (attributes.getNamedItem("type").getNodeValue().equalsIgnoreCase( "groupDn")) { Group group = groups.get(principalNode.getTextContent()); if (group != null) selectedGroups.append(group.getName()).append(","); } } } } return selectedGroups.length() > 0 ? selectedGroups.substring(0, selectedGroups.length() - 1) : null; } /** * Makes group keys from XML string. * @param groups groups * @param xml XML string * @return string representation of groups * @throws ParserConfigurationException * @throws SAXException * @throws IOException */ public String makeGroupsKeysfromXml(Groups groups, String xml) throws ParserConfigurationException, SAXException, IOException { StringBuffer selectedGroups = new StringBuffer(); Document document = null; if (xml != null && xml.trim().length() > 0) { document = DomUtil.makeDomFromString(xml, true); } else { return null; } if (document != null) { NodeList principalNodes = document.getElementsByTagName("principal"); if (principalNodes != null && principalNodes.getLength() > 0) { for (int i = 0; i < principalNodes.getLength(); i++) { Node principalNode = principalNodes.item(i); NamedNodeMap attributes = principalNode.getAttributes(); if (attributes.getNamedItem("type").getNodeValue().equalsIgnoreCase("groupDn")) { Group group = groups.get(principalNode.getTextContent()); if (group != null) selectedGroups.append(group.getKey()).append("\u2715"); } } } } return selectedGroups.length() > 0 ? selectedGroups.substring(0, selectedGroups.length() - 1) : null; } /** * Builds array of acl strings * @return user acl string array * @throws SQLException * @throws NamingException * @throws IdentityException */ public String[] makeUserAcl() { User user = _requestContext.getUser(); /* groups have already been read for the user try { _requestContext.newIdentityAdapter().readUserGroups(user); } catch (IdentityException e) { LOGGER.severe(e.getMessage()); } catch (NamingException e) { LOGGER.severe(e.getMessage()); } catch (SQLException e) { LOGGER.severe(e.getMessage()); } */ Groups groups = user.getGroups(); ArrayList<String> acls = new ArrayList<String>(); for (Group group : groups.values()) { acls.add(makeAclString(group)); } return acls.toArray(new String[0]); } }