/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF 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.apache.tomcat.util.descriptor.web;

import java.util.HashSet;
import java.util.Set;

import javax.servlet.HttpConstraintElement;
import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.ServletSecurityElement;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;

import org.junit.Assert;
import org.junit.Test;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;

public class TestSecurityConstraint {

    private static final String URL_PATTERN = "/test";
    private static final String ROLE1 = "R1";

    private static final Log DUMMY_LOG = LogFactory.getLog("DUMMY");

    private static final SecurityConstraint GET_ONLY;
    private static final SecurityConstraint POST_ONLY;

    private static final SecurityConstraint GET_OMIT;
    private static final SecurityConstraint POST_OMIT;

    static {
        // Configure the constraints to use in the tests
        GET_ONLY = new SecurityConstraint();
        GET_ONLY.addAuthRole(ROLE1);
        SecurityCollection scGetOnly = new SecurityCollection();
        scGetOnly.addMethod("GET");
        scGetOnly.addPatternDecoded(URL_PATTERN);
        scGetOnly.setName("GET-ONLY");
        GET_ONLY.addCollection(scGetOnly);

        POST_ONLY = new SecurityConstraint();
        POST_ONLY.addAuthRole(ROLE1);
        SecurityCollection scPostOnly = new SecurityCollection();
        scPostOnly.addMethod("POST");
        scPostOnly.addPatternDecoded(URL_PATTERN);
        scPostOnly.setName("POST_ONLY");
        POST_ONLY.addCollection(scPostOnly);

        GET_OMIT = new SecurityConstraint();
        GET_OMIT.addAuthRole(ROLE1);
        SecurityCollection scGetOmit = new SecurityCollection();
        scGetOmit.addOmittedMethod("GET");
        scGetOmit.addPatternDecoded(URL_PATTERN);
        scGetOmit.setName("GET_OMIT");
        GET_OMIT.addCollection(scGetOmit);

        POST_OMIT = new SecurityConstraint();
        POST_OMIT.addAuthRole(ROLE1);
        SecurityCollection scPostOmit = new SecurityCollection();
        scPostOmit.addOmittedMethod("POST");
        scPostOmit.addPatternDecoded(URL_PATTERN);
        scPostOmit.setName("POST_OMIT");
        POST_OMIT.addCollection(scPostOmit);
    }

    /**
     * Uses the examples in SRV.13.4 as the basis for these tests
     */
    @Test
    public void testCreateConstraints() {

        ServletSecurityElement element;
        SecurityConstraint[] result;
        Set<HttpMethodConstraintElement> hmces = new HashSet<>();

        // Example 13-1
        // @ServletSecurity
        element = new ServletSecurityElement();
        result = SecurityConstraint.createConstraints(element, URL_PATTERN);

        Assert.assertEquals(0, result.length);

        // Example 13-2
        // @ServletSecurity(
        //     @HttpConstraint(
        //         transportGuarantee = TransportGuarantee.CONFIDENTIAL))
        element = new ServletSecurityElement(
                new HttpConstraintElement(
                        ServletSecurity.TransportGuarantee.CONFIDENTIAL));
        result = SecurityConstraint.createConstraints(element, URL_PATTERN);

        Assert.assertEquals(1, result.length);
        Assert.assertFalse(result[0].getAuthConstraint());
        Assert.assertTrue(result[0].findCollections()[0].findPattern(URL_PATTERN));
        Assert.assertEquals(0, result[0].findCollections()[0].findMethods().length);
        Assert.assertEquals(ServletSecurity.TransportGuarantee.CONFIDENTIAL.name(),
                result[0].getUserConstraint());

        // Example 13-3
        // @ServletSecurity(@HttpConstraint(EmptyRoleSemantic.DENY))
        element = new ServletSecurityElement(
                new HttpConstraintElement(EmptyRoleSemantic.DENY));
        result = SecurityConstraint.createConstraints(element, URL_PATTERN);

        Assert.assertEquals(1, result.length);
        Assert.assertTrue(result[0].getAuthConstraint());
        Assert.assertTrue(result[0].findCollections()[0].findPattern(URL_PATTERN));
        Assert.assertEquals(0, result[0].findCollections()[0].findMethods().length);
        Assert.assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
                result[0].getUserConstraint());

