Пример #1
0
    def _post_save(self, instance, created, *args, **kwargs):
        Role_ = utils.get_current_apps().get_model('main', 'Role')
        ContentType_ = utils.get_current_apps().get_model('contenttypes', 'ContentType')
        ct_id = ContentType_.objects.get_for_model(instance).id

        Model = utils.get_current_apps().get_model('main', instance.__class__.__name__)
        latest_instance = Model.objects.get(pk=instance.pk)

        with batch_role_ancestor_rebuilding():
            # Create any missing role objects
            missing_roles = []
            for implicit_role_field in getattr(latest_instance.__class__, '__implicit_role_fields'):
                cur_role = getattr(latest_instance, implicit_role_field.name, None)
                if cur_role is None:
                    missing_roles.append(Role_(role_field=implicit_role_field.name, content_type_id=ct_id, object_id=latest_instance.id))

            if len(missing_roles) > 0:
                Role_.objects.bulk_create(missing_roles)
                updates = {}
                role_ids = []
                for role in Role_.objects.filter(content_type_id=ct_id, object_id=latest_instance.id):
                    setattr(latest_instance, role.role_field, role)
                    updates[role.role_field] = role.id
                    role_ids.append(role.id)
                type(latest_instance).objects.filter(pk=latest_instance.pk).update(**updates)
                Role.rebuild_role_ancestor_list(role_ids, [])

            update_role_parentage_for_instance(latest_instance)
            instance.refresh_from_db()
Пример #2
0
def test_roles_visibility(get, organization, project, admin, alice, bob):
    Role.singleton('system_auditor').members.add(alice)
    assert get(reverse('api:role_list') + '?id=%d' % project.update_role.id, user=admin).data['count'] == 1
    assert get(reverse('api:role_list') + '?id=%d' % project.update_role.id, user=alice).data['count'] == 1
    assert get(reverse('api:role_list') + '?id=%d' % project.update_role.id, user=bob).data['count'] == 0
    organization.auditor_role.members.add(bob)
    assert get(reverse('api:role_list') + '?id=%d' % project.update_role.id, user=bob).data['count'] == 1
Пример #3
0
def user_is_system_auditor(user, tf):
    if user.id:
        if tf:
            Role.singleton('system_auditor').members.add(user)
            user._is_system_auditor = True
        else:
            Role.singleton('system_auditor').members.remove(user)
            user._is_system_auditor = False
Пример #4
0
    def _post_delete(self, instance, *args, **kwargs):
        role_ids = []
        for implicit_role_field in getattr(instance.__class__, '__implicit_role_fields'):
            role_ids.append(getattr(instance, implicit_role_field.name + '_id'))

        Role_ = utils.get_current_apps().get_model('main', 'Role')
        child_ids = [x for x in Role_.parents.through.objects.filter(to_role_id__in=role_ids).distinct().values_list('from_role_id', flat=True)]
        Role_.objects.filter(id__in=role_ids).delete()
        Role.rebuild_role_ancestor_list([], child_ids)
Пример #5
0
def test_metrics_permissions(get, admin, org_admin, alice, bob, organization):
    assert get(get_metrics_view_db_only(), user=admin).status_code == 200
    assert get(get_metrics_view_db_only(), user=org_admin).status_code == 403
    assert get(get_metrics_view_db_only(), user=alice).status_code == 403
    assert get(get_metrics_view_db_only(), user=bob).status_code == 403
    organization.auditor_role.members.add(bob)
    assert get(get_metrics_view_db_only(), user=bob).status_code == 403

    Role.singleton('system_auditor').members.add(bob)
    bob.is_system_auditor = True
    assert get(get_metrics_view_db_only(), user=bob).status_code == 200
