Example #1
0
    def clean(self, value):
        """
        We clean every subwidget.
        """
        clean_data = []
        errors = ErrorList()
        is_empty = not value or not [v for v in value if v not in self.empty_values]
        if is_empty and not self.required:
            return []

        if is_empty and self.required:
            raise ValidationError(self.error_messages['required'])

        if value and not isinstance(value, (list, tuple)):
            raise ValidationError(self.error_messages['invalid'])

        for field_value, checkbox_value in value:
            try:
                clean_data.append([self.contained_field.clean(field_value), checkbox_value])
            except ValidationError as e:
                errors.extend(e.messages)
            # FIXME: copy paste from above
            if self.contained_field.required:
                self.contained_field.required = False
        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Example #2
0
    def clean_deck_order(self):
        """
        Cleans and validates the JSON POSTed in the deck_order field.
        This field describes how decks should be sorted in the collection.
        Errors are manually added to the errorlist because this is a custom field.
        """
        field = 'deck_order'
        deck_data = []
        errstr = ''
        errors = ErrorList()

        if field in self.data:
            deck_order = json.loads(self.data[field])
            if 'data' in deck_order:
                deck_data = deck_order['data']

        for d in deck_data:
            if ('deck_id' in d and 'sort_order' in d):
                try:
                    int(d['sort_order'])
                except ValueError:
                    errstr = "deck %s has invalid sort value: %s" % (d['deck_id'], d['sort_order'])
                    errors.append(errstr)
            else:
                errstr = "deck_id and sort_order required"
                errors.append(errstr)
                break

        if errors:
            self._errors.setdefault(field, errors)
            raise forms.ValidationError("Deck order field has errors")

        self.cleaned_data['deck_order'] = deck_data
Example #3
0
	def get_error_titles(self):
		errors = ErrorList()
		for form in self.formsets:
			for item in form.errors:
				if item:
					errors.extend(item)
		return errors
Example #4
0
    def clean(self, value):
        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [v for v in value if v not in self.empty_values]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return []
        else:
            raise ValidationError(self.error_messages['invalid'])
        
        for field_value in value:
            try:
                clean_data.append(self.contained_field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)
            if self.contained_field.required:
                self.contained_field.required = False
        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Example #5
0
def validation_error_as_text(error):
    """
    Given a ValidationError object, return a string representing the errors.
    """
    try:
        ed = ErrorDict(error.message_dict)
        return ed.as_text()
    except AttributeError:
        el = ErrorList(error.messages)
        return el.as_text()
Example #6
0
def login_view(request):
    """
    Standard Django login, with additions:
        Lowercase the login email (username)
        Check user has accepted ToS, if any.
    """
    if request.method == "POST":
        redirect_to = request.POST.get('next', request.GET.get('next', False))
        if not redirect_to:
            redirect_to = reverse('seed:home')

        form = LoginForm(request.POST)
        if form.is_valid():
            new_user = authenticate(
                username=form.cleaned_data['email'].lower(),
                password=form.cleaned_data['password']
            )
            if new_user and new_user.is_active:
                # determine if user has accepted ToS, if one exists
                try:
                    user_accepted_tos = has_user_agreed_latest_tos(new_user)
                except NoActiveTermsOfService:
                    # there's no active ToS, skip interstitial
                    user_accepted_tos = True

                if user_accepted_tos:
                    login(request, new_user)
                    return HttpResponseRedirect(redirect_to)
                else:
                    # store login info for django-tos to handle
                    request.session['tos_user'] = new_user.pk
                    request.session['tos_backend'] = new_user.backend
                    context = RequestContext(request)
                    context.update({
                        'next': redirect_to,
                        'tos': TermsOfService.objects.get_current_tos()
                    })
                    return render_to_response(
                        'tos/tos_check.html',
                        context_instance=context
                    )
            else:
                errors = ErrorList()
                errors = form._errors.setdefault(NON_FIELD_ERRORS, errors)
                errors.append('Username and/or password were invalid.')
    else:
        form = LoginForm()
    return render_to_response(
        'landing/login.html',
        locals(),
        context_instance=RequestContext(request),
    )
Example #7
0
    def clean(self, value):
        """
        Validates every value in the given list. A value is validated against
        the corresponding Field in self.fields.

        For example, if this MultiValueField was instantiated with
        fields=(DateField(), TimeField()), clean() would call
        DateField.clean(value[0]) and TimeField.clean(value[1]).
        """
        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [v for v in value if v not in self.empty_values]:
                if self.required:
                    raise ValidationError(self.error_messages['required'], code='required')
                else:
                    return self.compress([])
        else:
            raise ValidationError(self.error_messages['invalid'], code='invalid')
        for i, field in enumerate(self.fields):
            try:
                field_value = value[i]
            except IndexError:
                field_value = None
            if field_value in self.empty_values:
                if self.require_all_fields:
                    # Raise a 'required' error if the MultiValueField is
                    # required and any field is empty.
                    if self.required:
                        raise ValidationError(self.error_messages['required'], code='required')
                elif field.required:
                    # Otherwise, add an 'incomplete' error to the list of
                    # collected errors and skip field cleaning, if a required
                    # field is empty.
                    if field.error_messages['incomplete'] not in errors:
                        errors.append(field.error_messages['incomplete'])
                    continue
            try:
                clean_data.append(field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter. Skip duplicates.
                errors.extend(m for m in e.error_list if m not in errors)
        if errors:
            raise ValidationError(errors)

        out = self.compress(clean_data)
        self.validate(out)
        self.run_validators(out)
        return out
Example #8
0
 def post(self, request, *args, **kwargs):
     if self.async_response is not None:
         return self.async_response
     if self.subscription_form.is_valid():
         try:
             subscription = self.subscription_form.create_subscription()
             return HttpResponseRedirect(
                 reverse(EditSubscriptionView.urlname, args=(subscription.id,))
             )
         except NewSubscriptionError as e:
             errors = ErrorList()
             errors.extend([e.message])
             self.subscription_form._errors.setdefault(NON_FIELD_ERRORS, errors)
     return self.get(request, *args, **kwargs)
Example #9
0
    def clean(self, value):
        clean_data = {}
        errors = ErrorList()
        if not value or isinstance(value, dict):
            if not value or not [
                    v for v in value.values() if v not in self.empty_values
            ]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return {}
        else:
            raise ValidationError(self.error_messages['invalid'])

        # sort out required => at least one element must be in there
        for key, val in value.items():
            # ignore empties. Can they even come up here?
            if key in self.empty_values and val in self.empty_values:
                continue

            try:
                val = self.contained_field.clean(val)
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)

            try:
                self._validate_key(key)
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)

            clean_data[key] = val

            if self.contained_field.required:
                self.contained_field.required = False

        if errors:
            raise ValidationError(errors)

        self.validate(clean_data)
        self.run_validators(clean_data)
        return clean_data
Example #10
0
    def clean(self, value):
        """
        This is a copy of MultiValueField.clean() with a BUGFIX:
        -   if self.required and field_value in validators.EMPTY_VALUES:
        +   if field.required and field_value in validators.EMPTY_VALUES:
        """
        try:
            from django.forms.utils import ErrorList
        except ImportError:
            from django.forms.util import ErrorList
        from django.core import validators
        from django.core.exceptions import ValidationError

        clean_data = []
        errors = ErrorList()
        if not value or isinstance(value, (list, tuple)):
            if not value or not [v for v in value if v not in validators.EMPTY_VALUES]:
                if self.required:
                    raise ValidationError(self.error_messages['required'])
                else:
                    return self.compress(value)
        else:
            raise ValidationError(self.error_messages['invalid'])
        for i, field in enumerate(self.fields):
            try:
                field_value = value[i]
            except IndexError:
                field_value = None
            if field.required and field_value in validators.EMPTY_VALUES:
                raise ValidationError(self.error_messages['required'])
            try:
                clean_data.append(field.clean(field_value))
            except ValidationError as e:
                # Collect all validation errors in a single list, which we'll
                # raise at the end of clean(), rather than raising a single
                # exception for the first error we encounter.
                errors.extend(e.messages)
        if errors:
            raise ValidationError(errors)

        out = self.compress(clean_data)
        self.validate(out)
        self.run_validators(out)
        return out
Example #11
0
    def clean(self, value):
        # Get the value
        # Totally replaced validation.
        clean_data = []
        errors = ErrorList()

        # Only the visible field is required.
        radio_value = value[0]
        field_visible = [False] * len(self.fields)
        field_visible[0] = True
        if radio_value is None:
            # radio_value is None when models are deleted in formsets
            out = ''
        else:
            field_visible[self.url_type_registry.index(radio_value) + 1] = True

            # The validators only fire for visible fields.
            for i, field in enumerate(self.fields):
                try:
                    field_value = value[i]
                except IndexError:
                    field_value = None

                if not field_visible[i]:
                    clean_data.append(None)
                    continue

                if self.required and field_value in validators.EMPTY_VALUES:
                    raise ValidationError(self.error_messages['required'])

                try:
                    clean_data.append(field.clean(field_value))
                except ValidationError as e:
                    errors.extend(e.messages)  # Collect all widget errors
            if errors:
                raise ValidationError(errors)

            out = self.compress(clean_data)

        self.validate(out)
        return out
Example #12
0
def account_login(request):
    if request.user.is_authenticated():
        return redirect('home')
    else:
        if request.POST:
            login_form = LoginForm(request.POST)
            if login_form.is_valid():
                users = UserAccount.objects.filter(email=login_form.cleaned_data['email'].lower())
                if len(users) > 0:
                    user = authenticate(email=users[0].email, password=login_form.cleaned_data['password'])
                    if user is not None:
                        if user.is_active:
                            login(request, user)
                            return HttpResponseRedirect(request.POST['next'])
                    else:
                        # user does not authenticate
                        errors = ErrorList()
                        errors = login_form._errors.setdefault(forms.NON_FIELD_ERRORS, errors)
                        errors.append('The password for this account is incorrect.')
                else:
                    # user doesn't exist
                    errors = ErrorList()
                    errors = login_form._errors.setdefault(forms.NON_FIELD_ERRORS, errors)
                    errors.append('There is no account registered with this e-mail address.')
        else:
            login_form = LoginForm()
        return render(request, 'general/login.html', {'form': login_form, 'next': request.GET['next'] if request.GET and 'next' in request.GET.keys() else None})
