Beispiel #1
0
    def restore_object(self, attrs, instance=None):
        if instance:
            metadata = JsonField.to_json(attrs.get('metadata'))

            if self.partial and metadata:
                if not isinstance(instance.metadata, dict):
                    instance.metadata = {}

                instance.metadata.update(metadata)
                attrs['metadata'] = instance.metadata

            return super(ProjectSerializer,
                         self).restore_object(attrs, instance)

        if 'request' in self.context:
            created_by = self.context['request'].user

            return Project(
                name=attrs.get('name'),
                organization=attrs.get('organization'),
                created_by=created_by,
                metadata=attrs.get('metadata'),
            )

        return attrs
Beispiel #2
0
    def restore_object(self, attrs, instance=None):
        if instance:
            metadata = JsonField.to_json(attrs.get('metadata'))
            owner = attrs.get('organization')

            if self.partial and metadata:
                if not isinstance(instance.metadata, dict):
                    instance.metadata = {}

                instance.metadata.update(metadata)
                attrs['metadata'] = instance.metadata

            if self.partial and owner:
                # give the new owner permissions
                set_owners_permission(owner, instance)

                # clear cache
                safe_delete('{}{}'.format(PROJ_PERM_CACHE, self.object.pk))

            return super(ProjectSerializer,
                         self).restore_object(attrs, instance)

        if 'request' in self.context:
            created_by = self.context['request'].user

            return Project(
                name=attrs.get('name'),
                organization=attrs.get('organization'),
                created_by=created_by,
                metadata=attrs.get('metadata'),
            )

        return attrs
Beispiel #3
0
    def restore_object(self, attrs, instance=None):
        if instance:
            metadata = JsonField.to_json(attrs.get("metadata"))
            owner = attrs.get("organization")

            if self.partial and metadata:
                if not isinstance(instance.metadata, dict):
                    instance.metadata = {}

                instance.metadata.update(metadata)
                attrs["metadata"] = instance.metadata

            if self.partial and owner:
                # give the new owner permissions
                set_owners_permission(owner, instance)

                # clear cache
                safe_delete("{}{}".format(PROJ_PERM_CACHE, self.object.pk))

            return super(ProjectSerializer, self).restore_object(attrs, instance)

        if "request" in self.context:
            created_by = self.context["request"].user

            return Project(
                name=attrs.get("name"),
                organization=attrs.get("organization"),
                created_by=created_by,
                metadata=attrs.get("metadata"),
            )

        return attrs
    def update(self, instance, validated_data):
        metadata = JsonField.to_json(validated_data.get('metadata'))
        if metadata is None:
            metadata = dict()
        owner = validated_data.get('organization')

        if self.partial and metadata:
            if not isinstance(instance.metadata, dict):
                instance.metadata = {}

            instance.metadata.update(metadata)
            validated_data['metadata'] = instance.metadata

        if self.partial and owner:
            # give the new owner permissions
            set_owners_permission(owner, instance)

            if is_organization(owner.profile):
                owners_team = get_or_create_organization_owners_team(
                    owner.profile)
                members_team = get_organization_members_team(owner.profile)
                OwnerRole.add(owners_team, instance)
                ReadOnlyRole.add(members_team, instance)

            # clear cache
            safe_delete('{}{}'.format(PROJ_PERM_CACHE, instance.pk))

        project = super(ProjectSerializer, self)\
            .update(instance, validated_data)

        project.xform_set.exclude(shared=project.shared)\
            .update(shared=project.shared, shared_data=project.shared)

        return instance
Beispiel #5
0
    def update(self, instance, validated_data):
        metadata = JsonField.to_json(validated_data.get('metadata'))
        if metadata is None:
            metadata = dict()
        owner = validated_data.get('organization')

        if self.partial and metadata:
            if not isinstance(instance.metadata, dict):
                instance.metadata = {}

            instance.metadata.update(metadata)
            validated_data['metadata'] = instance.metadata

        if self.partial and owner:
            # give the new owner permissions
            set_owners_permission(owner, instance)

            if is_organization(owner.profile):
                owners_team = get_organization_owners_team(owner.profile)
                members_team = get_organization_members_team(owner.profile)
                OwnerRole.add(owners_team, instance)
                ReadOnlyRole.add(members_team, instance)

            # clear cache
            safe_delete('{}{}'.format(PROJ_PERM_CACHE, instance.pk))

        project = super(ProjectSerializer, self)\
            .update(instance, validated_data)

        project.xform_set.exclude(shared=project.shared)\
            .update(shared=project.shared, shared_data=project.shared)

        return instance
class BaseProjectSerializer(serializers.HyperlinkedModelSerializer):
    projectid = serializers.ReadOnlyField(source='id')
    url = serializers.HyperlinkedIdentityField(view_name='project-detail',
                                               lookup_field='pk')
    owner = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        source='organization',
        lookup_field='username',
        queryset=User.objects.exclude(
            username__iexact=settings.ANONYMOUS_DEFAULT_USERNAME))
    created_by = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                     lookup_field='username',
                                                     read_only=True)
    metadata = JsonField(required=False)
    starred = serializers.SerializerMethodField()
    users = serializers.SerializerMethodField()
    forms = serializers.SerializerMethodField()
    public = serializers.BooleanField(source='shared')
    tags = TagListSerializer(read_only=True)
    num_datasets = serializers.SerializerMethodField()
    last_submission_date = serializers.SerializerMethodField()
    teams = serializers.SerializerMethodField()

    class Meta:
        model = Project
        exclude = ('shared', 'organization', 'user_stars')

    def get_starred(self, obj):
        return get_starred(obj, self.context['request'])

    def get_users(self, obj):
        owner_query_param_in_request = \
          'request' in self.context and "owner" in self.context['request'].GET
        return get_users(obj, self.context, owner_query_param_in_request)

    @check_obj
    def get_forms(self, obj):
        forms = cache.get('{}{}'.format(PROJ_BASE_FORMS_CACHE, obj.pk))
        if forms:
            return forms

        xforms = get_obj_xforms(obj)
        request = self.context.get('request')
        serializer = BaseProjectXFormSerializer(xforms,
                                                context={'request': request},
                                                many=True)
        forms = list(serializer.data)
        cache.set('{}{}'.format(PROJ_BASE_FORMS_CACHE, obj.pk), forms)

        return forms

    def get_num_datasets(self, obj):
        return get_num_datasets(obj)

    def get_last_submission_date(self, obj):
        return get_last_submission_date(obj)

    def get_teams(self, obj):
        return get_teams(obj)
class DataViewMinimalSerializer(serializers.HyperlinkedModelSerializer):
    dataviewid = serializers.ReadOnlyField(source='id')
    name = serializers.CharField(max_length=255)
    url = serializers.HyperlinkedIdentityField(view_name='dataviews-detail',
                                               lookup_field='pk')
    xform = serializers.HyperlinkedRelatedField(view_name='xform-detail',
                                                lookup_field='pk',
                                                queryset=XForm.objects.all())
    project = serializers.HyperlinkedRelatedField(
        view_name='project-detail',
        lookup_field='pk',
        queryset=Project.objects.all())
    columns = JsonField()
    query = JsonField(required=False)
    matches_parent = serializers.BooleanField(default=True)

    class Meta:
        model = DataView
Beispiel #8
0
 def validate_metadata(self, value):
     msg = serializers.ValidationError(_("Invaid value for metadata"))
     try:
         json_val = JsonField.to_json(value)
     except ValueError:
         raise serializers.ValidationError(msg)
     else:
         if json_val is None:
             raise serializers.ValidationError(msg)
     return value
Beispiel #9
0
    def update(self, instance, validated_data):
        metadata = JsonField.to_json(validated_data.get('metadata'))

        if self.partial and metadata:
            if not isinstance(instance.metadata, dict):
                instance.metadata = {}

            instance.metadata.update(metadata)
            validated_data['metadata'] = instance.metadata

        return super(ProjectSerializer, self).update(instance, validated_data)
Beispiel #10
0
    def update(self, instance, validated_data):
        metadata = JsonField.to_json(validated_data.get('metadata'))

        if self.partial and metadata:
            if not isinstance(instance.metadata, dict):
                instance.metadata = {}

            instance.metadata.update(metadata)
            validated_data['metadata'] = instance.metadata

        return super(ProjectSerializer, self).update(instance, validated_data)
Beispiel #11
0
class BaseProjectSerializer(serializers.HyperlinkedModelSerializer):
    projectid = serializers.ReadOnlyField(source='id')
    url = serializers.HyperlinkedIdentityField(
        view_name='project-detail', lookup_field='pk')
    owner = serializers.HyperlinkedRelatedField(
        view_name='user-detail', source='organization',
        lookup_field='username',
        queryset=User.objects.exclude(
            username__iexact=settings.ANONYMOUS_DEFAULT_USERNAME
        )
    )
    created_by = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        lookup_field='username',
        read_only=True
    )
    metadata = JsonField(required=False)
    starred = serializers.SerializerMethodField()
    users = serializers.SerializerMethodField()
    forms = serializers.SerializerMethodField()
    public = serializers.BooleanField(source='shared')
    tags = TagListSerializer(read_only=True)
    num_datasets = serializers.SerializerMethodField()
    last_submission_date = serializers.SerializerMethodField()
    teams = serializers.SerializerMethodField()

    class Meta:
        model = Project
        exclude = ('shared', 'organization', 'user_stars')

    def get_starred(self, obj):
        return get_starred(obj, self.context['request'])

    def get_users(self, obj):
        return get_users(obj, self.context, False)

    @profile("get_project_forms.prof")
    @check_obj
    def get_forms(self, obj):
        xforms = get_obj_xforms(obj)
        request = self.context.get('request')
        serializer = BaseProjectXFormSerializer(
            xforms, context={'request': request}, many=True
        )
        return list(serializer.data)

    def get_num_datasets(self, obj):
        return get_num_datasets(obj)

    def get_last_submission_date(self, obj):
        return get_last_submission_date(obj)

    def get_teams(self, obj):
        return get_teams(obj)