        // Example 13-4
        // @ServletSecurity(@HttpConstraint(rolesAllowed = "R1"))
        element = new ServletSecurityElement(new HttpConstraintElement(
                ServletSecurity.TransportGuarantee.NONE, ROLE1));
        result = SecurityConstraint.createConstraints(element, URL_PATTERN);

        Assert.assertEquals(1, result.length);
        Assert.assertTrue(result[0].getAuthConstraint());
        Assert.assertEquals(1, result[0].findAuthRoles().length);
        Assert.assertTrue(result[0].findAuthRole(ROLE1));
        Assert.assertTrue(result[0].findCollections()[0].findPattern(URL_PATTERN));
        Assert.assertEquals(0, result[0].findCollections()[0].findMethods().length);
        Assert.assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
                result[0].getUserConstraint());

        // Example 13-5
        // @ServletSecurity((httpMethodConstraints = {
        //     @HttpMethodConstraint(value = "GET", rolesAllowed = "R1"),
        //     @HttpMethodConstraint(value = "POST", rolesAllowed = "R1",
        //     transportGuarantee = TransportGuarantee.CONFIDENTIAL)
        // })
        hmces.clear();
        hmces.add(new HttpMethodConstraintElement("GET",
                new HttpConstraintElement(
                        ServletSecurity.TransportGuarantee.NONE, ROLE1)));
        hmces.add(new HttpMethodConstraintElement("POST",
                new HttpConstraintElement(
                        ServletSecurity.TransportGuarantee.CONFIDENTIAL,
                        ROLE1)));
        element = new ServletSecurityElement(hmces);
        result = SecurityConstraint.createConstraints(element, URL_PATTERN);

        Assert.assertEquals(2, result.length);
        for (int i = 0; i < 2; i++) {
            Assert.assertTrue(result[i].getAuthConstraint());
            Assert.assertEquals(1, result[i].findAuthRoles().length);
            Assert.assertTrue(result[i].findAuthRole(ROLE1));
            Assert.assertTrue(result[i].findCollections()[0].findPattern(URL_PATTERN));
            Assert.assertEquals(1, result[i].findCollections()[0].findMethods().length);
            String method = result[i].findCollections()[0].findMethods()[0];
            if ("GET".equals(method)) {
                Assert.assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
                        result[i].getUserConstraint());
            } else if ("POST".equals(method)) {
                Assert.assertEquals(ServletSecurity.TransportGuarantee.CONFIDENTIAL.name(),
                        result[i].getUserConstraint());
            } else {
                Assert.fail("Unexpected method :[" + method + "]");
            }
        }

        // Example 13-6
        // @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"),
        //     httpMethodConstraints = @HttpMethodConstraint("GET"))
        hmces.clear();
        hmces.add(new HttpMethodConstraintElement("GET"));
        element = new ServletSecurityElement(
                new HttpConstraintElement(
                        ServletSecurity.TransportGuarantee.NONE,
                        ROLE1),
                hmces);
        result = SecurityConstraint.createConstraints(element, URL_PATTERN);

        Assert.assertEquals(2, result.length);
        for (int i = 0; i < 2; i++) {
            Assert.assertTrue(result[i].findCollections()[0].findPattern(URL_PATTERN));
            if (result[i].findCollections()[0].findMethods().length == 1) {
                Assert.assertEquals("GET",
                        result[i].findCollections()[0].findMethods()[0]);
                Assert.assertFalse(result[i].getAuthConstraint());
            } else if (result[i].findCollections()[0].findOmittedMethods().length == 1) {
                Assert.assertEquals("GET",
                        result[i].findCollections()[0].findOmittedMethods()[0]);
                Assert.assertTrue(result[i].getAuthConstraint());
                Assert.assertEquals(1, result[i].findAuthRoles().length);
                Assert.assertEquals(ROLE1, result[i].findAuthRoles()[0]);
            } else {
                Assert.fail("Unexpected number of methods defined");
            }
            Assert.assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
                    result[i].getUserConstraint());
        }

        // Example 13-7
        // @ServletSecurity(value = @HttpConstraint(rolesAllowed = "R1"),
        //     httpMethodConstraints = @HttpMethodConstraint(value="TRACE",
        //         emptyRoleSemantic = EmptyRoleSemantic.DENY))
        hmces.clear();
        hmces.add(new HttpMethodConstraintElement("TRACE",
                new HttpConstraintElement(EmptyRoleSemantic.DENY)));
        element = new ServletSecurityElement(
                new HttpConstraintElement(
                        ServletSecurity.TransportGuarantee.NONE,
                        ROLE1),
                hmces);
        result = SecurityConstraint.createConstraints(element, URL_PATTERN);

        Assert.assertEquals(2, result.length);
        for (int i = 0; i < 2; i++) {
            Assert.assertTrue(result[i].findCollections()[0].findPattern(URL_PATTERN));
            if (result[i].findCollections()[0].findMethods().length == 1) {
                Assert.assertEquals("TRACE",
                        result[i].findCollections()[0].findMethods()[0]);
                Assert.assertTrue(result[i].getAuthConstraint());
                Assert.assertEquals(0, result[i].findAuthRoles().length);
            } else if (result[i].findCollections()[0].findOmittedMethods().length == 1) {
                Assert.assertEquals("TRACE",
                        result[i].findCollections()[0].findOmittedMethods()[0]);
                Assert.assertTrue(result[i].getAuthConstraint());
                Assert.assertEquals(1, result[i].findAuthRoles().length);
                Assert.assertEquals(ROLE1, result[i].findAuthRoles()[0]);
            } else {
                Assert.fail("Unexpected number of methods defined");
            }
            Assert.assertEquals(ServletSecurity.TransportGuarantee.NONE.name(),
                    result[i].getUserConstraint());
        }

        // Example 13-8 is the same as 13-4
        // Example 13-9 is the same as 13-7
    }


    @Test
    public void testFindUncoveredHttpMethods01() {
        // No new constraints if denyUncoveredHttpMethods is false
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_ONLY}, false, DUMMY_LOG);
        Assert.assertEquals(0, result.length);
    }


    @Test
    public void testFindUncoveredHttpMethods02() {
        // No new constraints if denyUncoveredHttpMethods is false
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_OMIT}, false, DUMMY_LOG);
        Assert.assertEquals(0, result.length);
    }


    @Test
    public void testFindUncoveredHttpMethods03() {
        // No new constraints if denyUncoveredHttpMethods is false
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {POST_ONLY}, false, DUMMY_LOG);
        Assert.assertEquals(0, result.length);
    }


    @Test
    public void testFindUncoveredHttpMethods04() {
        // No new constraints if denyUncoveredHttpMethods is false
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {POST_OMIT}, false, DUMMY_LOG);
        Assert.assertEquals(0, result.length);
    }


    @Test
    public void testFindUncoveredHttpMethods05() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_ONLY}, true, DUMMY_LOG);
        Assert.assertEquals(1, result.length);
        // Should be a deny constraint
        Assert.assertTrue(result[0].getAuthConstraint());
        // Should have a single collection
        Assert.assertEquals(1, result[0].findCollections().length);
        SecurityCollection sc = result[0].findCollections()[0];
        // Should list GET as an omitted method
        Assert.assertEquals(0, sc.findMethods().length);
        Assert.assertEquals(1, sc.findOmittedMethods().length);
        Assert.assertEquals("GET", sc.findOmittedMethods()[0]);
    }


    @Test
    public void testFindUncoveredHttpMethods06() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {POST_ONLY}, true, DUMMY_LOG);
        Assert.assertEquals(1, result.length);
        // Should be a deny constraint
        Assert.assertTrue(result[0].getAuthConstraint());
        // Should have a single collection
        Assert.assertEquals(1, result[0].findCollections().length);
        SecurityCollection sc = result[0].findCollections()[0];
        // Should list POST as an omitted method
        Assert.assertEquals(0, sc.findMethods().length);
        Assert.assertEquals(1, sc.findOmittedMethods().length);
        Assert.assertEquals("POST", sc.findOmittedMethods()[0]);
    }


    @Test
    public void testFindUncoveredHttpMethods07() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_OMIT}, true, DUMMY_LOG);
        Assert.assertEquals(1, result.length);
        // Should be a deny constraint
        Assert.assertTrue(result[0].getAuthConstraint());
        // Should have a single collection
        Assert.assertEquals(1, result[0].findCollections().length);
        SecurityCollection sc = result[0].findCollections()[0];
        // Should list GET as an method
        Assert.assertEquals(0, sc.findOmittedMethods().length);
        Assert.assertEquals(1, sc.findMethods().length);
        Assert.assertEquals("GET", sc.findMethods()[0]);
    }


    @Test
    public void testFindUncoveredHttpMethods08() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {POST_OMIT}, true, DUMMY_LOG);
        Assert.assertEquals(1, result.length);
        // Should be a deny constraint
        Assert.assertTrue(result[0].getAuthConstraint());
        // Should have a single collection
        Assert.assertEquals(1, result[0].findCollections().length);
        SecurityCollection sc = result[0].findCollections()[0];
        // Should list POST as an method
        Assert.assertEquals(0, sc.findOmittedMethods().length);
        Assert.assertEquals(1, sc.findMethods().length);
        Assert.assertEquals("POST", sc.findMethods()[0]);
    }


    @Test
    public void testFindUncoveredHttpMethods09() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_ONLY, GET_OMIT}, true,
                        DUMMY_LOG);
        Assert.assertEquals(0, result.length);
    }


    @Test
    public void testFindUncoveredHttpMethods10() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {POST_ONLY, POST_OMIT}, true,
                        DUMMY_LOG);
        Assert.assertEquals(0, result.length);
    }


    @Test
    public void testFindUncoveredHttpMethods11() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_ONLY, POST_ONLY}, true,
                        DUMMY_LOG);
        Assert.assertEquals(1, result.length);
        // Should be a deny constraint
        Assert.assertTrue(result[0].getAuthConstraint());
        // Should have a single collection
        Assert.assertEquals(1, result[0].findCollections().length);
        SecurityCollection sc = result[0].findCollections()[0];
        // Should list GET and POST as omitted methods
        Assert.assertEquals(0, sc.findMethods().length);
        Assert.assertEquals(2, sc.findOmittedMethods().length);
        HashSet<String> omittedMethods = new HashSet<>();
        for (String omittedMethod : sc.findOmittedMethods()) {
            omittedMethods.add(omittedMethod);
        }
        Assert.assertTrue(omittedMethods.remove("GET"));
        Assert.assertTrue(omittedMethods.remove("POST"));
    }


    @Test
    public void testFindUncoveredHttpMethods12() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_OMIT, POST_OMIT}, true,
                        DUMMY_LOG);
        Assert.assertEquals(0, result.length);
    }


    @Test
    public void testFindUncoveredHttpMethods13() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_ONLY, POST_OMIT}, true,
                        DUMMY_LOG);
        Assert.assertEquals(1, result.length);
        // Should be a deny constraint
        Assert.assertTrue(result[0].getAuthConstraint());
        // Should have a single collection
        Assert.assertEquals(1, result[0].findCollections().length);
        SecurityCollection sc = result[0].findCollections()[0];
        // Should list POST as a method
        Assert.assertEquals(1, sc.findMethods().length);
        Assert.assertEquals(0, sc.findOmittedMethods().length);
        Assert.assertEquals("POST", sc.findMethods()[0]);
    }


    @Test
    public void testFindUncoveredHttpMethods14() {
        SecurityConstraint[] result =
                SecurityConstraint.findUncoveredHttpMethods(
                        new SecurityConstraint[] {GET_OMIT, POST_ONLY}, true,
                        DUMMY_LOG);
        Assert.assertEquals(1, result.length);
        // Should be a deny constraint
        Assert.assertTrue(result[0].getAuthConstraint());
        // Should have a single collection
        Assert.assertEquals(1, result[0].findCollections().length);
        SecurityCollection sc = result[0].findCollections()[0];
        // Should list GET as a method
        Assert.assertEquals(1, sc.findMethods().length);
        Assert.assertEquals(0, sc.findOmittedMethods().length);
        Assert.assertEquals("GET", sc.findMethods()[0]);
    }
}
