class EditOrganizationMemberForm(forms.ModelForm): type = CustomTypedChoiceField(label=_('Membership Type'), choices=(), coerce=int) has_global_access = forms.BooleanField( label= _('This member should have access to all teams within the organization.' ), required=False, ) teams = forms.ModelMultipleChoiceField( queryset=Team.objects.none(), widget=forms.CheckboxSelectMultiple(), required=False, ) class Meta: fields = ('type', 'has_global_access') model = OrganizationMember def __init__(self, authorizing_access, *args, **kwargs): super(EditOrganizationMemberForm, self).__init__(*args, **kwargs) self.fields['type'].choices = [ m for m in MEMBERSHIP_CHOICES if m[0] >= authorizing_access ] self.fields['teams'].queryset = Team.objects.filter( organization=self.instance.organization, ) def save(self, actor, organization, ip_address=None): om = super(EditOrganizationMemberForm, self).save() for team in self.cleaned_data['teams']: OrganizationMemberTeam.objects.create_or_update( team=team, organizationmember=om, ) OrganizationMemberTeam.objects.filter( organizationmember=om, is_active=True, ).exclude(team__in=self.cleaned_data['teams']).delete() AuditLogEntry.objects.create( organization=organization, actor=actor, ip_address=ip_address, target_object=om.id, target_user=om.user, event=AuditLogEntryEvent.MEMBER_EDIT, data=om.get_audit_log_data(), ) return om
class EditProjectForm(forms.ModelForm): name = forms.CharField( label=_('Project Name'), max_length=200, widget=forms.TextInput(attrs={'placeholder': _('Production')})) platform = forms.ChoiceField( choices=Project._meta.get_field('platform').get_choices( blank_choice=BLANK_CHOICE), widget=forms.Select( attrs={'data-placeholder': _('Select a platform')})) public = forms.BooleanField( required=False, help_text=_('Imply public access to any event for this project.')) team = CustomTypedChoiceField(choices=(), coerce=int, required=False) origins = OriginsField( label=_('Allowed Domains'), required=False, help_text=_('Separate multiple entries with a newline.')) token = forms.CharField( label=_('Security token'), required=True, help_text= _('Outbound requests matching Allowed Domains will have the header "X-Sentry-Token: {token}" appended.' )) resolve_age = RangeField(help_text=_( 'Treat an event as resolved if it hasn\'t been seen for this amount of time.' ), required=False, min_value=0, max_value=168, step_value=1) scrub_data = forms.BooleanField( label=_('Data Scrubber'), help_text= _('Apply server-side data scrubbing to prevent things like passwords and credit cards from being stored.' ), required=False) sensitive_fields = forms.CharField( label=_('Additional sensitive fields'), help_text= _('Additional field names to match against when scrubbing data. Separate multiple entries with a newline.' ), widget=forms.Textarea( attrs={ 'placeholder': mark_safe(_('e.g. email')), 'class': 'span8', 'rows': '3', }), required=False, ) scrub_ip_address = forms.BooleanField( label=_('Don\'t store IP Addresses'), help_text=_('Prevent IP addresses from being stored for new events.'), required=False) class Meta: fields = ('name', 'platform', 'public', 'team', 'slug') model = Project def __init__(self, request, organization, team_list, data, instance, *args, **kwargs): super(EditProjectForm, self).__init__(data=data, instance=instance, *args, **kwargs) self.organization = organization self.team_list = team_list if not can_set_public_projects(request.user): del self.fields['public'] self.fields['team'].choices = self.get_team_choices( team_list, instance.team) self.fields['team'].widget.choices = self.fields['team'].choices def get_team_label(self, team): return '%s (%s)' % (team.name, team.slug) def get_team_choices(self, team_list, default=None): sorted_team_list = sorted(team_list, key=lambda x: x.name) choices = [] for team in sorted_team_list: # TODO: optimize queries choices.append((team.id, self.get_team_label(team))) if default is None: choices.insert(0, (-1, mark_safe('–' * 8))) elif default not in sorted_team_list: choices.insert(0, (default.id, self.get_team_label(default))) return choices def clean_sensitive_fields(self): value = self.cleaned_data.get('sensitive_fields') if not value: return return filter(bool, (v.lower().strip() for v in value.split('\n'))) def clean_team(self): value = self.cleaned_data.get('team') if not value: return # TODO: why is this not already an int? value = int(value) if value == -1: return if self.instance.team and value == self.instance.team.id: return self.instance.team for team in self.team_list: if value == team.id: return team raise forms.ValidationError('Unable to find chosen team') def clean_slug(self): slug = self.cleaned_data.get('slug') if not slug: return exists_qs = Project.objects.filter( slug=slug, organization=self.organization).exclude(id=self.instance.id) if exists_qs.exists(): raise forms.ValidationError( 'Another project is already using that slug') return slug
class PasswordlessRegistrationForm(forms.ModelForm): name = forms.CharField( label=_('Name'), max_length=30, widget=forms.TextInput(attrs={'placeholder': 'Jane Doe'}), required=True ) username = forms.EmailField( label=_('Email'), max_length=128, widget=forms.TextInput(attrs={'placeholder': '*****@*****.**'}), required=True ) subscribe = CustomTypedChoiceField( coerce=lambda x: six.text_type(x) == u'1', label=_("Email updates"), choices=( (1, 'Yes, I would like to receive updates via email'), (0, "No, I'd prefer not to receive these updates"), ), widget=forms.RadioSelect, required=True, initial=False, ) def __init__(self, *args, **kwargs): super(PasswordlessRegistrationForm, self).__init__(*args, **kwargs) if not newsletter.is_enabled(): del self.fields['subscribe'] else: # NOTE: the text here is duplicated within the ``NewsletterConsent`` component # in the UI notice = ( "We'd love to keep you updated via email with product and feature " "announcements, promotions, educational materials, and events. " "Our updates focus on relevant information, and we'll never sell " "your data to third parties. See our " "<a href=\"{privacy_link}\">Privacy Policy</a> for more details." ) self.fields['subscribe'].help_text = mark_safe( notice.format(privacy_link=settings.PRIVACY_URL)) class Meta: fields = ('username', 'name') model = User def clean_username(self): value = (self.cleaned_data.get('username') or '').strip() if not value: return if User.objects.filter(username__iexact=value).exists(): raise forms.ValidationError( _('An account is already registered with that email address.')) return value.lower() def save(self, commit=True): user = super(PasswordlessRegistrationForm, self).save(commit=False) user.email = user.username if commit: user.save() if self.cleaned_data.get('subscribe'): newsletter.create_or_update_subscriptions( user, list_ids=newsletter.get_default_list_ids()) return user
class EditProjectForm(forms.ModelForm): name = forms.CharField( label=_('Project Name'), max_length=200, widget=forms.TextInput(attrs={'placeholder': _('Production')})) platform = forms.ChoiceField( choices=Project._meta.get_field('platform').get_choices( blank_choice=BLANK_CHOICE), widget=forms.Select( attrs={'data-placeholder': _('Select a platform')})) public = forms.BooleanField( required=False, help_text=_('Imply public access to any event for this project.')) team = CustomTypedChoiceField(choices=(), coerce=int, required=False) origins = OriginsField( label=_('Allowed Domains'), required=False, help_text=_('Separate multiple entries with a newline.')) resolve_age = RangeField(help_text=_( 'Treat an event as resolved if it hasn\'t been seen for this amount of time.' ), required=False, min_value=0, max_value=168, step_value=1) scrub_data = forms.BooleanField( label=_('Data Scrubber'), help_text= _('Apply server-side data scrubbing to prevent things like passwords and credit cards from being stored.' ), required=False) scrub_ip_address = forms.BooleanField( label=_('Don\'t store IP Addresses'), help_text=_('Prevent IP addresses from being stored for new events.'), required=False) class Meta: fields = ('name', 'platform', 'public', 'team', 'slug') model = Project def __init__(self, request, team_list, data, instance, *args, **kwargs): super(EditProjectForm, self).__init__(data=data, instance=instance, *args, **kwargs) self.team_list = team_list if not can_set_public_projects(request.user): del self.fields['public'] self.fields['team'].choices = self.get_team_choices( team_list, instance.team) self.fields['team'].widget.choices = self.fields['team'].choices def get_team_label(self, team): return '%s (%s)' % (team.name, team.slug) def get_team_choices(self, team_list, default=None): sorted_team_list = sorted(team_list, key=lambda x: x.name) choices = [] for team in sorted_team_list: # TODO: optimize queries choices.append((team.id, self.get_team_label(team))) if default is None: choices.insert(0, (-1, mark_safe('–' * 8))) elif default not in sorted_team_list: choices.insert(0, (default.id, self.get_team_label(default))) return choices def clean_team(self): value = self.cleaned_data.get('team') if not value: return # TODO: why is this not already an int? value = int(value) if value == -1: return if self.instance.team and value == self.instance.team.id: return self.instance.team for team in self.team_list: if value == team.id: return team raise forms.ValidationError('Unable to find chosen team')
class EditProjectForm(forms.ModelForm): name = forms.CharField( label=_('Project Name'), max_length=200, widget=forms.TextInput(attrs={'placeholder': _('Production')})) slug = forms.SlugField( label=_('Short name'), help_text=_('A unique ID used to identify this project.'), ) team = CustomTypedChoiceField(choices=(), coerce=int, required=False) origins = OriginsField( label=_('Allowed Domains'), required=False, help_text=_('Separate multiple entries with a newline.')) token = forms.CharField( label=_('Security token'), required=True, help_text= _('Outbound requests matching Allowed Domains will have the header "X-Sentry-Token: {token}" appended.' )) resolve_age = RangeField( label=_('Auto resolve'), required=False, min_value=0, max_value=168, step_value=1, help_text= _('Automatically resolve an issue if it hasn\'t been seen for this amount of time.' )) scrub_data = forms.BooleanField( label=_('Data Scrubber'), help_text=_('Enable server-side data scrubbing.'), required=False) scrub_defaults = forms.BooleanField( label=_('Use Default Scrubbers'), help_text= _('Apply default scrubbers to prevent things like passwords and credit cards from being stored.' ), required=False) sensitive_fields = forms.CharField( label=_('Additional sensitive fields'), help_text= _('Additional field names to match against when scrubbing data. Separate multiple entries with a newline.' ), widget=forms.Textarea( attrs={ 'placeholder': mark_safe(_('e.g. email')), 'class': 'span8', 'rows': '3', }), required=False, ) scrub_ip_address = forms.BooleanField( label=_('Don\'t store IP Addresses'), help_text=_('Prevent IP addresses from being stored for new events.'), required=False) # JavaScript options scrape_javascript = forms.BooleanField( label=_('Enable JavaScript source fetching'), help_text= _('Allow Sentry to scrape missing JavaScript source context when possible.' ), required=False, ) blacklisted_ips = IPNetworksField( label=_('Filtered IP Addresses'), required=False, help_text=_('Separate multiple entries with a newline.')) # Options that are overridden by Organization level settings org_overrides = ('scrub_data', 'scrub_defaults', 'scrub_ip_address') default_environment = forms.CharField( label=_('Default Environment'), help_text=_('The default selected environment when viewing issues.'), widget=forms.TextInput(attrs={'placeholder': _('e.g. production')}), required=False, ) class Meta: fields = ('name', 'team', 'slug') model = Project def __init__(self, request, organization, team_list, data, instance, *args, **kwargs): # First, we need to check for the value overrides from the Organization options # We need to do this before `initial` gets passed into the Form. disabled = [] if 'initial' in kwargs: for opt in self.org_overrides: value = bool( organization.get_option('sentry:require_%s' % (opt, ), False)) if value: disabled.append(opt) kwargs['initial'][opt] = value super(EditProjectForm, self).__init__(data=data, instance=instance, *args, **kwargs) self.organization = organization self.team_list = team_list self.fields['team'].choices = self.get_team_choices( team_list, instance.team) self.fields['team'].widget.choices = self.fields['team'].choices # After the Form is initialized, we now need to disable the fields that have been # overridden from Organization options. for opt in disabled: self.fields[opt].widget.attrs['disabled'] = 'disabled' def get_team_label(self, team): return '%s (%s)' % (team.name, team.slug) def get_team_choices(self, team_list, default=None): sorted_team_list = sorted(team_list, key=lambda x: x.name) choices = [] for team in sorted_team_list: # TODO: optimize queries choices.append((team.id, self.get_team_label(team))) if default is None: choices.insert(0, (-1, mark_safe('–' * 8))) elif default not in sorted_team_list: choices.insert(0, (default.id, self.get_team_label(default))) return choices def clean_sensitive_fields(self): value = self.cleaned_data.get('sensitive_fields') if not value: return return filter(bool, (v.lower().strip() for v in value.split('\n'))) def clean_team(self): value = self.cleaned_data.get('team') if not value: return # TODO: why is this not already an int? value = int(value) if value == -1: return if self.instance.team and value == self.instance.team.id: return self.instance.team for team in self.team_list: if value == team.id: return team raise forms.ValidationError('Unable to find chosen team') def clean_slug(self): slug = self.cleaned_data.get('slug') if not slug: return other = Project.objects.filter(slug=slug, organization=self.organization).exclude( id=self.instance.id).first() if other is not None: raise forms.ValidationError('Another project (%s) is already ' 'using that slug' % other.name) return slug
class EditProjectForm(forms.ModelForm): name = forms.CharField( label=_('Project Name'), max_length=200, widget=forms.TextInput(attrs={'placeholder': _('Production')})) slug = forms.SlugField( label=_('Short name'), help_text=_('A unique ID used to identify this project.'), ) team = CustomTypedChoiceField(choices=(), coerce=int, required=False) # add by hzwangzhiwei @20160411 redmine = forms.CharField( label= _("Redmine URL ( HOW to: <a href='http://qadoc.nie.netease.com/?/article/28' target='_blank'>http://qadoc.nie.netease.com/?/article/28</a> )" ), max_length=200, required=False, widget=forms.TextInput( attrs={ 'placeholder': _('eg. http://h11.pm.netease.com/projects/h11-bugs/issues/new') })) # add by hzwangzhiwei @20160922 redmine_token = forms.CharField( label= _("RedmineAPI Token ( What: <a href='http://redmineapi.nie.netease.com/home/' target='_blank'>http://redmineapi.nie.netease.com/home/</a> )" ), max_length=200, required=False, widget=forms.TextInput( attrs={'placeholder': _('eg. 70cfa944be845d3d9219a4a1c51bdba9')})) redmine_host = forms.CharField(label=_( "RedmineAPI Host ( What: <a href='http://redmineapi.nie.netease.com/home/' target='_blank'>http://redmineapi.nie.netease.com/home/</a> )" ), max_length=200, required=False, widget=forms.TextInput(attrs={ 'placeholder': _('eg. hm1.pm.netease.com') })) origins = OriginsField( label=_('Allowed Domains'), required=False, help_text=_('Separate multiple entries with a newline.')) token = forms.CharField( label=_('Security token'), required=True, help_text= _('Outbound requests matching Allowed Domains will have the header "X-Sentry-Token: {token}" appended.' )) # for #846 auto solve time, 30 days, add by hzwangzhiwei @20160803 resolve_age = RangeField( label=_('Auto resolve'), required=False, min_value=0, max_value=720, step_value=1, help_text= _('Treat an event as resolved if it hasn\'t been seen for this amount of time.' )) scrub_data = forms.BooleanField( label=_('Data Scrubber'), help_text=_('Enable server-side data scrubbing.'), required=False) scrub_defaults = forms.BooleanField( label=_('Use Default Scrubbers'), help_text= _('Apply default scrubbers to prevent things like passwords and credit cards from being stored.' ), required=False) sensitive_fields = forms.CharField( label=_('Additional sensitive fields'), help_text= _('Additional field names to match against when scrubbing data. Separate multiple entries with a newline.' ), widget=forms.Textarea( attrs={ 'placeholder': mark_safe(_('e.g. email')), 'class': 'span8', 'rows': '3', }), required=False, ) scrub_ip_address = forms.BooleanField( label=_('Don\'t store IP Addresses'), help_text=_('Prevent IP addresses from being stored for new events.'), required=False) scrape_javascript = forms.BooleanField( label=_('Enable JavaScript source fetching'), help_text= _('Allow Sentry to scrape missing JavaScript source context when possible.' ), required=False, ) blacklisted_ips = IPNetworksField( label=_('Blacklisted IP Addresses'), required=False, help_text=_('Separate multiple entries with a newline.')) # for #845 add server_name filter, add by hzwangzhiwei @20160802 allowed_servernames = ServerNameField( label=_('Allowed Server Names'), required=False, help_text= _('Server name whitelist, only the trace which has server_name in WhiteList can be save to the server.' )) class Meta: fields = ('name', 'team', 'slug', 'redmine', 'redmine_token', 'redmine_host') model = Project def __init__(self, request, organization, team_list, data, instance, *args, **kwargs): super(EditProjectForm, self).__init__(data=data, instance=instance, *args, **kwargs) self.organization = organization self.team_list = team_list self.fields['team'].choices = self.get_team_choices( team_list, instance.team) self.fields['team'].widget.choices = self.fields['team'].choices def get_team_label(self, team): return '%s (%s)' % (team.name, team.slug) def get_team_choices(self, team_list, default=None): sorted_team_list = sorted(team_list, key=lambda x: x.name) choices = [] for team in sorted_team_list: # TODO: optimize queries choices.append((team.id, self.get_team_label(team))) if default is None: choices.insert(0, (-1, mark_safe('–' * 8))) elif default not in sorted_team_list: choices.insert(0, (default.id, self.get_team_label(default))) return choices def clean_sensitive_fields(self): value = self.cleaned_data.get('sensitive_fields') if not value: return return filter(bool, (v.lower().strip() for v in value.split('\n'))) def clean_team(self): value = self.cleaned_data.get('team') if not value: return # TODO: why is this not already an int? value = int(value) if value == -1: return if self.instance.team and value == self.instance.team.id: return self.instance.team for team in self.team_list: if value == team.id: return team raise forms.ValidationError('Unable to find chosen team') def clean_slug(self): slug = self.cleaned_data.get('slug') if not slug: return exists_qs = Project.objects.filter( slug=slug, organization=self.organization).exclude(id=self.instance.id) if exists_qs.exists(): raise forms.ValidationError( 'Another project is already using that slug') return slug def clean_redmine(self): redmine = self.cleaned_data.get('redmine') if not redmine: return if not redmine.startswith('http://'): # TODO, url format raise forms.ValidationError( 'Redmine URL must a valid url. (http://qadoc.nie.netease.com/?/article/28)' ) return redmine def clean_redmine_token(self): redmine_token = self.cleaned_data.get('redmine_token') if not redmine_token: return return redmine_token def clean_redmine_host(self): redmine_host = self.cleaned_data.get('redmine_host') if not redmine_host: return return redmine_host