<commit_before>/*
 * 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.oauth2.validators;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
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.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils;
import org.wso2.carbon.identity.application.common.model.ClaimConfig;
import org.wso2.carbon.identity.application.common.model.ClaimMapping;
import org.wso2.carbon.identity.application.common.model.IdentityProvider;
import org.wso2.carbon.identity.application.common.model.RoleMapping;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth.cache.OAuthScopeBindingCache;
import org.wso2.carbon.identity.oauth.cache.OAuthScopeBindingCacheKey;
import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2ScopeServerException;
import org.wso2.carbon.identity.oauth2.OAuth2Constants;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.bean.Scope;
import org.wso2.carbon.identity.oauth2.bean.ScopeBinding;
import org.wso2.carbon.identity.oauth2.dao.OAuthTokenPersistenceFactory;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.oauth2.util.Oauth2ScopeUtils;
import org.wso2.carbon.user.api.AuthorizationManager;
import org.wso2.carbon.user.api.UserStoreException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.wso2.carbon.identity.oauth2.Oauth2ScopeConstants.SYSTEM_SCOPE;

/**
 * The JDBC Scope Validation implementation. This validates the Resource's scope (stored in IDN_OAUTH2_RESOURCE_SCOPE)
 * against the Access Token's scopes.
 */
public class JDBCPermissionBasedInternalScopeValidator {

    private static final String PERMISSION_ROOT = "/permission";

    private static final Log log = LogFactory.getLog(JDBCPermissionBasedInternalScopeValidator.class);
    private static final String PERMISSION_BINDING_TYPE = "PERMISSION";
    private static final String ROOT = "/";
    private static final String ADMIN_PERMISSION_ROOT = "/permission/admin";
    private static final String EVERYONE_PERMISSION = "everyone_permission";
    private static final String ATTRIBUTE_SEPARATOR = FrameworkUtils.getMultiAttributeSeparator();

    /**
     * Execute Internal scope Validation.
     * @param tokReqMsgCtx Oauth token request message.
     * @return array of validated scopes.
     */
    public String[] validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {

        // filter internal scopes
        String[] requestedScopes = Oauth2ScopeUtils.getRequestedScopes(tokReqMsgCtx.getScope());
        //If the token is not requested for specific scopes, return true
        if (ArrayUtils.isEmpty(requestedScopes)) {
            return requestedScopes;
        }
        List<Scope> userAllowedScopes = getUserAllowedScopes(tokReqMsgCtx.getAuthorizedUser(), requestedScopes,
                tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId());
        String[] userAllowedScopesAsArray = getScopes(userAllowedScopes);
        if (ArrayUtils.contains(requestedScopes, SYSTEM_SCOPE)) {
            return userAllowedScopesAsArray;
        }

        List<String> scopesToRespond = new ArrayList<>();
        for (String scope : requestedScopes) {
            if (ArrayUtils.contains(userAllowedScopesAsArray, scope)) {
                scopesToRespond.add(scope);
            }
        }
        return scopesToRespond.toArray(new String[0]);
    }

    /**
     * Execute Internal Scope Validation.
     * @param authzReqMessageContext OAuth authorization request message.
     * @return array of validated scopes.
     */
    public String[] validateScope(OAuthAuthzReqMessageContext authzReqMessageContext) {

        // Remove openid scope from the list if available
        String[] requestedScopes = Oauth2ScopeUtils.getRequestedScopes(authzReqMessageContext.getAuthorizationReqDTO
                ().getScopes());
        //If the token is not requested for specific scopes, return true
        if (ArrayUtils.isEmpty(requestedScopes)) {
            return requestedScopes;
        }
        List<Scope> userAllowedScopes =
                getUserAllowedScopes(authzReqMessageContext.getAuthorizationReqDTO().getUser(), requestedScopes,
                        authzReqMessageContext.getAuthorizationReqDTO().getConsumerKey());

        String[] userAllowedScopesAsArray = getScopes(userAllowedScopes);
        if (ArrayUtils.contains(requestedScopes, SYSTEM_SCOPE)) {
            return userAllowedScopesAsArray;
        }

        List<String> scopesToRespond = new ArrayList<>();
        for (String scope : requestedScopes) {
            if (ArrayUtils.contains(userAllowedScopesAsArray, scope)) {
                scopesToRespond.add(scope);
            }
        }
        return scopesToRespond.toArray(new String[0]);
    }

