Exemplo n.º 1
0
class UserSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'full_name',
        'given_name',
        'middle_names',
        'family_name',
        'id',
    ])
    writeable_method_fields = frozenset([
        'accepted_terms_of_service',
    ])
    non_anonymized_fields = ['type']
    id = IDField(source='_id', read_only=True)
    type = TypeField()
    full_name = ser.CharField(
        source='fullname',
        required=True,
        label='Full name',
        help_text='Display name used in the general user interface',
        max_length=186)
    given_name = ser.CharField(required=False,
                               allow_blank=True,
                               help_text='For bibliographic citations')
    middle_names = ser.CharField(required=False,
                                 allow_blank=True,
                                 help_text='For bibliographic citations')
    family_name = ser.CharField(required=False,
                                allow_blank=True,
                                help_text='For bibliographic citations')
    suffix = HideIfDisabled(
        ser.CharField(required=False,
                      allow_blank=True,
                      help_text='For bibliographic citations'))
    date_registered = HideIfDisabled(VersionedDateTimeField(read_only=True))
    active = HideIfDisabled(
        ser.BooleanField(read_only=True, source='is_active'))
    timezone = HideIfDisabled(
        ser.CharField(required=False,
                      help_text="User's timezone, e.g. 'Etc/UTC"))
    locale = HideIfDisabled(
        ser.CharField(required=False,
                      help_text="User's locale, e.g.  'en_US'"))
    social = SocialField(required=False, min_version='2.10')
    employment = JSONAPIListField(required=False, source='jobs')
    education = JSONAPIListField(required=False, source='schools')
    can_view_reviews = ShowIfCurrentUser(
        ser.SerializerMethodField(
            help_text=
            'Whether the current user has the `view_submissions` permission to ANY reviews provider.'
        ))
    accepted_terms_of_service = ShowIfCurrentUser(ser.SerializerMethodField())

    links = HideIfDisabled(
        LinksField(
            {
                'html': 'absolute_url',
                'profile_image': 'profile_image_url',
            }, ))

    nodes = HideIfDisabled(
        RelationshipField(
            related_view='users:user-nodes',
            related_view_kwargs={'user_id': '<_id>'},
            related_meta={
                'projects_in_common': 'get_projects_in_common',
                'count': 'get_node_count',
            },
        ))

    quickfiles = HideIfDisabled(
        QuickFilesRelationshipField(
            related_view='users:user-quickfiles',
            related_view_kwargs={'user_id': '<_id>'},
            related_meta={'count': 'get_quickfiles_count'},
        ))

    registrations = HideIfDisabled(
        RelationshipField(
            related_view='users:user-registrations',
            related_view_kwargs={'user_id': '<_id>'},
            related_meta={'count': 'get_registration_count'},
        ))

    institutions = HideIfDisabled(
        RelationshipField(
            related_view='users:user-institutions',
            related_view_kwargs={'user_id': '<_id>'},
            self_view='users:user-institutions-relationship',
            self_view_kwargs={'user_id': '<_id>'},
            related_meta={'count': 'get_institutions_count'},
        ))

    preprints = HideIfDisabled(
        RelationshipField(
            related_view='users:user-preprints',
            related_view_kwargs={'user_id': '<_id>'},
            related_meta={'count': 'get_preprint_count'},
        ))

    emails = ShowIfCurrentUser(
        RelationshipField(
            related_view='users:user-emails',
            related_view_kwargs={'user_id': '<_id>'},
        ))

    default_region = ShowIfCurrentUser(
        RegionRelationshipField(
            related_view='regions:region-detail',
            related_view_kwargs={'region_id': 'get_default_region_id'},
            read_only=False,
        ))

    settings = ShowIfCurrentUser(
        RelationshipField(
            related_view='users:user_settings',
            related_view_kwargs={'user_id': '<_id>'},
            read_only=True,
        ))

    class Meta:
        type_ = 'users'

    def get_projects_in_common(self, obj):
        user = get_user_auth(self.context['request']).user
        if obj == user:
            return user.contributor_to.count()
        return obj.n_projects_in_common(user)

    def absolute_url(self, obj):
        if obj is not None:
            return obj.absolute_url
        return None

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'users:user-detail',
            kwargs={
                'user_id':
                obj._id,
                'version':
                self.context['request'].parser_context['kwargs']['version'],
            },
        )

    def get_node_count(self, obj):
        auth = get_user_auth(self.context['request'])
        if obj != auth.user:
            return default_node_list_permission_queryset(
                user=auth.user,
                model_cls=Node).filter(contributor__user__id=obj.id).count()

        return default_node_list_queryset(model_cls=Node).filter(
            contributor__user__id=obj.id).count()

    def get_quickfiles_count(self, obj):
        return QuickFilesNode.objects.get(
            contributor__user__id=obj.id).files.filter(
                type='osf.osfstoragefile').count()

    def get_registration_count(self, obj):
        auth = get_user_auth(self.context['request'])
        user_registration = default_node_list_queryset(
            model_cls=Registration).filter(contributor__user__id=obj.id)
        return user_registration.can_view(
            user=auth.user, private_link=auth.private_link).count()

    def get_preprint_count(self, obj):
        auth_user = get_user_auth(self.context['request']).user
        user_preprints_query = Preprint.objects.filter(
            _contributors__guids___id=obj._id).exclude(machine_state='initial')
        return Preprint.objects.can_view(user_preprints_query,
                                         auth_user,
                                         allow_contribs=False).count()

    def get_institutions_count(self, obj):
        return obj.affiliated_institutions.count()

    def get_can_view_reviews(self, obj):
        group_qs = AbstractProviderGroupObjectPermission.objects.filter(
            group__user=obj, permission__codename='view_submissions')
        return group_qs.exists(
        ) or obj.abstractprovideruserobjectpermission_set.filter(
            permission__codename='view_submissions')

    def get_default_region_id(self, obj):
        try:
            # use the annotated value if possible
            region_id = obj.default_region
        except AttributeError:
            # use computed property if region annotation does not exist
            region_id = obj.osfstorage_region._id
        return region_id

    def get_accepted_terms_of_service(self, obj):
        return bool(obj.accepted_terms_of_service)

    def profile_image_url(self, user):
        size = self.context['request'].query_params.get('profile_image_size')
        return user.profile_image_url(size=size)

    def validate_employment(self, value):
        validate_user_json(value, 'employment-schema.json')
        return value

    def validate_education(self, value):
        validate_user_json(value, 'education-schema.json')
        return value

    def validate_social(self, value):
        schema = from_json('social-schema.json')
        try:
            jsonschema.validate(value, schema)
        except jsonschema.ValidationError as e:
            raise InvalidModelValueError(e)

        return value

    def update(self, instance, validated_data):
        assert isinstance(instance, OSFUser), 'instance must be a User'
        for attr, value in validated_data.items():
            if 'social' == attr:
                for key, val in value.items():
                    instance.social[key] = val
            elif 'accepted_terms_of_service' == attr:
                if value and not instance.accepted_terms_of_service:
                    instance.accepted_terms_of_service = timezone.now()
            elif 'region_id' == attr:
                region_id = validated_data.get('region_id')
                user_settings = instance._settings_model(
                    'osfstorage').objects.get(owner=instance)
                user_settings.default_region_id = region_id
                user_settings.save()
                instance.default_region = self.context['request'].data[
                    'default_region']
            else:
                setattr(instance, attr, value)
        try:
            instance.save()
        except ValidationValueError as e:
            raise InvalidModelValueError(detail=e.message)
        except ValidationError as e:
            raise InvalidModelValueError(e)

        return instance
