Example #1
0
 def setUp(self):
     self.field = UserField()
     self.serializer = Serializer(context={
         'request': APIRequestFactory().get('/'),
     })
     self.field.bind('user', self.serializer)
     self.user = UserFactory()
Example #2
0
class TeamMemberSerializer(serializers.Serializer):
    default_error_messages = {
        'user-does-not-exist': "User does not exist: {username}",
        'user-already-member': "User is already a team member",
        'user-cannot-change-own-role': "User cannot change their own role",
    }

    ROLE_CHOICES = (
        TeamMember.ROLE_OWNER,
        TeamMember.ROLE_ADMIN,
        TeamMember.ROLE_MANAGER,
        TeamMember.ROLE_CONTRIBUTOR,
    )

    user = UserField()
    role = serializers.ChoiceField(ROLE_CHOICES)
    resource_uri = serializers.SerializerMethodField()

    def create(self, validated_data):
        try:
            return self.context['team'].members.create(
                user=validated_data['user'],
                role=validated_data['role'],
            )
        except IntegrityError:
            self.fail('user-already-member')

    def get_resource_uri(self, member):
        return reverse('api:team-members-detail',
                       kwargs={
                           'team_slug': self.context['team'].slug,
                           'identifier': 'id$' + member.user.secure_id(),
                       },
                       request=self.context['request'])
Example #3
0
class TeamMemberUpdateSerializer(TeamMemberSerializer):
    user = UserField(read_only=True)

    def update(self, instance, validated_data):
        instance.role = validated_data['role']
        instance.save()
        return instance
Example #4
0
class NotesSerializer(serializers.Serializer):
    user = UserField(read_only=True)
    created = TimezoneAwareDateTimeField(read_only=True)
    body = serializers.CharField()

    def create(self, validated_data):
        if self.context['editor_notes'] is None:
            raise PermissionDenied()
        return self.context['editor_notes'].post(self.context['user'],
                                                 validated_data['body'])
Example #5
0
class ApplicationSerializer(serializers.ModelSerializer):
    user = UserField(read_only=True)
    status = MappedChoiceField(
        Application.STATUSES,
        default=Application._meta.get_field('status').get_default())
    resource_uri = serializers.SerializerMethodField()
    created = TimezoneAwareDateTimeField(read_only=True)
    modified = TimezoneAwareDateTimeField(read_only=True)

    default_error_messages = {
        'invalid-status-choice': "Unknown status: {status}",
        'not-pending': "Application not pending",
    }

    def get_resource_uri(self, application):
        return reverse('api:team-application-detail',
                       kwargs={
                           'team_slug': self.context['team'].slug,
                           'id': application.id,
                       },
                       request=self.context['request'])

    class Meta:
        model = Application
        fields = (
            'id',
            'status',
            'user',
            'note',
            'created',
            'modified',
            'resource_uri',
        )
        read_only_fields = (
            'id',
            'note',
            'created',
            'modified',
        )

    def validate_status(self, status):
        if status not in (Application.STATUS_APPROVED,
                          Application.STATUS_DENIED):
            self.fail('invalid-status-choice', status=status)
        return status

    def update(self, instance, validated_data):
        if instance.status != Application.STATUS_PENDING:
            self.fail('not-pending')

        if validated_data['status'] == Application.STATUS_APPROVED:
            instance.approve(self.context['user'], 'API')
        elif validated_data['status'] == Application.STATUS_DENIED:
            instance.deny(self.context['user'], 'API')
        return instance
Example #6
0
class TeamMemberUpdateSerializer(TeamMemberSerializer):
    user = UserField(read_only=True)

    def update(self, instance, validated_data):
        # don't allow users to change their own role via the API
        if self.context.get('user') == instance.user:
            self.fail('user-cannot-change-own-role')
        else:
            instance.role = validated_data['role']
            instance.save()
            return instance