class InstanceHistorySerializer(serializers.ModelSerializer):
    json = JsonField()

    class Meta:
        model = InstanceHistory
        fields = ('json', )

    def to_representation(self, instance):
        ret = super(InstanceHistorySerializer,
                    self).to_representation(instance)

        return ret['json'] if 'json' in ret else ret
 def validate_metadata(self, value):  # pylint: disable=no-self-use
     """
     Validate metadaata is a valid JSON value.
     """
     msg = serializers.ValidationError(_("Invaid value for metadata"))
     try:
         json_val = JsonField.to_json(value)
     except ValueError:
         raise serializers.ValidationError(msg)
     else:
         if json_val is None:
             raise serializers.ValidationError(msg)
     return value
class DataInstanceSerializer(serializers.ModelSerializer):
    json = JsonField()

    class Meta:
        model = Instance
        fields = ('json', )

    def to_representation(self, instance):
        ret = super(DataInstanceSerializer, self).to_representation(instance)
        if 'json' in ret:
            ret = ret['json']

        return ret
Beispiel #15
0
 def validate_metadata(self, value):  # pylint: disable=no-self-use
     """
     Validate metadaata is a valid JSON value.
     """
     msg = serializers.ValidationError(_("Invaid value for metadata"))
     try:
         json_val = JsonField.to_json(value)
     except ValueError:
         raise serializers.ValidationError(msg)
     else:
         if json_val is None:
             raise serializers.ValidationError(msg)
     return value
Beispiel #16
0
class DataInstanceSerializer(serializers.ModelSerializer):
    """
    DataInstanceSerializer class - for json field data representation on the
    Instance (submission) model.
    """
    json = JsonField()

    class Meta:
        model = Instance
        fields = ('json', )

    def to_representation(self, instance):
        ret = super(DataInstanceSerializer, self).to_representation(instance)
        if 'json' in ret:
            ret = ret['json']
        return ret
class UserProfileSerializer(serializers.Serializer):
    id = serializers.ReadOnlyField(source='user.id')
    username = serializers.ReadOnlyField(source='user.username')
    name = serializers.ReadOnlyField()
    email = serializers.ReadOnlyField(source='user.email')
    city = serializers.ReadOnlyField()
    country = serializers.ReadOnlyField()
    organization = serializers.ReadOnlyField()
    website = serializers.ReadOnlyField(source='home_page')
    twitter = serializers.ReadOnlyField()
    gravatar = serializers.ReadOnlyField()
    require_auth = serializers.ReadOnlyField()
    metadata = JsonField(read_only=True)

    class Meta:
        model = UserProfile

        fields = (
            'id',
            'username',
            'name',
            'email',
            'city',
            'country',
            'organization',
            'website',
            'twitter',
            'gravatar',
            'require_auth',
            'metadata',
        )

    def to_representation(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_representation(obj)

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, obj):
            del ret['email']

        return ret
Beispiel #18
0
class TableauDataSerializer(serializers.ModelSerializer):
    """
    TableauDataSerializer class - cleans out instance fields.
    """
    json = JsonField()

    class Meta:
        model = Instance
        fields = ('json', )

    def to_representation(self, instance):
        ret = super(TableauDataSerializer, self).to_representation(instance)
        if 'json' in ret:
            ret = ret['json']
            # Remove metadata fields from the instance
            remove_metadata_fields(ret)

        return ret
Beispiel #19
0
    def restore_object(self, attrs, instance=None):
        if instance:
            metadata = JsonField.to_json(attrs.get('metadata'))

            if self.partial and metadata:
                if not isinstance(instance.metadata, dict):
                    instance.metadata = {}

                instance.metadata.update(metadata)
                attrs['metadata'] = instance.metadata

            return super(ProjectSerializer, self).restore_object(
                attrs, instance)

        if 'request' in self.context:
            created_by = self.context['request'].user

            return Project(
                name=attrs.get('name'),
                organization=attrs.get('organization'),
                created_by=created_by,
                metadata=attrs.get('metadata'),)

        return attrs
Beispiel #20
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    is_org = serializers.SerializerMethodField('is_organization')
    username = serializers.WritableField(source='user.username')
    email = serializers.WritableField(source='user.email')
    website = serializers.WritableField(source='home_page', required=False)
    gravatar = serializers.Field(source='gravatar')
    password = serializers.WritableField(
        source='user.password', widget=widgets.PasswordInput(), required=False)
    user = serializers.HyperlinkedRelatedField(
        view_name='user-detail', lookup_field='username', read_only=True)
    metadata = JsonField(source='metadata', required=False)
    id = serializers.Field(source='user.id')
    joined_on = serializers.Field(source='user.date_joined')

    class Meta:
        model = UserProfile
        fields = ('id', 'is_org', 'url', 'username', 'name', 'password',
                  'email', 'city', 'country', 'organization', 'website',
                  'twitter', 'gravatar', 'require_auth', 'user', 'metadata',
                  'joined_on')
        lookup_field = 'user'

    def is_organization(self, obj):
        return is_organization(obj)

    def to_native(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_native(obj)
        if 'password' in ret:
            del ret['password']

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, obj):
            del ret['email']

        return ret

    def restore_object(self, attrs, instance=None):
        params = copy.deepcopy(attrs)
        username = attrs.get('user.username', None)
        password = attrs.get('user.password', None)
        name = attrs.get('name', None)
        email = attrs.get('user.email', None)

        if username:
            params['username'] = username

        if email:
            params['email'] = email

        if password:
            params.update({'password1': password, 'password2': password})

        if instance:
            form = UserProfileForm(params, instance=instance)

            # form.is_valid affects instance object for partial updates [PATCH]
            # so only use it for full updates [PUT], i.e shallow copy effect
            if not self.partial and form.is_valid():
                instance = form.save()

            # get user
            if email:
                instance.user.email = form.cleaned_data['email']

            if name:
                first_name, last_name = _get_first_last_names(name)
                instance.user.first_name = first_name
                instance.user.last_name = last_name

            if email or name:
                instance.user.save()

            return super(
                UserProfileSerializer, self).restore_object(attrs, instance)

        form = RegistrationFormUserProfile(params)
        # does not require captcha
        form.REGISTRATION_REQUIRE_CAPTCHA = False

        if form.is_valid():
            site = Site.objects.get(pk=settings.SITE_ID)
            new_user = RegistrationProfile.objects.create_inactive_user(
                username=username,
                password=password,
                email=email,
                site=site,
                send_email=True)
            new_user.is_active = True
            new_user.save()

            created_by = self.context['request'].user
            created_by = None if created_by.is_anonymous() else created_by
            profile = UserProfile(
                user=new_user, name=attrs.get('name', u''),
                created_by=created_by,
                city=attrs.get('city', u''),
                country=attrs.get('country', u''),
                organization=attrs.get('organization', u''),
                home_page=attrs.get('home_page', u''),
                twitter=attrs.get('twitter', u''))

            return profile

        else:
            self.errors.update(form.errors)

        return attrs

    def validate_username(self, attrs, source):
        request_method = self.context['request'].method

        if request_method == 'PATCH' and source not in attrs:
            return attrs

        current_username = self.object.user.username if self.object else None
        username = attrs[source].lower()
        is_edit = current_username is not None and current_username != username
        form = RegistrationFormUserProfile

        if username in form._reserved_usernames and is_edit:
            raise ValidationError(
                u"%s is a reserved name, please choose another" % username)
        elif not form.legal_usernames_re.search(username):
            raise ValidationError(
                u'username may only contain alpha-numeric characters and '
                u'underscores')
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            attrs[source] = username
        else:
            if not current_username or is_edit:
                raise ValidationError(u'%s already exists' % username)

        return attrs
