Пример #1
0
    class _Form(AMOModelForm):
        builtin = forms.TypedChoiceField(choices=cs, coerce=int,
            widget=forms.RadioSelect(attrs={'class': 'license'},
                                     renderer=LicenseChoiceRadio))
        name = forms.CharField(widget=TranslationTextInput(),
                               label=_("What is your license's name?"),
                               required=False, initial=_('Custom License'))
        text = forms.CharField(widget=TranslationTextarea(), required=False,
                               label=_('Provide the text of your license.'))

        class Meta:
            model = License
            fields = ('builtin', 'name', 'text')

        def clean_name(self):
            name = self.cleaned_data['name']
            return name.strip() or _('Custom License')

        def clean(self):
            data = self.cleaned_data
            if self.errors:
                return data
            elif data['builtin'] == License.OTHER and not data['text']:
                raise forms.ValidationError(
                    _('License text is required when choosing Other.'))
            return data

        def save(self, commit=True):
            builtin = self.cleaned_data['builtin']
            if builtin != License.OTHER:
                return License.objects.get(builtin=builtin)
            return super(_Form, self).save(commit)
Пример #2
0
class AppVersionForm(happyforms.ModelForm):
    releasenotes = TransField(widget=TransTextarea(), required=False)
    approvalnotes = forms.CharField(
        widget=TranslationTextarea(attrs={'rows': 4}), required=False)
    publish_immediately = forms.BooleanField(required=False)

    class Meta:
        model = Version
        fields = ('releasenotes', 'approvalnotes')

    def __init__(self, *args, **kwargs):
        super(AppVersionForm, self).__init__(*args, **kwargs)
        self.fields['publish_immediately'].initial = (
            self.instance.addon.make_public == amo.PUBLIC_IMMEDIATELY)

    def save(self, *args, **kwargs):
        rval = super(AppVersionForm, self).save(*args, **kwargs)
        if self.instance.all_files[0].status == amo.STATUS_PENDING:
            # If version is pending, allow changes to make_public, which lives
            # on the app itself.
            if self.cleaned_data.get('publish_immediately'):
                make_public = amo.PUBLIC_IMMEDIATELY
            else:
                make_public = amo.PUBLIC_WAIT
            self.instance.addon.update(make_public=make_public)
        return rval
Пример #3
0
class VersionForm(happyforms.ModelForm):
    releasenotes = TransField(widget=TransTextarea(), required=False)
    approvalnotes = forms.CharField(
        widget=TranslationTextarea(attrs={'rows': 4}), required=False)

    class Meta:
        model = Version
        fields = ('releasenotes', 'approvalnotes')
Пример #4
0
class VersionForm(WithSourceMixin, happyforms.ModelForm):
    releasenotes = TransField(widget=TransTextarea(), required=False)
    approvalnotes = forms.CharField(
        widget=TranslationTextarea(attrs={'rows': 4}), required=False)
    source = forms.FileField(required=False, widget=SourceFileInput)

    class Meta:
        model = Version
        fields = ('releasenotes', 'approvalnotes', 'source')
