/*
 * Copyright (c) 2019, 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.util.client;

import org.apache.axis2.AxisFault;
import org.apache.axis2.client.ServiceClient;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;

import org.wso2.carbon.identity.application.common.model.idp.xsd.IdentityProvider;
import org.wso2.carbon.identity.application.common.model.idp.xsd.IdentityProviderProperty;
import org.wso2.carbon.identity.mgt.endpoint.util.IdentityManagementEndpointConstants;
import org.wso2.carbon.identity.mgt.endpoint.util.IdentityManagementEndpointUtil;
import org.wso2.carbon.idp.mgt.stub.IdentityProviderMgtServiceStub;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;

import java.net.URLEncoder;

/**
 * Validates the call back URL passed in the recovery request.
 */
public class CallBackValidator {

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

    /**
     * This method is to validate the callback URL in the request with the configured one.
     *
     * @param callbackURL  passed in the request
     * @param tenantDomain of the user
     * @return the status of the validation
     * @throws IdentityRecoveryException
     */
    public boolean isValidCallbackURL(String callbackURL, String tenantDomain, boolean isUserPortalURL)
            throws IdentityRecoveryException {

        if (isUserPortalURL) {
            if (log.isDebugEnabled()) {
                log.debug("Callback URL is equal to the user portal URL: " + isUserPortalURL);
            }
            return true;
        }

        if (StringUtils.isBlank(tenantDomain)) {
            tenantDomain = MultitenantConstants.SUPER_TENANT_DOMAIN_NAME;
            if (log.isDebugEnabled()) {
                log.debug("Tenant domain is considered as super tenant domain: " + tenantDomain);
            }
        }

        IdentityProvider residentIdP;
        try {
            IdentityProviderMgtServiceStub idPMgtStub = new IdentityProviderMgtServiceStub();
            ServiceClient idpClient = idPMgtStub._getServiceClient();
            IdentityManagementEndpointUtil.authenticate(idpClient);
            residentIdP = idPMgtStub.getResidentIdP();
        } catch (AxisFault axisFault) {
            throw new IdentityRecoveryException("Error while instantiating IdentityProviderMgtServiceStub", axisFault);
        } catch (Exception e) {
            throw new IdentityRecoveryException("Error occurred when getting residentIDP configurations.", e);
        }

        IdentityProviderProperty[] idpProperties = null;
        if (residentIdP != null) {
            idpProperties = residentIdP.getIdpProperties();
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Resident identity provider is not found for the tenant domain: " + tenantDomain);
            }
        }

        String callbackRegex = null;
        if (idpProperties != null) {
            for (IdentityProviderProperty property : idpProperties) {
                if (IdentityManagementEndpointConstants.UserInfoRecovery.RECOVERY_CALLBACK_REGEX.equals(property
                        .getValue())) {
                    callbackRegex = property.getValue();
                    if (log.isDebugEnabled()) {
                        log.debug("Configured recovery callback URL regex: " + callbackRegex);
                    }
                    break;
                }
            }
        }

        if (StringUtils.isNotBlank(callbackURL)) {
            try {
                String encodeURL = URLEncoder.encode(callbackURL, IdentityManagementEndpointConstants.UTF_8);
                URI uri = new URI(encodeURL);
                callbackURL = new URI(uri.getScheme(), uri.getAuthority(), uri.getPath(), null, null)
                        .toString();
                if (log.isDebugEnabled()) {
                    log.debug("Callbck URL in the username recovery request: " + callbackURL);
                }
            } catch (URISyntaxException e) {
                throw new IdentityRecoveryException("Error occurred while formatting the provided callback URL. ", e);
            } catch (UnsupportedEncodingException e) {
                throw new IdentityRecoveryException("Error occurred while encoding the provided callback URL.", e);
            }
        }

        return callbackRegex == null || callbackURL.matches(callbackRegex);
    }
}

@@ -1848,17 +1848,29 @@
 ackURL  
-p
+CallbackURL P
 assed in
@@ -1881,16 +1881,17 @@
  request
+.
 %0A     * 
@@ -1910,16 +1910,29 @@
 tDomain 
+TenantDomain 
 of the u
@@ -1934,16 +1934,17 @@
 the user
+.
 %0A     * 
@@ -1951,17 +1951,17 @@
 @return 
-t
+T
 he statu
@@ -1975,24 +1975,25 @@
 e validation
+.
 %0A     * @thr
@@ -2021,16 +2021,43 @@
 xception
+ IdentityRecoveryException.
 %0A     */
@@ -2138,33 +2138,8 @@
 main
-, boolean isUserPortalURL
 )%0A  
@@ -2188,224 +2188,8 @@
  %7B%0A%0A
-        if (isUserPortalURL) %7B%0A            if (log.isDebugEnabled()) %7B%0A                log.debug(%22Callback URL is equal to the user portal URL: %22 + isUserPortalURL);%0A            %7D%0A            return true;%0A        %7D%0A%0A
     
@@ -4499,16 +4499,17 @@
 g(%22Callb
+a
 ck URL i
@@ -5018,11 +5018,972 @@
 );%0A    %7D
+%0A%0A    /**%0A     * This method is to validate the callback URL in the request with the configured one.%0A     *%0A     * @param callbackURL     CallbackURL Passed in the request.%0A     * @param tenantDomain    TenantDomain of the user.%0A     * @param isUserPortalURL Whether this is the user portal url.%0A     * @return The status of the validation.%0A     * @throws IdentityRecoveryException IdentityRecoveryException.%0A     * @deprecated As of release 5.17.61, replaced by %7B@link #isValidCallbackURL(String, String)%7D%0A     */%0A    @Deprecated%0A    public boolean isValidCallbackURL(String callbackURL, String tenantDomain, boolean isUserPortalURL)%0A            throws IdentityRecoveryException %7B%0A%0A        if (isUserPortalURL) %7B%0A            if (log.isDebugEnabled()) %7B%0A                log.debug(%22Callback URL is equal to the user portal URL: %22 + callbackURL);%0A            %7D%0A            return true;%0A        %7D%0A        return isValidCallbackURL(callbackURL, tenantDomain);%0A    %7D
 %0A%7D%0A

Refactor isValidCallbackURL API