Beispiel #21
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    is_org = serializers.SerializerMethodField('is_organization')
    username = serializers.WritableField(source='user.username')
    name = serializers.CharField(required=False)
    first_name = serializers.WritableField(source='user.first_name',
                                           required=False)
    last_name = serializers.WritableField(source='user.last_name',
                                          required=False)
    email = serializers.EmailField(source='user.email')
    website = serializers.WritableField(source='home_page', required=False)
    twitter = serializers.WritableField(required=False)
    gravatar = serializers.Field(source='gravatar')
    password = serializers.WritableField(source='user.password',
                                         widget=widgets.PasswordInput(),
                                         required=False)
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)
    metadata = JsonField(source='metadata', required=False)
    id = serializers.Field(source='user.id')
    joined_on = serializers.Field(source='user.date_joined')

    class Meta:
        model = UserProfile
        fields = ('id', 'is_org', 'url', 'username', 'password', 'first_name',
                  'last_name', 'email', 'city', 'country', 'organization',
                  'website', 'twitter', 'gravatar', 'require_auth', 'user',
                  'metadata', 'joined_on', 'name')
        lookup_field = 'user'

    def is_organization(self, obj):
        if obj:
            is_org = cache.get('{}{}'.format(IS_ORG, obj.pk))
            if is_org:
                return is_org

        is_org = is_organization(obj)
        cache.set('{}{}'.format(IS_ORG, obj.pk), is_org)
        return is_org

    def to_native(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_native(obj)
        if 'password' in ret:
            del ret['password']

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, obj):
            del ret['email']

        if 'first_name' in ret:
            ret['name'] = u' '.join(
                [ret.get('first_name'),
                 ret.get('last_name', "")])

        return ret

    def restore_object(self, attrs, instance=None):
        params = copy.deepcopy(attrs)
        username = attrs.get('user.username', None)
        password = attrs.get('user.password', None)
        first_name = attrs.get('user.first_name', None)
        last_name = attrs.get('user.last_name', None)
        email = attrs.get('user.email', None)
        name = attrs.get('name', None)

        if username:
            params['username'] = username

        if email:
            params['email'] = email

        if password:
            params.update({'password1': password, 'password2': password})

        if first_name:
            params['first_name'] = first_name

        if last_name:
            params['last_name'] = last_name

        # For backward compatibility, Users who still use only name
        if name:
            first_name, last_name = \
                _get_first_last_names(name)
            params['first_name'] = first_name
            params['last_name'] = last_name

        if instance:
            form = UserProfileForm(params, instance=instance)

            # form.is_valid affects instance object for partial updates [PATCH]
            # so only use it for full updates [PUT], i.e shallow copy effect
            if not self.partial and form.is_valid():
                instance = form.save()

            # get user
            if email:
                instance.user.email = email

            if first_name:
                instance.user.first_name = first_name

            if last_name:
                instance.user.last_name = last_name

            (email or first_name or last_name) and instance.user.save()

            return super(UserProfileSerializer,
                         self).restore_object(attrs, instance)

        form = RegistrationFormUserProfile(params)
        # does not require captcha
        form.REGISTRATION_REQUIRE_CAPTCHA = False

        if form.is_valid():

            site = Site.objects.get(pk=settings.SITE_ID)
            new_user = RegistrationProfile.objects.create_inactive_user(
                username=username,
                password=password,
                email=email,
                site=site,
                send_email=settings.SEND_EMAIL_ACTIVATION_API)
            new_user.is_active = True
            new_user.first_name = first_name
            new_user.last_name = last_name
            new_user.save()

            created_by = self.context['request'].user
            created_by = None if created_by.is_anonymous() else created_by
            profile = UserProfile(user=new_user,
                                  name=first_name,
                                  created_by=created_by,
                                  city=attrs.get('city', u''),
                                  country=attrs.get('country', u''),
                                  organization=attrs.get('organization', u''),
                                  home_page=attrs.get('home_page', u''),
                                  twitter=attrs.get('twitter', u''))

            return profile

        else:
            self.errors.update(form.errors)

        return attrs

    def validate_username(self, attrs, source):
        request_method = self.context['request'].method

        if request_method == 'PATCH' and source not in attrs:
            return attrs

        current_username = self.object.user.username if self.object else None
        username = attrs[source].lower()
        is_edit = current_username is not None and current_username != username
        form = RegistrationFormUserProfile

        if username in form._reserved_usernames and is_edit:
            raise ValidationError(
                u"%s is a reserved name, please choose another" % username)
        elif not form.legal_usernames_re.search(username):
            raise ValidationError(
                u'username may only contain alpha-numeric characters and '
                u'underscores')
        try:
            User.objects.get(username=username)
        except User.DoesNotExist:
            attrs[source] = username
        else:
            if not current_username or is_edit:
                raise ValidationError(u'%s already exists' % username)

        return attrs

    def validate_name(self, attrs, source):
        if (attrs.get('name') is None) and\
                (attrs.get('user.first_name') is None):
            raise ValidationError(
                u"Either name or first_name should be provided")

        return attrs

    def validate_email(self, attrs, source):
        request_method = self.context['request'].method
        if request_method == 'PUT' and source in attrs:
            return attrs

        if User.objects.filter(email=attrs.get('user.email')).exists():
            raise ValidationError("This email address is already in use. ")
        return attrs

    def validate_twitter(self, attrs, source):
        if isinstance(attrs.get('twitter'), basestring):
            if attrs.get('twitter'):
                match = re.search(r"^[A-Za-z0-9_]{1,15}$",
                                  attrs.get('twitter'))
                if not match:
                    raise ValidationError("Invalid twitter username")
        else:
            attrs['twitter'] = ''
        return attrs