Пример #5
0
class LicenseForm(AMOModelForm):
    builtin = forms.TypedChoiceField(choices=[],
                                     coerce=int,
                                     widget=forms.RadioSelect(
                                         attrs={'class': 'license'},
                                         renderer=LicenseChoiceRadio))
    name = forms.CharField(widget=TranslationTextInput(),
                           label=_lazy(u"What is your license's name?"),
                           required=False,
                           initial=_('Custom License'))
    text = forms.CharField(widget=TranslationTextarea(),
                           required=False,
                           label=_lazy(u'Provide the text of your license.'))

    def __init__(self, *args, **kw):
        addon = kw.pop('addon', None)
        self.version = None
        if addon:
            qs = addon.versions.order_by('-version')[:1]
            self.version = qs[0] if qs else None
            if self.version:
                kw['instance'], kw['initial'] = self.version.license, None
                # Clear out initial data if it's a builtin license.
                if getattr(kw['instance'], 'builtin', None):
                    kw['initial'] = {'builtin': kw['instance'].builtin}
                    kw['instance'] = None

        super(LicenseForm, self).__init__(*args, **kw)

        cs = [(x.builtin, x)
              for x in License.objects.builtins().filter(on_form=True)]
        cs.append((License.OTHER, _('Other')))
        self.fields['builtin'].choices = cs

    class Meta:
        model = License
        fields = ('builtin', 'name', 'text')

    def clean_name(self):
        name = self.cleaned_data['name']
        return name.strip() or _('Custom License')

    def clean(self):
        data = self.cleaned_data
        if self.errors:
            return data
        elif data['builtin'] == License.OTHER and not data['text']:
            raise forms.ValidationError(
                _('License text is required when choosing Other.'))
        return data

    def get_context(self):
        """Returns a view context dict having keys license_urls, license_form,
        and license_other_val.
        """
        license_urls = dict(License.objects.builtins().values_list(
            'builtin', 'url'))
        return dict(license_urls=license_urls,
                    version=self.version,
                    license_form=self.version and self,
                    license_other_val=License.OTHER)

    def save(self, *args, **kw):
        """Save all form data.

        This will only create a new license if it's not one of the builtin
        ones.

        Keyword arguments

        **log=True**
            Set to False if you do not want to log this action for display
            on the developer dashboard.
        """
        log = kw.pop('log', True)
        changed = self.changed_data

        builtin = self.cleaned_data['builtin']
        if builtin != License.OTHER:
            license = License.objects.get(builtin=builtin)
        else:
            # Save the custom license:
            license = super(LicenseForm, self).save(*args, **kw)

        if self.version:
            if changed or license != self.version.license:
                self.version.update(license=license)
                if log:
                    amo.log(amo.LOG.CHANGE_LICENSE, license,
                            self.version.addon)
        return license
Пример #6
0
class CollectionForm(ModelForm):

    name = forms.CharField(
        label=_lazy(u'Give your collection a name.'),
        widget=TranslationTextInput,
    )
    slug = forms.CharField(label=_lazy(u'URL:'))
    description = forms.CharField(
        label=_lazy(u'Describe your collection.'),
        widget=TranslationTextarea(attrs={'rows': 3}),
        max_length=200,
        required=False)
    listed = forms.ChoiceField(
        label=_lazy(u'Privacy:'),
        widget=forms.RadioSelect,
        choices=privacy_choices,
        initial=True,
    )

    icon = forms.FileField(label=_lazy(u'Icon'), required=False)

    def __init__(self, *args, **kw):
        super(CollectionForm, self).__init__(*args, **kw)
        # You can't edit the slugs for the special types.
        if (self.instance
                and self.instance.type in amo.COLLECTION_SPECIAL_SLUGS):
            del self.fields['slug']

    def clean_description(self):
        description = self.cleaned_data['description']
        if description.strip() == '':
            description = None

        return description

    def clean_slug(self):
        slug = slugify(self.cleaned_data['slug'])
        slug_validator(slug)
        if self.instance and self.instance.slug == slug:
            return slug

        author = self.initial['author']
        if author.collections.filter(slug=slug).count():
            raise forms.ValidationError(
                _('This url is already in use by another collection'))

        return slug

    def clean_icon(self):
        icon = self.cleaned_data['icon']
        if not icon:
            return
        if icon.content_type not in ('image/png', 'image/jpeg'):
            raise forms.ValidationError(_('Icons must be either PNG or JPG.'))

        if icon.size > settings.MAX_ICON_UPLOAD_SIZE:
            raise forms.ValidationError(
                _('Please use images smaller than %dMB.' %
                  (settings.MAX_ICON_UPLOAD_SIZE / 1024 / 1024 - 1)))
        return icon

    def save(self, default_locale=None):
        c = super(CollectionForm, self).save(commit=False)
        c.author = self.initial['author']
        c.application_id = self.initial['application_id']
        icon = self.cleaned_data.get('icon')

        if default_locale:
            c.default_locale = default_locale

        if icon:
            c.icontype = 'image/png'
        c.save()

        if icon:
            dirname = c.get_img_dir()

            destination = os.path.join(dirname, '%d.png' % c.id)
            tmp_destination = os.path.join(dirname,
                                           '%d.png__unconverted' % c.id)

            if not os.path.exists(dirname):
                os.mkdir(dirname)

            fh = open(tmp_destination, 'w')
            for chunk in icon.chunks():
                fh.write(chunk)

            fh.close()
            tasks.resize_icon.delay(tmp_destination,
                                    destination,
                                    set_modified_on=[c])

        return c

    class Meta:
        model = Collection
        fields = ('name', 'slug', 'description', 'listed')
