org.wso2.carbon.identity.mgt.endpoint.IdentityManagementEndpointUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.mgt.endpoint.IdentityManagementEndpointUtil.java

Source

/*
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 *  WSO2 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 org.wso2.carbon.identity.mgt.endpoint;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.apache.axiom.om.util.Base64;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.Bus;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
import org.json.JSONArray;
import org.json.JSONObject;
import org.owasp.encoder.Encode;
import org.wso2.carbon.identity.mgt.endpoint.client.ApiException;
import org.wso2.carbon.identity.mgt.endpoint.client.api.UsernameRecoveryApi;
import org.wso2.carbon.identity.mgt.endpoint.client.model.Claim;
import org.wso2.carbon.identity.mgt.endpoint.client.model.User;
import org.wso2.carbon.identity.mgt.stub.beans.VerificationBean;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * This class defines utility methods used within this web application.
 */
public class IdentityManagementEndpointUtil {

    public static final String PADDING_CHAR = "=";
    public static final String UNDERSCORE = "_";
    public static final String PII_CATEGORIES = "piiCategories";
    public static final String PII_CATEGORY = "piiCategory";
    public static final String PURPOSES = "purposes";
    public static final String MANDATORY = "mandatory";
    public static final String DISPLAY_NAME = "displayName";

    private static final Log log = LogFactory.getLog(IdentityManagementEndpointUtil.class);

    private IdentityManagementEndpointUtil() {

    }

    /**
     * Reruns the full qualified username of the user in below format.
     * <user_store_domain>/<username>@<tenant_domain>
     *
     * @param username        username of the user
     * @param tenantDomain    tenant domain the user belongs to
     * @param userStoreDomain user store domain usee belongs to
     * @return full qualified username
     */
    public static final String getFullQualifiedUsername(String username, String tenantDomain,
            String userStoreDomain) {

        String fullQualifiedUsername = username;
        if (StringUtils.isNotBlank(userStoreDomain)
                && !IdentityManagementEndpointConstants.PRIMARY_USER_STORE_DOMAIN.equals(userStoreDomain)) {
            fullQualifiedUsername = userStoreDomain
                    + IdentityManagementEndpointConstants.USER_STORE_DOMAIN_SEPARATOR + fullQualifiedUsername;
        }

        if (StringUtils.isNotBlank(tenantDomain)
                && !IdentityManagementEndpointConstants.SUPER_TENANT.equals(tenantDomain)) {
            fullQualifiedUsername = fullQualifiedUsername
                    + IdentityManagementEndpointConstants.TENANT_DOMAIN_SEPARATOR + tenantDomain;
        }

        return fullQualifiedUsername;
    }

    /**
     * Returns the error to be viewed for end user.
     *
     * @param errorMsgSummary  required error message to be viewed
     * @param optionalErrorMsg optional content to be viewed
     * @param verificationBean info recovery confirmation bean
     * @return error message to be viewed
     */
    public static String getPrintableError(String errorMsgSummary, String optionalErrorMsg,
            VerificationBean verificationBean) {

        StringBuilder errorMsg = new StringBuilder(errorMsgSummary);

        if (verificationBean != null && StringUtils.isNotBlank(verificationBean.getError())) {
            String[] error = verificationBean.getError().split(" ", 2);
            errorMsg.append(" ").append(error[1]);
        } else if (StringUtils.isNotBlank(optionalErrorMsg)) {
            errorMsg.append(" ").append(optionalErrorMsg);
        }

        return errorMsg.toString();
    }

    /**
     * Returns the end user portal url.
     *
     * @param userPortalUrl configured user portal url
     * @return configured url or the default url if configured url is empty
     */
    public static final String getUserPortalUrl(String userPortalUrl) {

        if (StringUtils.isNotBlank(userPortalUrl)) {
            return userPortalUrl;
        }
        return IdentityManagementEndpointConstants.DEFAULT_USER_PORTAL_URL;
    }

    /**
     * Cast the provided Object to a Boolean
     *
     * @param value Object
     * @return Boolean
     */
    public static boolean getBooleanValue(Object value) {

        if (value != null && value instanceof Boolean) {
            return (Boolean) value;
        }

        return false;
    }

    /**
     * Cast the provided Object to a String
     *
     * @param value Object
     * @return String
     */
    public static String getStringValue(Object value) {

        if (value != null && value instanceof String) {
            return (String) value;
        }

        return "";
    }

    /**
     * Cast provided Object to an Integer
     *
     * @param value Object
     * @return Integer
     */
    public static int getIntValue(Object value) {

        if (value != null && value instanceof Integer) {
            return (Integer) value;
        }

        return 0;
    }

    /**
     * Cast provided Object to a String[]
     *
     * @param value Object
     * @return String[]
     */
    public static String[] getStringArray(Object value) {

        if (value != null && value instanceof String[]) {
            return (String[]) value;
        }

        return ArrayUtils.EMPTY_STRING_ARRAY;
    }

    public static <T> T create(String baseAddress, Class<T> cls, List<?> providers, String configLocation,
            Map<String, String> headers) {

        JAXRSClientFactoryBean bean = getBean(baseAddress, cls, configLocation, headers);
        bean.setProviders(providers);
        return bean.create(cls, new Object[0]);
    }