Beispiel #22
0
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
    projectid = serializers.Field(source='id')
    url = serializers.HyperlinkedIdentityField(view_name='project-detail',
                                               lookup_field='pk')
    owner = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                source='organization',
                                                lookup_field='username')
    created_by = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                     source='created_by',
                                                     lookup_field='username',
                                                     read_only=True)
    metadata = JsonField(source='metadata', required=False)
    starred = serializers.SerializerMethodField('is_starred_project')
    users = serializers.SerializerMethodField('get_project_permissions')
    forms = serializers.SerializerMethodField('get_project_forms')
    public = BooleanField(source='shared', widget=widgets.CheckboxInput())
    tags = TagListSerializer(read_only=True)
    num_datasets = serializers.SerializerMethodField('get_num_datasets')
    last_submission_date = serializers.SerializerMethodField(
        'get_last_submission_date')

    class Meta:
        model = Project
        exclude = ('organization', 'user_stars')

    def restore_object(self, attrs, instance=None):
        if instance:
            metadata = JsonField.to_json(attrs.get('metadata'))
            owner = attrs.get('organization')

            if self.partial and metadata:
                if not isinstance(instance.metadata, dict):
                    instance.metadata = {}

                instance.metadata.update(metadata)
                attrs['metadata'] = instance.metadata

            if self.partial and owner:
                # give the new owner permissions
                set_owners_permission(owner, instance)

                # clear cache
                safe_delete('{}{}'.format(PROJ_PERM_CACHE, self.object.pk))

            return super(ProjectSerializer,
                         self).restore_object(attrs, instance)

        if 'request' in self.context:
            created_by = self.context['request'].user

            return Project(
                name=attrs.get('name'),
                organization=attrs.get('organization'),
                created_by=created_by,
                metadata=attrs.get('metadata'),
            )

        return attrs

    def save_object(self, obj, **kwargs):
        super(ProjectSerializer, self).save_object(obj, **kwargs)

        obj.xform_set.exclude(shared=obj.shared)\
            .update(shared=obj.shared, shared_data=obj.shared)

    def get_project_permissions(self, obj):
        if obj:
            users = cache.get('{}{}'.format(PROJ_PERM_CACHE, obj.pk))
            if users:
                return users

            user = get_object_users_with_permissions(obj)
            cache.set('{}{}'.format(PROJ_PERM_CACHE, obj.pk), user)

            return user

        return []

    @check_obj
    def get_project_forms(self, obj):
        if obj:
            forms = cache.get('{}{}'.format(PROJ_FORMS_CACHE, obj.pk))
            if forms:
                return forms

            xforms_details = obj.xform_set.values('pk', 'title')

            forms = [{
                'name': form['title'],
                'id': form['pk']
            } for form in xforms_details]
            cache.set('{}{}'.format(PROJ_FORMS_CACHE, obj.pk), forms)
            return forms

        return []

    @check_obj
    def get_num_datasets(self, obj):
        """Return the number of datasets attached to the object.

        :param obj: The project to find datasets for.
        """
        if obj:
            count = cache.get('{}{}'.format(PROJ_NUM_DATASET_CACHE, obj.pk))
            if count:
                return count

            count = obj.xform_set.count()
            cache.set('{}{}'.format(PROJ_NUM_DATASET_CACHE, obj.pk), count)
            return count

        return None

    @check_obj
    def get_last_submission_date(self, obj):
        """Return the most recent submission date to any of the projects
        datasets.

        :param obj: The project to find the last submission date for.
        """
        if obj:
            last_submission = cache.get('{}{}'.format(PROJ_SUB_DATE_CACHE,
                                                      obj.pk))
            if last_submission:
                return last_submission

            xform_ids = obj.xform_set.values_list('pk', flat=True)
            last_submission = Instance.objects.\
                order_by('-date_created').\
                filter(xform_id__in=xform_ids).values_list('date_created',
                                                           flat=True)
            cache.set('{}{}'.format(PROJ_SUB_DATE_CACHE, obj.pk),
                      last_submission and last_submission[0])
            return last_submission and last_submission[0]

        return None

    def is_starred_project(self, obj):
        request = self.context['request']
        user = request.user
        user_stars = obj.user_stars.all()
        if user in user_stars:
            return True

        return False
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
    """
    ProjectSerializer class - creates and updates a project.
    """
    projectid = serializers.ReadOnlyField(source='id')
    url = serializers.HyperlinkedIdentityField(view_name='project-detail',
                                               lookup_field='pk')
    owner = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        source='organization',
        lookup_field='username',
        queryset=User.objects.exclude(
            username__iexact=settings.ANONYMOUS_DEFAULT_USERNAME))
    created_by = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                     lookup_field='username',
                                                     read_only=True)
    metadata = JsonField(required=False)
    starred = serializers.SerializerMethodField()
    users = serializers.SerializerMethodField()
    forms = serializers.SerializerMethodField()
    public = serializers.BooleanField(source='shared')
    tags = TagListSerializer(read_only=True)
    num_datasets = serializers.SerializerMethodField()
    last_submission_date = serializers.SerializerMethodField()
    teams = serializers.SerializerMethodField()
    data_views = serializers.SerializerMethodField()

    class Meta:
        model = Project
        exclude = ('shared', 'user_stars', 'deleted_by')
        extra_kwargs = {
            'organization': {
                'write_only': True,
                'required': False,
                'lookup_field': 'username'
            }
        }

    def validate(self, attrs):
        name = attrs.get('name')
        organization = attrs.get('organization')
        if not self.instance and organization:
            project_w_same_name = Project.objects.filter(
                name__iexact=name, organization=organization)
            if project_w_same_name:
                raise serializers.ValidationError(
                    {'name': _(u"Project {} already exists.".format(name))})
        else:
            organization = organization or self.instance.organization
        request = self.context['request']
        try:
            has_perm = can_add_project_to_profile(request.user, organization)
        except OrganizationProfile.DoesNotExist:
            # most likely when transfering a project to an individual account
            # A user does not require permissions to the user's account forms.
            has_perm = False
        if not has_perm:
            raise serializers.ValidationError({
                'owner':
                _("You do not have permission to create a project "
                  "in the organization %(organization)s." %
                  {'organization': organization})
            })
        return attrs

    def validate_public(self, value):  # pylint: disable=no-self-use
        """
        Validate the public field
        """
        if not settings.ALLOW_PUBLIC_DATASETS and value:
            raise serializers.ValidationError(
                _('Public projects are currently disabled.'))
        return value

    def validate_metadata(self, value):  # pylint: disable=no-self-use
        """
        Validate metadaata is a valid JSON value.
        """
        msg = serializers.ValidationError(_("Invaid value for metadata"))
        try:
            json_val = JsonField.to_json(value)
        except ValueError:
            raise serializers.ValidationError(msg)
        else:
            if json_val is None:
                raise serializers.ValidationError(msg)
        return value

    def update(self, instance, validated_data):
        metadata = JsonField.to_json(validated_data.get('metadata'))
        if metadata is None:
            metadata = dict()
        owner = validated_data.get('organization')

        if self.partial and metadata:
            if not isinstance(instance.metadata, dict):
                instance.metadata = {}

            instance.metadata.update(metadata)
            validated_data['metadata'] = instance.metadata

        if self.partial and owner:
            # give the new owner permissions
            set_owners_permission(owner, instance)

            if is_organization(owner.profile):
                owners_team = get_or_create_organization_owners_team(
                    owner.profile)
                members_team = get_organization_members_team(owner.profile)
                OwnerRole.add(owners_team, instance)
                ReadOnlyRole.add(members_team, instance)

            # clear cache
            safe_delete('{}{}'.format(PROJ_PERM_CACHE, instance.pk))

        project = super(ProjectSerializer, self)\
            .update(instance, validated_data)

        project.xform_set.exclude(shared=project.shared)\
            .update(shared=project.shared, shared_data=project.shared)

        return instance

    def create(self, validated_data):
        metadata = validated_data.get('metadata', dict())
        if metadata is None:
            metadata = dict()
        created_by = self.context['request'].user

        try:
            project = Project.objects.create(  # pylint: disable=E1101
                name=validated_data.get('name'),
                organization=validated_data.get('organization'),
                created_by=created_by,
                shared=validated_data.get('shared', False),
                metadata=metadata)
        except IntegrityError:
            raise serializers.ValidationError(
                "The fields name, organization must make a unique set.")
        else:
            project.xform_set.exclude(shared=project.shared)\
                .update(shared=project.shared, shared_data=project.shared)
            request = self.context.get('request')
            serializer = ProjectSerializer(project,
                                           context={'request': request})
            response = serializer.data
            cache.set(f'{PROJ_OWNER_CACHE}{project.pk}', response)
            return project

    def get_users(self, obj):  # pylint: disable=no-self-use
        """
        Return a list of users and organizations that have access to the
        project.
        """
        return get_users(obj, self.context)

    @check_obj
    def get_forms(self, obj):  # pylint: disable=no-self-use
        """
        Return list of xforms in the project.
        """
        forms = cache.get('{}{}'.format(PROJ_FORMS_CACHE, obj.pk))
        if forms:
            return forms
        xforms = get_project_xforms(obj)
        request = self.context.get('request')
        serializer = ProjectXFormSerializer(xforms,
                                            context={'request': request},
                                            many=True)
        forms = list(serializer.data)
        cache.set('{}{}'.format(PROJ_FORMS_CACHE, obj.pk), forms)

        return forms

    def get_num_datasets(self, obj):  # pylint: disable=no-self-use
        """
        Return the number of datasets attached to the project.
        """
        return get_num_datasets(obj)

    def get_last_submission_date(self, obj):  # pylint: disable=no-self-use
        """
        Return the most recent submission date to any of the projects datasets.
        """
        return get_last_submission_date(obj)

    def get_starred(self, obj):  # pylint: disable=no-self-use
        """
        Return True if request user has starred this project.
        """
        return is_starred(obj, self.context['request'])

    def get_teams(self, obj):  # pylint: disable=no-self-use
        """
        Return the teams with access to the project.
        """
        return get_teams(obj)

    @check_obj
    def get_data_views(self, obj):
        """
        Return a list of filtered datasets.
        """
        data_views = cache.get('{}{}'.format(PROJECT_LINKED_DATAVIEWS, obj.pk))
        if data_views:
            return data_views

        data_views_obj = obj.dataview_prefetch if \
            hasattr(obj, 'dataview_prefetch') else\
            obj.dataview_set.filter(deleted_at__isnull=True)

        serializer = DataViewMinimalSerializer(data_views_obj,
                                               many=True,
                                               context=self.context)
        data_views = list(serializer.data)

        cache.set('{}{}'.format(PROJECT_LINKED_DATAVIEWS, obj.pk), data_views)

        return data_views
class BaseProjectSerializer(serializers.HyperlinkedModelSerializer):
    """
    BaseProjectSerializer class.
    """
    projectid = serializers.ReadOnlyField(source='id')
    url = serializers.HyperlinkedIdentityField(view_name='project-detail',
                                               lookup_field='pk')
    owner = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        source='organization',
        lookup_field='username',
        queryset=User.objects.exclude(
            username__iexact=settings.ANONYMOUS_DEFAULT_USERNAME))
    created_by = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                     lookup_field='username',
                                                     read_only=True)
    metadata = JsonField(required=False)
    starred = serializers.SerializerMethodField()
    users = serializers.SerializerMethodField()
    forms = serializers.SerializerMethodField()
    public = serializers.BooleanField(source='shared')
    tags = TagListSerializer(read_only=True)
    num_datasets = serializers.SerializerMethodField()
    last_submission_date = serializers.SerializerMethodField()
    teams = serializers.SerializerMethodField()

    class Meta:
        model = Project
        fields = [
            'url', 'projectid', 'owner', 'created_by', 'metadata', 'starred',
            'users', 'forms', 'public', 'tags', 'num_datasets',
            'last_submission_date', 'teams', 'name', 'date_created',
            'date_modified', 'deleted_at'
        ]

    def get_starred(self, obj):
        """
        Return True if request user has starred this project.
        """
        return is_starred(obj, self.context['request'])

    def get_users(self, obj):
        """
        Return a list of users and organizations that have access to the
        project.
        """
        owner_query_param_in_request = 'request' in self.context and\
            "owner" in self.context['request'].GET
        return get_users(obj, self.context, owner_query_param_in_request)

    @check_obj
    def get_forms(self, obj):
        """
        Return list of xforms in the project.
        """
        forms = cache.get('{}{}'.format(PROJ_BASE_FORMS_CACHE, obj.pk))
        if forms:
            return forms

        xforms = get_project_xforms(obj)
        request = self.context.get('request')
        serializer = BaseProjectXFormSerializer(xforms,
                                                context={'request': request},
                                                many=True)
        forms = list(serializer.data)
        cache.set('{}{}'.format(PROJ_BASE_FORMS_CACHE, obj.pk), forms)

        return forms

    def get_num_datasets(self, obj):  # pylint: disable=no-self-use
        """
        Return the number of datasets attached to the project.
        """
        return get_num_datasets(obj)

    def get_last_submission_date(self, obj):  # pylint: disable=no-self-use
        """
        Return the most recent submission date to any of the projects datasets.
        """
        return get_last_submission_date(obj)

    def get_teams(self, obj):  # pylint: disable=no-self-use
        """
        Return the teams with access to the project.
        """
        return get_teams(obj)