Example #7
0
class UserFieldTest(TestCase):
    def setUp(self):
        self.field = UserField()
        self.serializer = Serializer(context={
            'request': APIRequestFactory().get('/'),
        })
        self.field.bind('user', self.serializer)
        self.user = UserFactory()

    def test_output(self):
        assert_equal(self.field.to_representation(self.user),
                     user_field_data(self.user))

    @test_utils.patch_for_test('api.userlookup.lookup_user')
    def test_input(self, lookup_user):
        # Input should be done using the userlookup module.  This allows us to
        # input users using usernames, user ids, or partner ids
        lookup_user.return_value = self.user
        assert_equal(self.field.to_internal_value('test-user-id'), self.user)
        assert_equal(lookup_user.call_args, mock.call('test-user-id'))

    @test_utils.patch_for_test('api.userlookup.lookup_user')
    def test_user_not_found(self, lookup_user):
        # If lookup_user raises a User.DoesNotExist error, we should turn it
        # into a validation error
        lookup_user.side_effect = User.DoesNotExist
        with assert_raises(ValidationError):
            self.field.to_internal_value('test-user-id')
Example #8
0
class MessagesSerializer(serializers.Serializer):
    user = UserField(required=False)
    team = serializers.CharField(required=False)
    subject = serializers.CharField()
    content = serializers.CharField()

    default_error_messages = {
        'unknown-team': "Unknown team: {team}",
        'no-user-or-team': "Must specify either user or team",
    }

    def validate_team(self, slug):
        try:
            team = Team.objects.get(slug=slug)
        except Team.DoesNotExist:
            self.fail('unknown-team', team=slug)
        if not teams.permissions.can_message_all_members(
                team, self.context['user']):
            raise PermissionDenied()
        return team

    def validate(self, data):
        if not ('team' in data or 'user' in data):
            self.fail('no-user-or-team')
        return data

    def recipients(self):
        if 'user' in self.validated_data:
            yield self.validated_data['user']
        else:
            qs = self.validated_data['team'].members.select_related('user')
            for member in qs:
                yield member.user

    def create_messages(self):
        messages = [
            Message(user=user,
                    content=self.validated_data['content'],
                    subject=self.validated_data['subject'],
                    message_type='M',
                    author=self.context['user']) for user in self.recipients()
            if user != self.context['user']
        ]
        Message.objects.bulk_create(messages)
        if len(messages) == 1:
            self.context['user'].sent_message()
Example #9
0
class ActivitySerializer(serializers.ModelSerializer):
    type = serializers.SlugField()
    user = UserField(read_only=True)
    date = TimezoneAwareDateTimeField(source='created')
    video = serializers.CharField(source='video.video_id')
    language = serializers.SerializerMethodField()
    video_uri = serializers.HyperlinkedRelatedField(
        source='video',
        view_name='api:video-detail',
        lookup_field='video_id',
        read_only=True)
    language_uri = serializers.SerializerMethodField()

    def get_language(self, record):
        return record.language_code or None

    def get_language_uri(self, record):
        if not (record.language_code and record.video):
            return None
        return reverse('api:subtitle-language-detail',
                       kwargs={
                           'video_id': record.video.video_id,
                           'language_code': record.language_code,
                       },
                       request=self.context['request'])

    def to_representation(self, record):
        data = super(ActivitySerializer, self).to_representation(record)
        extra_data_method_name = 'get_{}_extra'.format(
            record.type.replace('-', '_'))
        extra_field_method = getattr(self, extra_data_method_name, None)
        if extra_field_method:
            data.update(extra_field_method(record))
        return data

    def get_video_url_added_extra(self, record):
        url_edit = record.get_related_obj()
        return {
            'url': url_edit.new_url,
        }

    def get_video_url_edited_extra(self, record):
        url_edit = record.get_related_obj()
        return {
            'old_url': url_edit.old_url,
            'new_url': url_edit.new_url,
        }

    def get_video_url_deleted_extra(self, record):
        url_edit = record.get_related_obj()
        return {
            'url': url_edit.old_url,
        }

    def get_video_deleted_extra(self, record):
        video_deletion = record.get_related_obj()
        return {
            'title': video_deletion.title,
        }

    class Meta:
        model = ActivityRecord
        fields = (
            'type',
            'date',
            'user',
            'video',
            'language',
            'video_uri',
            'language_uri',
        )