    private static JAXRSClientFactoryBean getBean(String baseAddress, Class<?> cls, String configLocation,
            Map<String, String> headers) {

        JAXRSClientFactoryBean bean = getBean(baseAddress, configLocation, headers);
        bean.setServiceClass(cls);
        return bean;
    }

    static JAXRSClientFactoryBean getBean(String baseAddress, String configLocation, Map<String, String> headers) {

        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
        if (configLocation != null) {
            SpringBusFactory bf = new SpringBusFactory();
            Bus bus = bf.createBus(configLocation);
            bean.setBus(bus);
        }
        bean.setAddress(baseAddress);
        if (headers != null && !headers.isEmpty()) {
            bean.setHeaders(headers);
        }
        return bean;
    }

    public static void addReCaptchaHeaders(HttpServletRequest request, Map<String, List<String>> headers) {

        if (headers != null && headers.get("reCaptcha") != null) {
            request.setAttribute("reCaptcha", Boolean.TRUE.toString());
            request.setAttribute("reCaptchaAPI", headers.get("reCaptchaAPI").get(0));
            request.setAttribute("reCaptchaKey", headers.get("reCaptchaKey").get(0));
        }
    }

    /**
     * Builds consent string according to consent API. This string can be used as the body of add receipt API
     *
     * @param username               Username of the user.
     * @param consent                Consent String which contains services.
     * @param jurisdiction           Jurisdiction.
     * @param collectionMethod       Collection Method.
     * @param language               Language.
     * @param policyURL              Policy URL.
     * @param consentType            Consent Type.
     * @param isPrimaryPurpose       Whether this this receipt is for primary purpose.
     * @param isThirdPartyDisclosure Whether this receipt can be disclosed to thrid parties.
     * @param termination            Termination date.
     * @return Consent string which contains above facts.
     */
    public static String buildConsentForResidentIDP(String username, String consent, String jurisdiction,
            String collectionMethod, String language, String policyURL, String consentType,
            boolean isPrimaryPurpose, boolean isThirdPartyDisclosure, String termination) {

        if (StringUtils.isEmpty(consent)) {
            if (log.isDebugEnabled()) {
                log.debug("Empty consent string. Hence returning without building consent from endpoint");
            }
            return consent;
        }
        String piiPrincipalId = getPiiPrincipalID(username);
        JSONObject receipt = new JSONObject(consent);
        receipt.put(IdentityManagementEndpointConstants.Consent.JURISDICTION_KEY, jurisdiction);
        receipt.put(IdentityManagementEndpointConstants.Consent.COLLECTION_METHOD_KEY, collectionMethod);
        receipt.put(IdentityManagementEndpointConstants.Consent.LANGUAGE_KEY, language);
        receipt.put(IdentityManagementEndpointConstants.Consent.PII_PRINCIPAL_ID_KEY, piiPrincipalId);
        receipt.put(IdentityManagementEndpointConstants.Consent.POLICY_URL_KEY, policyURL);
        buildServices(receipt, consentType, isPrimaryPurpose, isThirdPartyDisclosure, termination);
        if (log.isDebugEnabled()) {
            log.debug("Built consent from endpoint util : " + consent);
        }

        return receipt.toString();
    }

    private static String getPiiPrincipalID(String username) {

        User user = IdentityManagementServiceUtil.getInstance().getUser(username);
        String piiPrincipalId;

        if (StringUtils.isNotBlank(user.getRealm())
                && !IdentityManagementEndpointConstants.PRIMARY_USER_STORE_DOMAIN.equals(user.getRealm())) {
            piiPrincipalId = user.getRealm() + IdentityManagementEndpointConstants.USER_STORE_DOMAIN_SEPARATOR
                    + user.getUsername();
        } else {
            piiPrincipalId = user.getUsername();
        }
        return piiPrincipalId;
    }

    private static void buildServices(JSONObject receipt, String consentType, boolean isPrimaryPurpose,
            boolean isThirdPartyDisclosure, String termination) {

        JSONArray services = (JSONArray) receipt.get(IdentityManagementEndpointConstants.Consent.SERVICES);
        for (int serviceIndex = 0; serviceIndex < services.length(); serviceIndex++) {
            buildService((JSONObject) services.get(serviceIndex), consentType, isPrimaryPurpose,
                    isThirdPartyDisclosure, termination);
        }
    }

    private static void buildService(JSONObject service, String consentType, boolean isPrimaryPurpose,
            boolean isThirdPartyDisclosure, String termination) {

        JSONArray purposes = (JSONArray) service.get(IdentityManagementEndpointConstants.Consent.PURPOSES);

        for (int purposeIndex = 0; purposeIndex < purposes.length(); purposeIndex++) {
            buildPurpose((JSONObject) purposes.get(purposeIndex), consentType, isPrimaryPurpose,
                    isThirdPartyDisclosure, termination);
        }
    }

