Ejemplo n.º 1
0
    def is_valid(self, bundle, request=None):
        errors = super(LinkValidation, self).is_valid(bundle, request)

        if not bundle.data:
            errors['__all__'] = 'No data provided.'
            return errors

        # Make sure a limited user has links left to create
        if not bundle.obj.pk:  # if it's a new entry
            if not bundle.data.get('folder').organization:
                links_remaining = bundle.request.user.get_links_remaining()
                if links_remaining < 1:
                    errors['__all__'] = "You've already reached your limit."
                    return errors
                bundle.data['links_remaining'] = links_remaining - 1
            else:
                bundle.data['links_remaining'] = 'unlimited'

        errors = {}
        if bundle.data.get('url', '') == '':
            if not bundle.obj.pk:  # if it's a new entry
                errors['url'] = "URL cannot be empty."
        elif bundle.obj.tracker.has_changed('submitted_url'):  # url is aliased to submitted_url in the API
            try:
                validate = URLValidator()
                validate(bundle.obj.safe_url)

                # Don't force URL resolution validation if a file is provided
                if not bundle.data.get('file', None):
                    if not bundle.obj.ip:
                        errors['url'] = "Couldn't resolve domain."
                    elif not ip_in_allowed_ip_range(bundle.obj.ip):
                        errors['url'] = "Not a valid IP."
                    elif not bundle.obj.headers:
                        errors['url'] = "Couldn't load URL."
                    elif not self.is_valid_size(bundle.obj.headers):
                        errors['url'] = "Target page is too large (max size 1MB)."
            except ValidationError:
                errors['url'] = "Not a valid URL."
            except TooManyRedirects:
                errors['url'] = "URL caused a redirect loop."

        uploaded_file = bundle.data.get('file')
        if bundle.data.get('file_required', '') and not uploaded_file:
            errors['file'] = "You must upload a file."
        if uploaded_file:
            mime_type = get_mime_type(uploaded_file.name)

            # Get mime type string from tuple
            if not mime_type or not mime_type_lookup[mime_type]['valid_file'](uploaded_file):
                errors['file'] = "Invalid file."
            elif uploaded_file.size > settings.MAX_ARCHIVE_FILE_SIZE:
                errors['file'] = "File is too large."

        # Moving folder when not organization
        #elif bundle.data.get("folder", None):
            #if bundle.obj.organization_id and bundle.obj.organization_id != bundle.data['folder'].organization_id:
                #errors['folder'] = "Archives belonging to an organization cannot be moved out of the organization's shared folder."

        return errors
Ejemplo n.º 2
0
    def validate(self, data):
        user = self.context['request'].user
        errors = {}

        # since 'file' is not a field on the model, we have to access it through request.data rather than data
        uploaded_file = self.context['request'].data.get('file')

        # handle is_private and private_reason:
        if self.instance:
            if not user.is_staff:
                # only staff can manually change private_reason in all cases
                data.pop('private_reason', None)

                # if updating privacy, make sure user is allowed to change private status
                if 'is_private' in data and self.instance.is_private != bool(
                        data['is_private']):
                    if self.instance.private_reason and self.instance.private_reason not in [
                            'user', 'old_policy'
                    ]:
                        errors['is_private'] = 'Cannot change link privacy.'
                    else:
                        data['private_reason'] = 'user' if data[
                            'is_private'] else None
        else:
            # for new links, set private_reason based on is_private
            data['private_reason'] = 'user' if data.get('is_private') else None

        # check submitted URL for new link
        if not self.instance:
            if not data.get('submitted_url'):
                errors['url'] = "URL cannot be empty."
            else:
                try:
                    validate = URLValidator()
                    temp_link = Link(submitted_url=data['submitted_url'])
                    validate(temp_link.ascii_safe_url)

                    # Don't force URL resolution validation if a file is provided
                    if not uploaded_file:
                        if not temp_link.ip:
                            errors['url'] = "Couldn't resolve domain."
                        elif not ip_in_allowed_ip_range(temp_link.ip):
                            errors['url'] = "Not a valid IP."
                        elif not temp_link.headers:
                            errors['url'] = "Couldn't load URL."
                        else:
                            # preemptively reject URLs that report a size over settings.MAX_ARCHIVE_FILE_SIZE
                            try:
                                if int(
                                        temp_link.headers.get(
                                            'content-length', 0)
                                ) > settings.MAX_ARCHIVE_FILE_SIZE:
                                    errors[
                                        'url'] = "Target page is too large (max size %sMB)." % (
                                            settings.MAX_ARCHIVE_FILE_SIZE /
                                            1024 / 1024)
                            except ValueError:
                                # content-length header wasn't an integer. Carry on.
                                pass
                except DjangoValidationError:
                    errors['url'] = "Not a valid URL."
                except TooManyRedirects:
                    errors['url'] = "URL caused a redirect loop."

        # check uploaded file
        if uploaded_file == '':
            errors['file'] = "File cannot be blank."
        elif uploaded_file:

            if self.instance and self.instance.is_permanent():
                errors[
                    'file'] = "Archive contents cannot be replaced after 24 hours"

            else:
                mime_type = get_mime_type(uploaded_file.name)

                # Get mime type string from tuple
                if not mime_type or not mime_type_lookup[mime_type][
                        'valid_file'](uploaded_file):
                    errors['file'] = "Invalid file."
                elif uploaded_file.size > settings.MAX_ARCHIVE_FILE_SIZE:
                    errors['file'] = "File is too large."

        if errors:
            raise serializers.ValidationError(errors)

        return data
