SLING-11254 Make additional authorization on HTTP scan endpoint mandatory

use Commons Permissions
diff --git a/pom.xml b/pom.xml
index 56f083d..86008cd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -283,6 +283,12 @@
     </dependency>
     <dependency>
       <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.permissions</artifactId>
+      <version>1.0.0-SNAPSHOT</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.event</artifactId>
       <version>4.2.10</version>
       <scope>provided</scope>
diff --git a/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServlet.java b/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServlet.java
index 3cbc9f5..4cd9bb1 100644
--- a/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServlet.java
+++ b/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServlet.java
@@ -19,8 +19,6 @@
 package org.apache.sling.clam.http.internal;
 
 import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Set;
 import java.util.regex.Pattern;
 
@@ -34,6 +32,7 @@
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.clam.jcr.NodeDescendingJcrPropertyDigger;
+import org.apache.sling.commons.permissions.PermissionsService;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Activate;
@@ -47,7 +46,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static org.apache.sling.clam.http.internal.RequestUtil.isAuthorized;
 import static org.apache.sling.clam.http.internal.RequestUtil.maxDepth;
 import static org.apache.sling.clam.http.internal.RequestUtil.maxLength;
 import static org.apache.sling.clam.http.internal.RequestUtil.path;
@@ -78,6 +76,12 @@
     )
     private volatile NodeDescendingJcrPropertyDigger digger;
 
+    @Reference(
+        policy = ReferencePolicy.DYNAMIC,
+        policyOption = ReferencePolicyOption.GREEDY
+    )
+    private volatile PermissionsService permissionsService;
+
     private ClamJcrScanServletConfiguration configuration;
 
     private Pattern pattern;
@@ -122,10 +126,9 @@
     @Override
     @SuppressWarnings({"checkstyle:IllegalCatch", "checkstyle:ReturnCount", "checkstyle:ExecutableStatementCount"})
     protected void doPost(@NotNull final SlingHttpServletRequest request, @NotNull final SlingHttpServletResponse response) throws ServletException, IOException {
-        final List<String> groups = Arrays.asList(configuration.scan_authorized_groups());
         boolean isAuthorized = false;
         try {
-            isAuthorized = isAuthorized(request, groups);
+            isAuthorized = permissionsService.hasPermission(request.getUserPrincipal(), configuration.scan_permission());
         } catch (Exception e) {
             logger.error(e.getMessage(), e);
         }
diff --git a/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServletConfiguration.java b/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServletConfiguration.java
index be42e58..1605d13 100644
--- a/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServletConfiguration.java
+++ b/src/main/java/org/apache/sling/clam/http/internal/ClamJcrScanServletConfiguration.java
@@ -42,10 +42,10 @@
     String[] sling_auth_requirements() default {"/system/clam-jcr-scan"};
 
     @AttributeDefinition(
-        name = "scan authorized groups",
-        description = "User groups authorized for scanning"
+        name = "scan permission",
+        description = "Permission required for scanning"
     )
-    String[] scan_authorized_groups() default {"sling-clam-scan"};
+    String scan_permission() default "sling/clam/scan";
 
     @AttributeDefinition(
         name = "default property types",
diff --git a/src/main/java/org/apache/sling/clam/http/internal/RequestUtil.java b/src/main/java/org/apache/sling/clam/http/internal/RequestUtil.java
index dcb3ddb..c29096f 100644
--- a/src/main/java/org/apache/sling/clam/http/internal/RequestUtil.java
+++ b/src/main/java/org/apache/sling/clam/http/internal/RequestUtil.java
@@ -19,13 +19,9 @@
 package org.apache.sling.clam.http.internal;
 
 import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
 import java.util.Set;
 import java.util.regex.Pattern;
 
-import org.apache.jackrabbit.api.security.user.Authorizable;
-import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.jetbrains.annotations.NotNull;
 
@@ -104,20 +100,4 @@
         }
     }
 