Пример #7
0
class UserEditForm(UserRegisterForm, PasswordMixin):
    oldpassword = forms.CharField(max_length=255, required=False,
                            widget=forms.PasswordInput(render_value=False))
    password = forms.CharField(max_length=255, required=False,
                               min_length=PasswordMixin.min_length,
                               error_messages=PasswordMixin.error_msg,
                               widget=PasswordMixin.widget(render_value=False))

    password2 = forms.CharField(max_length=255, required=False,
                                widget=forms.PasswordInput(render_value=False))

    bio = forms.CharField(widget=TranslationTextarea(),
                          max_length=200,
                          required=False)
    photo = forms.FileField(label=_lazy(u'Profile Photo'), required=False)

    notifications = forms.MultipleChoiceField(
            choices=[],
            widget=NotificationsSelectMultiple,
            initial=email.NOTIFICATIONS_DEFAULT,
            required=False)

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(UserEditForm, self).__init__(*args, **kwargs)

        if self.instance:
            default = dict((i, n.default_checked) for i, n
                           in email.NOTIFICATIONS_BY_ID.items())
            user = dict((n.notification_id, n.enabled) for n
                        in self.instance.notifications.all())
            default.update(user)

            # Add choices to Notification.
            choices = email.NOTIFICATIONS_CHOICES
            if not self.instance.is_developer:
                choices = email.NOTIFICATIONS_CHOICES_NOT_DEV

            # Append a "NEW" message to new notification options.
            saved = self.instance.notifications.values_list('notification_id',
                                                            flat=True)
            self.choices_status = {}
            for idx, label in choices:
                self.choices_status[idx] = idx not in saved

            self.fields['notifications'].choices = choices
            self.fields['notifications'].initial = [i for i, v
                                                    in default.items() if v]
            self.fields['notifications'].widget.form_instance = self

        # TODO: We should inherit from a base form not UserRegisterForm
        if self.fields.get('recaptcha'):
            del self.fields['recaptcha']

    class Meta:
        model = UserProfile
        exclude = ('password', 'picture_type')

    def clean(self):
        data = self.cleaned_data
        amouser = self.request.user.get_profile()

        # Passwords
        p1 = data.get("password")
        p2 = data.get("password2")

        if p1 or p2:
            if not amouser.check_password(data["oldpassword"]):
                msg = _("Wrong password entered!")
                self._errors["oldpassword"] = ErrorList([msg])
                del data["oldpassword"]

        super(UserEditForm, self).clean()
        return data

    def clean_photo(self):
        photo = self.cleaned_data['photo']

        if not photo:
            return

        if photo.content_type not in ('image/png', 'image/jpeg'):
            raise forms.ValidationError(
                    _('Images must be either PNG or JPG.'))

        if photo.size > settings.MAX_PHOTO_UPLOAD_SIZE:
            raise forms.ValidationError(
                    _('Please use images smaller than %dMB.' %
                      (settings.MAX_PHOTO_UPLOAD_SIZE / 1024 / 1024 - 1)))

        return photo

    def clean_bio(self):
        bio = self.cleaned_data['bio']
        normalized = clean_nl(unicode(bio))
        if remove_links(normalized) != normalized:
            # There's some links, we don't want them.
            raise forms.ValidationError(_('No links are allowed.'))
        return bio

    def save(self, log_for_developer=True):
        u = super(UserEditForm, self).save(commit=False)
        data = self.cleaned_data
        photo = data['photo']
        if photo:
            u.picture_type = 'image/png'
            tmp_destination = u.picture_path + '__unconverted'

            with storage.open(tmp_destination, 'wb') as fh:
                for chunk in photo.chunks():
                    fh.write(chunk)

            tasks.resize_photo.delay(tmp_destination, u.picture_path,
                                     set_modified_on=[u])

        if data['password']:
            u.set_password(data['password'])
            log_cef('Password Changed', 5, self.request, username=u.username,
                    signature='PASSWORDCHANGED', msg='User changed password')
            if log_for_developer:
                amo.log(amo.LOG.CHANGE_PASSWORD)
                log.info(u'User (%s) changed their password' % u)

        for (i, n) in email.NOTIFICATIONS_BY_ID.items():
            enabled = n.mandatory or (str(i) in data['notifications'])
            UserNotification.update_or_create(user=u, notification_id=i,
                    update={'enabled': enabled})

        log.debug(u'User (%s) updated their profile' % u)

        u.save()
        return u