Example #13
0
class ActiveProject(Metadata, UnpublishedProject, SubmissionInfo):
    """
    The project used for submitting

    The submission_status field:
    - 0 : Not submitted
    - 10 : Submitting author submits. Awaiting editor assignment.
    - 20 : Editor assigned. Awaiting editor decision.
    - 30 : Revisions requested. Waiting for resubmission. Loops back
          to 20 when author resubmits.
    - 40 : Accepted. In copyedit stage. Awaiting editor to copyedit.
    - 50 : Editor completes copyedit. Awaiting authors to approve.
    - 60 : Authors approve copyedit. Ready for editor to publish

    """
    submission_status = models.PositiveSmallIntegerField(default=0)

    # Max number of active submitting projects a user is allowed to have
    MAX_SUBMITTING_PROJECTS = 10
    INDIVIDUAL_FILE_SIZE_LIMIT = 10 * 1024**3
    # Where all the active project files are kept

    FILE_ROOT = os.path.join(ProjectFiles().file_root, 'active-projects')

    REQUIRED_FIELDS = (
        # 0: Database
        ('title', 'abstract', 'background', 'methods', 'content_description',
         'usage_notes', 'conflicts_of_interest', 'version', 'license',
         'short_description'),
        # 1: Software
        ('title', 'abstract', 'background', 'content_description',
         'usage_notes', 'installation', 'conflicts_of_interest', 'version',
         'license', 'short_description'),
        # 2: Challenge
        ('title', 'abstract', 'background', 'methods', 'content_description',
         'usage_notes', 'conflicts_of_interest', 'version', 'license',
         'short_description'),
        # 3: Model
        ('title', 'abstract', 'background', 'methods', 'content_description',
         'usage_notes', 'installation', 'conflicts_of_interest', 'version',
         'license', 'short_description'),
    )

    # Custom labels that don't match model field names
    LABELS = (
        # 0: Database
        {
            'content_description': 'Data Description'
        },
        # 1: Software
        {
            'content_description': 'Software Description',
            'methods': 'Technical Implementation',
            'installation': 'Installation and Requirements'
        },
        # 2: Challenge
        {
            'background': 'Objective',
            'methods': 'Participation',
            'content_description': 'Data Description',
            'usage_notes': 'Evaluation'
        },
        # 3: Model
        {
            'content_description': 'Model Description',
            'methods': 'Technical Implementation',
            'installation': 'Installation and Requirements'
        },
    )

    SUBMISSION_STATUS_LABELS = {
        0: 'Not submitted.',
        10: 'Awaiting editor assignment.',
        20: 'Awaiting editor decision.',
        30: 'Revisions requested.',
        40: 'Submission accepted; awaiting editor copyedits.',
        50: 'Awaiting authors to approve publication.',
        60: 'Awaiting editor to publish.',
    }

    class Meta:
        default_permissions = ('change', )
        permissions = [('can_assign_editor', 'Can assign editor')]

    def storage_used(self):
        """
        Total storage used in bytes.

        This includes the total size of new files uploaded to this
        project, as well as the total size of files published in past
        versions of this CoreProject.  (The QuotaManager should ensure
        that the same file is not counted twice in this total.)
        """
        current = ProjectFiles().active_project_storage_used(self)
        published = self.core_project.total_published_size

        return current + published

    def storage_allowance(self):
        """
        Storage allowed in bytes
        """
        return self.core_project.storage_allowance

    def get_inspect_dir(self, subdir):
        """
        Return the folder to inspect if valid. subdir joined onto
        the file root of this project.
        """
        # Sanitize subdir for illegal characters
        validate_subdir(subdir)
        # Folder must be a subfolder of the file root
        # (but not necessarily exist or be a directory)
        inspect_dir = os.path.join(self.file_root(), subdir)
        if inspect_dir.startswith(self.file_root()):
            return inspect_dir
        else:
            raise Exception('Invalid directory request')

    def file_url(self, subdir, file):
        """
        Url of a file to download in this project
        """
        return reverse('serve_active_project_file',
                       args=(self.slug, os.path.join(subdir, file)))

    def file_display_url(self, subdir, file):
        """
        URL of a file to display in this project
        """
        return reverse('display_active_project_file',
                       args=(self.slug, os.path.join(subdir, file)))

    def under_submission(self):
        """
        Whether the project is under submission
        """
        return bool(self.submission_status)

    def submission_deadline(self):
        return self.creation_datetime + timedelta(days=180)

    def submission_days_remaining(self):
        return (self.submission_deadline() - timezone.now()).days

    def submission_status_label(self):
        return ActiveProject.SUBMISSION_STATUS_LABELS[self.submission_status]

    def author_editable(self):
        """
        Whether the project can be edited by its authors
        """
        if self.submission_status in [0, 30]:
            return True

    def copyeditable(self):
        """
        Whether the project can be copyedited
        """
        if self.submission_status == 40:
            return True

    def archive(self, archive_reason):
        """
        Archive the project. Create an ArchivedProject object, copy over
        the fields, and delete this object
        """
        archived_project = ArchivedProject(archive_reason=archive_reason,
                                           slug=self.slug)

        modified_datetime = self.modified_datetime

        # Direct copy over fields
        for attr in [f.name for f in Metadata._meta.fields
                     ] + [f.name for f in SubmissionInfo._meta.fields]:
            setattr(archived_project, attr, getattr(self, attr))

        archived_project.save()

        # Redirect the related objects
        for reference in self.references.all():
            reference.project = archived_project
            reference.save()
        for publication in self.publications.all():
            publication.project = archived_project
            publication.save()
        for topic in self.topics.all():
            topic.project = archived_project
            topic.save()
        for author in self.authors.all():
            author.project = archived_project
            author.save()
        for edit_log in self.edit_logs.all():
            edit_log.project = archived_project
            edit_log.save()
        for copyedit_log in self.copyedit_logs.all():
            copyedit_log.project = archived_project
            copyedit_log.save()
        for parent_project in self.parent_projects.all():
            archived_project.parent_projects.add(parent_project)

        UploadedDocument.objects.filter(
            object_id=self.pk,
            content_type=ContentType.objects.get_for_model(ActiveProject)
        ).update(
            object_id=archived_project.pk,
            content_type=ContentType.objects.get_for_model(ArchivedProject))

        if self.resource_type.id == 1:
            languages = self.programming_languages.all()
            if languages:
                archived_project.programming_languages.add(*list(languages))

        # Voluntary delete
        if archive_reason == 1:
            self.clear_files()
        else:
            # Move over files
            os.rename(self.file_root(), archived_project.file_root())

        # Copy the ActiveProject timestamp to the ArchivedProject.
        # Since this is an auto_now field, save() doesn't allow
        # setting an arbitrary value.
        queryset = ArchivedProject.objects.filter(id=archived_project.id)
        queryset.update(modified_datetime=modified_datetime)

        return self.delete()

    def fake_delete(self):
        """
        Appear to delete this project. Actually archive it.
        """
        self.archive(archive_reason=1)

    def check_integrity(self):
        """
        Run integrity tests on metadata fields and return whether the
        project passes the checks
        """
        self.integrity_errors = ErrorList()

        # Invitations
        for invitation in self.authorinvitations.filter(is_active=True):
            self.integrity_errors.append(
                'Outstanding author invitation to {0}'.format(
                    invitation.email))

        # Storage requests
        for storage_request in self.storagerequests.filter(is_active=True):
            self.integrity_errors.append('Outstanding storage request')

        # Authors
        for author in self.authors.all().order_by('display_order'):
            if not author.get_full_name():
                self.integrity_errors.append(
                    'Author {0} has not fill in name'.format(
                        author.user.username))
            if not author.affiliations.all():
                self.integrity_errors.append(
                    'Author {0} has not filled in affiliations'.format(
                        author.user.username))

        # Metadata
        for attr in ActiveProject.REQUIRED_FIELDS[self.resource_type.id]:
            value = getattr(self, attr)
            text = unescape(strip_tags(str(value)))
            if value is None or not text or text.isspace():
                l = self.LABELS[
                    self.resource_type.id][attr] if attr in self.LABELS[
                        self.resource_type.id] else attr.title().replace(
                            '_', ' ')
                self.integrity_errors.append(
                    'Missing required field: {0}'.format(l))

        # Ethics
        if not self.ethics_statement:
            self.integrity_errors.append(
                'Missing required field: Ethics Statement')

        published_projects = self.core_project.publishedprojects.all()
        if published_projects:
            published_versions = [p.version for p in published_projects]
            if self.version in published_versions:
                self.integrity_errors.append(
                    'The version matches a previously published version.')
                self.version_clash = True
            else:
                self.version_clash = False

        if self.access_policy != AccessPolicy.OPEN and self.dua is None:
            self.integrity_errors.append(
                'You have to choose one of the data use agreements.')

        if self.integrity_errors:
            return False
        else:
            return True

    def is_submittable(self):
        """
        Whether the project can be submitted
        """
        return (not self.under_submission() and self.check_integrity())

    def submit(self, author_comments):
        """
        Submit the project for review.
        """
        if not self.is_submittable():
            raise Exception('ActiveProject is not submittable')

        self.submission_status = 10
        self.submission_datetime = timezone.now()
        self.author_comments = author_comments
        self.save()
        # Create the first edit log
        EditLog.objects.create(project=self, author_comments=author_comments)

    def set_submitting_author(self):
        """
        Used to save query time in templates
        """
        self.submitting_author = self.submitting_author()

    def assign_editor(self, editor):
        """
        Assign an editor to the project and set the submission status to the
        edit stage.
        """
        self.editor = editor
        self.submission_status = 20
        self.editor_assignment_datetime = timezone.now()
        self.save()

    def reassign_editor(self, editor):
        """
        Reassign the current project editor with new editor
        """
        self.editor = editor
        self.save()

    def reject(self):
        """
        Reject a project under submission
        """
        self.archive(archive_reason=3)

    def is_resubmittable(self):
        """
        Submit the project for review.
        """
        return (self.submission_status == 30 and self.check_integrity())

    def resubmit(self, author_comments):
        """
        """
        if not self.is_resubmittable():
            raise Exception('ActiveProject is not resubmittable')

        with transaction.atomic():
            self.submission_status = 20
            self.resubmission_datetime = timezone.now()
            self.save()
            # Create a new edit log
            EditLog.objects.create(project=self,
                                   is_resubmission=True,
                                   author_comments=author_comments)

    def reopen_copyedit(self):
        """
        Reopen the project for copyediting
        """
        if self.submission_status == 50:
            self.submission_status = 40
            self.copyedit_completion_datetime = None
            self.save()
            CopyeditLog.objects.create(project=self, is_reedit=True)
            self.authors.all().update(approval_datetime=None)

    def approve_author(self, author):
        """"
        Approve an author. Move the project into the next state if the
        author is the final outstanding one. Return whether the
        process was successful.
        """
        if self.submission_status == 50 and not author.approval_datetime:
            now = timezone.now()
            author.approval_datetime = now
            author.save()
            if self.all_authors_approved():
                self.author_approval_datetime = now
                self.submission_status = 60
                self.save()
            return True

    def all_authors_approved(self):
        """
        Whether all authors have approved the publication
        """
        authors = self.authors.all()
        return len(authors) == len(
            authors.filter(approval_datetime__isnull=False))

    def is_publishable(self):
        """
        Check whether a project may be published
        """
        if self.submission_status == 60 and self.check_integrity(
        ) and self.all_authors_approved():
            return True
        return False

    def clear_files(self):
        """
        Delete the project file directory
        """
        ProjectFiles().rmtree(self.file_root())

    def publish(self, slug=None, make_zip=True, title=None):
        """
        Create a published version of this project and update the
        submission status.

        Parameters
        ----------
        slug : the desired custom slug of the published project.
        make_zip : whether to make a zip of all the files.
        """
        if not self.is_publishable():
            raise Exception('The project is not publishable')

        published_project = PublishedProject(has_wfdb=self.has_wfdb())

        # Direct copy over fields
        for field in [f.name for f in Metadata._meta.fields
                      ] + [f.name for f in SubmissionInfo._meta.fields]:
            setattr(published_project, field, getattr(self, field))

        published_project.slug = slug or self.slug

        # Create project file root if this is first version or the first
        # version with a different access policy

        ProjectFiles().publish_initial(self, published_project)

        try:
            with transaction.atomic():
                # If this is a new version, previous fields need to be updated
                # and slug needs to be carried over
                if self.version_order:
                    previous_published_projects = self.core_project.publishedprojects.all(
                    )

                    slug = previous_published_projects.first().slug
                    title = previous_published_projects.first().title
                    if slug != published_project.slug:
                        raise ValueError({
                            "message":
                            "The published project has different slugs."
                        })

                # Set the slug if specified
                published_project.slug = slug or self.slug
                published_project.title = title or self.title
                published_project.doi = self.doi

                # Change internal links (that point to files within
                # the active project) to point to their new locations
                # in the published project
                published_project.update_internal_links(old_project=self)

                published_project.save()

                # If this is a new version, all version fields have to be updated
                if self.version_order > 0:
                    published_project.set_version_order()

                # Same content, different objects.
                for reference in self.references.all().order_by('id'):
                    published_reference = PublishedReference.objects.create(
                        description=reference.description,
                        project=published_project)

                for publication in self.publications.all():
                    published_publication = PublishedPublication.objects.create(
                        citation=publication.citation,
                        url=publication.url,
                        project=published_project)

                published_project.set_topics(
                    [t.description for t in self.topics.all()])

                for parent_project in self.parent_projects.all():
                    published_project.parent_projects.add(parent_project)

                if self.resource_type.id == 1:
                    languages = self.programming_languages.all()
                    if languages:
                        published_project.programming_languages.add(
                            *list(languages))

                for author in self.authors.all():
                    author_profile = author.user.profile
                    published_author = PublishedAuthor.objects.create(
                        project=published_project,
                        user=author.user,
                        is_submitting=author.is_submitting,
                        is_corresponding=author.is_corresponding,
                        approval_datetime=author.approval_datetime,
                        display_order=author.display_order,
                        first_names=author_profile.first_names,
                        last_name=author_profile.last_name,
                    )

                    affiliations = author.affiliations.all()
                    for affiliation in affiliations:
                        published_affiliation = PublishedAffiliation.objects.create(
                            name=affiliation.name, author=published_author)

                    UploadedDocument.objects.filter(
                        object_id=self.pk,
                        content_type=ContentType.objects.get_for_model(
                            ActiveProject)).update(
                                object_id=published_project.pk,
                                content_type=ContentType.objects.get_for_model(
                                    PublishedProject),
                            )

                    if author.is_corresponding:
                        published_author.corresponding_email = author.corresponding_email.email
                        published_author.save()
                        Contact.objects.create(
                            name=author.get_full_name(),
                            affiliations='; '.join(a.name
                                                   for a in affiliations),
                            email=author.corresponding_email,
                            project=published_project)

                # Move the edit and copyedit logs
                for edit_log in self.edit_logs.all():
                    edit_log.project = published_project
                    edit_log.save()
                for copyedit_log in self.copyedit_logs.all():
                    copyedit_log.project = published_project
                    copyedit_log.save()

                published_project.required_trainings.set(
                    self.required_trainings.all())

                # Set files read only and make zip file if requested
                move_files_as_readonly(
                    published_project.id,
                    self.file_root(),
                    published_project.file_root(),
                    make_zip,
                    verbose_name='Read Only Files - {}'.format(
                        published_project),
                )

                # Remove the ActiveProject
                self.delete()

        except BaseException:
            ProjectFiles().publish_rollback(self, published_project)

            raise

        ProjectFiles().publish_complete(self, published_project)

        return published_project