    /**
     * Execute Internal Scope Validation.
     * @param requestedScopes Array of scopes that needs to be validated.
     * @param authenticatedUser Authenticated user.
     * @param clientId ID of the client.
     * @return Array of validated scopes.
     */
    public String[] validateScope(String[] requestedScopes, AuthenticatedUser authenticatedUser, String clientId) {

        List<Scope> userAllowedScopes = getUserAllowedScopes(authenticatedUser, requestedScopes, clientId);

        String[] userAllowedScopesAsArray = getScopes(userAllowedScopes);
        if (ArrayUtils.contains(requestedScopes, SYSTEM_SCOPE)) {
            return userAllowedScopesAsArray;
        }

        List<String> scopesToRespond = new ArrayList<>();<commit_msg>Remove duplicate code snippet from validateScope method<commit_after>/*
 * 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.oauth2.validators;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
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.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.identity.application.authentication.framework.exception.UserIdNotFoundException;
import org.wso2.carbon.identity.application.authentication.framework.model.AuthenticatedUser;
import org.wso2.carbon.identity.application.authentication.framework.util.FrameworkUtils;
import org.wso2.carbon.identity.application.common.model.ClaimConfig;
import org.wso2.carbon.identity.application.common.model.ClaimMapping;
import org.wso2.carbon.identity.application.common.model.IdentityProvider;
import org.wso2.carbon.identity.application.common.model.RoleMapping;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.oauth.cache.OAuthScopeBindingCache;
import org.wso2.carbon.identity.oauth.cache.OAuthScopeBindingCacheKey;
import org.wso2.carbon.identity.oauth.internal.OAuthComponentServiceHolder;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception;
import org.wso2.carbon.identity.oauth2.IdentityOAuth2ScopeServerException;
import org.wso2.carbon.identity.oauth2.OAuth2Constants;
import org.wso2.carbon.identity.oauth2.authz.OAuthAuthzReqMessageContext;
import org.wso2.carbon.identity.oauth2.bean.Scope;
import org.wso2.carbon.identity.oauth2.bean.ScopeBinding;
import org.wso2.carbon.identity.oauth2.dao.OAuthTokenPersistenceFactory;
import org.wso2.carbon.identity.oauth2.internal.OAuth2ServiceComponentHolder;
import org.wso2.carbon.identity.oauth2.token.OAuthTokenReqMessageContext;
import org.wso2.carbon.identity.oauth2.util.OAuth2Util;
import org.wso2.carbon.identity.oauth2.util.Oauth2ScopeUtils;
import org.wso2.carbon.user.api.AuthorizationManager;
import org.wso2.carbon.user.api.UserStoreException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.wso2.carbon.identity.oauth2.Oauth2ScopeConstants.SYSTEM_SCOPE;

/**
 * The JDBC Scope Validation implementation. This validates the Resource's scope (stored in IDN_OAUTH2_RESOURCE_SCOPE)
 * against the Access Token's scopes.
 */
public class JDBCPermissionBasedInternalScopeValidator {

    private static final String PERMISSION_ROOT = "/permission";

    private static final Log log = LogFactory.getLog(JDBCPermissionBasedInternalScopeValidator.class);
    private static final String PERMISSION_BINDING_TYPE = "PERMISSION";
    private static final String ROOT = "/";
    private static final String ADMIN_PERMISSION_ROOT = "/permission/admin";
    private static final String EVERYONE_PERMISSION = "everyone_permission";
    private static final String ATTRIBUTE_SEPARATOR = FrameworkUtils.getMultiAttributeSeparator();

    /**
     * Execute Internal scope Validation.
     * @param tokReqMsgCtx Oauth token request message.
     * @return array of validated scopes.
     */
    public String[] validateScope(OAuthTokenReqMessageContext tokReqMsgCtx) {

        // filter internal scopes
        String[] requestedScopes = Oauth2ScopeUtils.getRequestedScopes(tokReqMsgCtx.getScope());
        //If the token is not requested for specific scopes, return true
        if (ArrayUtils.isEmpty(requestedScopes)) {
            return requestedScopes;
        }
        List<Scope> userAllowedScopes = getUserAllowedScopes(tokReqMsgCtx.getAuthorizedUser(), requestedScopes,
                tokReqMsgCtx.getOauth2AccessTokenReqDTO().getClientId());
        String[] userAllowedScopesAsArray = getScopes(userAllowedScopes);
        if (ArrayUtils.contains(requestedScopes, SYSTEM_SCOPE)) {
            return userAllowedScopesAsArray;
        }

        List<String> scopesToRespond = new ArrayList<>();
        for (String scope : requestedScopes) {
            if (ArrayUtils.contains(userAllowedScopesAsArray, scope)) {
                scopesToRespond.add(scope);
            }
        }
        return scopesToRespond.toArray(new String[0]);
    }

    /**
     * Execute Internal Scope Validation.
     * @param authzReqMessageContext OAuth authorization request message.
     * @return array of validated scopes.
     */
    public String[] validateScope(OAuthAuthzReqMessageContext authzReqMessageContext) {

        // Remove openid scope from the list if available
        String[] requestedScopes = Oauth2ScopeUtils.getRequestedScopes(authzReqMessageContext.getAuthorizationReqDTO
                ().getScopes());
        //If the token is not requested for specific scopes, return true
        if (ArrayUtils.isEmpty(requestedScopes)) {
            return requestedScopes;
        }
        return validateScope(requestedScopes, authzReqMessageContext.getAuthorizationReqDTO().getUser(),
                authzReqMessageContext.getAuthorizationReqDTO().getConsumerKey());
    }

    /**
     * Execute Internal Scope Validation.
     * @param requestedScopes Array of scopes that needs to be validated.
     * @param authenticatedUser Authenticated user.
     * @param clientId ID of the client.
     * @return Array of validated scopes.
     */
    public String[] validateScope(String[] requestedScopes, AuthenticatedUser authenticatedUser, String clientId) {

        List<Scope> userAllowedScopes = getUserAllowedScopes(authenticatedUser, requestedScopes, clientId);

        String[] userAllowedScopesAsArray = getScopes(userAllowedScopes);
        if (ArrayUtils.contains(requestedScopes, SYSTEM_SCOPE)) {
            return userAllowedScopesAsArray;
        }

        List<String> scopesToRespond = new ArrayList<>();
{'fraction_non_alphanumeric': 0.08766164178038151, 'fraction_numerical': 0.009216260627277274, 'mean_word_length': 4.155801104972376, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '383339', 'n_tokens_mistral': 4065, 'n_tokens_neox': 3954, 'n_words': 855}