class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
    """
    Organization profile serializer
    """
    url = serializers.HyperlinkedIdentityField(
        view_name='organizationprofile-detail', lookup_field='user')
    org = serializers.CharField(source='user.username', max_length=30)
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)
    creator = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                  lookup_field='username',
                                                  read_only=True)
    users = serializers.SerializerMethodField()
    metadata = JsonField(required=False)
    name = serializers.CharField(max_length=30)

    class Meta:
        model = OrganizationProfile
        exclude = ('created_by', 'is_organization', 'organization')
        owner_only_fields = ('metadata', )

    def __init__(self, *args, **kwargs):
        super(OrganizationSerializer, self).__init__(*args, **kwargs)

        if self.instance and hasattr(self.Meta, 'owner_only_fields'):
            request = self.context.get('request')
            is_permitted = (request and request.user and request.user.has_perm(
                'api.view_organizationprofile', self.instance))
            if isinstance(self.instance, QuerySet) or not is_permitted or \
                    not request:
                for field in getattr(self.Meta, 'owner_only_fields'):
                    self.fields.pop(field)

    def update(self, instance, validated_data):
        # update the user model
        if 'name' in validated_data:
            first_name, last_name = \
                _get_first_last_names(validated_data.get('name'))
            instance.user.first_name = first_name
            instance.user.last_name = last_name
            instance.user.save()

        return super(OrganizationSerializer,
                     self).update(instance, validated_data)

    def create(self, validated_data):
        org = validated_data.get('user')
        if org:
            org = org.get('username')

        org_name = validated_data.get('name', None)
        creator = None

        if 'request' in self.context:
            creator = self.context['request'].user

        validated_data['organization'] = org_name

        profile = tools.create_organization_object(org, creator,
                                                   validated_data)
        profile.save()

        return profile

    def validate_org(self, value):  # pylint: disable=no-self-use
        """
        Validate organization name.
        """
        org = value.lower() if isinstance(value, basestring) else value

        if org in RegistrationFormUserProfile.RESERVED_USERNAMES:
            raise serializers.ValidationError(
                _(u"%s is a reserved name, please choose another" % org))
        elif not RegistrationFormUserProfile.legal_usernames_re.search(org):
            raise serializers.ValidationError(
                _(u"Organization may only contain alpha-numeric characters and "
                  u"underscores"))
        try:
            User.objects.get(username=org)
        except User.DoesNotExist:
            return org

        raise serializers.ValidationError(
            _(u"Organization %s already exists." % org))

    def get_users(self, obj):  # pylint: disable=no-self-use
        """
        Return organization members.
        """
        members = get_organization_members(obj) if obj else []

        return [{
            'user': u.username,
            'role': get_role_in_org(u, obj),
            'first_name': u.first_name,
            'last_name': u.last_name,
            'gravatar': u.profile.gravatar,
        } for u in members]
class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(
        view_name='organizationprofile-detail', lookup_field='user')
    org = serializers.CharField(source='user.username', max_length=30)
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)
    creator = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                  lookup_field='username',
                                                  read_only=True)
    users = serializers.SerializerMethodField()
    metadata = JsonField(required=False)
    name = serializers.CharField(max_length=30)

    class Meta:
        model = OrganizationProfile
        exclude = ('created_by', 'is_organization', 'organization')

    def update(self, instance, validated_data):
        # update the user model
        if 'name' in validated_data:
            first_name, last_name = \
                _get_first_last_names(validated_data.get('name'))
            instance.user.first_name = first_name
            instance.user.last_name = last_name
            instance.user.save()

        return super(OrganizationSerializer,
                     self).update(instance, validated_data)

    def create(self, validated_data):
        org = validated_data.get('user')
        if org:
            org = org.get('username')

        org_name = validated_data.get('name', None)
        creator = None

        if 'request' in self.context:
            creator = self.context['request'].user

        validated_data['organization'] = org_name

        profile = tools.create_organization_object(org, creator,
                                                   validated_data)
        profile.save()

        return profile

    def validate_org(self, value):
        org = value.lower() if isinstance(value, basestring) else value

        if org in RegistrationFormUserProfile._reserved_usernames:
            raise serializers.ValidationError(
                _(u"%s is a reserved name, please choose another" % org))
        elif not RegistrationFormUserProfile.legal_usernames_re.search(org):
            raise serializers.ValidationError(
                _(u"Organization may only contain alpha-numeric characters and "
                  u"underscores"))
        try:
            User.objects.get(username=org)
        except User.DoesNotExist:
            return org

        raise serializers.ValidationError(
            _(u"Organization %s already exists." % org))

    def get_users(self, obj):
        members = get_organization_members(obj) if obj else []

        return [{
            'user': u.username,
            'role': get_role_in_org(u, obj),
            'first_name': u.first_name,
            'last_name': u.last_name,
            'gravatar': u.profile.gravatar,
            'metadata': u.profile.metadata,
        } for u in members]
class WidgetSerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.ReadOnlyField()
    url = serializers.HyperlinkedIdentityField(
        view_name='widgets-detail',
        lookup_field='pk'
    )
    content_object = GenericRelatedField()
    key = serializers.CharField(read_only=True)
    data = serializers.SerializerMethodField()
    order = serializers.IntegerField(required=False)
    metadata = JsonField(required=False)

    class Meta:
        model = Widget
        fields = ('id', 'url', 'key', 'title', 'description', 'widget_type',
                  'order', 'view_type', 'column', 'group_by', 'content_object',
                  'data', 'aggregation', 'metadata')

    def get_data(self, obj):
        # Get the request obj
        request = self.context.get('request')

        # Check if data flag is present
        data_flag = request.GET.get('data')
        key = request.GET.get('key')

        if (str2bool(data_flag) or key) and obj:
            data = Widget.query_data(obj)
        else:
            data = []

        return data

    def validate(self, attrs):
        column = attrs.get('column')

        # Get the form
        if 'content_object' in attrs:
            content_object = attrs.get('content_object')

            if isinstance(content_object, XForm):
                xform = content_object
            elif isinstance(content_object, DataView):
                # must be a dataview
                xform = content_object.xform

            try:
                # Check if column exists in xform
                get_field_from_field_xpath(column, xform)
            except Http404:
                raise serializers.ValidationError({
                    'column': (u"'{}' not in the form.".format(column))
                })

        order = attrs.get('order')

        # Set the order
        if order:
            self.instance.to(order)

        return attrs

    def validate_content_object(self, value):
        request = self.context.get('request')
        users = get_users_with_perms(
            value.project, attach_perms=False, with_group_users=False
        )

        profile = value.project.organization.profile
        # Shared or an admin in the organization
        if request.user not in users and not\
            is_organization(profile) and not\
            OwnerRole.user_has_role(request.user,
                                    profile):
            raise serializers.ValidationError(_(
                u"You don't have permission to the Project."
            ))

        return value
Beispiel #28
0
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
    projectid = serializers.Field(source='id')
    url = serializers.HyperlinkedIdentityField(view_name='project-detail',
                                               lookup_field='pk')
    owner = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                source='organization',
                                                lookup_field='username')
    created_by = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                     source='created_by',
                                                     lookup_field='username',
                                                     read_only=True)
    metadata = JsonField(source='metadata', required=False)
    starred = serializers.SerializerMethodField('is_starred_project')
    users = serializers.SerializerMethodField('get_project_permissions')
    forms = serializers.SerializerMethodField('get_project_forms')
    public = BooleanField(source='shared', widget=widgets.CheckboxInput())
    tags = TagListSerializer(read_only=True)
    num_datasets = serializers.SerializerMethodField('get_num_datasets')
    last_submission_date = serializers.SerializerMethodField(
        'get_last_submission_date')

    class Meta:
        model = Project
        exclude = ('organization', 'user_stars')

    def restore_object(self, attrs, instance=None):
        if instance:
            metadata = JsonField.to_json(attrs.get('metadata'))

            if self.partial and metadata:
                if not isinstance(instance.metadata, dict):
                    instance.metadata = {}

                instance.metadata.update(metadata)
                attrs['metadata'] = instance.metadata

            return super(ProjectSerializer,
                         self).restore_object(attrs, instance)

        if 'request' in self.context:
            created_by = self.context['request'].user

            return Project(
                name=attrs.get('name'),
                organization=attrs.get('organization'),
                created_by=created_by,
                metadata=attrs.get('metadata'),
            )

        return attrs

    def get_project_permissions(self, obj):
        return get_object_users_with_permissions(obj)

    @check_obj
    def get_project_forms(self, obj):
        xforms_details = obj.projectxform_set.values('xform__pk',
                                                     'xform__title')
        return [{
            'name': form['xform__title'],
            'id': form['xform__pk']
        } for form in xforms_details]

    @check_obj
    def get_num_datasets(self, obj):
        """Return the number of datasets attached to the object.

        :param obj: The project to find datasets for.
        """
        return obj.projectxform_set.count()

    @check_obj
    def get_last_submission_date(self, obj):
        """Return the most recent submission date to any of the projects
        datasets.

        :param obj: The project to find the last submission date for.
        """
        xform_ids = obj.projectxform_set.values_list('xform', flat=True)
        last_submission = Instance.objects.\
            order_by('-date_created').\
            filter(xform_id__in=xform_ids).values_list('date_created',
                                                       flat=True)

        return last_submission and last_submission[0]

    def is_starred_project(self, obj):
        request = self.context['request']
        user = request.user
        user_stars = obj.user_stars.all()
        if user in user_stars:
            return True

        return False