Example #14
0
 def form(self, form):
     if form.instance.user == self.request.user:
         return super(TweetCreateView, self).form_valid(form)
     else:
         form._errors[forms.forms.NON_FIELD_ERRORS] = ErrorList(["This user is not allowed to change this data. Login to continue."])
         return self.form_invalid(form)
Example #15
0
    def clean(self, value):
        cleaned_data = []
        errors = {}
        non_block_errors = ErrorList()
        for i, child in enumerate(value):  # child is a StreamChild instance
            try:
                cleaned_data.append((child.block.name,
                                     child.block.clean(child.value), child.id))
            except ValidationError as e:
                errors[i] = ErrorList([e])

        if self.meta.min_num is not None and self.meta.min_num > len(value):
            non_block_errors.append(
                ValidationError(
                    _("The minimum number of items is %d") %
                    self.meta.min_num))
        elif self.required and len(value) == 0:
            non_block_errors.append(
                ValidationError(_("This field is required.")))

        if self.meta.max_num is not None and self.meta.max_num < len(value):
            non_block_errors.append(
                ValidationError(
                    _("The maximum number of items is %d") %
                    self.meta.max_num))

        if self.meta.block_counts:
            block_counts = defaultdict(int)
            for item in value:
                block_counts[item.block_type] += 1

            for block_name, min_max in self.meta.block_counts.items():
                block = self.child_blocks[block_name]
                max_num = min_max.get("max_num", None)
                min_num = min_max.get("min_num", None)
                block_count = block_counts[block_name]
                if min_num is not None and min_num > block_count:
                    non_block_errors.append(
                        ValidationError("{}: {}".format(
                            block.label,
                            _("The minimum number of items is %d") % min_num,
                        )))
                if max_num is not None and max_num < block_count:
                    non_block_errors.append(
                        ValidationError("{}: {}".format(
                            block.label,
                            _("The maximum number of items is %d") % max_num,
                        )))

        if errors or non_block_errors:
            # The message here is arbitrary - outputting error messages is delegated to the child blocks,
            # which only involves the 'params' list
            raise StreamBlockValidationError(block_errors=errors,
                                             non_block_errors=non_block_errors)

        return StreamValue(self, cleaned_data)
Example #16
0
    def form_valid(self, form):

        workshop = Workshop.objects.get(
            id=self.kwargs.get('workshop_id', None))

        try:
            application = WorkshopRegistration.objects.filter(
                workshop=workshop, email=form.cleaned_data.get('email'))
        except WorkshopRegistration.DoesNotExist:
            application = None

        if application.exists():
            form._errors[forms.forms.NON_FIELD_ERRORS] = ErrorList(
                [u'You are already registered'])
            return self.form_invalid(form)

        valid_form = super(WorkshopRegisterFormView, self).form_valid(form)

        # generate urls
        # list_url = ''.join(['http://', get_current_site(self.request).domain,
        #                     reverse('workshop_list', kwargs={'workshop_id': workshop.id})])
        #
        # # mail data
        # subject = 'Registration for ' + workshop.name + ' - ' + form.cleaned_data.get('name')
        # content = form.cleaned_data.get('name') + ' registered for ' + workshop.name + ' at ' + \
        #           str(datetime.datetime.now()) + '. \n\nPlease visit ' + list_url + ' for more details.'
        #
        # to_address_list = list(User.objects.filter(is_superuser=True).values_list('email', flat=True))

        # sent mail when application is submitted
        # send_mail(subject, content, '*****@*****.**', to_address_list, fail_silently=False)

        mail_content = "Hi " + form.cleaned_data.get('name') + ", \n\n" + \
                       "Great to know that you are interested in '" + workshop.name + "' workshop conducted by" \
                                                                                      "FOSS@Amrita. We got your application and it's being processed. " + \
                       "We will get back to you once your payment process is is complete.\n\n" \
                       "Please pay Rs" + str(workshop.price) + " at FOSS club, ground floor lab after 4:30pm on or " + \
                       "before " + str(workshop.start_date_time.date()) + " or contact us at " + \
                       str(workshop.contact_info) + " during breaks. \n\nNote: Payment has to completed " + \
                       "before the last date. You should show the confirmation e-mail to attend the workshop." + \
                       " \n\nThank you, \n\nFOSS@Amrita"

        to_address_list = [
            '*****@*****.**',
            form.cleaned_data.get('email')
        ]
        email = EmailMessage(
            workshop.name + ' registartion',
            mail_content,
            '*****@*****.**',
            to_address_list,
            join_application_mail_list,
            reply_to=join_application_reply_to,
            headers={'Message-ID': 'foss@amrita'},
        )
        email.send(fail_silently=False)
        to_address_list.remove(form.cleaned_data.get('email'))

        self.object.workshop = workshop
        self.object.save()

        return valid_form
Example #17
0
	def get_error_list(self):
		errors = ErrorList()
		if self.form_obj.is_bound:
			errors.extend(self.form_obj.errors.values())
		return errors
Example #18
0
 def form_valid(self, form):
     if self.request.user.is_authenticated():
         return super(FormUserMixin, self).form_valid(form)
     else:
         form.errors[forms.forms.NON_FIELD_ERRORS] = ErrorList(['U cannot modify this data need be logged'])
         return self.form_invalid(form)
Example #19
0
 def test_error_list_html_safe(self):
     e = ErrorList(["Invalid username."])
     self.assertTrue(hasattr(ErrorList, "__html__"))
     self.assertEqual(str(e), e.__html__())
Example #20
0
 def form_valid(self, form):
     if form.instance.user == self.request.user:
         return super(UserOwnerMixin, self).form_valid(form)
     else:
         form._errors[forms.forms.NON_FIELD_ERRORS] = ErrorList(["This user is not allowed to change this data."])
         return self.form_invalid(form)