Пример #8
0
class CollectionForm(ModelForm):

    name = forms.CharField(
        label=_lazy(u'Give your collection a name.'),
        widget=TranslationTextInput)
    slug = forms.CharField(label=_lazy(u'URL:'))
    description = forms.CharField(
        label=_lazy(u'Describe your collection (no links allowed).'),
        widget=TranslationTextarea(attrs={'rows': 3}),
        max_length=200,
        required=False)
    listed = forms.ChoiceField(
        label=_lazy(u'Privacy:'),
        widget=forms.RadioSelect,
        choices=privacy_choices,
        initial=True)

    icon = forms.FileField(label=_lazy(u'Icon'),
                           required=False)

    # This is just a honeypot field for bots to get caught
    # L10n: bots is short for robots
    your_name = forms.CharField(
        label=_lazy(
            u"Please don't fill out this field, it's used to catch bots"),
        required=False)

    def __init__(self, *args, **kw):
        super(CollectionForm, self).__init__(*args, **kw)
        # You can't edit the slugs for the special types.
        if (self.instance and
                self.instance.type in amo.COLLECTION_SPECIAL_SLUGS):
            del self.fields['slug']

    def clean(self):
        # Check the honeypot here instead of 'clean_your_name' so the
        # error message appears at the top of the form in the __all__ section
        if self.cleaned_data['your_name']:
            statsd.incr('collections.honeypotted')
            log.info('Bot trapped in honeypot at collections.create')
            raise forms.ValidationError(
                "You've been flagged as spam, sorry about that.")
        return super(CollectionForm, self).clean()

    def clean_name(self):
        name = self.cleaned_data['name']
        if BlacklistedName.blocked(name):
            raise forms.ValidationError(_('This name cannot be used.'))
        return name

    def clean_description(self):
        description = self.cleaned_data['description']
        normalized = clean_nl(description)
        if has_links(normalized):
            # There's some links, we don't want them.
            raise forms.ValidationError(_('No links are allowed.'))
        return description

    def clean_slug(self):
        slug = slugify(self.cleaned_data['slug'])
        slug_validator(slug)
        if self.instance and self.instance.slug == slug:
            return slug

        author = self.initial['author']
        if author.collections.filter(slug=slug).count():
            raise forms.ValidationError(
                _('This url is already in use by another collection'))

        return slug

    def clean_icon(self):
        icon = self.cleaned_data['icon']
        if not icon:
            return
        if icon.content_type not in ('image/png', 'image/jpeg'):
            raise forms.ValidationError(
                _('Icons must be either PNG or JPG.'))

        if icon.size > settings.MAX_ICON_UPLOAD_SIZE:
            raise forms.ValidationError(
                _('Please use images smaller than %dMB.' %
                  (settings.MAX_ICON_UPLOAD_SIZE / 1024 / 1024 - 1)))
        return icon

    def save(self, default_locale=None):
        c = super(CollectionForm, self).save(commit=False)
        c.author = self.initial['author']
        c.application = self.initial['application']
        icon = self.cleaned_data.get('icon')

        if default_locale:
            c.default_locale = default_locale

        if icon:
            c.icontype = 'image/png'

        c.save()

        if icon:
            dirname = c.get_img_dir()

            destination = os.path.join(dirname, '%d.png' % c.id)
            tmp_destination = os.path.join(dirname,
                                           '%d.png__unconverted' % c.id)
            with storage.open(tmp_destination, 'w') as fh:
                for chunk in icon.chunks():
                    fh.write(chunk)
            tasks.resize_icon.delay(tmp_destination, destination,
                                    set_modified_on=[c])

        return c

    class Meta:
        model = Collection
        fields = ('name', 'slug', 'description', 'listed')