package org.gcube.portlets.user.geoportaldataentry.server.config; import static org.gcube.resources.discovery.icclient.ICFactory.client; import java.io.File; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.gcube.application.geoportalcommon.shared.exception.ApplicationProfileNotFoundException; import org.gcube.common.resources.gcore.utils.XPathHelper; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.portlets.user.geoportaldataentry.shared.ACTION_ON_ITEM; import org.gcube.portlets.user.geoportaldataentry.shared.GNAUserRightsConfigException; import org.gcube.portlets.user.geoportaldataentry.shared.GcubeUserRole; import org.gcube.portlets.user.geoportaldataentry.shared.RoleRights; import org.gcube.portlets.user.geoportaldataentry.shared.RoleRights.OPERATION_TYPE; import org.gcube.resources.discovery.client.api.DiscoveryClient; import org.gcube.resources.discovery.client.queries.api.Query; import org.gcube.resources.discovery.client.queries.impl.QueryBox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.xml.sax.InputSource; /** * The Class GNADataEntryConfigsProfileReader. * * @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it * * Dec 2, 2021 */ public class GNADataEntryConfigsProfileReader { private static final String RESOURCE_PROFILE_BODY = "/Resource/Profile/Body"; public static final String SECONDARY_TYPE = "ApplicationProfile"; public static final String GENERIC_RESOURCE_NAME = "GNA-DataEntry-Configs"; private static final String TEMP_ROLE_RIGHTS_CONFIG_FILENAME = "GNA_RoleRights_Configurations"; private String scope; private static final Logger LOG = LoggerFactory.getLogger(GNADataEntryConfigsProfileReader.class); /** * Instantiates a new application profile reader. */ public GNADataEntryConfigsProfileReader() { } /** * Read profile from infrastrucure. * * @return the map * @throws Exception the exception */ public GNADataEntryConfigs readProfileFromInfrastrucure() throws Exception { LOG.info("called readProfileFromInfrastrucure"); String queryString = getGcubeGenericQueryString(SECONDARY_TYPE, GENERIC_RESOURCE_NAME); LOG.info("Scope " + scope + ", trying to perform query: " + queryString); this.scope = ScopeProvider.instance.get(); if (scope == null) throw new Exception("Scope is null, set scope into ScopeProvider"); GNADataEntryConfigs gnDEC = new GNADataEntryConfigs(); String permissions_for_role = ""; try { LOG.info("Trying to fetch GR named: " + GENERIC_RESOURCE_NAME + ", in the scope: " + scope + ", SecondaryType: " + SECONDARY_TYPE); Query q = new QueryBox(queryString); DiscoveryClient client = client(); List appProfile = client.submit(q); if (appProfile == null || appProfile.size() == 0) throw new ApplicationProfileNotFoundException("GR with SecondaryType: " + SECONDARY_TYPE + ", and name: " + GENERIC_RESOURCE_NAME + " is not registered in the scope: " + scope); else { String elem = appProfile.get(0); DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = docBuilder.parse(new InputSource(new StringReader(elem))); XPathHelper helper = new XPathHelper(doc.getDocumentElement()); List currValue = null; String xPathExp = RESOURCE_PROFILE_BODY + "/permssions_for_role/text()"; currValue = helper.evaluate(xPathExp); if (currValue != null && currValue.size() > 0) { permissions_for_role = currValue.get(0); } else throw new Exception("I'm not able to read the path: " + xPathExp); //replacing \n with new_line string LOG.debug("read permissions_for_role: " + permissions_for_role); String pfr_with_new_lines = permissions_for_role.replaceAll("\\\\n", System.lineSeparator()); LOG.debug("permissions_for_role with new lines: " + pfr_with_new_lines); List listRoleRights = readRoleRightsConfig(pfr_with_new_lines); gnDEC.setPermissionsForRole(listRoleRights); LOG.info("returning: " + gnDEC); return gnDEC; } } catch (Exception e) { LOG.error("Error while trying to read the " + SECONDARY_TYPE + " with SecondaryType " + GENERIC_RESOURCE_NAME + " from scope " + scope, e); return null; } finally { } } /** * To gcube user role. * * @param name the name * @return the gcube user role */ public static GcubeUserRole toGcubeUserRole(String name) { for (GcubeUserRole gCubeUserRole : GcubeUserRole.values()) { if (gCubeUserRole.getName().equalsIgnoreCase(name)) return gCubeUserRole; } return null; } /** * Read user rights config. * * @param permissions_for_role the permissions for role * @return the list * @throws GNAUserRightsConfigException the GNA user rights config not found * exception */ public List readRoleRightsConfig(String permissions_for_role) throws GNAUserRightsConfigException { LOG.debug("readRoleRightsConfig called"); File configurationFile = null; List listUserRights = new ArrayList(); try { configurationFile = FileUtil.inputStreamToTempFile(permissions_for_role, TEMP_ROLE_RIGHTS_CONFIG_FILENAME); CSVReader reader = new CSVReader(configurationFile); CSVFile csvFile = reader.getCsvFile(); List headerKeys = csvFile.getHeaderRow().getListValues(); List rows = csvFile.getValueRows(); // MAPPING OPERATION TYPE AS READ, WRITE, etc. Map mapOperationTypes = new HashMap(); CSVRow operationTypeRow = rows.get(0); List rowValues = operationTypeRow.getListValues(); for (int j = 1; j < rowValues.size(); j++) { String operationType = rowValues.get(j); RoleRights.OPERATION_TYPE ot = RoleRights.OPERATION_TYPE.UNKNOWN; if (operationType.equalsIgnoreCase("R")) { ot = RoleRights.OPERATION_TYPE.READ; } else if (operationType.equalsIgnoreCase("RW")) { ot = RoleRights.OPERATION_TYPE.READ_WRITE; } else if (operationType.equalsIgnoreCase("W")) { ot = RoleRights.OPERATION_TYPE.WRITE; } mapOperationTypes.put(headerKeys.get(j), ot); } LOG.debug("Map of operation types: " + mapOperationTypes); // Starting from index 1 (means the second row in the CSV) for (int i = 1; i < rows.size(); i++) { LOG.trace(i + " row"); RoleRights useRights = new RoleRights(); CSVRow row = rows.get(i); // to map properties rowValues = row.getListValues(); LOG.debug("rowValues: " + rowValues); Map mapUserRolePermissions = new HashMap(); GcubeUserRole gCubeUserRole = toGcubeUserRole(rowValues.get(0)); if (gCubeUserRole == null) { LOG.warn("The Role " + rowValues.get(0) + " not found into roleName of: " + GcubeUserRole.values()); continue; } useRights.setUserRole(gCubeUserRole); for (int j = 1; j < rowValues.size(); j++) { mapUserRolePermissions.put(headerKeys.get(j), rowValues.get(j)); } LOG.debug("Role: " + useRights.getUserRole()); LOG.debug("Permissions read: " + mapUserRolePermissions); Map listPermessions = new HashMap(); for (ACTION_ON_ITEM value : ACTION_ON_ITEM.values()) { String yesno = mapUserRolePermissions.get(value.name()); if (yesno != null && yesno.equalsIgnoreCase("yes")) { listPermessions.put(value, mapOperationTypes.get(value.name())); } } useRights.setListPermessions(listPermessions); // String writeOwn = mapUserRolePermissions.get(WRITE_OWN_CONFIG); // if (writeOwn != null && writeOwn.equalsIgnoreCase("yes")) { // useRights.setWriteOwn(true); // } // // String writeAny = mapUserRolePermissions.get(WRITE_ANY_CONFIG); // if (writeAny != null && writeAny.equalsIgnoreCase("yes")) { // useRights.setWriteAny(true); // } listUserRights.add(useRights); } LOG.info("Returning user rights config: " + listUserRights); return listUserRights; } catch (Exception e) { LOG.error("An error occurred on reading the GNA DataEntry config from: " + permissions_for_role, e); throw new GNAUserRightsConfigException("Error on reading the GNA DataEntry from: " + permissions_for_role); } finally { if (configurationFile != null) { try { configurationFile.delete(); } catch (Exception e) { // silent } } } } /** * Gets the gcube generic query string. * * @param secondaryType the secondary type * @param genericResourceName the generic resource name * @return the gcube generic query string */ public static String getGcubeGenericQueryString(String secondaryType, String genericResourceName) { return "for $profile in collection('/db/Profiles/GenericResource')//Resource " + "where $profile/Profile/SecondaryType/string() eq '" + secondaryType + "' and $profile/Profile/Name/string() " + " eq '" + genericResourceName + "'" + "return $profile"; } /** * Gets the secondary type. * * @return the secondary type */ public String getSecondaryType() { return SECONDARY_TYPE; } /** * Gets the scope. * * @return the scope */ public String getScope() { return scope; } }