Example #21
0
def document_metadata(
        request,
        docid,
        template='documents/document_metadata.html',
        ajax=True):

    document = None
    try:
        document = _resolve_document(
            request,
            docid,
            'base.change_resourcebase_metadata',
            _PERMISSION_MSG_METADATA)

    except Http404:
        return HttpResponse(
            loader.render_to_string(
                '404.html', context={
                }, request=request), status=404)

    except PermissionDenied:
        return HttpResponse(
            loader.render_to_string(
                '401.html', context={
                    'error_message': _("You are not allowed to edit this document.")}, request=request), status=403)

    if document is None:
        return HttpResponse(
            'An unknown error has occured.',
            content_type="text/plain",
            status=401
        )

    else:
        poc = document.poc
        metadata_author = document.metadata_author
        topic_category = document.category

        if request.method == "POST":
            document_form = DocumentForm(
                request.POST,
                instance=document,
                prefix="resource")
            category_form = CategoryForm(request.POST, prefix="category_choice_field", initial=int(
                request.POST["category_choice_field"]) if "category_choice_field" in request.POST and
                request.POST["category_choice_field"] else None)
            tkeywords_form = TKeywordForm(request.POST)
        else:
            document_form = DocumentForm(instance=document, prefix="resource")
            category_form = CategoryForm(
                prefix="category_choice_field",
                initial=topic_category.id if topic_category else None)

            # Keywords from THESAURUS management
            doc_tkeywords = document.tkeywords.all()
            tkeywords_list = ''
            lang = 'en'  # TODO: use user's language
            if doc_tkeywords and len(doc_tkeywords) > 0:
                tkeywords_ids = doc_tkeywords.values_list('id', flat=True)
                if hasattr(settings, 'THESAURUS') and settings.THESAURUS:
                    el = settings.THESAURUS
                    thesaurus_name = el['name']
                    try:
                        t = Thesaurus.objects.get(identifier=thesaurus_name)
                        for tk in t.thesaurus.filter(pk__in=tkeywords_ids):
                            tkl = tk.keyword.filter(lang=lang)
                            if len(tkl) > 0:
                                tkl_ids = ",".join(
                                    map(str, tkl.values_list('id', flat=True)))
                                tkeywords_list += "," + \
                                    tkl_ids if len(
                                        tkeywords_list) > 0 else tkl_ids
                    except BaseException:
                        tb = traceback.format_exc()
                        logger.error(tb)

            tkeywords_form = TKeywordForm(instance=document)

        if request.method == "POST" and document_form.is_valid(
        ) and category_form.is_valid():
            new_poc = document_form.cleaned_data['poc']
            new_author = document_form.cleaned_data['metadata_author']
            new_keywords = document_form.cleaned_data['keywords']
            new_regions = document_form.cleaned_data['regions']

            new_category = None
            if category_form and 'category_choice_field' in category_form.cleaned_data and\
            category_form.cleaned_data['category_choice_field']:
                new_category = TopicCategory.objects.get(
                    id=int(category_form.cleaned_data['category_choice_field']))

            if new_poc is None:
                if poc is None:
                    poc_form = ProfileForm(
                        request.POST,
                        prefix="poc",
                        instance=poc)
                else:
                    poc_form = ProfileForm(request.POST, prefix="poc")
                if poc_form.is_valid():
                    if len(poc_form.cleaned_data['profile']) == 0:
                        # FIXME use form.add_error in django > 1.7
                        errors = poc_form._errors.setdefault(
                            'profile', ErrorList())
                        errors.append(
                            _('You must set a point of contact for this resource'))
                        poc = None
                if poc_form.has_changed and poc_form.is_valid():
                    new_poc = poc_form.save()

            if new_author is None:
                if metadata_author is None:
                    author_form = ProfileForm(request.POST, prefix="author",
                                              instance=metadata_author)
                else:
                    author_form = ProfileForm(request.POST, prefix="author")
                if author_form.is_valid():
                    if len(author_form.cleaned_data['profile']) == 0:
                        # FIXME use form.add_error in django > 1.7
                        errors = author_form._errors.setdefault(
                            'profile', ErrorList())
                        errors.append(
                            _('You must set an author for this resource'))
                        metadata_author = None
                if author_form.has_changed and author_form.is_valid():
                    new_author = author_form.save()

            document = document_form.instance
            if new_poc is not None and new_author is not None:
                document.poc = new_poc
                document.metadata_author = new_author
            document.keywords.clear()
            document.keywords.add(*new_keywords)
            document.regions.clear()
            document.regions.add(*new_regions)
            document.category = new_category
            document.save()
            document_form.save_many2many()

            register_event(request, EventType.EVENT_CHANGE_METADATA, document)
            if not ajax:
                return HttpResponseRedirect(
                    reverse(
                        'document_detail',
                        args=(
                            document.id,
                        )))

            message = document.id

            try:
                # Keywords from THESAURUS management
                # Rewritten to work with updated autocomplete
                if not tkeywords_form.is_valid():
                    return HttpResponse(json.dumps({'message': "Invalid thesaurus keywords"}, status_code=400))

                tkeywords_data = tkeywords_form.cleaned_data['tkeywords']

                thesaurus_setting = getattr(settings, 'THESAURUS', None)
                if thesaurus_setting:
                    tkeywords_data = tkeywords_data.filter(
                        thesaurus__identifier=thesaurus_setting['name']
                    )
                    document.tkeywords = tkeywords_data
            except BaseException:
                tb = traceback.format_exc()
                logger.error(tb)

            return HttpResponse(json.dumps({'message': message}))

        # - POST Request Ends here -

        # Request.GET
        if poc is not None:
            document_form.fields['poc'].initial = poc.id
            poc_form = ProfileForm(prefix="poc")
            poc_form.hidden = True

        if metadata_author is not None:
            document_form.fields['metadata_author'].initial = metadata_author.id
            author_form = ProfileForm(prefix="author")
            author_form.hidden = True

        metadata_author_groups = []
        if request.user.is_superuser or request.user.is_staff:
            metadata_author_groups = GroupProfile.objects.all()
        else:
            try:
                all_metadata_author_groups = chain(
                    request.user.group_list_all(),
                    GroupProfile.objects.exclude(
                        access="private").exclude(access="public-invite"))
            except BaseException:
                all_metadata_author_groups = GroupProfile.objects.exclude(
                    access="private").exclude(access="public-invite")
            [metadata_author_groups.append(item) for item in all_metadata_author_groups
                if item not in metadata_author_groups]

        if settings.ADMIN_MODERATE_UPLOADS:
            if not request.user.is_superuser:
                document_form.fields['is_published'].widget.attrs.update(
                    {'disabled': 'true'})

                can_change_metadata = request.user.has_perm(
                    'change_resourcebase_metadata',
                    document.get_self_resource())
                try:
                    is_manager = request.user.groupmember_set.all().filter(role='manager').exists()
                except BaseException:
                    is_manager = False
                if not is_manager or not can_change_metadata:
                    document_form.fields['is_approved'].widget.attrs.update(
                        {'disabled': 'true'})

        register_event(request, EventType.EVENT_VIEW_METADATA, document)
        return render(request, template, context={
            "resource": document,
            "document": document,
            "document_form": document_form,
            "poc_form": poc_form,
            "author_form": author_form,
            "category_form": category_form,
            "tkeywords_form": tkeywords_form,
            "metadata_author_groups": metadata_author_groups,
            "TOPICCATEGORY_MANDATORY": getattr(settings, 'TOPICCATEGORY_MANDATORY', False),
            "GROUP_MANDATORY_RESOURCES": getattr(settings, 'GROUP_MANDATORY_RESOURCES', False),
        })
Example #22
0
def document_metadata(request,
                      docid,
                      template='documents/document_metadata.html',
                      ajax=True):
    document = None
    try:
        document = _resolve_document(request, docid,
                                     'base.change_resourcebase_metadata',
                                     _PERMISSION_MSG_METADATA)
    except PermissionDenied:
        return HttpResponse(_("Not allowed"), status=403)
    except Exception:
        raise Http404(_("Not found"))
    if not document:
        raise Http404(_("Not found"))

    # Add metadata_author or poc if missing
    document.add_missing_metadata_author_or_poc()
    poc = document.poc
    metadata_author = document.metadata_author
    topic_category = document.category
    current_keywords = [keyword.name for keyword in document.keywords.all()]

    if request.method == "POST":
        document_form = DocumentForm(request.POST,
                                     instance=document,
                                     prefix="resource",
                                     user=request.user)
        category_form = CategoryForm(
            request.POST,
            prefix="category_choice_field",
            initial=int(request.POST["category_choice_field"])
            if "category_choice_field" in request.POST
            and request.POST["category_choice_field"] else None)

        if hasattr(settings, 'THESAURUS'):
            tkeywords_form = TKeywordForm(request.POST)
        else:
            tkeywords_form = ThesaurusAvailableForm(request.POST,
                                                    prefix='tkeywords')

    else:
        document_form = DocumentForm(instance=document,
                                     prefix="resource",
                                     user=request.user)
        document_form.disable_keywords_widget_for_non_superuser(request.user)
        category_form = CategoryForm(
            prefix="category_choice_field",
            initial=topic_category.id if topic_category else None)

        # Keywords from THESAURUS management
        doc_tkeywords = document.tkeywords.all()
        if hasattr(settings, 'THESAURUS') and settings.THESAURUS:
            warnings.warn(
                'The settings for Thesaurus has been moved to Model, \
            this feature will be removed in next releases', DeprecationWarning)
            tkeywords_list = ''
            lang = 'en'  # TODO: use user's language
            if doc_tkeywords and len(doc_tkeywords) > 0:
                tkeywords_ids = doc_tkeywords.values_list('id', flat=True)
                if hasattr(settings, 'THESAURUS') and settings.THESAURUS:
                    el = settings.THESAURUS
                    thesaurus_name = el['name']
                    try:
                        t = Thesaurus.objects.get(identifier=thesaurus_name)
                        for tk in t.thesaurus.filter(pk__in=tkeywords_ids):
                            tkl = tk.keyword.filter(lang=lang)
                            if len(tkl) > 0:
                                tkl_ids = ",".join(
                                    map(str, tkl.values_list('id', flat=True)))
                                tkeywords_list += f",{tkl_ids}" if len(
                                    tkeywords_list) > 0 else tkl_ids
                    except Exception:
                        tb = traceback.format_exc()
                        logger.error(tb)

            tkeywords_form = TKeywordForm(instance=document)
        else:
            tkeywords_form = ThesaurusAvailableForm(prefix='tkeywords')
            #  set initial values for thesaurus form
            for tid in tkeywords_form.fields:
                values = []
                values = [
                    keyword.id for keyword in doc_tkeywords
                    if int(tid) == keyword.thesaurus.id
                ]
                tkeywords_form.fields[tid].initial = values

    if request.method == "POST" and document_form.is_valid(
    ) and category_form.is_valid() and tkeywords_form.is_valid():
        new_poc = document_form.cleaned_data['poc']
        new_author = document_form.cleaned_data['metadata_author']
        new_keywords = current_keywords if request.keyword_readonly else document_form.cleaned_data[
            'keywords']
        new_regions = document_form.cleaned_data['regions']

        new_category = None
        if category_form and 'category_choice_field' in category_form.cleaned_data and \
                category_form.cleaned_data['category_choice_field']:
            new_category = TopicCategory.objects.get(
                id=int(category_form.cleaned_data['category_choice_field']))

        if new_poc is None:
            if poc is None:
                poc_form = ProfileForm(request.POST,
                                       prefix="poc",
                                       instance=poc)
            else:
                poc_form = ProfileForm(request.POST, prefix="poc")
            if poc_form.is_valid():
                if len(poc_form.cleaned_data['profile']) == 0:
                    # FIXME use form.add_error in django > 1.7
                    errors = poc_form._errors.setdefault(
                        'profile', ErrorList())
                    errors.append(
                        _('You must set a point of contact for this resource'))
            if poc_form.has_changed and poc_form.is_valid():
                new_poc = poc_form.save()

        if new_author is None:
            if metadata_author is None:
                author_form = ProfileForm(request.POST,
                                          prefix="author",
                                          instance=metadata_author)
            else:
                author_form = ProfileForm(request.POST, prefix="author")
            if author_form.is_valid():
                if len(author_form.cleaned_data['profile']) == 0:
                    # FIXME use form.add_error in django > 1.7
                    errors = author_form._errors.setdefault(
                        'profile', ErrorList())
                    errors.append(
                        _('You must set an author for this resource'))
            if author_form.has_changed and author_form.is_valid():
                new_author = author_form.save()

        document = document_form.instance
        resource_manager.update(
            document.uuid,
            instance=document,
            keywords=new_keywords,
            regions=new_regions,
            vals=dict(poc=new_poc or document.poc,
                      metadata_author=new_author or document.metadata_author,
                      category=new_category),
            notify=True,
            extra_metadata=json.loads(
                document_form.cleaned_data['extra_metadata']))

        resource_manager.set_thumbnail(document.uuid,
                                       instance=document,
                                       overwrite=False)
        document_form.save_many2many()

        register_event(request, EventType.EVENT_CHANGE_METADATA, document)
        url = hookset.document_detail_url(document)
        if not ajax:
            return HttpResponseRedirect(url)
        message = document.id

        try:
            # Keywords from THESAURUS management
            # Rewritten to work with updated autocomplete
            if not tkeywords_form.is_valid():
                return HttpResponse(
                    json.dumps({'message': "Invalid thesaurus keywords"},
                               status_code=400))

            thesaurus_setting = getattr(settings, 'THESAURUS', None)
            if thesaurus_setting:
                tkeywords_data = tkeywords_form.cleaned_data['tkeywords']
                tkeywords_data = tkeywords_data.filter(
                    thesaurus__identifier=thesaurus_setting['name'])
                document.tkeywords.set(tkeywords_data)
            elif Thesaurus.objects.all().exists():
                fields = tkeywords_form.cleaned_data
                document.tkeywords.set(tkeywords_form.cleanx(fields))

        except Exception:
            tb = traceback.format_exc()
            logger.error(tb)

        return HttpResponse(json.dumps({'message': message}))
    elif request.method == "POST" and (not document_form.is_valid()
                                       or not category_form.is_valid()
                                       or not tkeywords_form.is_valid()):
        errors_list = {
            **document_form.errors.as_data(),
            **category_form.errors.as_data(),
            **tkeywords_form.errors.as_data()
        }
        logger.error(f"GeoApp Metadata form is not valid: {errors_list}")
        out = {
            'success': False,
            "errors":
            [f"{x}: {y[0].messages[0]}" for x, y in errors_list.items()]
        }
        return HttpResponse(json.dumps(out),
                            content_type='application/json',
                            status=400)
    # - POST Request Ends here -

    # Request.GET
    if poc is not None:
        document_form.fields['poc'].initial = poc.id
        poc_form = ProfileForm(prefix="poc")
        poc_form.hidden = True

    if metadata_author is not None:
        document_form.fields['metadata_author'].initial = metadata_author.id
        author_form = ProfileForm(prefix="author")
        author_form.hidden = True

    metadata_author_groups = get_user_visible_groups(request.user)

    if settings.ADMIN_MODERATE_UPLOADS:
        if not request.user.is_superuser:
            can_change_metadata = request.user.has_perm(
                'change_resourcebase_metadata', document.get_self_resource())
            try:
                is_manager = request.user.groupmember_set.all().filter(
                    role='manager').exists()
            except Exception:
                is_manager = False
            if not is_manager or not can_change_metadata:
                if settings.RESOURCE_PUBLISHING:
                    document_form.fields['is_published'].widget.attrs.update(
                        {'disabled': 'true'})
                document_form.fields['is_approved'].widget.attrs.update(
                    {'disabled': 'true'})

    register_event(request, EventType.EVENT_VIEW_METADATA, document)
    return render(
        request,
        template,
        context={
            "resource":
            document,
            "document":
            document,
            "document_form":
            document_form,
            "poc_form":
            poc_form,
            "author_form":
            author_form,
            "category_form":
            category_form,
            "tkeywords_form":
            tkeywords_form,
            "metadata_author_groups":
            metadata_author_groups,
            "TOPICCATEGORY_MANDATORY":
            getattr(settings, 'TOPICCATEGORY_MANDATORY', False),
            "GROUP_MANDATORY_RESOURCES":
            getattr(settings, 'GROUP_MANDATORY_RESOURCES', False),
            "UI_MANDATORY_FIELDS":
            list(
                set(getattr(settings, 'UI_DEFAULT_MANDATORY_FIELDS', []))
                | set(getattr(settings, 'UI_REQUIRED_FIELDS', [])))
        })
