def test_get_statements_matching_action(self):
        cooks = Group.objects.create(name="cooks")
        user = User.objects.create(id=5)
        user.groups.add(cooks)

        statements = [
            {
                "principal": ["id:5"],
                "action": ["create"]
            },
            {
                "principal": ["group:dev"],
                "action": ["delete"]
            },
            {
                "principal": ["group:cooks"],
                "action": ["do_something"]
            },
            {
                "principal": ["*"],
                "action": ["*"]
            },
            {
                "principal": ["id:79"],
                "action": ["vote"]
            },
        ]

        policy = AccessPolicy()

        result = policy._get_statements_matching_action("delete", statements)

        self.assertEqual(len(result), 2)
        self.assertEqual(result[0]["action"], ["delete"])
        self.assertEqual(result[1]["action"], ["*"])
    def test_get_statements_matching_action_when_method_safe(self):
        cooks = Group.objects.create(name="cooks")
        user = User.objects.create(id=5)
        user.groups.add(cooks)

        statements = [
            {
                "principal": ["*"],
                "action": ["list"]
            },
            {
                "principal": ["id:5"],
                "action": ["*"]
            },
            {
                "principal": ["group:cooks"],
                "action": ["<safe_methods>"]
            },
            {
                "principal": ["group:devs"],
                "action": ["destroy"]
            },
        ]

        policy = AccessPolicy()

        result = policy._get_statements_matching_action(
            FakeRequest(user, method="GET"), "list", statements)

        self.assertEqual(len(result), 3)
        self.assertEqual(result[0]["principal"], ["*"])
        self.assertEqual(result[1]["principal"], ["id:5"])
        self.assertEqual(result[2]["principal"], ["group:cooks"])
    def test_get_statements_matching_principal_if_user_is_anonymous(self):
        user = AnonymousUser()

        statements = [
            {
                "principal": ["id:5"],
                "action": ["create"]
            },
            {
                "principal": ["*"],
                "action": ["list"]
            },
            {
                "principal": ["authenticated"],
                "action": ["authenticated_action"]
            },
            {
                "principal": ["anonymous"],
                "action": ["anonymous_action"]
            },
        ]

        policy = AccessPolicy()

        result = policy._get_statements_matching_principal(
            FakeRequest(user), statements)

        self.assertEqual(len(result), 2)
        self.assertEqual(result[0]["action"], ["list"])
        self.assertEqual(result[1]["action"], ["anonymous_action"])
    def test_get_statements_matching_action_when_using_http_method_placeholder(
            self):
        cooks = Group.objects.create(name="cooks")
        user = User.objects.create(id=5)
        user.groups.add(cooks)

        statements = [
            {
                "principal": ["*"],
                "action": ["create"]
            },
            {
                "principal": ["group:cooks"],
                "action": ["<method:post>"]
            },
            {
                "principal": ["group:devs"],
                "action": ["destroy"]
            },
        ]

        policy = AccessPolicy()

        result = policy._get_statements_matching_action(
            FakeRequest(user, method="POST"), "an action that won't match",
            statements)

        self.assertEqual(len(result), 1)
        self.assertEqual(result[0]["principal"], ["group:cooks"])
    def test_get_statements_matching_principalif_user_is_authenticated(self):
        cooks = Group.objects.create(name="cooks")
        user = User.objects.create(id=5)
        user.groups.add(cooks)

        statements = [
            {"principal": ["id:5"], "action": ["create"]},
            {"principal": ["group:dev"], "action": ["delete"]},
            {"principal": ["group:cooks"], "action": ["do_something"]},
            {"principal": ["*"], "action": ["*"]},
            {"principal": ["id:79"], "action": ["vote"]},
            {"principal": ["anonymous"], "action": ["anonymous_action"]},
            {"principal": ["authenticated"], "action": ["authenticated_action"]},
        ]

        policy = AccessPolicy()

        result = policy._get_statements_matching_principal(
            FakeRequest(user), statements
        )

        self.assertEqual(len(result), 4)
        self.assertEqual(result[0]["action"], ["create"])
        self.assertEqual(result[1]["action"], ["do_something"])
        self.assertEqual(result[2]["action"], ["*"])
        self.assertEqual(result[3]["action"], ["authenticated_action"])
    def test_get_invoked_action_from_class_based_view(self):
        class UserViewSet(ModelViewSet):
            pass

        policy = AccessPolicy()
        view_instance = UserViewSet()
        view_instance.action = "create"

        result = policy._get_invoked_action(view_instance)
        self.assertEqual(result, "create")
    def test_get_invoked_action_from_function_based_view(self):
        @api_view(["GET"])
        def my_view(request):
            return ""

        policy = AccessPolicy()
        view_instance = my_view.cls()

        result = policy._get_invoked_action(view_instance)
        self.assertEqual(result, "my_view")
    def test_get_user_group_values(self):
        group1 = Group.objects.create(name="admin")
        group2 = Group.objects.create(name="ceo")
        user = User.objects.create(username="******")

        user.groups.add(group1, group2)

        policy = AccessPolicy()
        result = sorted(policy.get_user_group_values(user))

        self.assertEqual(result, ["admin", "ceo"])
    def test_evaluate_statements_false_any_deny(self,):
        policy = AccessPolicy()
        user = User.objects.create(username="******")

        statements = [
            {"principal": "*", "action": "*", "effect": "deny"},
            {"principal": "*", "action": "*", "effect": "allow"},
        ]

        result = policy._evaluate_statements([], FakeRequest(user), None, "create")
        self.assertFalse(result)
    def test_evaluate_statements_true_if_any_allow_and_none_deny(self,):
        policy = AccessPolicy()
        user = User.objects.create(username="******")

        statements = [
            {"principal": "*", "action": "create", "effect": "allow"},
            {"principal": "*", "action": "take_out_the_trash", "effect": "allow"},
        ]

        result = policy._evaluate_statements(
            statements, FakeRequest(user), None, "create"
        )
        self.assertTrue(result)
    def test_normalize_statements(self):
        policy = AccessPolicy()

        result = policy._normalize_statements([{
            "principal": "group:admin",
            "action": "delete",
            "condition": "is_nice_day",
        }])

        self.assertEqual(
            result,
            [{
                "principal": ["group:admin"],
                "action": ["delete"],
                "condition": ["is_nice_day"],
            }],
        )
    def test_get_statements_matching_action_when_method_unsafe(self):
        cooks = Group.objects.create(name="cooks")
        user = User.objects.create(id=5)
        user.groups.add(cooks)

        statements = [
            {
                "principal": ["id:5"],
                "action": ["create"]
            },
            {
                "principal": ["group:dev"],
                "action": ["destroy"]
            },
            {
                "principal": ["group:cooks"],
                "action": ["do_something"]
            },
            {
                "principal": ["*"],
                "action": ["*"]
            },
            {
                "principal": ["id:79"],
                "action": ["vote"]
            },
            {
                "principal": ["id:900"],
                "action": ["<safe_methods>"]
            },
        ]

        policy = AccessPolicy()

        result = policy._get_statements_matching_action(
            FakeRequest(user, method="DELETE"), "destroy", statements)

        self.assertEqual(len(result), 2)
        self.assertEqual(result[0]["action"], ["destroy"])
        self.assertEqual(result[1]["action"], ["*"])
 def test_get_user_group_values_empty_if_user_is_anonymous(self):
     user = AnonymousUser()
     policy = AccessPolicy()
     result = sorted(policy.get_user_group_values(user))
     self.assertEqual(result, [])