Exemplo n.º 2
0
class UserSerializer(JSONAPISerializer):
    filterable_fields = frozenset([
        'full_name', 'given_name', 'middle_names', 'family_name', 'id', 'uid'
    ])
    non_anonymized_fields = ['type']
    id = IDField(source='_id', read_only=True)
    uid = IDField(source='id', read_only=True)
    type = TypeField()
    full_name = ser.CharField(
        source='fullname',
        required=True,
        label='Full name',
        help_text='Display name used in the general user interface',
        max_length=186)
    given_name = ser.CharField(required=False,
                               allow_blank=True,
                               help_text='For bibliographic citations')
    middle_names = ser.CharField(required=False,
                                 allow_blank=True,
                                 help_text='For bibliographic citations')
    family_name = ser.CharField(required=False,
                                allow_blank=True,
                                help_text='For bibliographic citations')
    suffix = HideIfDisabled(
        ser.CharField(required=False,
                      allow_blank=True,
                      help_text='For bibliographic citations'))
    date_registered = HideIfDisabled(VersionedDateTimeField(read_only=True))
    active = HideIfDisabled(
        ser.BooleanField(read_only=True, source='is_active'))
    timezone = HideIfDisabled(
        ser.CharField(required=False,
                      help_text="User's timezone, e.g. 'Etc/UTC"))
    locale = HideIfDisabled(
        ser.CharField(required=False,
                      help_text="User's locale, e.g.  'en_US'"))
    social = ListDictField(required=False)
    can_view_reviews = ShowIfCurrentUser(
        ser.SerializerMethodField(
            help_text=
            'Whether the current user has the `view_submissions` permission to ANY reviews provider.'
        ))

    links = HideIfDisabled(
        LinksField({
            'html': 'absolute_url',
            'profile_image': 'profile_image_url',
        }))

    nodes = HideIfDisabled(
        RelationshipField(
            related_view='users:user-nodes',
            related_view_kwargs={'user_id': '<_id>'},
            related_meta={'projects_in_common': 'get_projects_in_common'},
        ))

    quickfiles = HideIfDisabled(
        QuickFilesRelationshipField(
            related_view='users:user-quickfiles',
            related_view_kwargs={'user_id': '<_id>'},
        ))

    registrations = HideIfDisabled(
        RelationshipField(
            related_view='users:user-registrations',
            related_view_kwargs={'user_id': '<_id>'},
        ))

    institutions = HideIfDisabled(
        RelationshipField(
            related_view='users:user-institutions',
            related_view_kwargs={'user_id': '<_id>'},
            self_view='users:user-institutions-relationship',
            self_view_kwargs={'user_id': '<_id>'},
        ))

    preprints = HideIfDisabled(
        RelationshipField(
            related_view='users:user-preprints',
            related_view_kwargs={'user_id': '<_id>'},
        ))

    class Meta:
        type_ = 'users'

    def get_projects_in_common(self, obj):
        user = get_user_auth(self.context['request']).user
        if obj == user:
            return user.contributor_to.count()
        return obj.n_projects_in_common(user)

    def absolute_url(self, obj):
        if obj is not None:
            return obj.absolute_url
        return None

    def get_absolute_url(self, obj):
        return absolute_reverse(
            'users:user-detail',
            kwargs={
                'user_id':
                obj._id,
                'version':
                self.context['request'].parser_context['kwargs']['version']
            })

    def get_can_view_reviews(self, obj):
        group_qs = GroupObjectPermission.objects.filter(
            group__user=obj, permission__codename='view_submissions')
        return group_qs.exists() or obj.userobjectpermission_set.filter(
            permission__codename='view_submissions')

    def profile_image_url(self, user):
        size = self.context['request'].query_params.get('profile_image_size')
        return user.profile_image_url(size=size)

    def update(self, instance, validated_data):
        assert isinstance(instance, OSFUser), 'instance must be a User'
        for attr, value in validated_data.items():
            if 'social' == attr:
                for key, val in value.items():
                    # currently only profileWebsites are a list, the rest of the social key only has one value
                    if key == 'profileWebsites':
                        instance.social[key] = val
                    else:
                        if len(val) > 1:
                            raise InvalidModelValueError(
                                detail=
                                '{} only accept a list of one single value'.
                                format(key))
                        instance.social[key] = val[0]
            else:
                setattr(instance, attr, value)
        try:
            instance.save()
        except ValidationValueError as e:
            raise InvalidModelValueError(detail=e.message)
        except ValidationError as e:
            raise InvalidModelValueError(e)

        return instance