Example #23
0
    def bulk_view(self, request, form_url='', extra_context=None):
        to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR))
        if to_field and not self.to_field_allowed(request, to_field):
            raise DisallowedModelAdminToField("The field %s cannot be referenced." % to_field)

        model = self.model
        opts = model._meta

        continue_requested = request.POST.get('_continue', request.GET.get('_continue'))
        force_continue = False
        inline = self.get_bulk_inline(request)
        formset_class = inline.get_formset(request)
        formset_params = {}
        prefix = formset_class.get_default_prefix()
        queryset = inline.get_queryset(request)

        if not self.has_add_permission(request):
            formset_class.max_num = 0

        if request.method == 'GET':
            if 'pks' in request.GET and self.has_change_permission(request):
                pks = [opts.pk.to_python(pk) for pk in request.GET.get('pks').split(',')]
                queryset = queryset.filter(pk__in=pks)
            else:
                queryset = queryset.none()

        elif request.method == 'POST':
            management_form = ManagementForm(request.POST, prefix=prefix)

            if not management_form.is_valid():
                raise ValidationError(
                    _('ManagementForm data is missing or has been tampered with'),
                    code='missing_management_form',
                )

            if not self.has_add_permission(request) and management_form.cleaned_data[INITIAL_FORM_COUNT] < management_form.cleaned_data[TOTAL_FORM_COUNT]:
                raise PermissionDenied

            if not self.has_change_permission(request) and management_form.cleaned_data[INITIAL_FORM_COUNT] > 0:
                raise PermissionDenied

            queryset = self.transform_queryset(request, queryset, management_form, prefix)

            post, files, force_continue = self.transform_post_and_files(request, prefix)
            formset_params.update({
                'data': post,
                'files': files,
            })

        formset_params['queryset'] = queryset

        formset = formset_class(**formset_params)

        if request.method == 'POST':
            if formset.is_valid():
                self.save_formset(request, form=None, formset=formset, change=False)

                if continue_requested or force_continue:
                    # The implementation of ModelAdmin redirects to the change view if valid and continue was requested
                    # The change view then reads the edited model again from database
                    # In our case, we can't make a redirect as we would loose the information which models should be edited
                    # Thus, we create a new formset with the edited models and continue as this would have been a usual GET request

                    if self.has_change_permission(request):
                        queryset = _ListQueryset(queryset)
                        queryset.extend(formset.new_objects)
                    else:
                        queryset = _ListQueryset()

                    formset_params.update({
                        'data': None,
                        'files': None,
                        'queryset': queryset,
                    })

                    formset = formset_class(**formset_params)

                    msg = _('The %s were bulk added successfully. You may edit them again below.') % (force_text(opts.verbose_name_plural),)
                    self.message_user(request, msg, messages.SUCCESS)

                else:
                    return self.response_bulk(request, formset)

        media = self.media

        inline_formsets = self.get_inline_formsets(request, [formset], [inline], obj=None)
        for inline_formset in inline_formsets:
            media = media + inline_formset.media

        errors = ErrorList()

        if formset.is_bound:
            errors.extend(formset.non_form_errors())
            for formset_errors in formset.errors:
                errors.extend(list(six.itervalues(formset_errors)))

        context = dict(
            self.admin_site.each_context(request) if django.VERSION >= (1, 8) else self.admin_site.each_context(),
            bulk=True,
            bulk_formset_prefix=prefix,
            bulk_upload_fields=self.get_bulk_upload_fields(request),
            title=_('Bulk add %s') % force_text(opts.verbose_name_plural),
            is_popup=(IS_POPUP_VAR in request.POST or
                      IS_POPUP_VAR in request.GET),
            to_field=to_field,
            media=media,
            inline_admin_formsets=inline_formsets,
            errors=errors,
            preserved_filters=self.get_preserved_filters(request),
        )

        context.update(extra_context or {})

        return self.render_change_form(request, context, add=True, change=False, obj=None, form_url=form_url)
Example #24
0
    def check_integrity(self):
        """
        Run integrity tests on metadata fields and return whether the
        project passes the checks
        """
        self.integrity_errors = ErrorList()

        # Invitations
        for invitation in self.authorinvitations.filter(is_active=True):
            self.integrity_errors.append(
                'Outstanding author invitation to {0}'.format(
                    invitation.email))

        # Storage requests
        for storage_request in self.storagerequests.filter(is_active=True):
            self.integrity_errors.append('Outstanding storage request')

        # Authors
        for author in self.authors.all().order_by('display_order'):
            if not author.get_full_name():
                self.integrity_errors.append(
                    'Author {0} has not fill in name'.format(
                        author.user.username))
            if not author.affiliations.all():
                self.integrity_errors.append(
                    'Author {0} has not filled in affiliations'.format(
                        author.user.username))

        # Metadata
        for attr in ActiveProject.REQUIRED_FIELDS[self.resource_type.id]:
            value = getattr(self, attr)
            text = unescape(strip_tags(str(value)))
            if value is None or not text or text.isspace():
                l = self.LABELS[
                    self.resource_type.id][attr] if attr in self.LABELS[
                        self.resource_type.id] else attr.title().replace(
                            '_', ' ')
                self.integrity_errors.append(
                    'Missing required field: {0}'.format(l))

        # Ethics
        if not self.ethics_statement:
            self.integrity_errors.append(
                'Missing required field: Ethics Statement')

        published_projects = self.core_project.publishedprojects.all()
        if published_projects:
            published_versions = [p.version for p in published_projects]
            if self.version in published_versions:
                self.integrity_errors.append(
                    'The version matches a previously published version.')
                self.version_clash = True
            else:
                self.version_clash = False

        if self.access_policy != AccessPolicy.OPEN and self.dua is None:
            self.integrity_errors.append(
                'You have to choose one of the data use agreements.')

        if self.integrity_errors:
            return False
        else:
            return True
Example #25
0
    def clean(self, value):
        cleaned_data = []
        errors = {}
        non_block_errors = ErrorList()
        for i, child in enumerate(value):  # child is a StreamChild instance
            try:
                cleaned_data.append(
                    (child.block.name, child.block.clean(child.value), child.id)
                )
            except ValidationError as e:
                errors[i] = ErrorList([e])

        if self.meta.min_num is not None and self.meta.min_num > len(value):
            non_block_errors.append(ValidationError(
                _('The minimum number of items is %d') % self.meta.min_num
            ))
        elif self.required and len(value) == 0:
            non_block_errors.append(ValidationError(_('This field is required.')))

        if self.meta.max_num is not None and self.meta.max_num < len(value):
            non_block_errors.append(ValidationError(
                _('The maximum number of items is %d') % self.meta.max_num
            ))

        if self.meta.block_counts:
            block_counts = collections.defaultdict(int)
            for item in value:
                block_counts[item.block_type] += 1

            for block_name, min_max in self.meta.block_counts.items():
                block = self.child_blocks[block_name]
                max_num = min_max.get('max_num', None)
                min_num = min_max.get('min_num', None)
                block_count = block_counts[block_name]
                if min_num is not None and min_num > block_count:
                    non_block_errors.append(ValidationError(
                        '{}: {}'.format(block.label, _('The minimum number of items is %d') % min_num)
                    ))
                if max_num is not None and max_num < block_count:
                    non_block_errors.append(ValidationError(
                        '{}: {}'.format(block.label, _('The maximum number of items is %d') % max_num)
                    ))

        if errors or non_block_errors:
            # The message here is arbitrary - outputting error messages is delegated to the child blocks,
            # which only involves the 'params' list
            raise StreamBlockValidationError(block_errors=errors, non_block_errors=non_block_errors)

        return StreamValue(self, cleaned_data)