class ProjectSerializer(serializers.HyperlinkedModelSerializer):
    projectid = serializers.ReadOnlyField(source='id')
    url = serializers.HyperlinkedIdentityField(view_name='project-detail',
                                               lookup_field='pk')
    owner = serializers.HyperlinkedRelatedField(
        view_name='user-detail',
        source='organization',
        lookup_field='username',
        queryset=User.objects.exclude(
            username__iexact=settings.ANONYMOUS_DEFAULT_USERNAME))
    created_by = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                     lookup_field='username',
                                                     read_only=True)
    metadata = JsonField(required=False)
    starred = serializers.SerializerMethodField()
    users = serializers.SerializerMethodField()
    forms = serializers.SerializerMethodField()
    public = serializers.BooleanField(source='shared')
    tags = TagListSerializer(read_only=True)
    num_datasets = serializers.SerializerMethodField()
    last_submission_date = serializers.SerializerMethodField()
    teams = serializers.SerializerMethodField()
    data_views = serializers.SerializerMethodField()

    class Meta:
        model = Project
        exclude = ('shared', 'organization', 'user_stars')

    def validate(self, attrs):
        name = attrs.get('name')
        organization = attrs.get('organization')
        if not self.instance and \
                Project.objects.filter(name__iexact=name,
                                       organization=organization):
            raise serializers.ValidationError(
                {'name': _(u"Project {} already exists.".format(name))})

        return attrs

    def update(self, instance, validated_data):
        metadata = JsonField.to_json(validated_data.get('metadata'))
        owner = validated_data.get('organization')

        if self.partial and metadata:
            if not isinstance(instance.metadata, dict):
                instance.metadata = {}

            instance.metadata.update(metadata)
            validated_data['metadata'] = instance.metadata

        if self.partial and owner:
            # give the new owner permissions
            set_owners_permission(owner, instance)

            if is_organization(owner.profile):
                owners_team = get_organization_owners_team(owner.profile)
                members_team = get_organization_members_team(owner.profile)
                OwnerRole.add(owners_team, instance)
                ReadOnlyRole.add(members_team, instance)

            # clear cache
            safe_delete('{}{}'.format(PROJ_PERM_CACHE, instance.pk))

        project = super(ProjectSerializer, self)\
            .update(instance, validated_data)

        project.xform_set.exclude(shared=project.shared)\
            .update(shared=project.shared, shared_data=project.shared)

        return instance

    def create(self, validated_data):
        created_by = self.context['request'].user
        project = Project.objects.create(
            name=validated_data.get('name'),
            organization=validated_data.get('organization'),
            created_by=created_by,
            shared=validated_data.get('shared', False),
            metadata=validated_data.get('metadata', dict()))

        project.xform_set.exclude(shared=project.shared)\
            .update(shared=project.shared, shared_data=project.shared)

        return project

    def get_users(self, obj):
        return get_users(obj, self.context)

    @check_obj
    def get_forms(self, obj):
        forms = cache.get('{}{}'.format(PROJ_FORMS_CACHE, obj.pk))
        if forms:
            return forms
        xforms = get_obj_xforms(obj)
        request = self.context.get('request')
        serializer = ProjectXFormSerializer(xforms,
                                            context={'request': request},
                                            many=True)
        forms = list(serializer.data)
        cache.set('{}{}'.format(PROJ_FORMS_CACHE, obj.pk), forms)

        return forms

    def get_num_datasets(self, obj):
        return get_num_datasets(obj)

    def get_last_submission_date(self, obj):
        return get_last_submission_date(obj)

    def get_starred(self, obj):
        return get_starred(obj, self.context['request'])

    def get_teams(self, obj):
        return get_teams(obj)

    @check_obj
    def get_data_views(self, obj):
        data_views = cache.get('{}{}'.format(PROJECT_LINKED_DATAVIEWS, obj.pk))
        if data_views:
            return data_views

        data_views_obj = obj.dataview_prefetch if \
            hasattr(obj, 'dataview_prefetch') else obj.dataview_set.all()

        serializer = DataViewMinimalSerializer(data_views_obj,
                                               many=True,
                                               context=self.context)
        data_views = list(serializer.data)

        cache.set('{}{}'.format(PROJECT_LINKED_DATAVIEWS, obj.pk), data_views)

        return data_views
Beispiel #30
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    is_org = serializers.SerializerMethodField('is_organization')
    username = serializers.CharField(source='user.username')

    # Added this field so it's required in the API in a clean way
    # and triggers validatino
    name = serializers.CharField(required=True)

    email = serializers.CharField(source='user.email')
    website = serializers.CharField(source='home_page', required=False)
    gravatar = serializers.ReadOnlyField()
    password = serializers.CharField(
        source='user.password', style={'input_type': 'password'}, required=False)
    user = serializers.HyperlinkedRelatedField(
        view_name='user-detail', lookup_field='username', read_only=True)
    metadata = JsonField(required=False)
    id = serializers.ReadOnlyField(source='user.id')

    class Meta:
        model = UserProfile

        fields = ('id', 'is_org', 'url', 'username', 'name', 'password',
                  'email', 'city', 'country', 'organization', 'website',
                  'twitter', 'gravatar', 'require_auth', 'user', 'metadata')
        extra_kwargs = {
            'url': {'lookup_field': 'user'}
        }

    def is_organization(self, obj):
        return is_organization(obj)

    def to_representation(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_representation(obj)
        if 'password' in ret:
            del ret['password']

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, obj):
            del ret['email']

        return ret

    # Those 2 validations methods where embeded in the same code as
    # the create() method but DRF3 needs it to be separted now.
    # It uses to fill merge the form.errors and self._errors,
    # but you can't do it anymore so we validate the username, catch
    # the validation exception and reraise it in an exception DRF will
    # understand
    def validate_name(self, value):
        try:
            RegistrationFormUserProfile.validate_username(value)
        except FormValidationError as e:
            raise serializers.ValidationError(list(e))

        return value

    def validate_username(self, value):
        return self.validate_name(value)

    def create(self, validated_data):
        user = validated_data.get('user', {})
        username = user.get('username', None)
        password = user.get('password', None)
        email = user.get('email', None)

        site = Site.objects.get(pk=settings.SITE_ID)
        new_user = RegistrationProfile.objects.create_inactive_user(
            site,
            username=username,
            password=password,
            email=email,
            send_email=True)
        new_user.is_active = True
        new_user.save()

        created_by = self.context['request'].user
        created_by = None if created_by.is_anonymous() else created_by
        profile = UserProfile.objects.create(
            user=new_user, name=validated_data.get('name', u''),
            created_by=created_by,
            city=validated_data.get('city', u''),
            country=validated_data.get('country', u''),
            organization=validated_data.get('organization', u''),
        #    home_page=validated_data.get('home_page', u''),
        #    twitter=validated_data.get('twitter', u'')
            
            )

        return profile

    def update(self, instance, validated_data):

        params = copy.deepcopy(validated_data)
        username = validated_data.get('user.username', None)
        password = validated_data.get('user.password', None)
        name = validated_data.get('name', None)
        email = validated_data.get('user.email', None)

        if username:
            params['username'] = username

        if email:
            params['email'] = email

        if password:
            params.update({'password1': password, 'password2': password})

            form = UserProfileForm(params, instance=instance)

            # form.is_valid affects instance object for partial updates [PATCH]
            # so only use it for full updates [PUT], i.e shallow copy effect
            if not self.partial and form.is_valid():
                instance = form.save()

            # get user
            if email:
                instance.user.email = form.cleaned_data['email']

            if name:
                first_name, last_name = _get_first_last_names(name)
                instance.user.first_name = first_name
                instance.user.last_name = last_name

            if email or name:
                instance.user.save()

        return super(UserProfileSerializer, self).update(instance, validated_data)