Пример #6
0
def test_roles_filter_visibility(get, organization, project, admin, alice, bob):
    Role.singleton('system_auditor').members.add(alice)
    project.update_role.members.add(admin)

    assert get(reverse('api:user_roles_list', kwargs={'pk': admin.id}) + '?id=%d' % project.update_role.id, user=admin).data['count'] == 1
    assert get(reverse('api:user_roles_list', kwargs={'pk': admin.id}) + '?id=%d' % project.update_role.id, user=alice).data['count'] == 1
    assert get(reverse('api:user_roles_list', kwargs={'pk': admin.id}) + '?id=%d' % project.update_role.id, user=bob).data['count'] == 0
    organization.auditor_role.members.add(bob)
    assert get(reverse('api:user_roles_list', kwargs={'pk': admin.id}) + '?id=%d' % project.update_role.id, user=bob).data['count'] == 1
    organization.auditor_role.members.remove(bob)
    project.use_role.members.add(bob) # sibling role should still grant visibility
    assert get(reverse('api:user_roles_list', kwargs={'pk': admin.id}) + '?id=%d' % project.update_role.id, user=bob).data['count'] == 1
Пример #7
0
def user_is_system_auditor(user, tf):
    if user.id:
        if tf:
            role = Role.singleton('system_auditor')
            # must check if member to not duplicate activity stream
            if user not in role.members.all():
                role.members.add(user)
            user._is_system_auditor = True
        else:
            role = Role.singleton('system_auditor')
            if user in role.members.all():
                role.members.remove(user)
            user._is_system_auditor = False
Пример #8
0
def rebuild_role_hierarchy(apps, schema_editor):
    logger.info('Computing role roots..')
    start = time()
    roots = Role.objects \
                .all() \
                .values_list('id', flat=True)
    stop = time()
    logger.info('Found %d roots in %f seconds, rebuilding ancestry map' %
                (len(roots), stop - start))
    start = time()
    Role.rebuild_role_ancestor_list(roots, [])
    stop = time()
    logger.info('Rebuild completed in %f seconds' % (stop - start))
    logger.info('Done.')
Пример #9
0
def apply_fake_roles(obj):
    '''
    Creates an un-saved role for all the implicit role fields on an object
    '''
    for fd in obj._meta.fields:
        if not isinstance(fd, ImplicitRoleField):
            continue
        r = Role(role_field=fd.name)
        setattr(obj, fd.name, r)
        with mock.patch(
                'django.contrib.contenttypes.fields.GenericForeignKey.get_content_type'
        ) as mck_ct:
            mck_ct.return_value = ContentType(model=obj._meta.model_name)
            r.content_object = obj
Пример #10
0
def test_get_roles_list_user(organization, inventory, team, get, user):
    'Users can see all roles they have access to, but not all roles'
    this_user = user('user-test_get_roles_list_user')
    organization.member_role.members.add(this_user)
    custom_role = Role.objects.create(
        role_field='custom_role-test_get_roles_list_user')
    organization.member_role.children.add(custom_role)

    url = reverse('api:role_list')
    response = get(url, this_user)
    assert response.status_code == 200
    roles = response.data
    assert roles['count'] > 0
    assert roles['count'] == len(
        roles['results'])  # just to make sure the tests below are valid

    role_hash = {}

    for r in roles['results']:
        role_hash[r['id']] = r

    assert Role.singleton(ROLE_SINGLETON_SYSTEM_ADMINISTRATOR).id in role_hash
    assert organization.admin_role.id in role_hash
    assert organization.member_role.id in role_hash
    assert this_user.admin_role.id in role_hash
    assert custom_role.id in role_hash

    assert inventory.admin_role.id not in role_hash
    assert team.member_role.id not in role_hash
Пример #11
0
def rebuild_role_hierarchy(apps, schema_editor):
    """
    This should be called in any migration when ownerships are changed.
    Ex. I remove a user from the admin_role of a credential.
    Ancestors are cached from parents for performance, this re-computes ancestors.
    """
    logger.info('Computing role roots..')
    start = time()
    roots = Role.objects.all().values_list('id', flat=True)
    stop = time()
    logger.info('Found %d roots in %f seconds, rebuilding ancestry map' % (len(roots), stop - start))
    start = time()
    Role.rebuild_role_ancestor_list(roots, [])
    stop = time()
    logger.info('Rebuild ancestors completed in %f seconds' % (stop - start))
    logger.info('Done.')
