Пример #1
0
    def handle(self, *args, **options):
        UserModel = get_user_model()
        for user_blocked in UserModel.objects.filter(is_active=False):
            divider_manager = getattr(
                user_blocked, '{}s'.format(DIVIDER_MODEL.lower())
            )
            user_dividers = divider_manager.values_list('uid', flat=True)
            remove_instances_user_tracked_fields(user_blocked, user_dividers)
            divider_manager.clear()
            user_blocked.concrete_groups.clear()

        all_dividers = apps.get_model(
            "concrete.{}".format(DIVIDER_MODEL)
        ).objects.all()
        for user_active in UserModel.objects.filter(is_active=True):
            divider_manager = getattr(
                user_active, '{}s'.format(DIVIDER_MODEL.lower())
            )
            user_dividers = divider_manager.all()
            dividers_to_remove = all_dividers.difference(user_dividers)
            remove_instances_user_tracked_fields(
                user_active, dividers_to_remove.values_list('uid', flat=True)
            )

        for meta_model in meta_models:
            if meta_model.get_model_name() in [
                "EntityDividerModel",
                "UndividedModel",
            ]:
                continue
            model_name = meta_model.get_model_name()
            # pylint: disable=no-member
            ConcretePermission.objects.get_or_create(model_name=model_name)
    def test_filter_objects_by_divider(self):
        url_projects = '/api/v1/project/'
        # User get only projects from cloisonX
        url_filter = '/api/v1/project/?{}={}'.format(DIVIDER_MODEL.lower(),
                                                     str(self.cloisonX.uid))
        resp = self.client.get(url_filter,
                               HTTP_AUTHORIZATION='Token {}'.format(
                                   self.token_a))
        self.assertEqual(resp.status_code,
                         status.HTTP_200_OK,
                         msg=resp.content)
        results = resp.json()['results']

        self.assertEqual(len(results), 1)
        self.assertEqual(results[0]['name'], "projet A")

        # User get only projects from cloisonY
        url_filter = '/api/v1/project/?{}={}'.format(DIVIDER_MODEL.lower(),
                                                     str(self.cloisonY.uid))
        resp = self.client.get(url_filter,
                               HTTP_AUTHORIZATION='Token {}'.format(
                                   self.token_a))
        self.assertEqual(resp.status_code,
                         status.HTTP_200_OK,
                         msg=resp.content)
        results = resp.json()['results']

        self.assertEqual(len(results), 1)
        self.assertEqual(results[0]['name'], "projet B")

        # User get two projects without filter
        resp = self.client.get(url_projects,
                               HTTP_AUTHORIZATION='Token {}'.format(
                                   self.token_a))
        self.assertEqual(len(resp.json()['results']), 2)
Пример #3
0
def unsubscribe_notifications_view(request, token):
    '''
    token is the uid of UserNotificationChoice instance.
    '''
    user = get_object_or_404(get_user_model(),
                             subscription_notification_token=token)
    lookup_as_json = (
        settings.CONCRETE_SCOPES_FILTER_LOOKUP_FOR_UNSUBSCRIBE_JSON)

    queryset = getattr(user, '{}s'.format(DIVIDER_MODEL.lower())).all()
    scopes = filter_scopes_for_unsubscribe(
        queryset=queryset,
        lookup_as_dict=parse_lookup_for_unsubscribe(
            model=queryset.model,
            lookup_as_json=lookup_as_json,
            fields=[f.name for f in queryset.model._meta.fields],
        ),
    )
    return render(
        request,
        'mainApp/unsubscribe.html',
        {
            "token": token,
            "user_email": user.email,
            "scopes": scopes,
            'error_message': '',
            'platform_name': settings.PLATFORM_NAME,
        },
    )
def make_account_me_serialier(api_namespace=DEFAULT_API_NAMESPACE):
    meta = get_meta_definition_by_model_name('User')
    meta_serializer_class = make_serializer_class(meta_model=meta,
                                                  api_namespace=api_namespace,
                                                  nested=False,
                                                  safe=True)

    Meta = meta_serializer_class.Meta

    Meta.fields = [
        field for field in Meta.fields
        if field not in ['admin', 'is_staff', 'is_superuser', 'is_active']
    ] + ['level']

    Meta.read_only_fields = Meta.read_only_fields + [
        'uid',
        'public',
        'creation_date',
        'modification_date',
        '{}s'.format(DIVIDER_MODEL.lower()),
    ]

    return type(
        str('AccountMeSerializer'),
        (meta_serializer_class, ),
        {
            'Meta': Meta,
            'level': serializers.SerializerMethodField(),
            'get_level': lambda self, obj: obj.get_level(),
        },
    )
