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
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
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