/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License;
 * you may not use this file except in compliance with the Elastic License.
 */
package org.elasticsearch.xpack.security.action.interceptor;

import org.elasticsearch.action.CompositeIndicesRequest;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.logging.LoggerMessageFormat;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.license.XPackLicenseState;
import org.elasticsearch.xpack.security.user.User;
import org.elasticsearch.xpack.security.authz.AuthorizationService;
import org.elasticsearch.xpack.security.authz.accesscontrol.IndicesAccessControl;

import java.util.Collections;
import java.util.List;

/**
 * Base class for interceptors that disables features when field level security is configured for indices a request
 * is going to execute on.
 */
abstract class FieldAndDocumentLevelSecurityRequestInterceptor<Request> extends AbstractComponent implements
        RequestInterceptor<Request> {

    private final ThreadContext threadContext;
    private final XPackLicenseState licenseState;

    FieldAndDocumentLevelSecurityRequestInterceptor(Settings settings, ThreadContext threadContext,
                                                           XPackLicenseState licenseState) {
        super(settings);
        this.threadContext = threadContext;
        this.licenseState = licenseState;
    }

    public void intercept(Request request, User user) {
        if (licenseState.isDocumentAndFieldLevelSecurityAllowed() == false) {
            return;
        }

        List<? extends IndicesRequest> indicesRequests;
        if (request instanceof CompositeIndicesRequest) {
            indicesRequests = ((CompositeIndicesRequest) request).subRequests();
        } else if (request instanceof IndicesRequest) {
            indicesRequests = Collections.singletonList((IndicesRequest) request);
        } else {
            throw new IllegalArgumentException(LoggerMessageFormat.format("expected a request of type [{}] or [{}] but got [{}] instead",
                    CompositeIndicesRequest.class, IndicesRequest.class, request.getClass()));
        }
        IndicesAccessControl indicesAccessControl = threadContext.getTransient(AuthorizationService.INDICES_PERMISSIONS_KEY);
        for (IndicesRequest indicesRequest : indicesRequests) {
            for (String index : indicesRequest.indices()) {
                IndicesAccessControl.IndexAccessControl indexAccessControl = indicesAccessControl.getIndexPermissions(index);
                if (indexAccessControl != null) {
                    boolean fieldLevelSecurityEnabled = indexAccessControl.getFieldPermissions().hasFieldLevelSecurity();
                    boolean documentLevelSecurityEnabled = indexAccessControl.getQueries() != null;
                    if (fieldLevelSecurityEnabled || documentLevelSecurityEnabled) {
                        if (fieldLevelSecurityEnabled || documentLevelSecurityEnabled) {
                            logger.trace("intercepted request for index [{}] with field level access controls [{}] document level access " +
                                    "controls [{}]. disabling conflicting features", index, fieldLevelSecurityEnabled,
                                    documentLevelSecurityEnabled);
                        }
                        disableFeatures(request, fieldLevelSecurityEnabled, documentLevelSecurityEnabled);
                        return;
                    }
                }
                logger.trace("intercepted request for index [{}] without field or document level access controls", index);
            }
        }
    }

    protected abstract void disableFeatures(Request request, boolean fieldLevelSecurityEnabled, boolean documentLevelSecurityEnabled);

}

@@ -301,65 +301,8 @@
 r;%0A%0A
-import org.elasticsearch.action.CompositeIndicesRequest;%0A
 impo
@@ -410,69 +410,8 @@
 nt;%0A
-import org.elasticsearch.common.logging.LoggerMessageFormat;%0A
 impo
@@ -576,59 +576,8 @@
 te;%0A
-import org.elasticsearch.xpack.security.user.User;%0A
 impo
@@ -726,60 +726,57 @@
 ol;%0A
-%0A
 import 
-java.util.Collections;%0Aimport java.util.List
+org.elasticsearch.xpack.security.user.User
 ;%0A%0A/
@@ -995,16 +995,39 @@
 %3CRequest
+ extends IndicesRequest
 %3E extend
@@ -1672,603 +1672,8 @@
    %7D
-%0A%0A        List%3C? extends IndicesRequest%3E indicesRequests;%0A        if (request instanceof CompositeIndicesRequest) %7B%0A            indicesRequests = ((CompositeIndicesRequest) request).subRequests();%0A        %7D else if (request instanceof IndicesRequest) %7B%0A            indicesRequests = Collections.singletonList((IndicesRequest) request);%0A        %7D else %7B%0A            throw new IllegalArgumentException(LoggerMessageFormat.format(%22expected a request of type %5B%7B%7D%5D or %5B%7B%7D%5D but got %5B%7B%7D%5D instead%22,%0A                    CompositeIndicesRequest.class, IndicesRequest.class, request.getClass()));%0A        %7D
 %0A   
@@ -1799,76 +1799,8 @@
 Y);%0A
-        for (IndicesRequest indicesRequest : indicesRequests) %7B%0A    
     
@@ -1827,16 +1827,9 @@
 x : 
-indicesR
+r
 eque
@@ -1840,28 +1840,24 @@
 ndices()) %7B%0A
-    
             
@@ -1974,28 +1974,24 @@
             
- 
-   
 if (indexAcc
@@ -2008,28 +2008,24 @@
  != null) %7B%0A
-    
             
@@ -2138,36 +2138,32 @@
                 
-    
 boolean document
@@ -2234,36 +2234,32 @@
                 
- 
-   
 if (fieldLevelSe
@@ -2299,36 +2299,32 @@
 urityEnabled) %7B%0A
-    
                 
@@ -2384,36 +2384,32 @@
 urityEnabled) %7B%0A
-    
                 
@@ -2565,16 +2565,20 @@
         
+    
 %22control
@@ -2684,20 +2684,16 @@
         
-    
 document
@@ -2707,36 +2707,32 @@
 curityEnabled);%0A
-    
                 
@@ -2757,20 +2757,16 @@
         
-    
 disableF
@@ -2852,36 +2852,32 @@
                 
-    
 return;%0A        
@@ -2880,34 +2880,26 @@
             
-   
- 
 %7D%0A
-    
             
@@ -2892,36 +2892,32 @@
 %7D%0A            %7D%0A
-    
             logg
@@ -3019,30 +3019,16 @@
 index);%0A
-            %7D%0A
         

Simplify FieldAndDocumentLevelSecurityRequestInterceptor