def on_post_save(sender, instance, **kwargs):
    if instance.level == 'blocked':
        divider_manager = getattr(instance,
                                  '{}s'.format(DIVIDER_MODEL.lower()))
        user_dividers = divider_manager.values_list('uid', flat=True)
        remove_instances_user_tracked_fields(instance, user_dividers)
        divider_manager.clear()
        instance.concrete_groups.clear()
Пример #6
0
        def get_scopes(self, obj):
            user = self.context.get('request').user
            superuser = user.is_superuser is True
            at_least_admin = (False
                              if user.is_anonymous else user.is_at_least_admin)
            staff = False if user.is_anonymous else user.is_at_least_staff

            if staff or at_least_admin or superuser:
                divider = getattr(obj, DIVIDER_MODEL.lower(), None)
                if divider:
                    return {"entity_uid": divider.uid}
            return None
 class Meta:
     model = get_user_model()
     fields = (
         "uid",
         'email',
         "url",
         "token",
         'first_name',
         "password",
         "last_name",
         "level",
         'is_verified',
         'groups',
         'external_auth',
         "{}s".format(DIVIDER_MODEL.lower()),
     )
 def get_scopes(self, obj):
     divider = getattr(obj, DIVIDER_MODEL.lower(), None)
     if divider:
         return {"entity_uid": divider.uid}
     return None