Example #10
0
class SubtitlesSerializer(serializers.Serializer):
    ORIGIN_CHOICES = [
        ('api', _('API')),
        ('editor', _('Subtitle editor')),
        ('upload', _('Upload')),
    ]
    version_number = serializers.IntegerField(read_only=True)
    sub_format = SubFormatField(required=False, default='dfxp', initial='dfxp')
    subtitles = SubtitlesField(required=False)
    subtitles_url = serializers.URLField(max_length=512,
                                         required=False,
                                         write_only=True)
    author = UserField(read_only=True)
    action = serializers.CharField(required=False,
                                   write_only=True,
                                   allow_blank=True)
    is_complete = serializers.NullBooleanField(required=False, write_only=True)
    origin = serializers.ChoiceField(required=False,
                                     write_only=True,
                                     default='api',
                                     choices=ORIGIN_CHOICES)
    language = LanguageForSubtitlesSerializer(source='*', read_only=True)
    title = serializers.CharField(required=False, allow_blank=True)
    duration = serializers.IntegerField(required=False, write_only=True)
    description = serializers.CharField(required=False, allow_blank=True)
    metadata = VideoMetadataSerializer(required=False)
    video_title = serializers.CharField(source='video.title_display',
                                        read_only=True)
    video_description = serializers.CharField(source='video.description',
                                              read_only=True)
    actions_uri = serializers.SerializerMethodField()
    notes_uri = serializers.SerializerMethodField()
    resource_uri = serializers.SerializerMethodField()
    site_uri = serializers.SerializerMethodField()

    def __init__(self, *args, **kwargs):
        super(SubtitlesSerializer, self).__init__(*args, **kwargs)
        if 'sub_format' in self.fields:
            for format in self.fields['sub_format'].choices:
                if not user_can_access_subtitles_format(
                        self.context['user'], format):
                    self.fields['sub_format'].choices.pop(format)

    def get_actions_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'language_code': version.language_code,
        }
        return reverse('api:subtitle-actions',
                       kwargs=kwargs,
                       request=self.context['request'])

    def get_notes_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'language_code': version.language_code,
        }
        return reverse('api:subtitle-notes',
                       kwargs=kwargs,
                       request=self.context['request'])

    def get_resource_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'language_code': version.language_code,
        }
        uri = reverse('api:subtitles',
                      kwargs=kwargs,
                      request=self.context['request'])
        if self.context['version_number']:
            uri += '?version_number={}'.format(self.context['version_number'])
        return uri

    def get_site_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'lang': version.language_code,
            'lang_id': version.subtitle_language_id,
            'version_id': version.id,
        }
        return reverse('videos:subtitleversion_detail',
                       kwargs=kwargs,
                       request=self.context['request'])

    def validate(self, data):
        """
        Check that subtitles are provided, either via a string
        or a URL.
        """
        if ('subtitles' in data) == ('subtitles_url' in data):
            raise serializers.ValidationError(
                "Subtitles must be provided either via a string or a URL")
        return data

    def validate_origin(self, value):
        if not value or value == 'api':
            return ORIGIN_API
        elif value == 'editor':
            return ORIGIN_WEB_EDITOR
        elif value == 'upload':
            return ORIGIN_UPLOAD
        else:
            raise ValidationError('invalid origin value: {}'.format(value))

    def to_representation(self, version):
        data = super(SubtitlesSerializer, self).to_representation(version)
        # copy a fields to deprecated names
        data['video'] = data['video_title']
        data['version_no'] = data['version_number']
        if self.context['allow_language_extra']:
            extra.video_language.add_data(self.context['request'],
                                          data,
                                          video=self.context['video'],
                                          language=version.subtitle_language)
        return data

    def to_internal_value(self, data):
        # set sub_format from the inputted data.  We need this to properly
        # parse the subtitles param
        if data.get('sub_format'):
            self.context['sub_format'] = data['sub_format']
        else:
            self.context['sub_format'] = 'dfxp'
        return super(SubtitlesSerializer, self).to_internal_value(data)

    def _process_subtitles_url(self, subtitles_url):
        value = data_from_url(subtitles_url)
        if not isinstance(value, basestring):
            raise serializers.ValidationError("Invalid subtitle data")
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        try:
            return load_subtitles(self.context['language_code'], value,
                                  self.context['sub_format'])
        except babelsubs.SubtitleParserError, e:
            logger.warn("Error parsing subtitles ({}/{})".format(
                self.context['video'].video_id, self.context['language_code']),
                        exc_info=True)
            raise serializers.ValidationError("Invalid subtitle data")