Пример #12
0
def user_is_system_auditor(user, tf):
    if not user.id:
        # If the user doesn't have a primary key yet (i.e., this is the *first*
        # time they've logged in, and we've just created the new User in this
        # request), we need one to set up the system auditor role
        user.save()
    if tf:
        role = Role.singleton('system_auditor')
        # must check if member to not duplicate activity stream
        if user not in role.members.all():
            role.members.add(user)
        user._is_system_auditor = True
    else:
        role = Role.singleton('system_auditor')
        if user in role.members.all():
            role.members.remove(user)
        user._is_system_auditor = False
Пример #13
0
    def _post_save(self, instance, created, *args, **kwargs):
        Role_ = utils.get_current_apps().get_model('main', 'Role')
        ContentType_ = utils.get_current_apps().get_model(
            'contenttypes', 'ContentType')
        ct_id = ContentType_.objects.get_for_model(instance).id
        with batch_role_ancestor_rebuilding():
            # Create any missing role objects
            missing_roles = []
            for implicit_role_field in getattr(instance.__class__,
                                               '__implicit_role_fields'):
                cur_role = getattr(instance, implicit_role_field.name, None)
                if cur_role is None:
                    missing_roles.append(
                        Role_(role_field=implicit_role_field.name,
                              content_type_id=ct_id,
                              object_id=instance.id))
            if len(missing_roles) > 0:
                Role_.objects.bulk_create(missing_roles)
                updates = {}
                role_ids = []
                for role in Role_.objects.filter(content_type_id=ct_id,
                                                 object_id=instance.id):
                    setattr(instance, role.role_field, role)
                    updates[role.role_field] = role.id
                    role_ids.append(role.id)
                type(instance).objects.filter(pk=instance.pk).update(**updates)
                Role.rebuild_role_ancestor_list(role_ids, [])

            # Update parentage if necessary
            for implicit_role_field in getattr(instance.__class__,
                                               '__implicit_role_fields'):
                cur_role = getattr(instance, implicit_role_field.name)
                original_parents = set(json.loads(cur_role.implicit_parents))
                new_parents = implicit_role_field._resolve_parent_roles(
                    instance)
                cur_role.parents.remove(*list(original_parents - new_parents))
                cur_role.parents.add(*list(new_parents - original_parents))
                new_parents_list = list(new_parents)
                new_parents_list.sort()
                new_parents_json = json.dumps(new_parents_list)
                if cur_role.implicit_parents != new_parents_json:
                    cur_role.implicit_parents = new_parents_json
                    cur_role.save()
Пример #14
0
def test_user_view_other_user_roles(organization, inventory, team, get, alice,
                                    bob):
    'Users can see roles for other users, but only the roles that that user has access to see as well'
    organization.member_role.members.add(alice)
    organization.admin_role.members.add(bob)
    organization.member_role.members.add(bob)
    custom_role = Role.objects.create(
        role_field='custom_role-test_user_view_admin_roles_list')
    organization.member_role.children.add(custom_role)
    team.member_role.members.add(bob)

    # alice and bob are in the same org and can see some child role of that org.
    # Bob is an org admin, alice can see this.
    # Bob is in a team that alice is not, alice cannot see that bob is a member of that team.

    url = reverse('api:user_roles_list', kwargs={'pk': bob.id})
    response = get(url, alice)
    assert response.status_code == 200
    roles = response.data
    assert roles['count'] > 0
    assert roles['count'] == len(
        roles['results'])  # just to make sure the tests below are valid

    role_hash = {}
    for r in roles['results']:
        role_hash[r['id']] = r['name']

    assert organization.admin_role.id in role_hash
    assert custom_role.id not in role_hash  # doesn't show up in the user roles list, not an explicit grant
    assert Role.singleton(
        ROLE_SINGLETON_SYSTEM_ADMINISTRATOR).id not in role_hash
    assert inventory.admin_role.id not in role_hash
    assert team.member_role.id not in role_hash  # alice can't see this

    # again but this time alice is part of the team, and should be able to see the team role
    team.member_role.members.add(alice)
    response = get(url, alice)
    assert response.status_code == 200
    roles = response.data
    assert roles['count'] > 0
    assert roles['count'] == len(
        roles['results'])  # just to make sure the tests below are valid

    role_hash = {}
    for r in roles['results']:
        role_hash[r['id']] = r['name']

    assert team.member_role.id in role_hash  # Alice can now see this