def make_serializer_class(
    meta_model,
    api_namespace=DEFAULT_API_NAMESPACE,
    limit_fields=None,
    nested=True,
    safe=False,
):
    enum_fields = list(meta_model.get_fields())
    dict_fields = OrderedDict(enum_fields)
    _all_fields = (list(dict_fields.keys()) +
                   list(get_common_fields().keys()) + ['url', 'verbose_name'])

    custom_fields_names, custom_fields_attrs = make_custom_serializer_fields(
        meta_model, api_namespace=api_namespace)

    _all_fields += custom_fields_names
    if meta_model.get_model_name() not in ('User', ):
        _all_fields += get_user_tracked_fields().keys()
    if meta_model.get_model_name() not in ('User', DIVIDER_MODEL):
        _all_fields += ['scopes']
    api_display_fields = meta_model.get_property('m_api_list_display') or []
    if api_display_fields == []:
        if limit_fields is None:
            _fields = _all_fields
        else:
            _fields = [f for f in _all_fields if f in limit_fields]
    else:
        _fields = api_display_fields
    if meta_model.get_model_name() == 'User' and api_display_fields == []:
        _fields += [
            'last_name',
            'first_name',
            "{}s".format(DIVIDER_MODEL.lower()),
            "admin",
            "is_staff",
            "level",
            "unsubscribe_notification_url",
            "unsubscribe_all",
            "unsubscribe_to",
            "external_auth",
        ]

        if safe:
            _fields += ['email']

    # TODO: rajouter les <name>_uid dans _fields
    fk_read_only_fields = []
    for name, field in enum_fields:

        if field.type.startswith("rel_"):
            _fields += ['{}_uid'.format(name)]
            fk_read_only_fields += [name]

    class Meta:
        model = concrete.models[meta_model.get_model_name().lower()]
        fields = _fields

        read_only_fields = (
            ['created_by', 'admin', 'is_staff'] + fk_read_only_fields +
            [f for f in _all_fields if f.startswith('resource_')])
        extra_kwargs = {
            name: {
                'required': is_field_required(field)
            }
            for name, field in enum_fields
        }

        # TODO: DEACTIVATED by LCO on 06/11/18
        # vars_model = vars(model)
        # for key, value in vars_model.items():
        #     # TODO: Exclude model User
        #     if isinstance(value, ReverseManyToOneDescriptor):
        #         if not (key.startswith('divider') or (key.startswith('can'))):
        #             fields.append(key)
        #             read_only_fields.append(key)

    attrs = {'Meta': Meta}

    # TODO : if field is relational, expose pk and url serialized
    for name, field in enum_fields:

        if field.f_type == 'FileField':
            attrs.update({
                name:
                serializers.FileField(
                    required=False,
                    allow_null=True,
                    validators=[validate_file],
                )
            })
        if field.f_type == 'PointField':
            attrs.update({
                name:
                PointField(
                    required=not field.f_args.get("blank", False),
                    allow_null=True,
                )
            })
        if field.f_type == 'JSONField':
            attrs.update(
                {name: serializers.JSONField(binary=False, required=False)})
        if field.type.startswith("rel_") and nested is True:

            force_nested = getattr(field, 'force_nested', False)

            attrs.update({
                name:
                make_related_serializer_class(
                    target_model_name=field.f_args['to'],
                    many=(field.type == 'rel_iterable'),
                    nested=force_nested,
                    api_namespace=api_namespace,
                )
            })

    attrs.update(custom_fields_attrs)

    class _ModelSerializer(serializers.ModelSerializer):
        url = serializers.SerializerMethodField()
        verbose_name = serializers.SerializerMethodField()
        scopes = serializers.SerializerMethodField()

        def get_scopes(self, obj):
            divider = getattr(obj, DIVIDER_MODEL.lower(), None)
            if divider:
                return {"entity_uid": divider.uid}
            return None

        def get_url(self, obj):
            uri = reverse(
                "{}:{}-detail".format(api_namespace,
                                      meta_model.get_dashed_case_class_name()),
                args=(obj.pk, ),
            )
            if hasattr(self, '_context'):
                if 'request' in self._context:
                    request = self._context['request']
                    return request.build_absolute_uri(uri)
            return build_absolute_uri(uri)  # skip-test-coverage

        def get_verbose_name(self, obj):
            try:
                return str(obj)
            except Exception:
                return ''

    for name, field in enum_fields:
        attrs.update({f'validate_{name}': get_field_validator(field=field)})
        if field.type.startswith("rel_i"):
            x = field.f_args["to"].split('.')
            field_model = apps.get_model(app_label=x[0], model_name=x[1])
            required = not field.f_args.get("blank", False)
            attrs.update({
                '{}_uid'.format(name):
                serializers.PrimaryKeyRelatedField(
                    source=name,
                    many=True,
                    allow_null=True,
                    required=required,
                    queryset=field_model.objects.all(),
                )
            })

        if field.type.startswith("rel_s"):
            # Ex: concrete.Category, split to get
            # Django model with apps.get_model()
            x = field.f_args["to"].split('.')
            field_model = apps.get_model(app_label=x[0], model_name=x[1])
            required = not field.f_args.get("blank", False)
            null = field.f_args.get("null", False)
            attrs.update({
                '{}_uid'.format(name):
                serializers.PrimaryKeyRelatedField(
                    many=False,
                    source=name,
                    allow_null=null,
                    required=required,
                    queryset=field_model.objects.all(),
                )
            })

    if meta_model.get_model_name() == 'User':
        attrs.update({'level': serializers.CharField()})

        def validate_level(self, value):
            value = value.lower()

            if value not in LIST_USER_LEVEL:
                raise serializers.ValidationError("Wrong value")

            else:
                user_level = self.context.get('request').user.level
                forbidden_for_admin = user_level == "admin" and value in [
                    "admin",
                    "superuser",
                ]
                forbidden_for_manager = user_level == "manager" and value in [
                    "admin",
                    "superuser",
                    "manager",
                    "blocked",
                ]
                forbidden_for_simple = user_level == "simpleuser"
                if (forbidden_for_manager or forbidden_for_admin
                        or forbidden_for_simple):
                    raise serializers.ValidationError(
                        "You don't have permission to set this level")
            return value

        _ModelSerializer.validate_level = validate_level

        attrs.update({
            'unsubscribe_notification_url':
            serializers.SerializerMethodField('get_unsubscribe_url')
        })

        def get_unsubscribe_url(self, obj):
            return '{scheme}://{domain}:{port}{uri}'.format(
                scheme=settings.SCHEME,
                domain=settings.HOSTNAME,
                port=settings.PORT,
                uri=reverse(
                    'concrete:unsubscribe_notifications',
                    kwargs={'token': obj.subscription_notification_token},
                ),
            )

        _ModelSerializer.get_unsubscribe_url = get_unsubscribe_url

    api_model_serializer = type(
        str('{}ModelSerializer'.format(meta_model.get_model_name())),
        (_ModelSerializer, ),
        attrs,
    )
    return api_model_serializer
Пример #10
0
from django.db.models import Q
from django.conf import settings
from django.contrib.auth import get_user_model

from rest_framework.exceptions import APIException
from rest_framework import permissions, status

from concrete_datastore.concrete.models import (
    ConcretePermission,
    DIVIDER_MODEL,
    UNDIVIDED_MODEL,
)

DIVIDER_MODELs = "{}s".format(DIVIDER_MODEL)
DIVIDER_MODELs_LOWER = DIVIDER_MODELs.lower()
DIVIDER_MODEL_LOWER = DIVIDER_MODEL.lower()


class PreconditionFailed(APIException):
    status_code = status.HTTP_412_PRECONDITION_FAILED
    default_detail = 'Precondition Fail to perform this action'
    default_code = 'precondition_failed'


CONCRETE_SETTINGS = getattr(settings, 'CONCRETE', {})
API_PERMISSIONS_CLASSES = CONCRETE_SETTINGS.get('API_PERMISSIONS_CLASSES', {})


def get_permissions_classes_by_meta_model(meta_model):
    permissions_classes_path = API_PERMISSIONS_CLASSES.get(
        meta_model._specifier.name,