Example #26
0
    def clean(self):
        """Verify fields"""

        cleaned_data = self.cleaned_data

        name = cleaned_data.get("name")
        action = cleaned_data.get("action")
        parent = cleaned_data.get("parent")
        pf = cleaned_data.get("passphrase")
        pf_v = cleaned_data.get("passphrase_verify")
        p_pf = cleaned_data.get("parent_passphrase")
        extension = cleaned_data.get("extension")
        crl_dpoints = cleaned_data.get("crl_dpoints")

        enc_p_pf = None

        if name in PKI_CA_NAME_BLACKLIST:
            self._errors["name"] = ErrorList(
                ['Name "%s" is blacklisted!' % name])
            return cleaned_data

        if action in ("create", "renew"):
            if action == "create":
                if not pf_v or pf != pf_v:
                    self.errors["passphrase_verify"] = ErrorList(
                        ["Passphrase mismtach!"])

                # Verify that we're not creating a certificate that already exists
                if name and os.path.isdir(os.path.join(PKI_DIR, name)):
                    self._errors["name"] = ErrorList(
                        ['Name "%s" is already in use!' % name])

            # Take care that parent is active when action is revoke
            if action == "renew":
                ca = CertificateAuthority.objects.get(name="%s" % name)

                # Prevent renewal when parent is disabled
                if ca.parent is not None and ca.parent.active is not True:
                    self._errors["action"] = ErrorList([
                        'Cannot renew CA certificate when parent "%s" isn\'t active!'
                        % ca.parent.name
                    ])
                    return cleaned_data

                # Compare passphrase
                if not pf or (ca.passphrase != md5(pf).hexdigest()):
                    self._errors["passphrase"] = ErrorList([
                        'Passphrase is wrong. Enter correct passphrase for CA "%s"'
                        % cleaned_data.get("common_name")
                    ])

            if parent:
                ca = CertificateAuthority.objects.get(name="%s" % parent.name)
                if p_pf:
                    enc_p_pf = md5(p_pf).hexdigest()

                # Check if parent allows sub CA
                if ca.is_edge_ca():
                    self._errors["parent"] = ErrorList([
                        "Parent's x509 extension doesn't allow a sub CA. Only non CA certificates can be created"
                    ])

                # Check parent passphrase if not RootCA
                if ca.passphrase != enc_p_pf:
                    self._errors["parent_passphrase"] = ErrorList([
                        'Passphrase is wrong. Enter correct passphrase for CA "%s"'
                        % parent
                    ])

            # Verify CRL distribution settings
            x509 = get_object_or_404(X509Extension, name=extension)
            if x509.crl_distribution_point and not crl_dpoints:
                self._errors["crl_dpoints"] = ErrorList([
                    'CRL Distribution Points are required by x509 extension "%s"'
                    % extension
                ])
        elif action == "revoke":
            if parent:
                ca = CertificateAuthority.objects.get(name="%s" % parent.name)
                enc_p_pf = md5(
                    cleaned_data.get("parent_passphrase")).hexdigest()

                # Check parent passphrase
                if ca.passphrase != enc_p_pf:
                    self._errors["parent_passphrase"] = ErrorList([
                        'Passphrase is wrong. Enter correct passphrase for CA "%s"'
                        % parent
                    ])
            else:
                self._errors["action"] = ErrorList([
                    "You cannot revoke a self-signed root certificate as there"
                    "s no CA to revoke against. Delete it instead!"
                ])

        return cleaned_data
Example #27
0
    def form_valid(self, form):
        try:
            token = stripe.Token.create(card={
                "number":
                form.cleaned_data['number'],
                "exp_month":
                form.cleaned_data["expiration"].month,
                "exp_year":
                form.cleaned_data["expiration"].year,
                "cvc":
                form.cleaned_data['cvc'],
                'name':
                form.cleaned_data['name'],
            }, )
        except Exception as e:
            errors = form._errors.setdefault("number", ErrorList())
            errors.append(e.message)
            return self.form_invalid(form)

        customer = stripe.Customer.create(
            source=token.id,
            description="Payment for {}".format(self.request.user.username),
        )

        user = self.request.user
        user.stripe_id = customer['id']
        user.default_card = customer['default_source']
        card = customer['sources']['data'][0]
        user.card_type = card['brand']
        user.card_last = card['last4']
        user.card_expiry = '{}/{}'.format(str(card['exp_month']),
                                          str(card['exp_year']))
        user.payment_active = True
        user.save()

        amount = get_price('standard')

        if Coupon.objects.filter(activated_by=user).exists():
            coupon = Coupon.objects.get(activated_by=user)
            if not coupon.duration:
                discount = amount * Coupon.objects.get(
                    activated_by=user).discount / 100
                amount -= discount
            else:
                if coupon.activated_at + datetime.timedelta(
                        days=coupon.duration) > timezone.now():
                    discount = amount * Coupon.objects.get(
                        activated_by=user).discount / 100
                    amount -= discount

        try:
            widget = Widget.objects.get(owner=user)
        except Widget.DoesNotExist:
            token = generate_token()
            widget = Widget.objects.create(owner=user, token=token)
        except Widget.MultipleObjectsReturned:
            widget = Widget.objects.filter(owner=user)[0]
        try:
            payment = UserPayment.objects.create(
                user=user,
                widget=widget,
                amount=amount,
                description="Charge for monthly subscription {}".format(
                    user.email))
            charge = stripe.Charge.create(
                amount=int(amount * 100),
                currency="usd",
                customer=user.stripe_id,
                description="Charge for monthly subscription {}".format(
                    user.email),
            )
            payment.trx_id = charge.id
            payment.status = '2'
            payment.history = charge
            payment.save()

            user.plan = '1'
            user.is_trial = False
            user.paid_at = timezone.now()
            user.save()

            domain = Site.objects.get_current().domain
            url = "https://{}/users/{}/".format(domain, user.username)

            context = {
                'username': user.username,
                'email': user.email,
                'cost': int(payment.amount),
                'url': url,
                'transaction_id': payment.trx_id
            }
            PaymentConfirmNotifyMailer(None).send(context)
        except Exception, e:
            errors = form._errors.setdefault("number", ErrorList())
            errors.append(e.message)
            return self.form_invalid(form)
Example #28
0
    def test_validation_error(self):
        ###################
        # ValidationError #
        ###################

        # Can take a string.
        self.assertHTMLEqual(
            str(ErrorList(ValidationError("There was an error.").messages)),
            '<ul class="errorlist"><li>There was an error.</li></ul>',
        )
        # Can take a Unicode string.
        self.assertHTMLEqual(
            str(ErrorList(ValidationError("Not \u03C0.").messages)),
            '<ul class="errorlist"><li>Not π.</li></ul>',
        )
        # Can take a lazy string.
        self.assertHTMLEqual(
            str(ErrorList(ValidationError(gettext_lazy("Error.")).messages)),
            '<ul class="errorlist"><li>Error.</li></ul>',
        )
        # Can take a list.
        self.assertHTMLEqual(
            str(
                ErrorList(
                    ValidationError(["Error one.", "Error two."]).messages)),
            '<ul class="errorlist"><li>Error one.</li><li>Error two.</li></ul>',
        )
        # Can take a dict.
        self.assertHTMLEqual(
            str(
                ErrorList(
                    sorted(
                        ValidationError({
                            "error_1": "1. Error one.",
                            "error_2": "2. Error two."
                        }).messages))),
            '<ul class="errorlist"><li>1. Error one.</li><li>2. Error two.</li></ul>',
        )
        # Can take a mixture in a list.
        self.assertHTMLEqual(
            str(
                ErrorList(
                    sorted(
                        ValidationError([
                            "1. First error.",
                            "2. Not \u03C0.",
                            gettext_lazy("3. Error."),
                            {
                                "error_1": "4. First dict error.",
                                "error_2": "5. Second dict error.",
                            },
                        ]).messages))),
            '<ul class="errorlist">'
            "<li>1. First error.</li>"
            "<li>2. Not π.</li>"
            "<li>3. Error.</li>"
            "<li>4. First dict error.</li>"
            "<li>5. Second dict error.</li>"
            "</ul>",
        )

        class VeryBadError:
            def __str__(self):
                return "A very bad error."

        # Can take a non-string.
        self.assertHTMLEqual(
            str(ErrorList(ValidationError(VeryBadError()).messages)),
            '<ul class="errorlist"><li>A very bad error.</li></ul>',
        )

        # Escapes non-safe input but not input marked safe.
        example = 'Example of link: <a href="http://www.example.com/">example</a>'
        self.assertHTMLEqual(
            str(ErrorList([example])),
            '<ul class="errorlist"><li>Example of link: '
            "&lt;a href=&quot;http://www.example.com/&quot;&gt;example&lt;/a&gt;"
            "</li></ul>",
        )
        self.assertHTMLEqual(
            str(ErrorList([mark_safe(example)])),
            '<ul class="errorlist"><li>Example of link: '
            '<a href="http://www.example.com/">example</a></li></ul>',
        )
        self.assertHTMLEqual(
            str(ErrorDict({"name": example})),
            '<ul class="errorlist"><li>nameExample of link: '
            "&lt;a href=&quot;http://www.example.com/&quot;&gt;example&lt;/a&gt;"
            "</li></ul>",
        )
        self.assertHTMLEqual(
            str(ErrorDict({"name": mark_safe(example)})),
            '<ul class="errorlist"><li>nameExample of link: '
            '<a href="http://www.example.com/">example</a></li></ul>',
        )