Example #11
0
class MiniSubtitleVersionSerializer(serializers.Serializer):
    """Serialize a subtitle version for SubtitleLanguageSerializer """
    author = UserField(read_only=True)
    published = serializers.BooleanField(source='is_public')
    version_no = serializers.IntegerField(source='version_number')
Example #12
0
class SubtitlesSerializer(serializers.Serializer):
    version_number = serializers.IntegerField(read_only=True)
    sub_format = SubFormatField(required=False, default='dfxp', initial='dfxp')
    subtitles = SubtitlesField()
    author = UserField(read_only=True)
    action = serializers.CharField(required=False,
                                   write_only=True,
                                   allow_blank=True)
    is_complete = serializers.NullBooleanField(required=False, write_only=True)
    from_editor = serializers.BooleanField(
        required=False,
        write_only=True,
        help_text=("Check to flag this version as coming from the "
                   "amara editor."))
    language = LanguageForSubtitlesSerializer(source='*', read_only=True)
    title = serializers.CharField(required=False, allow_blank=True)
    duration = serializers.IntegerField(required=False, write_only=True)
    description = serializers.CharField(required=False, allow_blank=True)
    metadata = VideoMetadataSerializer(required=False)
    video_title = serializers.CharField(source='video.title_display',
                                        read_only=True)
    video_description = serializers.CharField(source='video.description',
                                              read_only=True)
    actions_uri = serializers.SerializerMethodField()
    notes_uri = serializers.SerializerMethodField()
    resource_uri = serializers.SerializerMethodField()
    site_uri = serializers.SerializerMethodField()

    def __init__(self, *args, **kwargs):
        super(SubtitlesSerializer, self).__init__(*args, **kwargs)
        if 'sub_format' in self.fields:
            for format in self.fields['sub_format'].choices:
                if not user_can_access_subtitles_format(
                        self.context['user'], format):
                    self.fields['sub_format'].choices.pop(format)

    def get_actions_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'language_code': version.language_code,
        }
        return reverse('api:subtitle-actions',
                       kwargs=kwargs,
                       request=self.context['request'])

    def get_notes_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'language_code': version.language_code,
        }
        return reverse('api:subtitle-notes',
                       kwargs=kwargs,
                       request=self.context['request'])

    def get_resource_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'language_code': version.language_code,
        }
        uri = reverse('api:subtitles',
                      kwargs=kwargs,
                      request=self.context['request'])
        if self.context['version_number']:
            uri += '?version_number={}'.format(self.context['version_number'])
        return uri

    def get_site_uri(self, version):
        kwargs = {
            'video_id': version.video.video_id,
            'lang': version.language_code,
            'lang_id': version.subtitle_language_id,
            'version_id': version.id,
        }
        return reverse('videos:subtitleversion_detail',
                       kwargs=kwargs,
                       request=self.context['request'])

    def to_representation(self, version):
        data = super(SubtitlesSerializer, self).to_representation(version)
        # copy a fields to deprecated names
        data['video'] = data['video_title']
        data['version_no'] = data['version_number']
        if self.context['allow_language_extra']:
            extra.video_language.add_data(self.context['request'],
                                          data,
                                          video=self.context['video'],
                                          language=version.subtitle_language)
        return data

    def to_internal_value(self, data):
        # set sub_format from the inputted data.  We need this to properly
        # parse the subtitles param
        if data.get('sub_format'):
            self.context['sub_format'] = data['sub_format']
        else:
            self.context['sub_format'] = 'dfxp'
        return super(SubtitlesSerializer, self).to_internal_value(data)

    def create(self, validated_data):
        if validated_data.get('from_editor'):
            origin = ORIGIN_WEB_EDITOR
        else:
            origin = ORIGIN_API
        action = complete = None
        if 'action' in validated_data:
            action = validated_data.get("action")
        elif 'is_complete' in validated_data:
            complete = validated_data['is_complete']
        return pipeline.add_subtitles(
            self.context['video'],
            self.context['language_code'],
            validated_data['subtitles'],
            action=action,
            complete=complete,
            title=validated_data.get('title'),
            description=validated_data.get('description'),
            duration=validated_data.get('duration'),
            metadata=validated_data.get('metadata'),
            author=self.context['user'],
            committer=self.context['user'],
            origin=origin)