Пример #15
0
def system_auditor(user):
    u = user('an-auditor', False)
    Role.singleton('system_auditor').members.add(u)
    return u
Пример #16
0
def rebuild_role_parentage(apps, schema_editor, models=None):
    """
    This should be called in any migration when any parent_role entry
    is modified so that the cached parent fields will be updated. Ex:
        foo_role = ImplicitRoleField(
            parent_role=['bar_role']  # change to parent_role=['admin_role']
        )

    This is like rebuild_role_hierarchy, but that method updates ancestors,
    whereas this method updates parents.
    """
    start = time()
    seen_models = set()
    model_ct = 0
    noop_ct = 0
    ContentType = apps.get_model('contenttypes', "ContentType")
    additions = set()
    removals = set()

    role_qs = Role.objects
    if models:
        # update_role_parentage_for_instance is expensive
        # if the models have been downselected, ignore those which are not in the list
        ct_ids = list(
            ContentType.objects.filter(
                model__in=[name.lower()
                           for name in models]).values_list('id', flat=True))
        role_qs = role_qs.filter(content_type__in=ct_ids)

    for role in role_qs.iterator():
        if not role.object_id:
            continue
        model_tuple = (role.content_type_id, role.object_id)
        if model_tuple in seen_models:
            continue
        seen_models.add(model_tuple)

        # The GenericForeignKey does not work right in migrations
        # with the usage as role.content_object
        # so we do the lookup ourselves with current migration models
        ct = role.content_type
        app = ct.app_label
        ct_model = apps.get_model(app, ct.model)
        content_object = ct_model.objects.get(pk=role.object_id)

        parents_added, parents_removed = update_role_parentage_for_instance(
            content_object)
        additions.update(parents_added)
        removals.update(parents_removed)
        if parents_added:
            model_ct += 1
            logger.debug('Added to parents of roles {} of {}'.format(
                parents_added, content_object))
        if parents_removed:
            model_ct += 1
            logger.debug('Removed from parents of roles {} of {}'.format(
                parents_removed, content_object))
        else:
            noop_ct += 1

    logger.debug('No changes to role parents for {} resources'.format(noop_ct))
    logger.debug('Added parents to {} roles'.format(len(additions)))
    logger.debug('Removed parents from {} roles'.format(len(removals)))
    if model_ct:
        logger.info(
            'Updated implicit parents of {} resources'.format(model_ct))

    logger.info('Rebuild parentage completed in %f seconds' % (time() - start))

    # this is ran because the ordinary signals for
    # Role.parents.add and Role.parents.remove not called in migration
    Role.rebuild_role_ancestor_list(list(additions), list(removals))
Пример #17
0
def system_auditor():
    return Role(role_field=ROLE_SINGLETON_SYSTEM_AUDITOR,
                singleton_name=ROLE_SINGLETON_SYSTEM_AUDITOR)
Пример #18
0
def system_administrator():
    return Role(role_field=ROLE_SINGLETON_SYSTEM_ADMINISTRATOR,
                singleton_name=ROLE_SINGLETON_SYSTEM_ADMINISTRATOR)