Example #29
0
def document_metadata(request,
                      docid,
                      template='documents/document_metadata.html',
                      ajax=True):
    document = None
    try:
        document = _resolve_document(request, docid,
                                     'base.change_resourcebase_metadata',
                                     _PERMISSION_MSG_METADATA)

    except Http404:
        return HttpResponse(loader.render_to_string('404.html',
                                                    context={},
                                                    request=request),
                            status=404)

    except PermissionDenied:
        return HttpResponse(loader.render_to_string(
            '401.html',
            context={
                'error_message':
                _("You are not allowed to edit this document.")
            },
            request=request),
                            status=403)

    if document is None:
        return HttpResponse('An unknown error has occured.',
                            content_type="text/plain",
                            status=401)

    else:
        poc = document.poc
        metadata_author = document.metadata_author
        topic_category = document.category

        if request.method == "POST":
            document_form = DocumentForm(request.POST,
                                         instance=document,
                                         prefix="resource")
            category_form = CategoryForm(
                request.POST,
                prefix="category_choice_field",
                initial=int(request.POST["category_choice_field"])
                if "category_choice_field" in request.POST else None)
        else:
            document_form = DocumentForm(instance=document, prefix="resource")
            category_form = CategoryForm(
                prefix="category_choice_field",
                initial=topic_category.id if topic_category else None)

        if request.method == "POST" and document_form.is_valid(
        ) and category_form.is_valid():
            new_poc = document_form.cleaned_data['poc']
            new_author = document_form.cleaned_data['metadata_author']
            new_keywords = document_form.cleaned_data['keywords']
            new_regions = document_form.cleaned_data['regions']
            new_category = TopicCategory.objects.get(
                id=category_form.cleaned_data['category_choice_field'])

            if new_poc is None:
                if poc is None:
                    poc_form = ProfileForm(request.POST,
                                           prefix="poc",
                                           instance=poc)
                else:
                    poc_form = ProfileForm(request.POST, prefix="poc")
                if poc_form.is_valid():
                    if len(poc_form.cleaned_data['profile']) == 0:
                        # FIXME use form.add_error in django > 1.7
                        errors = poc_form._errors.setdefault(
                            'profile', ErrorList())
                        errors.append(
                            _('You must set a point of '
                              'contact for this resource'))
                        poc = None
                if poc_form.has_changed and poc_form.is_valid():
                    new_poc = poc_form.save()

            if new_author is None:
                if metadata_author is None:
                    author_form = ProfileForm(request.POST,
                                              prefix="author",
                                              instance=metadata_author)
                else:
                    author_form = ProfileForm(request.POST, prefix="author")
                if author_form.is_valid():
                    if len(author_form.cleaned_data['profile']) == 0:
                        # FIXME use form.add_error in django > 1.7
                        errors = author_form._errors.setdefault(
                            'profile', ErrorList())
                        errors.append(
                            _('You must set an author for this resource'))
                        metadata_author = None
                if author_form.has_changed and author_form.is_valid():
                    new_author = author_form.save()

            the_document = document_form.instance
            if new_poc is not None and new_author is not None:
                the_document.poc = new_poc
                the_document.metadata_author = new_author
            if new_keywords:
                the_document.keywords.clear()
                the_document.keywords.add(*new_keywords)
            if new_regions:
                the_document.regions.clear()
                the_document.regions.add(*new_regions)
            the_document.save()
            document_form.save_many2many()
            Document.objects.filter(id=the_document.id).update(
                category=new_category)

            # Update taxon links
            doc = Document.objects.get(id=the_document.id)
            taxon_links = request.POST.get('taxon-links', None)
            old_taxon_links = Taxon.objects.filter(
                documents__id=the_document.id)
            for taxon_link in old_taxon_links:
                taxon_link.documents.remove(doc)
            if taxon_links:
                taxon_links = taxon_links.split(',')
                for taxon_link in taxon_links:
                    try:
                        taxon = Taxon.objects.get(id=taxon_link)
                        taxon.documents.add(doc)
                        taxon.save()
                    except Taxon.DoesNotExist as e:  # noqa
                        pass

            if getattr(settings, 'SLACK_ENABLED', False):
                try:
                    from geonode.contrib.slack.utils import \
                        build_slack_message_document, send_slack_messages
                    send_slack_messages(
                        build_slack_message_document("document_edit",
                                                     the_document))
                except BaseException:
                    print("Could not send slack "
                          "message for modified document.")

            if not ajax:
                return HttpResponseRedirect(
                    reverse('document_detail', args=(document.id, )))

            message = document.id

            return HttpResponse(json.dumps({'message': message}))

        # - POST Request Ends here -

        # Request.GET
        if poc is not None:
            document_form.fields['poc'].initial = poc.id
            poc_form = ProfileForm(prefix="poc")
            poc_form.hidden = True

        if metadata_author is not None:
            document_form.fields[
                'metadata_author'].initial = metadata_author.id
            author_form = ProfileForm(prefix="author")
            author_form.hidden = True

        metadata_author_groups = []
        if request.user.is_superuser or request.user.is_staff:
            metadata_author_groups = GroupProfile.objects.all()
        else:
            try:
                all_metadata_author_groups = chain(
                    request.user.group_list_all(),
                    GroupProfile.objects.exclude(access="private").exclude(
                        access="public-invite"))
            except BaseException:
                all_metadata_author_groups = GroupProfile.objects.exclude(
                    access="private").exclude(access="public-invite")
            [
                metadata_author_groups.append(item)
                for item in all_metadata_author_groups
                if item not in metadata_author_groups
            ]

        if settings.ADMIN_MODERATE_UPLOADS:
            if not request.user.is_superuser:
                document_form.fields['is_published'].widget.attrs.update(
                    {'disabled': 'true'})

                can_change_metadata = request.user.has_perm(
                    'change_resourcebase_metadata',
                    document.get_self_resource())
                try:
                    is_manager = request.user.groupmember_set.all().filter(
                        role='manager').exists()
                except BaseException:
                    is_manager = False
                if not is_manager or not can_change_metadata:
                    document_form.fields['is_approved'].widget.attrs.update(
                        {'disabled': 'true'})

        return render(request,
                      template,
                      context={
                          "resource":
                          document,
                          "document":
                          document,
                          "document_form":
                          document_form,
                          "poc_form":
                          poc_form,
                          "author_form":
                          author_form,
                          "category_form":
                          category_form,
                          "metadata_author_groups":
                          metadata_author_groups,
                          "GROUP_MANDATORY_RESOURCES":
                          getattr(settings, 'GROUP_MANDATORY_RESOURCES',
                                  False),
                      })
def hidden_field_errors(form):
    hidden_field_errors = ErrorList()
    for field in form.hidden_fields():
        hidden_field_errors.extend(field.errors)
    return hidden_field_errors
Example #31
0
def _show_components_student(request, course_slug, activity_slug, userid=None, template="dashboard_student.html", staff=False):
    """
    Show all the component submission history of this activity
    """
    if userid == None:
        userid = request.user.username
    course = get_object_or_404(CourseOffering, slug=course_slug)
    activity = get_object_or_404(course.activity_set,slug=activity_slug, deleted=False)
    student = get_object_or_404(Person, find_userid_or_emplid(userid))
    cansubmit = True

    submission, submitted_components = get_current_submission(student, activity, include_deleted=staff)
    if len(submitted_components) == 0:
        return NotFoundResponse(request)

    if submission and activity.due_date and activity.due_date < submission.created_at:
        late = submission.created_at - activity.due_date
    else:
        late = 0
    
    if activity.group:
        gm = GroupMember.objects.filter(student__person=student, activity=activity, confirmed=True)
        if gm:
            group = gm[0].group
            member = gm[0].student
        else:
            group = None
            #cansubmit = False
            #messages.add_message(request, messages.INFO, "This is a group submission. You cannot submit since you aren't in a group.")
    else:
        group = None

    # activity should be submitable
    cansubmit = cansubmit and activity.submitable()

    if not cansubmit:
        messages.add_message(request, messages.ERROR, "This activity is not submittable.")
        return render(request, "submission/" + template,
        {"course":course, "activity":activity, "submission": submission, "submitted_components":submitted_components,
         "userid":userid, "late":late, "student":student, "group":group, "cansubmit":cansubmit})

    # get all components of activity
    component_list = select_all_components(activity)
    component_list.sort()
    component_form_list=[]

    if request.method == 'POST':
        component_form_list = make_form_from_list(component_list, request=request)
        submitted_comp = []    # list all components which has content submitted in the POST
        not_submitted_comp = [] #list allcomponents which has no content submitted in the POST
        if not activity.group:
            new_sub = StudentSubmission()   # the submission foreign key for newly submitted components
            new_sub.member = get_object_or_404(Member, offering__slug=course_slug, person__userid=request.user.username)
        elif gm:
            new_sub = GroupSubmission()
            new_sub.group = group
            new_sub.creator = member
        else:
            messages.add_message(request, messages.ERROR, "This is a group submission. You cannot submit since you aren't in a group.")
            return ForbiddenResponse(request)
        new_sub.activity = activity

        # begin validating uploaded data
        submitted_comp = []
        not_submitted_comp = []
        # validate forms one by one
        for data in component_form_list:
            component = data['comp']
            form = data['form']
            if form.is_valid():
                sub = form.save(commit=False)
                sub.component = component
                submitted_comp.append(sub)
            else:
                # hack to replace the "required" message to something more appropriate
                for k,v in form.errors.items():
                    for i,e in enumerate(v):
                        if e == "This field is required.":
                            v[i] = "Nothing submitted."

                not_submitted_comp.append(component)
        # check duplicate filenames here
        all_ok = False
        while not all_ok:
            all_ok = True
            d = {}
            for c,s in submitted_components:
                d[c] = s and s.get_filename()
            for s in submitted_comp:
                d[s.component] = s.get_filename()
            # a list holding all file names
            file_name_list = [a[1] for a in d.items() if a[1] is not None]
            to_be_removed = []
            for (i, s) in enumerate(submitted_comp):
                if file_name_list.count(s.get_filename()) > 1:
                    all_ok = False
                    to_be_removed.append(i)
                    not_submitted_comp.append(s.component)
                    #HACK: modify the 'errors' field in the form
                    for data in component_form_list:
                        if s.component == data['comp']:
                            # assume we have only one field for submission form
                            field_name = data['form'].fields.keys()[0]
                            data['form']._errors[field_name] = ErrorList([u"This file has the same name as another file in your submission."])
            # remove those has errors in submitted_comp
            to_be_removed.reverse()
            for t in to_be_removed:
                submitted_comp.pop(t)
        # all okay now
        # end validating, begin saving
        if len(submitted_comp) > 0:
            new_sub.save()    
        for sub in submitted_comp:
            sub.submission = new_sub
            sub.save()
            #LOG EVENT#
            if activity.group:
                group_str = " as a member of group %s" % new_sub.group.name
            else:
                group_str = ""
            l = LogEntry(userid=request.user.username,
                  description=u"submitted for %s %s%s" % (activity, sub.component.title, group_str),
                  related_object=sub)
            l.save()

        if len(not_submitted_comp) == 0:
            messages.add_message(request, messages.SUCCESS, "Your submission was successful.")
            return HttpResponseRedirect(reverse(show_components, args=[course_slug, activity_slug]))

        return render(request, "submission/submission_error.html",
            {"course":course, "activity":activity, "component_list":component_form_list,
            "submitted_comp":submitted_comp, "not_submitted_comp":not_submitted_comp})
    else: #not POST
        if activity.group and gm:
            messages.add_message(request, messages.INFO, "This is a group submission. You will submit on behalf of the group %s." % group.name)
        
        component_form_list = make_form_from_list(component_list)
        return render(request, "submission/" + template,
        {'component_form_list': component_form_list, "course": course, "activity": activity, "submission": submission,
         "submitted_components":submitted_components, "userid":userid, "late":late, "student":student, "group":group,
         "cansubmit":cansubmit, "is_staff":staff})
