# -*- coding: utf-8 -*-
from __future__ import with_statement, unicode_literals

import pytest

from ziggurat_foundations.models.services.group_permission import \
    GroupPermissionService
from ziggurat_foundations.models.services.group_resource_permission import \
    GroupResourcePermissionService
from ziggurat_foundations.models.services.user_permission import \
    UserPermissionService
from ziggurat_foundations.models.services.user_resource_permission import \
    UserResourcePermissionService

from ziggurat_foundations.models.services.resource import ResourceService

from ziggurat_foundations.permissions import PermissionTuple, ALL_PERMISSIONS
from ziggurat_foundations.tests import (
    add_user, check_one_in_other, add_resource, add_resource_b, add_group,
    BaseTestCase)
from ziggurat_foundations.tests.conftest import (
    User,
    UserPermission,
    GroupPermission,
    UserResourcePermission,
    GroupResourcePermission, TestResourceB)


class TestUserPermissions(BaseTestCase):
    def test_user_permissions(self, db_session):
        created_user = add_user(db_session)
        permissions = created_user.permissions
        expected = [
            PermissionTuple(created_user, 'alter_users', 'user', None, None,
                            False, True),
            PermissionTuple(created_user, 'root', 'user', None, None, False,
                            True)]
        check_one_in_other(permissions, expected)

    def test_owned_permissions(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        created_user.resources.append(resource)
        db_session.flush()
        resources = created_user.resources_with_perms(
            ['test_perm'], db_session=db_session).all()
        assert resources[0] == resource

    def test_resources_with_perm(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        permission = UserResourcePermission(
            perm_name='test_perm', user_id=created_user.id,
            resource_id=resource.resource_id)
        resource.user_permissions.append(permission)
        db_session.flush()
        resources = created_user.resources_with_perms(['test_perm'],
                                                      db_session=db_session).all()
        assert resources[0] == resource

    def test_mixed_perms(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        permission = UserResourcePermission(
            perm_name='test_perm', user_id=created_user.id,
            resource_id=resource.resource_id)
        resource.user_permissions.append(permission)
        resource2 = add_resource(db_session, 2, 'test_resource')
        created_user.resources.append(resource2)
        resource3 = add_resource(db_session, 3, 'test_resource')
        resource4 = add_resource_b(db_session, 4, 'test_resource')
        db_session.flush()
        resources = created_user.resources_with_perms(['test_perm'],
                                                      db_session=db_session).all()
        found_ids = [r.resource_id for r in resources]
        assert sorted(found_ids) == [1, 2]

    def test_resources_with_perm_type_found(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        permission = UserResourcePermission(perm_name='test_perm',
                                            user_id=created_user.id,
                                            resource_id=resource.resource_id)
        resource.user_permissions.append(permission)
        db_session.flush()
        resources = created_user.resources_with_perms(['test_perm'],
                                                      resource_types=[
                                                          'test_resource'],
                                                      db_session=db_session).all()
        assert resources[0] == resource

    def test_resources_with_perm_type_not_found(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        permission = UserResourcePermission(perm_name='test_perm',
                                            user_id=created_user.id,
                                            resource_id=resource.resource_id)
        resource.user_permissions.append(permission)
        db_session.flush()
        resources = created_user.resources_with_perms(['test_perm'],
                                                      resource_types=[
                                                          'test_resource_b'],
                                                      db_session=db_session).all()
        assert resources == []

    def test_resources_with_perm_type_other_found(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        resource2 = add_resource_b(db_session, 2, 'test_resource')
        resource3 = add_resource(db_session, 3, 'test_resource')
        resource4 = add_resource_b(db_session, 4, 'test_resource')
        db_session.flush()
        permission = UserResourcePermission(perm_name='test_perm',
                                            user_id=created_user.id,
                                            resource_id=resource.resource_id)
        resource.user_permissions.append(permission)
        permission2 = UserResourcePermission(perm_name='test_perm',
                                             user_id=created_user.id,
                                             resource_id=resource2.resource_id)
        resource2.user_permissions.append(permission2)
        permission3 = UserResourcePermission(perm_name='test_perm',
                                             user_id=created_user.id,
                                             resource_id=resource3.resource_id)
        resource3.user_permissions.append(permission3)
        permission4 = UserResourcePermission(perm_name='test_perm',
                                             user_id=created_user.id,
                                             resource_id=resource4.resource_id)
        resource4.user_permissions.append(permission4)
        db_session.flush()
        resources = created_user.resources_with_perms(['test_perm'],
                                                      resource_types=[
                                                          'test_resource_b'],
                                                      db_session=db_session).all()
        assert len(resources) == 2

    def test_resources_with_wrong_perm(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        permission = UserResourcePermission(
            perm_name='test_perm_bad',
            user_id=created_user.id,
            resource_id=resource.resource_id
        )
        with pytest.raises(AssertionError):
            resource.user_permissions.append(permission)

    def test_multiple_resources_with_perm(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        permission = UserResourcePermission(perm_name='test_perm',
                                            user_id=created_user.id,
                                            resource_id=resource.resource_id
                                            )
        resource.user_permissions.append(permission)
        resource2 = add_resource(db_session, 2, 'test_resource2')
        permission2 = UserResourcePermission(perm_name='test_perm',
                                             user_id=created_user.id,
                                             resource_id=resource2.resource_id
                                             )
        resource2.user_permissions.append(permission2)
        resources = created_user.resources_with_perms(['test_perm'],
                                                      db_session=db_session).all()
        assert resources == [resource, resource2]

    def test_resources_ids_with_perm(self, db_session):
        created_user = add_user(db_session)
        resource1 = add_resource(db_session, 1, 'test_resource1')
        resource2 = add_resource(db_session, 2, 'test_resource2')
        resource3 = add_resource(db_session, 3, 'test_resource3')

        permission1 = UserResourcePermission(perm_name='test_perm',
                                             user_id=created_user.id,
                                             resource_id=resource1.resource_id)
        permission2 = UserResourcePermission(perm_name='test_perm',
                                             user_id=created_user.id,
                                             resource_id=resource2.resource_id)
        permission3 = UserResourcePermission(perm_name='test_perm',
                                             user_id=created_user.id,
                                             resource_id=resource3.resource_id)

        resource1.user_permissions.append(permission1)
        resource2.user_permissions.append(permission2)
        resource3.user_permissions.append(permission3)

        db_session.flush()
        resources = created_user.resources_with_perms(['test_perm'],
                                                      resource_ids=[1, 3],
                                                      db_session=db_session).all()
        assert resources == [resource1, resource3]

    def test_resources_with_wrong_group_permission(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        group = add_group(db_session, )
        group.users.append(created_user)
        group_permission = GroupResourcePermission(
            perm_name='test_perm_bad',
            group_id=group.id,
            resource_id=resource.resource_id
        )
        with pytest.raises(AssertionError):
            resource.group_permissions.append(group_permission)

    def test_resources_with_group_permission(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        resource2 = add_resource(db_session, 2, 'test_resource2')
        add_resource(db_session, 3, 'test_resource3')
        group = add_group(db_session, )
        group.users.append(created_user)
        group_permission = GroupResourcePermission(
            perm_name='test_perm',
            group_id=1,
            resource_id=resource.resource_id
        )
        group_permission2 = GroupResourcePermission(
            perm_name='foo_perm',
            group_id=1,
            resource_id=resource2.resource_id
        )
        resource.group_permissions.append(group_permission)
        resource2.group_permissions.append(group_permission2)
        db_session.flush()
        resources = created_user.resources_with_perms(['foo_perm'],
                                                      db_session=db_session).all()
        assert resources[0] == resource2

    def test_resources_with_direct_user_perms(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        # test_perm1 from group perms should be ignored
        perms = self.resource.direct_perms_for_user(
            self.user, db_session=db_session)
        second = [PermissionTuple(self.user, 'foo_perm', 'user', None,
                                  self.resource, False, True),
                  PermissionTuple(self.user, 'test_perm2', 'user', None,
                                  self.resource, False, True)]

        check_one_in_other(perms, second)

    def test_resources_with_direct_group_perms(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        # test_perm1 from group perms should be ignored
        perms = self.resource.group_perms_for_user(
            self.user, db_session=db_session)
        second = [
            PermissionTuple(self.user, 'group_perm', 'group', self.group,
                            self.resource, False, True)]

        check_one_in_other(perms, second)

    def test_resources_with_user_perms(self, db_session):
        self.maxDiff = 9999
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource.perms_for_user(
            self.user, db_session=db_session)
        second = [PermissionTuple(self.user, 'foo_perm', 'user', None,
                                  self.resource, False, True),
                  PermissionTuple(self.user, 'group_perm', 'group',
                                  self.group, self.resource, False, True),
                  PermissionTuple(self.user, 'test_perm2', 'user', None,
                                  self.resource, False, True)]

        check_one_in_other(perms, second)

    def test_resource_users_for_perm(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource.users_for_perm(
            'foo_perm', db_session=db_session)
        second = [PermissionTuple(self.user, 'foo_perm', 'user', None,
                                  self.resource, False, True)]

        check_one_in_other(perms, second)

    def test_resource_users_for_any_perm(self, db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource.users_for_perm(
            '__any_permission__', db_session=db_session)
        second = [
            PermissionTuple(self.user, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user, 'test_perm2', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user, 'foo_perm', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user4, 'group_perm', 'group', self.group2,
                            self.resource, False, True),
        ]

        check_one_in_other(perms, second)

    def test_resource_users_for_any_perm_resource_2(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource2.users_for_perm(
            '__any_permission__', db_session=db_session)
        second = [
            PermissionTuple(self.user2, 'foo_perm', 'user', None,
                            self.resource2, False, True),
            PermissionTuple(self.user3, 'test_perm', 'user', None,
                            self.resource2, False, True),
        ]

        check_one_in_other(perms, second)

    def test_resource_users_limited_users(self, db_session):
        self.maxDiff = 9999
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource.users_for_perm('__any_permission__',
                                             user_ids=[self.user.id],
                                             db_session=db_session)
        second = [
            PermissionTuple(self.user, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user, 'test_perm2', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user, 'foo_perm', 'user', None,
                            self.resource, False, True)
        ]

        check_one_in_other(perms, second)

    def test_resource_users_limited_group(self, db_session):
        self.maxDiff = 9999
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource.users_for_perm('__any_permission__',
                                             user_ids=[self.user.id],
                                             group_ids=[self.group2.id],
                                             db_session=db_session)
        second = [
            PermissionTuple(self.user, 'test_perm2', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user, 'foo_perm', 'user', None,
                            self.resource, False, True)
        ]

        check_one_in_other(perms, second)

    def test_resource_users_limited_group_other_user_3(self, db_session):
        self.maxDiff = 9999
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource2.users_for_perm('__any_permission__',
                                              user_ids=[self.user3.id],
                                              db_session=db_session)
        second = [
            PermissionTuple(self.user3, 'test_perm', 'user', None,
                            self.resource2, False, True)
        ]

        check_one_in_other(perms, second)

    def test_resource_users_limited_group_other_user_4(self, db_session):
        self.maxDiff = 9999
        self.set_up_user_group_and_perms(db_session)
        perms = self.resource.users_for_perm('__any_permission__',
                                             user_ids=[self.user4.id],
                                             group_ids=[self.group2.id],
                                             db_session=db_session)
        second = [
            PermissionTuple(self.user4, 'group_perm', 'group', self.group2,
                            self.resource, False, True)
        ]

        check_one_in_other(perms, second)

    def test_resource_users_limited_group_ownage(self, db_session):
        self.maxDiff = 9999
        self.set_up_user_group_and_perms(db_session)
        resource = TestResourceB(resource_id=99,
                                 resource_name='other',
                                 owner_user_id=self.user2.id)
        group3 = add_group(db_session, 'group 3')
        user2_permission = UserResourcePermission(
            perm_name='foo_perm',
            user_id=self.user2.id,
        )
        group3_permission = GroupResourcePermission(
            perm_name='group_perm',
            group_id=group3.id
        )
        resource.group_permissions.append(group3_permission)
        resource.user_permissions.append(user2_permission)
        group3.users.append(self.user3)
        self.user.resources.append(resource)
        self.group2.resources.append(resource)
        db_session.flush()
        perms = resource.users_for_perm('__any_permission__',
                                        db_session=db_session)
        second = [
            PermissionTuple(self.user2, 'foo_perm', 'user', None, resource,
                            False, True),
            PermissionTuple(self.user, ALL_PERMISSIONS, 'user', None, resource,
                            True, True),
            PermissionTuple(self.user4, ALL_PERMISSIONS, 'group', self.group2,
                            resource, True, True),
            PermissionTuple(self.user3, 'group_perm', 'group', group3,
                            resource, False, True)
        ]

        check_one_in_other(perms, second)

    def test_users_for_perms(self, db_session):
        user = User(user_name='aaa', email='aaa', status=0)
        user.set_password('password')
        aaa_perm = UserPermission(perm_name='aaa')
        bbb_perm = UserPermission(perm_name='bbb')
        bbb2_perm = UserPermission(perm_name='bbb')
        user.user_permissions.append(aaa_perm)
        user.user_permissions.append(bbb_perm)
        user2 = User(user_name='bbb', email='bbb', status=0)
        user2.set_password('password')
        user2.user_permissions.append(bbb2_perm)
        user3 = User(user_name='ccc', email='ccc', status=0)
        user3.set_password('password')
        group = add_group(db_session, )
        group.users.append(user3)
        db_session.add(user)
        db_session.add(user2)
        db_session.flush()
        users = User.users_for_perms(['aaa'], db_session=db_session)
        assert len(users.all()) == 1
        assert users[0].user_name == 'aaa'
        users = User.users_for_perms(['bbb'], db_session=db_session).all()
        assert len(users) == 2
        assert ['aaa', 'bbb'] == sorted([u.user_name for u in users])
        users = User.users_for_perms(['aaa', 'bbb', 'manage_apps'],
                                     db_session=db_session)
        assert ['aaa', 'bbb', 'ccc'] == sorted([u.user_name for u in users])

    def test_resources_with_possible_perms(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        resource = TestResourceB(resource_id=3,
                                 resource_name='other',
                                 owner_user_id=self.user.id)
        self.user.resources.append(resource)
        resource_g = TestResourceB(resource_id=4,
                                   resource_name='group owned')
        self.group.resources.append(resource_g)
        db_session.flush()
        perms = self.user.resources_with_possible_perms()
        second = [PermissionTuple(self.user, 'foo_perm', 'user', None,
                                  self.resource, False, True),
                  PermissionTuple(self.user, 'group_perm', 'group',
                                  self.group, self.resource, False, True),
                  PermissionTuple(self.user, 'test_perm2', 'user', None,
                                  self.resource, False, True),
                  PermissionTuple(self.user, ALL_PERMISSIONS, 'user', None,
                                  resource, True, True),
                  PermissionTuple(self.user, ALL_PERMISSIONS, 'group',
                                  self.group, resource_g, True, True),
                  ]

        check_one_in_other(perms, second)

    def test_resource_users_for_any_perm_additional_users(self, db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        user6 = add_user(db_session, 6, 'user 6')
        user7 = add_user(db_session, 7, 'user 7')
        perm2 = GroupResourcePermission(
            perm_name='group_perm2',
            resource_id=self.resource.resource_id
        )
        self.group.resource_permissions.append(perm2)
        self.group.users.append(user6)
        self.group.users.append(user7)
        perms = self.resource.users_for_perm(
            '__any_permission__', db_session=db_session)
        second = [
            PermissionTuple(self.user, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user6, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user7, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user6, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user7, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user, 'test_perm2', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user, 'foo_perm', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user4, 'group_perm', 'group', self.group2,
                            self.resource, False, True),
        ]

        check_one_in_other(perms, second)

    def test_resource_users_for_any_perm_limited_group_perms(self, db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        user6 = add_user(db_session, 6, 'user 6')
        user7 = add_user(db_session, 7, 'user 7')
        perm2 = GroupResourcePermission(
            perm_name='group_perm2',
            resource_id=self.resource.resource_id
        )
        self.group.resource_permissions.append(perm2)
        self.group.users.append(user6)
        self.group.users.append(user7)
        perms = self.resource.users_for_perm(
            '__any_permission__', limit_group_permissions=True,
            db_session=db_session)
        second = [
            PermissionTuple(None, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user, 'test_perm2', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user, 'foo_perm', 'user', None,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm', 'group', self.group2,
                            self.resource, False, True),
        ]

        check_one_in_other(perms, second)

    def test_resource_groups_for_any_perm_additional_users(self, db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        user6 = add_user(db_session, 6, 'user 6')
        user7 = add_user(db_session, 7, 'user 7')
        perm2 = GroupResourcePermission(
            perm_name='group_perm2',
            resource_id=self.resource.resource_id
        )
        self.group.resource_permissions.append(perm2)
        self.group.users.append(user6)
        self.group.users.append(user7)
        perms = self.resource.groups_for_perm(
            '__any_permission__', db_session=db_session)
        second = [
            PermissionTuple(self.user, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user6, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user7, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user6, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(user7, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user4, 'group_perm', 'group', self.group2,
                            self.resource, False, True),
        ]

        check_one_in_other(perms, second)

    def test_resource_groups_for_any_perm_just_group_perms_limited(self,
                                                                   db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        user6 = add_user(db_session, 6, 'user 6')
        user7 = add_user(db_session, 7, 'user 7')
        perm2 = GroupResourcePermission(
            perm_name='group_perm2',
            resource_id=self.resource.resource_id
        )
        self.group.resource_permissions.append(perm2)
        self.group.users.append(user6)
        self.group.users.append(user7)
        perms = self.resource.groups_for_perm(
            '__any_permission__', limit_group_permissions=True,
            db_session=db_session)
        second = [
            PermissionTuple(None, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm', 'group', self.group2,
                            self.resource, False, True),
        ]

        check_one_in_other(perms, second)

    def test_resource_users_for_any_perm_excluding_group_perms(
            self, db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        user6 = add_user(db_session, 6, 'user 6')
        user7 = add_user(db_session, 7, 'user 7')
        perm2 = GroupResourcePermission(
            perm_name='group_perm2',
            resource_id=self.resource.resource_id
        )
        self.group.resource_permissions.append(perm2)
        self.group.users.append(user6)
        self.group.users.append(user7)
        perms = self.resource.users_for_perm(
            '__any_permission__', limit_group_permissions=True,
            skip_group_perms=True, db_session=db_session)
        second = [
            PermissionTuple(self.user, 'test_perm2', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user, 'foo_perm', 'user', None,
                            self.resource, False, True)
        ]

        check_one_in_other(perms, second)

    def test_resource_groups_for_any_perm_just_group_perms_limited_empty_group(
            self, db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        user6 = add_user(db_session, 6, 'user 6')
        user7 = add_user(db_session, 7, 'user 7')
        perm2 = GroupResourcePermission(
            perm_name='group_perm2',
            resource_id=self.resource.resource_id
        )
        self.group.resource_permissions.append(perm2)
        self.group.users.append(user6)
        self.group.users.append(user7)

        group3 = add_group(db_session, 'Empty group')
        perm3 = GroupResourcePermission(
            perm_name='group_permx',
            resource_id=self.resource.resource_id
        )
        group3.resource_permissions.append(perm3)
        perms = self.resource.groups_for_perm(
            '__any_permission__', limit_group_permissions=True,
            db_session=db_session)

        second = [
            PermissionTuple(None, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm', 'group', self.group2,
                            self.resource, False, True),
            PermissionTuple(None, 'group_permx', 'group', group3,
                            self.resource, False, True)
        ]

        check_one_in_other(perms, second)

    def test_resource_users_for_any_perm_limited_group_perms_empty_group(
            self, db_session):
        self.maxDiff = 99999
        self.set_up_user_group_and_perms(db_session)
        user6 = add_user(db_session, 6, 'user 6')
        user7 = add_user(db_session, 7, 'user 7')
        perm2 = GroupResourcePermission(
            perm_name='group_perm2',
            resource_id=self.resource.resource_id
        )
        self.group.resource_permissions.append(perm2)
        self.group.users.append(user6)
        self.group.users.append(user7)
        group3 = add_group(db_session, 'Empty group')
        perm3 = GroupResourcePermission(
            perm_name='group_permx',
            resource_id=self.resource.resource_id
        )
        group3.resource_permissions.append(perm3)

        perms = self.resource.users_for_perm(
            '__any_permission__', limit_group_permissions=True,
            db_session=db_session)

        second = [
            PermissionTuple(None, 'group_perm', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm2', 'group', self.group,
                            self.resource, False, True),
            PermissionTuple(self.user, 'test_perm2', 'user', None,
                            self.resource, False, True),
            PermissionTuple(self.user, 'foo_perm', 'user', None,
                            self.resource, False, True),
            PermissionTuple(None, 'group_perm', 'group', self.group2,
                            self.resource, False, True),
            PermissionTuple(None, 'group_permx', 'group', group3,
                            self.resource, False, True),
        ]

        check_one_in_other(perms, second)

    def test_get_resource_permission(self, db_session):
        created_user = add_user(db_session)
        resource = add_resource(db_session, 1, 'test_resource')
        permission = UserResourcePermission(
            perm_name='test_perm', user_id=created_user.id,
            resource_id=resource.resource_id)
        resource.user_permissions.append(permission)
        db_session.flush()
        perm = UserResourcePermissionService.get(
            user_id=created_user.id,
            resource_id=resource.resource_id,
            perm_name='test_perm',
            db_session=db_session
        )
        assert perm.perm_name == 'test_perm'
        assert perm.resource_id == resource.resource_id
        assert perm.user_id == created_user.id


class TestGroupPermission(BaseTestCase):
    def test_repr(self, db_session):
        group_permission = GroupPermission(group_id=1,
                                           perm_name='perm')
        assert repr(group_permission) == '<GroupPermission: perm>'

    def test_get(self, db_session):
        org_group = add_group(db_session, 'group1')
        group = GroupPermissionService.get(
            group_id=org_group.id, perm_name='manage_apps',
            db_session=db_session)
        assert group.group_id == 1
        assert group.perm_name == 'manage_apps'

    def test_by_group_and_perm(self, db_session):
        add_group(db_session, )
        queried = GroupPermission.by_group_and_perm(1, 'manage_apps',
                                                    db_session=db_session)
        assert queried.group_id == 1
        assert queried.perm_name == 'manage_apps'

    def test_by_group_and_perm_wrong_group(self, db_session):
        add_group(db_session, )
        queried = GroupPermission.by_group_and_perm(2,
                                                    'manage_apps',
                                                    db_session=db_session)
        assert queried is None

    def test_by_group_and_perm_wrong_perm(self, db_session):
        add_group(db_session, )
        queried = GroupPermission.by_group_and_perm(1, 'wrong_perm',
                                                    db_session=db_session)
        assert queried is None

    def test_resources_with_possible_perms(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        perms = self.group.resources_with_possible_perms()
        second = [PermissionTuple(None, 'group_perm', 'group', self.group,
                                  self.resource, False, True),
                  ]

        check_one_in_other(perms, second)

    def test_resources_with_possible_perms_group2(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        resource3 = add_resource_b(db_session, 3, 'other resource')
        self.group2.resources.append(resource3)
        group_permission2 = GroupResourcePermission(
            perm_name='group_perm2',
            group_id=self.group2.id,
        )
        self.resource2.group_permissions.append(group_permission2)

        perms = self.group2.resources_with_possible_perms()
        second = [PermissionTuple(None, 'group_perm', 'group', self.group2,
                                  self.resource, False, True),
                  PermissionTuple(None, 'group_perm2', 'group', self.group2,
                                  self.resource2, False, True),
                  PermissionTuple(None, ALL_PERMISSIONS, 'group', self.group2,
                                  resource3, True, True),
                  ]

        check_one_in_other(perms, second)

    def test_group_resource_permission(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        resource3 = add_resource_b(db_session, 3, 'other resource')
        db_session.flush()
        group_permission2 = GroupResourcePermission(
            perm_name='group_perm2',
            group_id=self.group2.id,
        )
        row = GroupResourcePermissionService.get(
            group_id=self.group2.id, resource_id=self.resource2.resource_id,
            perm_name='group_perm2', db_session=db_session)
        assert row is None
        self.resource2.group_permissions.append(group_permission2)
        row = GroupResourcePermissionService.get(
            group_id=self.group2.id, resource_id=self.resource2.resource_id,
            perm_name='group_perm2', db_session=db_session)
        assert row is not None

    def test_group_resource_permission_wrong(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        perm_name = 'group_permX'
        perm = ResourceService.perm_by_group_and_perm_name(
            resource_id=self.resource.resource_id,
            group_id=self.group.id,
            perm_name=perm_name,
            db_session=db_session
        )
        assert perm is None

    def test_group_resource_permission(self, db_session):
        self.set_up_user_group_and_perms(db_session)
        perm_name = 'group_perm'
        perm = ResourceService.perm_by_group_and_perm_name(
            resource_id=self.resource.resource_id,
            group_id=self.group.id,
            perm_name=perm_name,
            db_session=db_session
        )
        assert perm.group_id == self.group.id
        assert perm.resource_id == self.resource.resource_id
        assert perm.perm_name == perm_name


class TestUserPermission(BaseTestCase):
    def test_repr(self, db_session):
        user_permission = UserPermission(user_id=1, perm_name='perm')
        assert repr(user_permission) == '<UserPermission: perm>'

    def test_get(self, db_session):
        user = add_user(db_session)
        perm = UserPermissionService.get(
            user_id=user.id, perm_name='root', db_session=db_session)
        assert perm.user_id == user.id
        assert perm.perm_name == 'root'

    def test_by_user_and_perm(self, db_session):
        add_user(db_session)
        user_permission = UserPermission.by_user_and_perm(1, 'root',
                                                          db_session=db_session)

        assert user_permission.user_id == 1
        assert user_permission.perm_name == 'root'

    def test_by_user_and_perm_wrong_username(self, db_session):
        add_user(db_session)
        user_permission = UserPermission.by_user_and_perm(999, 'root',
                                                          db_session=db_session)

        assert user_permission is None

    def test_by_user_and_perm_wrong_permname(self, db_session):
        add_user(db_session)
        user_permission = UserPermission.by_user_and_perm(1, 'wrong',
                                                          db_session=db_session)

        assert user_permission is None