Beispiel #31
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name='userprofile-detail',
                                               lookup_field='user')
    is_org = serializers.SerializerMethodField()
    username = serializers.CharField(source='user.username',
                                     min_length=3,
                                     max_length=30)
    name = serializers.CharField(required=False, allow_blank=True)
    first_name = serializers.CharField(source='user.first_name',
                                       required=False,
                                       allow_blank=True,
                                       max_length=30)
    last_name = serializers.CharField(source='user.last_name',
                                      required=False,
                                      allow_blank=True,
                                      max_length=30)
    email = serializers.EmailField(source='user.email')
    website = serializers.CharField(source='home_page',
                                    required=False,
                                    allow_blank=True)
    twitter = serializers.CharField(required=False, allow_blank=True)
    gravatar = serializers.ReadOnlyField()
    password = serializers.CharField(source='user.password',
                                     allow_blank=True,
                                     required=False)
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)
    metadata = JsonField(required=False)
    id = serializers.ReadOnlyField(source='user.id')
    joined_on = serializers.ReadOnlyField(source='user.date_joined')

    class Meta:
        model = UserProfile
        fields = ('id', 'is_org', 'url', 'username', 'password', 'first_name',
                  'last_name', 'email', 'city', 'country', 'organization',
                  'website', 'twitter', 'gravatar', 'require_auth', 'user',
                  'metadata', 'joined_on', 'name')

    def get_is_org(self, obj):
        if obj:
            is_org = cache.get('{}{}'.format(IS_ORG, obj.pk))
            if is_org:
                return is_org

        is_org = is_organization(obj)
        cache.set('{}{}'.format(IS_ORG, obj.pk), is_org)
        return is_org

    def to_representation(self, obj):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_representation(obj)
        if 'password' in ret:
            del ret['password']

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, obj):
            del ret['email']

        if 'first_name' in ret:
            ret['name'] = u' '.join(
                [ret.get('first_name'),
                 ret.get('last_name', "")])
            ret['name'] = ret['name'].strip()

        return ret

    def _get_params(self, attrs):
        params = copy.deepcopy(attrs)
        name = params.get('name', None)
        user = params.pop('user', None)
        if user:
            username = user.pop('username', None)
            password = user.pop('password', None)
            first_name = user.pop('first_name', None)
            last_name = user.pop('last_name', None)
            email = user.pop('email', None)

            if username:
                params['username'] = username

            if email:
                params['email'] = email

            if password:
                params.update({'password1': password, 'password2': password})

            if first_name:
                params['first_name'] = first_name

            params['last_name'] = last_name or ''

        # For backward compatibility, Users who still use only name
        if name:
            first_name, last_name = \
                _get_first_last_names(name)
            params['first_name'] = first_name
            params['last_name'] = last_name

        return params

    def update(self, instance, validated_data):
        params = validated_data
        password = params.get("password1")
        email = params.get('email')

        # Check password if email is being updated
        if email and not password:
            raise serializers.ValidationError(
                _(u'Your password is required when updating your email '
                  u'address.'))
        if password and not instance.user.check_password(password):
            raise serializers.ValidationError(_(u'Invalid password'))

        # get user
        instance.user.email = email or instance.user.email

        instance.user.first_name = params.get('first_name',
                                              instance.user.first_name)

        instance.user.last_name = params.get('last_name',
                                             instance.user.last_name)

        instance.user.username = params.get('username', instance.user.username)

        instance.user.save()

        if password:
            # force django-digest to regenerate its stored partial digests
            update_partial_digests(instance.user, password)

        return super(UserProfileSerializer, self).update(instance, params)

    def create(self, validated_data):
        params = validated_data

        site = Site.objects.get(pk=settings.SITE_ID)
        new_user = RegistrationProfile.objects.create_inactive_user(
            username=params.get('username'),
            password=params.get('password1'),
            email=params.get('email'),
            site=site,
            send_email=settings.SEND_EMAIL_ACTIVATION_API)
        new_user.is_active = True
        new_user.first_name = params.get('first_name')
        new_user.last_name = params.get('last_name')
        new_user.save()

        created_by = self.context['request'].user
        created_by = None if created_by.is_anonymous() else created_by
        profile = UserProfile(user=new_user,
                              name=params.get('first_name'),
                              created_by=created_by,
                              city=params.get('city', u''),
                              country=params.get('country', u''),
                              organization=params.get('organization', u''),
                              home_page=params.get('home_page', u''),
                              twitter=params.get('twitter', u''))
        profile.save()

        return profile

    def validate_username(self, value):
        username = value.lower() if isinstance(value, basestring) else value

        if username in RESERVED_NAMES:
            raise serializers.ValidationError(
                _(u"%s is a reserved name, please choose another" % username))
        elif not LEGAL_USERNAMES_REGEX.search(username):
            raise serializers.ValidationError(
                _(u"username may only contain alpha-numeric characters and "
                  u"underscores"))
        elif len(username) < 3:
            raise serializers.ValidationError(
                _(u"Username must have 3 or more characters"))
        users = User.objects.filter(username=username)
        if self.instance:
            users = users.exclude(pk=self.instance.user.pk)
        if users.exists():
            raise serializers.ValidationError(
                _(u"%s already exists" % username))

        return username

    def validate_email(self, value):
        users = User.objects.filter(email=value)
        if self.instance:
            users = users.exclude(pk=self.instance.user.pk)

        if users.exists():
            raise serializers.ValidationError(
                _(u"This email address is already in use. "))

        return value

    def validate_twitter(self, value):
        if isinstance(value, basestring) and len(value) > 0:
            match = re.search(r"^[A-Za-z0-9_]{1,15}$", value)
            if not match:
                raise serializers.ValidationError(
                    _(u"Invalid twitter username {}".format(value)))

        return value

    def validate(self, attrs):
        params = self._get_params(attrs)
        if not self.instance and params.get('name') is None and \
                params.get('first_name') is None:
            raise serializers.ValidationError(
                {'name': _(u"Either name or first_name should be provided")})

        return params
Beispiel #32
0
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
    """
    UserProfile serializer.
    """
    url = serializers.HyperlinkedIdentityField(view_name='userprofile-detail',
                                               lookup_field='user')
    is_org = serializers.SerializerMethodField()
    username = serializers.CharField(source='user.username',
                                     min_length=3,
                                     max_length=30)
    name = serializers.CharField(required=False, allow_blank=True)
    first_name = serializers.CharField(source='user.first_name',
                                       required=False,
                                       allow_blank=True,
                                       max_length=30)
    last_name = serializers.CharField(source='user.last_name',
                                      required=False,
                                      allow_blank=True,
                                      max_length=30)
    email = serializers.EmailField(source='user.email')
    website = serializers.CharField(source='home_page',
                                    required=False,
                                    allow_blank=True)
    twitter = serializers.CharField(required=False, allow_blank=True)
    gravatar = serializers.ReadOnlyField()
    password = serializers.CharField(source='user.password',
                                     allow_blank=True,
                                     required=False)
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)
    metadata = JsonField(required=False)
    id = serializers.ReadOnlyField(source='user.id')  # pylint: disable=C0103
    joined_on = serializers.ReadOnlyField(source='user.date_joined')

    class Meta:
        model = UserProfile
        fields = ('id', 'is_org', 'url', 'username', 'password', 'first_name',
                  'last_name', 'email', 'city', 'country', 'organization',
                  'website', 'twitter', 'gravatar', 'require_auth', 'user',
                  'metadata', 'joined_on', 'name')
        owner_only_fields = ('metadata', )

    def __init__(self, *args, **kwargs):
        super(UserProfileSerializer, self).__init__(*args, **kwargs)

        if self.instance and hasattr(self.Meta, 'owner_only_fields'):
            request = self.context.get('request')
            if isinstance(self.instance, QuerySet) or \
                    (request and request.user != self.instance.user) or \
                    not request:
                for field in getattr(self.Meta, 'owner_only_fields'):
                    self.fields.pop(field)

    def get_is_org(self, obj):  # pylint: disable=no-self-use
        """
        Returns True if it is an organization profile.
        """
        if obj:
            is_org = cache.get('{}{}'.format(IS_ORG, obj.pk))
            if is_org:
                return is_org

        is_org = is_organization(obj)
        cache.set('{}{}'.format(IS_ORG, obj.pk), is_org)
        return is_org

    def to_representation(self, instance):
        """
        Serialize objects -> primitives.
        """
        ret = super(UserProfileSerializer, self).to_representation(instance)
        if 'password' in ret:
            del ret['password']

        request = self.context['request'] \
            if 'request' in self.context else None

        if 'email' in ret and request is None or request.user \
                and not request.user.has_perm(CAN_VIEW_PROFILE, instance):
            del ret['email']

        if 'first_name' in ret:
            ret['name'] = u' '.join(
                [ret.get('first_name'),
                 ret.get('last_name', "")])
            ret['name'] = ret['name'].strip()

        return ret

    def update(self, instance, validated_data):
        params = validated_data
        password = params.get("password1")
        email = params.get('email')

        # Check password if email is being updated
        if email and not password:
            raise serializers.ValidationError(
                _(u'Your password is required when updating your email '
                  u'address.'))
        if password and not instance.user.check_password(password):
            raise serializers.ValidationError(_(u'Invalid password'))

        # get user
        instance.user.email = email or instance.user.email

        instance.user.first_name = params.get('first_name',
                                              instance.user.first_name)

        instance.user.last_name = params.get('last_name',
                                             instance.user.last_name)

        instance.user.username = params.get('username', instance.user.username)

        instance.user.save()

        if email:
            instance.metadata.update({"is_email_verified": False})
            instance.save()

            request = self.context.get('request')
            redirect_url = params.get('redirect_url')
            _send_verification_email(redirect_url, instance.user, request)

        if password:
            # force django-digest to regenerate its stored partial digests
            update_partial_digests(instance.user, password)

        return super(UserProfileSerializer, self).update(instance, params)

    def create(self, validated_data):
        params = validated_data
        request = self.context.get('request')
        metadata = {}

        site = Site.objects.get(pk=settings.SITE_ID)
        try:
            new_user = RegistrationProfile.objects.create_inactive_user(
                username=params.get('username'),
                password=params.get('password1'),
                email=params.get('email'),
                site=site,
                send_email=settings.SEND_EMAIL_ACTIVATION_API)
        except IntegrityError:
            raise serializers.ValidationError(
                _(u"User account {} already exists".format(
                    params.get('username'))))
        new_user.is_active = True
        new_user.first_name = params.get('first_name')
        new_user.last_name = params.get('last_name')
        new_user.save()

        if getattr(settings, 'ENABLE_EMAIL_VERIFICATION', False):
            redirect_url = params.get('redirect_url')
            _send_verification_email(redirect_url, new_user, request)

        created_by = request.user
        created_by = None if created_by.is_anonymous else created_by
        metadata['last_password_edit'] = timezone.now().isoformat()
        profile = UserProfile(user=new_user,
                              name=params.get('first_name'),
                              created_by=created_by,
                              city=params.get('city', u''),
                              country=params.get('country', u''),
                              organization=params.get('organization', u''),
                              home_page=params.get('home_page', u''),
                              twitter=params.get('twitter', u''),
                              metadata=metadata)
        profile.save()

        # cache user profile object
        cache.set(f'{USER_PROFILE_PREFIX}{new_user.username}', profile)

        return profile

    def validate_username(self, value):
        """
        Validate username.
        """
        username = value.lower() if isinstance(value, basestring) else value

        if username in RESERVED_NAMES:
            raise serializers.ValidationError(
                _(u"%s is a reserved name, please choose another" % username))
        elif not LEGAL_USERNAMES_REGEX.search(username):
            raise serializers.ValidationError(
                _(u"username may only contain alpha-numeric characters and "
                  u"underscores"))
        elif len(username) < 3:
            raise serializers.ValidationError(
                _(u"Username must have 3 or more characters"))
        users = User.objects.filter(username=username)
        if self.instance:
            users = users.exclude(pk=self.instance.user.pk)
        if users.exists():
            raise serializers.ValidationError(
                _(u"%s already exists" % username))

        return username

    def validate_email(self, value):
        """
        Checks if user with the same email has already been registered.
        """
        users = User.objects.filter(email=value)
        if self.instance:
            users = users.exclude(pk=self.instance.user.pk)

        if users.exists():
            raise serializers.ValidationError(
                _(u"This email address is already in use. "))

        return value

    def validate_twitter(self, value):  # pylint: disable=no-self-use
        """
        Checks if the twitter handle is valid.
        """
        if isinstance(value, basestring) and value:
            match = re.search(r"^[A-Za-z0-9_]{1,15}$", value)
            if not match:
                raise serializers.ValidationError(
                    _(u"Invalid twitter username {}".format(value)))

        return value

    def validate(self, attrs):
        params = _get_registration_params(attrs)
        if not self.instance and params.get('name') is None and \
                params.get('first_name') is None:
            raise serializers.ValidationError(
                {'name': _(u"Either name or first_name should be provided")})

        return params