Example #32
0
def document_metadata(request,
                      docid,
                      template='documents/document_metadata.html',
                      ajax=True):

    document = None
    try:
        document = _resolve_document(request, docid,
                                     'base.change_resourcebase_metadata',
                                     _PERMISSION_MSG_METADATA)

    except Http404:
        return HttpResponse(loader.render_to_string('404.html',
                                                    context={},
                                                    request=request),
                            status=404)

    except PermissionDenied:
        return HttpResponse(loader.render_to_string(
            '401.html',
            context={
                'error_message':
                _("You are not allowed to edit this document.")
            },
            request=request),
                            status=403)

    if document is None:
        return HttpResponse('An unknown error has occured.',
                            content_type="text/plain",
                            status=401)

    else:
        poc = document.poc
        metadata_author = document.metadata_author
        topic_category = document.category

        if request.method == "POST":
            document_form = DocumentForm(request.POST,
                                         instance=document,
                                         prefix="resource")
            category_form = CategoryForm(
                request.POST,
                prefix="category_choice_field",
                initial=int(request.POST["category_choice_field"])
                if "category_choice_field" in request.POST else None)
        else:
            document_form = DocumentForm(instance=document, prefix="resource")
            category_form = CategoryForm(
                prefix="category_choice_field",
                initial=topic_category.id if topic_category else None)

        if request.method == "POST" and document_form.is_valid(
        ) and category_form.is_valid():
            new_poc = document_form.cleaned_data['poc']
            new_author = document_form.cleaned_data['metadata_author']
            new_keywords = document_form.cleaned_data['keywords']
            new_regions = document_form.cleaned_data['regions']
            new_category = TopicCategory.objects.get(
                id=category_form.cleaned_data['category_choice_field'])

            if new_poc is None:
                if poc.user is None:
                    poc_form = ProfileForm(request.POST,
                                           prefix="poc",
                                           instance=poc)
                else:
                    poc_form = ProfileForm(request.POST, prefix="poc")
                if poc_form.is_valid():
                    if len(poc_form.cleaned_data['profile']) == 0:
                        # FIXME use form.add_error in django > 1.7
                        errors = poc_form._errors.setdefault(
                            'profile', ErrorList())
                        errors.append(
                            _('You must set a point of contact for this resource'
                              ))
                        poc = None
                if poc_form.has_changed and poc_form.is_valid():
                    new_poc = poc_form.save()

            if new_author is None:
                if metadata_author is None:
                    author_form = ProfileForm(request.POST,
                                              prefix="author",
                                              instance=metadata_author)
                else:
                    author_form = ProfileForm(request.POST, prefix="author")
                if author_form.is_valid():
                    if len(author_form.cleaned_data['profile']) == 0:
                        # FIXME use form.add_error in django > 1.7
                        errors = author_form._errors.setdefault(
                            'profile', ErrorList())
                        errors.append(
                            _('You must set an author for this resource'))
                        metadata_author = None
                if author_form.has_changed and author_form.is_valid():
                    new_author = author_form.save()

            # rename document file if any title fields changed
            # TODO: in Geonode 2.8 there is separate 'version' field which in DRR used 'edition' field
            title_fields = [
                'category', 'regions', 'datasource', 'title', 'subtitle',
                'papersize', 'date', 'version'
            ]
            title_fields_changed = [
                i for e in title_fields for i in document_form.changed_data
                if e == i
            ]
            if title_fields_changed:
                doc_file_path = os.path.dirname(document.doc_file.name)
                new_filename = '%s.%s' % (get_valid_filename('_'.join([
                    'afg', new_category.identifier, '-'.join([
                        r.code for r in Region.objects.all().filter(
                            pk__in=document_form.cleaned_data['regions'])
                    ]), document_form.cleaned_data['datasource'],
                    slugify(document_form.cleaned_data['title'],
                            allow_unicode=True),
                    slugify(document_form.cleaned_data['subtitle'],
                            allow_unicode=True),
                    document_form.cleaned_data['papersize'],
                    document_form.cleaned_data['date'].strftime('%Y-%m-%d'),
                    document_form.cleaned_data['version']
                ])), document.extension)
                new_doc_file = os.path.join(doc_file_path, new_filename)
                old_path = os.path.join(settings.MEDIA_ROOT,
                                        document.doc_file.name)
                new_path = os.path.join(settings.MEDIA_ROOT, new_doc_file)
                os.rename(old_path, new_path)
                document.doc_file.name = new_doc_file
                document.save()

            the_document = document_form.instance
            if new_poc is not None and new_author is not None:
                the_document = document_form.save()
                the_document.poc = new_poc
                the_document.metadata_author = new_author
            if new_keywords:
                the_document.keywords.clear()
                the_document.keywords.add(*new_keywords)
            if new_regions:
                the_document.regions.clear()
                the_document.regions.add(*new_regions)
            the_document.save()
            document_form.save_many2many()
            Document.objects.filter(id=the_document.id).update(
                category=new_category)

            if getattr(settings, 'SLACK_ENABLED', False):
                try:
                    from geonode.contrib.slack.utils import build_slack_message_document, send_slack_messages
                    send_slack_messages(
                        build_slack_message_document("document_edit",
                                                     the_document))
                except BaseException:
                    print "Could not send slack message for modified document."

            if not ajax:
                return HttpResponseRedirect(
                    reverse('document_detail', args=(document.id, )))

            message = document.id

            return HttpResponse(json.dumps({'message': message}))

        # - POST Request Ends here -

        # Request.GET
        if poc is None:
            poc_form = ProfileForm(request.POST, prefix="poc")
        else:
            if poc is None:
                poc_form = ProfileForm(instance=poc, prefix="poc")
            else:
                document_form.fields['poc'].initial = poc.id
                poc_form = ProfileForm(prefix="poc")
                poc_form.hidden = True

        if metadata_author is None:
            author_form = ProfileForm(request.POST, prefix="author")
        else:
            if metadata_author is None:
                author_form = ProfileForm(instance=metadata_author,
                                          prefix="author")
            else:
                document_form.fields[
                    'metadata_author'].initial = metadata_author.id
                author_form = ProfileForm(prefix="author")
                author_form.hidden = True

        metadata_author_groups = []
        if request.user.is_superuser or request.user.is_staff:
            metadata_author_groups = GroupProfile.objects.all()
        else:
            try:
                all_metadata_author_groups = chain(
                    request.user.group_list_all(),
                    GroupProfile.objects.exclude(access="private").exclude(
                        access="public-invite"))
            except BaseException:
                all_metadata_author_groups = GroupProfile.objects.exclude(
                    access="private").exclude(access="public-invite")
            [
                metadata_author_groups.append(item)
                for item in all_metadata_author_groups
                if item not in metadata_author_groups
            ]

        if settings.ADMIN_MODERATE_UPLOADS:
            if not request.user.is_superuser:
                document_form.fields['is_published'].widget.attrs.update(
                    {'disabled': 'true'})

                can_change_metadata = request.user.has_perm(
                    'change_resourcebase_metadata',
                    document.get_self_resource())
                try:
                    is_manager = request.user.groupmember_set.all().filter(
                        role='manager').exists()
                except BaseException:
                    is_manager = False
                if not is_manager or not can_change_metadata:
                    document_form.fields['is_approved'].widget.attrs.update(
                        {'disabled': 'true'})

        return render(request,
                      template,
                      context={
                          "resource":
                          document,
                          "document":
                          document,
                          "document_form":
                          document_form,
                          "poc_form":
                          poc_form,
                          "author_form":
                          author_form,
                          "category_form":
                          category_form,
                          "metadata_author_groups":
                          metadata_author_groups,
                          "GROUP_MANDATORY_RESOURCES":
                          getattr(settings, 'GROUP_MANDATORY_RESOURCES',
                                  False),
                      })
Example #33
0
 def check_hex_color(self, color_code, field_name):
     if not re.match('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$', color_code):
         self._errors.setdefault(field_name, ErrorList())
         self._errors[field_name].append(
             "This is not a valid color code. Valid examples: #39F or #9AAED8"
         )
Example #34
0
 def test_error_list_html_safe(self):
     e = ErrorList(['Invalid username.'])
     self.assertTrue(hasattr(ErrorList, '__html__'))
     self.assertEqual(force_text(e), e.__html__())
Example #35
0
    def clean(self):
        """Verify crucial fields"""

        cleaned_data = self.cleaned_data

        name = cleaned_data.get("name")
        action = cleaned_data.get("action")
        parent = cleaned_data.get("parent")
        pf = cleaned_data.get("passphrase")
        pf_v = cleaned_data.get("passphrase_verify")
        p_pf = cleaned_data.get("parent_passphrase")
        extension = cleaned_data.get("extension")
        crl_dpoints = cleaned_data.get("crl_dpoints")

        enc_p_pf = None

        if action in ("create", "renew"):
            if action == "create":
                if (pf and not pf_v) or pf != pf_v:
                    self.errors["passphrase_verify"] = ErrorList(
                        ["Passphrase mismtach detected"])

                # Verify that we're not creating a certificate that already exists
                if parent:
                    if os.path.exists(
                            os.path.join(PKI_DIR, parent.name, "certs",
                                         "%s.key.pem" % name)):
                        self._errors["name"] = ErrorList(
                            ['Name "%s" is already in use!' % name])
                else:
                    if os.path.exists(
                            os.path.join(PKI_DIR, "_SELF_SIGNED_CERTIFICATES",
                                         "certs", "%s.key.pem" % name)):
                        self._errors["name"] = ErrorList(
                            ['Name "%s" is already in use!' % name])

            # Take care that parent is active when action is revoke
            if action == "renew":
                cert = Certificate.objects.get(name="%s" % name)

                if cert.parent is not None and cert.parent.active is not True:
                    self._errors["action"] = ErrorList([
                        'Cannot renew certificate when parent CA "%s" isn\'t active!'
                        % cert.parent
                    ])
                    return cleaned_data

            if parent:
                ca = CertificateAuthority.objects.get(name="%s" % parent.name)
                if p_pf:
                    enc_p_pf = md5(p_pf.encode("utf-8")).hexdigest()

                # Check parent passphrase
                if ca.passphrase != enc_p_pf:
                    self._errors["parent_passphrase"] = ErrorList([
                        'Passphrase is wrong. Enter correct passphrase for CA "%s"'
                        % parent
                    ])

            # Verify CRL distribution settings
            x509 = get_object_or_404(X509Extension, name=extension)
            if x509.crl_distribution_point and not crl_dpoints:
                self._errors["crl_dpoints"] = ErrorList([
                    'CRL Distribution Points are required by x509 extension "%s"'
                    % extension
                ])
        elif action == "revoke":
            if parent:
                ca = CertificateAuthority.objects.get(name="%s" % parent.name)
                if p_pf:
                    enc_p_pf = md5(p_pf).hexdigest()

                # Check parent passphrase
                if ca.passphrase != enc_p_pf:
                    self._errors["parent_passphrase"] = ErrorList([
                        'Passphrase is wrong. Enter correct passphrase for CA "%s"'
                        % parent
                    ])
            else:
                self._errors["action"] = ErrorList([
                    "You cannot revoke a self-signed certificate as there's"
                    " no CA to revoke against. Delete it instead!"
                ])

        return cleaned_data