Ejemplo n.º 3
0
    def is_valid(self, bundle, request=None):
        errors = super(LinkValidation, self).is_valid(bundle, request)

        if not bundle.data:
            errors['__all__'] = 'No data provided.'
            return errors

        # Make sure a limited user has links left to create
        if not bundle.obj.pk:  # if it's a new entry
            if not bundle.data.get('folder').organization:
                links_remaining = bundle.request.user.get_links_remaining()
                if links_remaining < 1:
                    errors['__all__'] = "You've already reached your limit."
                    return errors
                bundle.data['links_remaining'] = links_remaining - 1
            else:
                bundle.data['links_remaining'] = 'unlimited'

        errors = {}
        if bundle.data.get('url', '') == '':
            if not bundle.obj.pk:  # if it's a new entry
                errors['url'] = "URL cannot be empty."
        elif bundle.obj.tracker.has_changed(
                'submitted_url'):  # url is aliased to submitted_url in the API
            try:
                validate = URLValidator()
                validate(bundle.obj.safe_url)

                # Don't force URL resolution validation if a file is provided
                if not bundle.data.get('file', None):
                    if not bundle.obj.ip:
                        errors['url'] = "Couldn't resolve domain."
                    elif not ip_in_allowed_ip_range(bundle.obj.ip):
                        errors['url'] = "Not a valid IP."
                    elif not bundle.obj.headers:
                        errors['url'] = "Couldn't load URL."
                    elif not self.is_valid_size(bundle.obj.headers):
                        errors[
                            'url'] = "Target page is too large (max size 1MB)."
            except UnicodeError:
                # see https://github.com/harvard-lil/perma/issues/1841
                errors['url'] = "Unicode error while processing URL."
            except ValidationError:
                errors['url'] = "Not a valid URL."
            except TooManyRedirects:
                errors['url'] = "URL caused a redirect loop."

        uploaded_file = bundle.data.get('file')
        if bundle.data.get('file_required', '') and not uploaded_file:
            errors['file'] = "You must upload a file."
        if uploaded_file:
            mime_type = get_mime_type(uploaded_file.name)

            # Get mime type string from tuple
            if not mime_type or not mime_type_lookup[mime_type]['valid_file'](
                    uploaded_file):
                errors['file'] = "Invalid file."
            elif uploaded_file.size > settings.MAX_ARCHIVE_FILE_SIZE:
                errors['file'] = "File is too large."

        # Moving folder when not organization
        #elif bundle.data.get("folder", None):
        #if bundle.obj.organization_id and bundle.obj.organization_id != bundle.data['folder'].organization_id:
        #errors['folder'] = "Archives belonging to an organization cannot be moved out of the organization's shared folder."

        return errors