    private static void buildPurpose(JSONObject purpose, String consentType, boolean isPrimaryPurpose,
            boolean isThirdPartyDisclosure, String termination) {

        purpose.put(IdentityManagementEndpointConstants.Consent.CONSENT_TYPE_KEY, consentType);
        purpose.put(IdentityManagementEndpointConstants.Consent.PRIMARY_PURPOSE_KEY, isPrimaryPurpose);
        purpose.put(IdentityManagementEndpointConstants.Consent.THRID_PARTY_DISCLOSURE_KEY, isThirdPartyDisclosure);
        purpose.put(IdentityManagementEndpointConstants.Consent.TERMINATION_KEY, termination);
        JSONArray piiCategories = (JSONArray) purpose.get(IdentityManagementEndpointConstants.Consent.PII_CATEGORY);
        for (int categoryIndex = 0; categoryIndex < piiCategories.length(); categoryIndex++) {
            buildCategory((JSONObject) piiCategories.get(categoryIndex), termination);
        }
    }

    private static void buildCategory(JSONObject piiCategory, String validity) {

        piiCategory.put(IdentityManagementEndpointConstants.Consent.VALIDITY_KEY, validity);
    }

    /**
     * To get the property value for the given key from the ResourceBundle
     * Retrieve the value of property entry for key, return key if a value is not found for key
     *
     * @param resourceBundle name of the resourcebundle object
     * @param key            name of the key
     * @return property value entry of the key or key value itself
     */
    public static String i18n(ResourceBundle resourceBundle, String key) {

        try {
            return Encode.forHtml(
                    (StringUtils.isNotBlank(resourceBundle.getString(key)) ? resourceBundle.getString(key) : key));
        } catch (Exception e) {
            // Intentionally catching Exception and if something goes wrong while finding the value for key, return
            // default, not to break the UI
            return Encode.forHtml(key);
        }
    }

    /**
     * To get the property value for the base64 encoded value of the key from the ResourceBundle
     * Retrieve the value of property entry for where key is obtained after replacing "=" with "_" of base64 encoded
     * value of the given key,
     * return key if a value is not found for above calculated
     *
     * @param resourceBundle name of the resourcebundle object
     * @param key            name of the key
     * @return property value entry of the base64 encoded key value or key value itself
     */
    public static String i18nBase64(ResourceBundle resourceBundle, String key) {

        String base64Key = Base64.encode(key.getBytes(StandardCharsets.UTF_8)).replaceAll(PADDING_CHAR, UNDERSCORE);
        try {
            return Encode.forHtml((StringUtils.isNotBlank(resourceBundle.getString(base64Key))
                    ? resourceBundle.getString(base64Key)
                    : key));
        } catch (Exception e) {
            // Intentionally catching Exception and if something goes wrong while finding the value for key, return
            // default, not to break the UI
            return Encode.forHtml(key);
        }
    }

    /**
     * Get unique PIIs out of given purposes.
     *
     * @param purposesResponseString Purposes response JSON received from Consent Mgt API.
     * @return Unique PIIs out of given purposes in the purposes JSON String.
     */
    public static Map<String, Claim> getUniquePIIs(String purposesResponseString) {

        Map<String, Claim> claimsMap = new HashMap<>();
        JSONObject purposes = new JSONObject(purposesResponseString);
        JSONArray purposesArray = purposes.getJSONArray(PURPOSES);
        for (int i = 0; i < purposesArray.length(); i++) {
            JSONObject purpose = purposesArray.getJSONObject(i);
            JSONArray piis = (JSONArray) purpose.get(PII_CATEGORIES);
            for (int j = 0; j < piis.length(); j++) {
                JSONObject pii = piis.getJSONObject(j);
                if (claimsMap.get(pii.getString(PII_CATEGORY)) == null) {
                    Claim claim = new Claim();
                    claim.displayName(getStringValue(pii.get(DISPLAY_NAME)));
                    claim.setUri(getStringValue(pii.get(PII_CATEGORY)));
                    claim.required(pii.getBoolean(MANDATORY));
                    claimsMap.put(getStringValue(pii.get(PII_CATEGORY)), claim);
                } else {
                    Claim claim = claimsMap.get(pii.getString(PII_CATEGORY));
                    if (pii.getBoolean(MANDATORY)) {
                        claim.required(true);
                    }
                }
            }
        }
        return claimsMap;
    }

    public static Map<String, Claim> fillPiisWithClaimInfo(Map<String, Claim> piis, List<Claim> defaultClaims) {

        if (piis != null) {
            for (Claim defaultClaim : defaultClaims) {
                if (defaultClaim != null && defaultClaim.getUri() != null
                        && piis.get(defaultClaim.getUri()) != null) {
                    piis.get(defaultClaim.getUri()).setValidationRegex(defaultClaim.getValidationRegex());
                    piis.get(defaultClaim.getUri()).setReadOnly(defaultClaim.getReadOnly());
                }
            }
        } else {
            piis = new HashMap<>();
            for (Claim defaultClaim : defaultClaims) {
                if (defaultClaim != null && defaultClaim.getUri() != null) {
                    piis.put(defaultClaim.getUri(), defaultClaim);
                }
            }
        }
        return piis;
    }
}