class DataViewSerializer(serializers.HyperlinkedModelSerializer):
    dataviewid = serializers.ReadOnlyField(source='id')
    name = serializers.CharField(max_length=255)
    url = serializers.HyperlinkedIdentityField(view_name='dataviews-detail',
                                               lookup_field='pk')
    xform = serializers.HyperlinkedRelatedField(view_name='xform-detail',
                                                lookup_field='pk',
                                                queryset=XForm.objects.all())
    project = serializers.HyperlinkedRelatedField(
        view_name='project-detail',
        lookup_field='pk',
        queryset=Project.objects.all())
    columns = JsonField()
    query = JsonField(required=False)
    count = serializers.SerializerMethodField()
    instances_with_geopoints = serializers.SerializerMethodField()
    matches_parent = serializers.BooleanField(default=True)
    last_submission_time = serializers.SerializerMethodField()
    has_hxl_support = serializers.SerializerMethodField()

    class Meta:
        model = DataView

    def create(self, validated_data):
        validated_data = match_columns(validated_data)

        return super(DataViewSerializer, self).create(validated_data)

    def update(self, instance, validated_data):
        validated_data = match_columns(validated_data, instance)

        return super(DataViewSerializer, self).update(instance, validated_data)

    def validate_query(self, value):
        if value:
            for q in value:
                if 'column' not in q:
                    raise serializers.ValidationError(
                        _(u"`column` not set in query"))

                if 'filter' not in q:
                    raise serializers.ValidationError(
                        _(u"`filter` not set in query"))

                if 'value' not in q:
                    raise serializers.ValidationError(
                        _(u"`value` not set in query"))

                comp = q.get('filter')

                if comp not in SUPPORTED_FILTERS:
                    raise serializers.ValidationError(
                        _(u"Filter not supported"))

        return value

    def validate_columns(self, value):
        if not isinstance(value, list):
            raise serializers.ValidationError(
                _(u"`columns` should be a list of columns"))

        return value

    def validate(self, attrs):
        if 'xform' in attrs and attrs.get('xform'):
            xform = attrs.get('xform')
            know_dates = [
                e.name for e in xform.get_survey_elements_of_type('date')
            ]
            know_dates.append('_submission_time')
            for q in attrs.get('query', []):
                column = q.get('column')
                value = q.get('value')

                if column in know_dates and not \
                        (validate_datetime(value) or validate_date(value)):
                    raise serializers.ValidationError(
                        _(u"Date value in {} should be yyyy-mm-ddThh:m:s or "
                          u"yyyy-mm-dd".format(column)))

        return super(DataViewSerializer, self).validate(attrs)

    def get_count(self, obj):
        if obj:
            count_dict = cache.get('{}{}'.format(DATAVIEW_COUNT, obj.xform.pk))

            if count_dict:
                if obj.pk in count_dict:
                    return count_dict.get(obj.pk)
            else:
                count_dict = {}

            count_rows = DataView.query_data(obj, count=True)
            if 'error' in count_rows:
                raise ParseError(count_rows.get('error'))

            count_row = count_rows[0]
            if 'count' in count_row:
                count = count_row.get('count')
                count_dict.setdefault(obj.pk, count)
                cache.set('{}{}'.format(DATAVIEW_COUNT, obj.xform.pk),
                          count_dict)

                return count

        return None

    def get_last_submission_time(self, obj):
        if obj:
            last_submission_time = cache.get('{}{}'.format(
                DATAVIEW_LAST_SUBMISSION_TIME, obj.xform.pk))

            if last_submission_time:
                return last_submission_time

            last_submission_rows = DataView.query_data(
                obj, last_submission_time=True)  # data is returned as list

            if 'error' in last_submission_rows:
                raise ParseError(last_submission_rows.get('error'))

            if len(last_submission_rows):
                last_submission_row = last_submission_rows[0]

                if LAST_SUBMISSION_TIME in last_submission_row:
                    last_submission_time = last_submission_row.get(
                        LAST_SUBMISSION_TIME)
                    cache.set(
                        '{}{}'.format(DATAVIEW_LAST_SUBMISSION_TIME,
                                      obj.xform.pk), last_submission_time)

                return last_submission_time

        return None

    def get_instances_with_geopoints(self, obj):

        if obj:
            check_geo = obj.has_geo_columnn_n_data()
            if obj.instances_with_geopoints != check_geo:
                obj.instances_with_geopoints = check_geo
                obj.save()

            return obj.instances_with_geopoints

        return False

    def get_has_hxl_support(self, obj):
        columns_with_hxl = get_columns_with_hxl(
            obj.xform.survey.get('children'))

        return include_hxl_row(obj.columns, columns_with_hxl.keys())
Beispiel #34
0
class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
    org = serializers.WritableField(source='user.username')
    user = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                               lookup_field='username',
                                               read_only=True)
    creator = serializers.HyperlinkedRelatedField(view_name='user-detail',
                                                  lookup_field='username',
                                                  read_only=True)
    users = serializers.SerializerMethodField('get_org_permissions')
    metadata = JsonField(source='metadata', required=False)

    class Meta:
        model = OrganizationProfile
        lookup_field = 'user'
        exclude = ('created_by', 'is_organization', 'organization')

    def restore_object(self, attrs, instance=None):
        if instance:
            return super(OrganizationSerializer, self)\
                .restore_object(attrs, instance)

        org = attrs.get('user.username', None)
        org_name = attrs.get('name', None)
        org_exists = False
        creator = None

        try:
            User.objects.get(username=org)
        except User.DoesNotExist:
            pass
        else:
            self.errors['org'] = u'Organization %s already exists.' % org
            org_exists = True

        if 'request' in self.context:
            creator = self.context['request'].user

        if org and org_name and creator and not org_exists:
            attrs['organization'] = org_name
            orgprofile = tools.create_organization_object(org, creator, attrs)

            return orgprofile

        if not org:
            self.errors['org'] = u'org is required!'

        if not org_name:
            self.errors['name'] = u'name is required!'

        return attrs

    def validate_org(self, attrs, source):
        org = attrs[source].lower()
        if org in RegistrationFormUserProfile._reserved_usernames:
            raise ValidationError(
                u"%s is a reserved name, please choose another" % org)
        elif not RegistrationFormUserProfile.legal_usernames_re.search(org):
            raise ValidationError(
                u'organization may only contain alpha-numeric characters and '
                u'underscores')
        try:
            User.objects.get(username=org)
        except User.DoesNotExist:
            attrs[source] = org

            return attrs
        raise ValidationError(u'%s already exists' % org)

    def get_org_permissions(self, obj):
        members = get_organization_members(obj) if obj else []

        return [{
            'user': u.username,
            'role': get_role_in_org(u, obj),
            'first_name': u.first_name,
            'last_name': u.last_name,
            'gravatar': u.profile.gravatar,
            'metadata': u.profile.metadata,
        } for u in members]