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