-    @SuppressWarnings({"java:S112", "checkstyle:ReturnCount"})
-    static boolean isAuthorized(@NotNull final SlingHttpServletRequest request, @NotNull final Collection<String> authorizedGroups) throws Exception {
-        final Authorizable authorizable = request.getResourceResolver().adaptTo(Authorizable.class);
-        if (authorizable == null) {
-            return false;
-        }
-        final Iterator<Group> groups = authorizable.memberOf();
-        while (groups.hasNext()) {
-            final String id = groups.next().getID();
-            if (authorizedGroups.contains(id)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
 }
diff --git a/src/test/java/org/apache/sling/clam/it/tests/ClamJcrScanServletIT.java b/src/test/java/org/apache/sling/clam/it/tests/ClamJcrScanServletIT.java
index 6811a51..d95c227 100644
--- a/src/test/java/org/apache/sling/clam/it/tests/ClamJcrScanServletIT.java
+++ b/src/test/java/org/apache/sling/clam/it/tests/ClamJcrScanServletIT.java
@@ -38,6 +38,7 @@
 import static io.restassured.RestAssured.given;
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.sling.testing.paxexam.SlingOptions.slingCommonsPermissionsSling;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingJcrJackrabbitUsermanager;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingResourcePresence;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingStarterContent;
@@ -55,6 +56,14 @@
 
     private static final String URL_TEMPLATE = "http://localhost:%s/system/clam-jcr-scan";
 
+    private static final String AUTHORIZED_USER_USERNAME = "alice";
+
+    private static final String AUTHORIZED_USER_PASSWORD = "foo";
+
+    private static final String UNAUTHORIZED_USER_USERNAME = "bob";
+
+    private static final String UNAUTHORIZED_USER_PASSWORD = "bar";
+
     @Configuration
     public Option[] configuration() {
         return options(
@@ -65,7 +74,27 @@
                 .put("path", "/content/starter/img/sling-logo.svg")
                 .asOption(),
             slingStarterContent(),
-            slingJcrJackrabbitUsermanager()
+            slingJcrJackrabbitUsermanager(),
+            factoryConfiguration("org.apache.sling.jcr.repoinit.RepositoryInitializer")
+                .put("scripts", new String[]{
+                    "create group sling-clam-scan\n" +
+                    String.format("create user %s with password %s\n", UNAUTHORIZED_USER_USERNAME, UNAUTHORIZED_USER_PASSWORD) +
+                    String.format("create user %s with password %s\n", AUTHORIZED_USER_USERNAME, AUTHORIZED_USER_PASSWORD) +
+                    String.format("add %s to group sling-clam-scan\n", AUTHORIZED_USER_USERNAME) +
+                    "create path (sling:Folder) /libs/sling/permissions/sling/clam/scan\n" +
+                    "set ACL for sling-clam-scan\nallow jcr:read on /libs/sling/permissions/sling/clam/scan\nend\n"
+                })
+                .asOption(),
+            // Sling Commons Permissions Sling
+            slingCommonsPermissionsSling(),
+            factoryConfiguration("org.apache.sling.commons.permissions.sling.internal.SlingPermissionsService")
+                .put("path", "/libs/sling/permissions")
+                .asOption(),
+            factoryConfiguration("org.apache.sling.jcr.base.internal.LoginAdminWhitelist.fragment")
+                .put("whitelist.bundles", new String[]{
+                    "org.apache.sling.commons.permissions.sling"
+                })
+                .asOption()
         );
     }
 
@@ -84,7 +113,7 @@
         final String url = String.format(URL_TEMPLATE, httpPort());
         given()
             .auth()
-            .basic(ADMIN_USERNAME, ADMIN_PASSWORD)
+            .basic(UNAUTHORIZED_USER_USERNAME, UNAUTHORIZED_USER_PASSWORD)
             .param("path", "/content/starter")
             .when()
             .post(url)
@@ -97,7 +126,7 @@
         final String url = String.format(URL_TEMPLATE, httpPort());
         given()
             .auth()
-            .basic(USER_USERNAME, USER_PASSWORD)
+            .basic(AUTHORIZED_USER_USERNAME, AUTHORIZED_USER_PASSWORD)
             .param("path", "/content/starter")
             .when()
             .post(url)
@@ -113,7 +142,7 @@
         final String url = String.format(URL_TEMPLATE, httpPort());
         given()
             .auth()
-            .basic(USER_USERNAME, USER_PASSWORD)
+            .basic(AUTHORIZED_USER_USERNAME, AUTHORIZED_USER_PASSWORD)
             .param("path", "/content/starter")
             .when()
             .post(url)
diff --git a/src/test/java/org/apache/sling/clam/it/tests/ClamTestSupport.java b/src/test/java/org/apache/sling/clam/it/tests/ClamTestSupport.java
index d3089e6..38ca07f 100644
--- a/src/test/java/org/apache/sling/clam/it/tests/ClamTestSupport.java
+++ b/src/test/java/org/apache/sling/clam/it/tests/ClamTestSupport.java
@@ -40,6 +40,7 @@
 import static org.apache.sling.testing.paxexam.SlingOptions.awaitility;
 import static org.apache.sling.testing.paxexam.SlingOptions.restassured;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingCommonsClam;
+import static org.apache.sling.testing.paxexam.SlingOptions.slingCommonsPermissions;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingEvent;
 import static org.apache.sling.testing.paxexam.SlingOptions.slingQuickstartOakTar;
 import static org.apache.sling.testing.paxexam.SlingOptions.testcontainers;
@@ -65,10 +66,6 @@
 
     static final String ADMIN_PASSWORD = "admin";
 
-    static final String USER_USERNAME = "bob";
-
-    static final String USER_PASSWORD = "foo";
-
     protected ModifiableCompositeOption baseConfiguration() {
         return composite(
             super.baseConfiguration(),
@@ -78,14 +75,13 @@
             factoryConfiguration("org.apache.sling.jcr.repoinit.RepositoryInitializer")
                 .put("scripts", new String[]{"create service user sling-clam with path system/sling\ncreate path (sling:Folder) /var/clam/results(sling:OrderedFolder)\nset principal ACL for sling-clam\nallow jcr:read on /\nallow rep:write on /var/clam\nend"})
                 .asOption(),
-            factoryConfiguration("org.apache.sling.jcr.repoinit.RepositoryInitializer")
-                .put("scripts", new String[]{"create user bob with password foo\ncreate group sling-clam-scan\nadd bob to group sling-clam-scan"})
-                .asOption(),
             factoryConfiguration("org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended")
                 .put("user.mapping", new String[]{"org.apache.sling.clam=[sling-clam]", "org.apache.sling.clam:result-writer=[sling-clam]"})
                 .asOption(),
             // Sling Commons Clam
             slingCommonsClam(),
+            // Sling Commons Permissions
+            slingCommonsPermissions(),
             // testing
             newConfiguration("org.apache.sling.jcr.base.internal.LoginAdminWhitelist")
                 .put("whitelist.bundles.regexp", "PAXEXAM-PROBE-.*")