##// END OF EJS Templates
forms: now that AE is open source this is not required
ergo -
Show More
@@ -1,903 +1,901 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # AppEnlight Enterprise Edition, including its added features, Support
18 # AppEnlight Enterprise Edition, including its added features, Support
19 # services, and proprietary license terms, please see
19 # services, and proprietary license terms, please see
20 # https://rhodecode.com/licenses/
20 # https://rhodecode.com/licenses/
21
21
22 import wtforms
22 import wtforms
23 import formencode
23 import formencode
24 import re
24 import re
25 import pyramid.threadlocal
25 import pyramid.threadlocal
26 import datetime
26 import datetime
27 import appenlight.lib.helpers as h
27 import appenlight.lib.helpers as h
28
28
29 from appenlight.models.user import User
29 from appenlight.models.user import User
30 from appenlight.models.group import Group
30 from appenlight.models.group import Group
31 from appenlight.models import DBSession
31 from appenlight.models import DBSession
32 from appenlight.models.alert_channel import AlertChannel
32 from appenlight.models.alert_channel import AlertChannel
33 from appenlight.models.integrations import IntegrationException
33 from appenlight.models.integrations import IntegrationException
34 from appenlight.models.integrations.campfire import CampfireIntegration
34 from appenlight.models.integrations.campfire import CampfireIntegration
35 from appenlight.models.integrations.bitbucket import BitbucketIntegration
35 from appenlight.models.integrations.bitbucket import BitbucketIntegration
36 from appenlight.models.integrations.github import GithubIntegration
36 from appenlight.models.integrations.github import GithubIntegration
37 from appenlight.models.integrations.flowdock import FlowdockIntegration
37 from appenlight.models.integrations.flowdock import FlowdockIntegration
38 from appenlight.models.integrations.hipchat import HipchatIntegration
38 from appenlight.models.integrations.hipchat import HipchatIntegration
39 from appenlight.models.integrations.jira import JiraClient
39 from appenlight.models.integrations.jira import JiraClient
40 from appenlight.models.integrations.slack import SlackIntegration
40 from appenlight.models.integrations.slack import SlackIntegration
41 from appenlight.lib.ext_json import json
41 from appenlight.lib.ext_json import json
42 from wtforms.ext.csrf.form import SecureForm
42 from wtforms.ext.csrf.form import SecureForm
43 from wtforms.compat import iteritems
43 from wtforms.compat import iteritems
44 from collections import defaultdict
44 from collections import defaultdict
45
45
46 _ = str
46 _ = str
47
47
48 strip_filter = lambda x: x.strip() if x else None
48 strip_filter = lambda x: x.strip() if x else None
49 uppercase_filter = lambda x: x.upper() if x else None
49 uppercase_filter = lambda x: x.upper() if x else None
50
50
51 FALSE_VALUES = ('false', '', False, None)
51 FALSE_VALUES = ('false', '', False, None)
52
52
53
53
54 class CSRFException(Exception):
54 class CSRFException(Exception):
55 pass
55 pass
56
56
57
57
58 class ReactorForm(SecureForm):
58 class ReactorForm(SecureForm):
59 def __init__(self, formdata=None, obj=None, prefix='', csrf_context=None,
59 def __init__(self, formdata=None, obj=None, prefix='', csrf_context=None,
60 **kwargs):
60 **kwargs):
61 super(ReactorForm, self).__init__(formdata=formdata, obj=obj,
61 super(ReactorForm, self).__init__(formdata=formdata, obj=obj,
62 prefix=prefix,
62 prefix=prefix,
63 csrf_context=csrf_context, **kwargs)
63 csrf_context=csrf_context, **kwargs)
64 self._csrf_context = csrf_context
64 self._csrf_context = csrf_context
65
65
66 def generate_csrf_token(self, csrf_context):
66 def generate_csrf_token(self, csrf_context):
67 return csrf_context.session.get_csrf_token()
67 return csrf_context.session.get_csrf_token()
68
68
69 def validate_csrf_token(self, field):
69 def validate_csrf_token(self, field):
70 request = self._csrf_context or pyramid.threadlocal.get_current_request()
70 request = self._csrf_context or pyramid.threadlocal.get_current_request()
71 is_from_auth_token = 'auth:auth_token' in request.effective_principals
71 is_from_auth_token = 'auth:auth_token' in request.effective_principals
72 if is_from_auth_token:
72 if is_from_auth_token:
73 return True
73 return True
74
74
75 if field.data != field.current_token:
75 if field.data != field.current_token:
76 # try to save the day by using token from angular
76 # try to save the day by using token from angular
77 if request.headers.get('X-XSRF-TOKEN') != field.current_token:
77 if request.headers.get('X-XSRF-TOKEN') != field.current_token:
78 raise CSRFException('Invalid CSRF token')
78 raise CSRFException('Invalid CSRF token')
79
79
80 @property
80 @property
81 def errors_dict(self):
81 def errors_dict(self):
82 r_dict = defaultdict(list)
82 r_dict = defaultdict(list)
83 for k, errors in self.errors.items():
83 for k, errors in self.errors.items():
84 r_dict[k].extend([str(e) for e in errors])
84 r_dict[k].extend([str(e) for e in errors])
85 return r_dict
85 return r_dict
86
86
87 @property
87 @property
88 def errors_json(self):
88 def errors_json(self):
89 return json.dumps(self.errors_dict)
89 return json.dumps(self.errors_dict)
90
90
91 def populate_obj(self, obj, ignore_none=False):
91 def populate_obj(self, obj, ignore_none=False):
92 """
92 """
93 Populates the attributes of the passed `obj` with data from the form's
93 Populates the attributes of the passed `obj` with data from the form's
94 fields.
94 fields.
95
95
96 :note: This is a destructive operation; Any attribute with the same name
96 :note: This is a destructive operation; Any attribute with the same name
97 as a field will be overridden. Use with caution.
97 as a field will be overridden. Use with caution.
98 """
98 """
99 if ignore_none:
99 if ignore_none:
100 for name, field in iteritems(self._fields):
100 for name, field in iteritems(self._fields):
101 if field.data is not None:
101 if field.data is not None:
102 field.populate_obj(obj, name)
102 field.populate_obj(obj, name)
103 else:
103 else:
104 for name, field in iteritems(self._fields):
104 for name, field in iteritems(self._fields):
105 field.populate_obj(obj, name)
105 field.populate_obj(obj, name)
106
106
107 css_classes = {}
107 css_classes = {}
108 ignore_labels = {}
108 ignore_labels = {}
109
109
110
110
111 class SignInForm(ReactorForm):
111 class SignInForm(ReactorForm):
112 came_from = wtforms.HiddenField()
112 came_from = wtforms.HiddenField()
113 sign_in_user_name = wtforms.StringField(_('User Name'))
113 sign_in_user_name = wtforms.StringField(_('User Name'))
114 sign_in_user_password = wtforms.PasswordField(_('Password'))
114 sign_in_user_password = wtforms.PasswordField(_('Password'))
115
115
116 ignore_labels = ['submit']
116 ignore_labels = ['submit']
117 css_classes = {'submit': 'btn btn-primary'}
117 css_classes = {'submit': 'btn btn-primary'}
118
118
119 html_attrs = {'sign_in_user_name': {'placeholder': 'Your login'},
119 html_attrs = {'sign_in_user_name': {'placeholder': 'Your login'},
120 'sign_in_user_password': {
120 'sign_in_user_password': {
121 'placeholder': 'Your password'}}
121 'placeholder': 'Your password'}}
122
122
123
123
124 from wtforms.widgets import html_params, HTMLString
124 from wtforms.widgets import html_params, HTMLString
125
125
126
126
127 def select_multi_checkbox(field, ul_class='set', **kwargs):
127 def select_multi_checkbox(field, ul_class='set', **kwargs):
128 """Render a multi-checkbox widget"""
128 """Render a multi-checkbox widget"""
129 kwargs.setdefault('type', 'checkbox')
129 kwargs.setdefault('type', 'checkbox')
130 field_id = kwargs.pop('id', field.id)
130 field_id = kwargs.pop('id', field.id)
131 html = ['<ul %s>' % html_params(id=field_id, class_=ul_class)]
131 html = ['<ul %s>' % html_params(id=field_id, class_=ul_class)]
132 for value, label, checked in field.iter_choices():
132 for value, label, checked in field.iter_choices():
133 choice_id = '%s-%s' % (field_id, value)
133 choice_id = '%s-%s' % (field_id, value)
134 options = dict(kwargs, name=field.name, value=value, id=choice_id)
134 options = dict(kwargs, name=field.name, value=value, id=choice_id)
135 if checked:
135 if checked:
136 options['checked'] = 'checked'
136 options['checked'] = 'checked'
137 html.append('<li><input %s /> ' % html_params(**options))
137 html.append('<li><input %s /> ' % html_params(**options))
138 html.append('<label for="%s">%s</label></li>' % (choice_id, label))
138 html.append('<label for="%s">%s</label></li>' % (choice_id, label))
139 html.append('</ul>')
139 html.append('</ul>')
140 return HTMLString(''.join(html))
140 return HTMLString(''.join(html))
141
141
142
142
143 def button_widget(field, button_cls='ButtonField btn btn-default', **kwargs):
143 def button_widget(field, button_cls='ButtonField btn btn-default', **kwargs):
144 """Render a button widget"""
144 """Render a button widget"""
145 kwargs.setdefault('type', 'button')
145 kwargs.setdefault('type', 'button')
146 field_id = kwargs.pop('id', field.id)
146 field_id = kwargs.pop('id', field.id)
147 kwargs.setdefault('value', field.label.text)
147 kwargs.setdefault('value', field.label.text)
148 html = ['<button %s>%s</button>' % (html_params(id=field_id,
148 html = ['<button %s>%s</button>' % (html_params(id=field_id,
149 class_=button_cls),
149 class_=button_cls),
150 kwargs['value'],)]
150 kwargs['value'],)]
151 return HTMLString(''.join(html))
151 return HTMLString(''.join(html))
152
152
153
153
154 def clean_whitespace(value):
154 def clean_whitespace(value):
155 if value:
155 if value:
156 return value.strip()
156 return value.strip()
157 return value
157 return value
158
158
159
159
160 def found_username_validator(form, field):
160 def found_username_validator(form, field):
161 user = User.by_user_name(field.data)
161 user = User.by_user_name(field.data)
162 # sets user to recover in email validator
162 # sets user to recover in email validator
163 form.field_user = user
163 form.field_user = user
164 if not user:
164 if not user:
165 raise wtforms.ValidationError('This username does not exist')
165 raise wtforms.ValidationError('This username does not exist')
166
166
167
167
168 def found_username_email_validator(form, field):
168 def found_username_email_validator(form, field):
169 user = User.by_email(field.data)
169 user = User.by_email(field.data)
170 if not user:
170 if not user:
171 raise wtforms.ValidationError('Email is incorrect')
171 raise wtforms.ValidationError('Email is incorrect')
172
172
173
173
174 def unique_username_validator(form, field):
174 def unique_username_validator(form, field):
175 user = User.by_user_name(field.data)
175 user = User.by_user_name(field.data)
176 if user:
176 if user:
177 raise wtforms.ValidationError('This username already exists in system')
177 raise wtforms.ValidationError('This username already exists in system')
178
178
179
179
180 def unique_groupname_validator(form, field):
180 def unique_groupname_validator(form, field):
181 group = Group.by_group_name(field.data)
181 group = Group.by_group_name(field.data)
182 mod_group = getattr(form, '_modified_group', None)
182 mod_group = getattr(form, '_modified_group', None)
183 if group and (not mod_group or mod_group.id != group.id):
183 if group and (not mod_group or mod_group.id != group.id):
184 raise wtforms.ValidationError(
184 raise wtforms.ValidationError(
185 'This group name already exists in system')
185 'This group name already exists in system')
186
186
187
187
188 def unique_email_validator(form, field):
188 def unique_email_validator(form, field):
189 user = User.by_email(field.data)
189 user = User.by_email(field.data)
190 if user:
190 if user:
191 raise wtforms.ValidationError('This email already exists in system')
191 raise wtforms.ValidationError('This email already exists in system')
192
192
193
193
194 def email_validator(form, field):
194 def email_validator(form, field):
195 validator = formencode.validators.Email()
195 validator = formencode.validators.Email()
196 try:
196 try:
197 validator.to_python(field.data)
197 validator.to_python(field.data)
198 except formencode.Invalid as e:
198 except formencode.Invalid as e:
199 raise wtforms.ValidationError(e)
199 raise wtforms.ValidationError(e)
200
200
201
201
202 def unique_alert_email_validator(form, field):
202 def unique_alert_email_validator(form, field):
203 q = DBSession.query(AlertChannel)
203 q = DBSession.query(AlertChannel)
204 q = q.filter(AlertChannel.channel_name == 'email')
204 q = q.filter(AlertChannel.channel_name == 'email')
205 q = q.filter(AlertChannel.channel_value == field.data)
205 q = q.filter(AlertChannel.channel_value == field.data)
206 email = q.first()
206 email = q.first()
207 if email:
207 if email:
208 raise wtforms.ValidationError(
208 raise wtforms.ValidationError(
209 'This email already exists in alert system')
209 'This email already exists in alert system')
210
210
211
211
212 def blocked_email_validator(form, field):
212 def blocked_email_validator(form, field):
213 blocked_emails = [
213 blocked_emails = [
214 'goood-mail.org',
214 'goood-mail.org',
215 'shoeonlineblog.com',
215 'shoeonlineblog.com',
216 'louboutinemart.com',
216 'louboutinemart.com',
217 'guccibagshere.com',
217 'guccibagshere.com',
218 'nikeshoesoutletforsale.com'
218 'nikeshoesoutletforsale.com'
219 ]
219 ]
220 data = field.data or ''
220 data = field.data or ''
221 domain = data.split('@')[-1]
221 domain = data.split('@')[-1]
222 if domain in blocked_emails:
222 if domain in blocked_emails:
223 raise wtforms.ValidationError('Don\'t spam')
223 raise wtforms.ValidationError('Don\'t spam')
224
224
225
225
226 def old_password_validator(form, field):
226 def old_password_validator(form, field):
227 if not field.user.check_password(field.data or ''):
227 if not field.user.check_password(field.data or ''):
228 raise wtforms.ValidationError('You need to enter correct password')
228 raise wtforms.ValidationError('You need to enter correct password')
229
229
230
230
231 class UserRegisterForm(ReactorForm):
231 class UserRegisterForm(ReactorForm):
232 user_name = wtforms.StringField(
232 user_name = wtforms.StringField(
233 _('User Name'),
233 _('User Name'),
234 filters=[strip_filter],
234 filters=[strip_filter],
235 validators=[
235 validators=[
236 wtforms.validators.Length(min=2, max=30),
236 wtforms.validators.Length(min=2, max=30),
237 wtforms.validators.Regexp(
237 wtforms.validators.Regexp(
238 re.compile(r'^[\.\w-]+$', re.UNICODE),
238 re.compile(r'^[\.\w-]+$', re.UNICODE),
239 message="Invalid characters used"),
239 message="Invalid characters used"),
240 unique_username_validator,
240 unique_username_validator,
241 wtforms.validators.DataRequired()
241 wtforms.validators.DataRequired()
242 ])
242 ])
243
243
244 user_password = wtforms.PasswordField(_('User Password'),
244 user_password = wtforms.PasswordField(_('User Password'),
245 filters=[strip_filter],
245 filters=[strip_filter],
246 validators=[
246 validators=[
247 wtforms.validators.Length(min=4),
247 wtforms.validators.Length(min=4),
248 wtforms.validators.DataRequired()
248 wtforms.validators.DataRequired()
249 ])
249 ])
250
250
251 email = wtforms.StringField(_('Email Address'),
251 email = wtforms.StringField(_('Email Address'),
252 filters=[strip_filter],
252 filters=[strip_filter],
253 validators=[email_validator,
253 validators=[email_validator,
254 unique_email_validator,
254 unique_email_validator,
255 blocked_email_validator,
255 blocked_email_validator,
256 wtforms.validators.DataRequired()],
256 wtforms.validators.DataRequired()])
257 description=_("We promise we will not share "
258 "your email with anyone"))
259 first_name = wtforms.HiddenField(_('First Name'))
257 first_name = wtforms.HiddenField(_('First Name'))
260 last_name = wtforms.HiddenField(_('Last Name'))
258 last_name = wtforms.HiddenField(_('Last Name'))
261
259
262 ignore_labels = ['submit']
260 ignore_labels = ['submit']
263 css_classes = {'submit': 'btn btn-primary'}
261 css_classes = {'submit': 'btn btn-primary'}
264
262
265 html_attrs = {'user_name': {'placeholder': 'Your login'},
263 html_attrs = {'user_name': {'placeholder': 'Your login'},
266 'user_password': {'placeholder': 'Your password'},
264 'user_password': {'placeholder': 'Your password'},
267 'email': {'placeholder': 'Your email'}}
265 'email': {'placeholder': 'Your email'}}
268
266
269
267
270 class UserCreateForm(UserRegisterForm):
268 class UserCreateForm(UserRegisterForm):
271 status = wtforms.BooleanField('User status',
269 status = wtforms.BooleanField('User status',
272 false_values=FALSE_VALUES)
270 false_values=FALSE_VALUES)
273
271
274
272
275 class UserUpdateForm(UserCreateForm):
273 class UserUpdateForm(UserCreateForm):
276 user_name = None
274 user_name = None
277 user_password = wtforms.PasswordField(_('User Password'),
275 user_password = wtforms.PasswordField(_('User Password'),
278 filters=[strip_filter],
276 filters=[strip_filter],
279 validators=[
277 validators=[
280 wtforms.validators.Length(min=4),
278 wtforms.validators.Length(min=4),
281 wtforms.validators.Optional()
279 wtforms.validators.Optional()
282 ])
280 ])
283 email = wtforms.StringField(_('Email Address'),
281 email = wtforms.StringField(_('Email Address'),
284 filters=[strip_filter],
282 filters=[strip_filter],
285 validators=[email_validator,
283 validators=[email_validator,
286 wtforms.validators.DataRequired()])
284 wtforms.validators.DataRequired()])
287
285
288
286
289 class LostPasswordForm(ReactorForm):
287 class LostPasswordForm(ReactorForm):
290 email = wtforms.StringField(_('Email Address'),
288 email = wtforms.StringField(_('Email Address'),
291 filters=[strip_filter],
289 filters=[strip_filter],
292 validators=[email_validator,
290 validators=[email_validator,
293 found_username_email_validator,
291 found_username_email_validator,
294 wtforms.validators.DataRequired()])
292 wtforms.validators.DataRequired()])
295
293
296 submit = wtforms.SubmitField(_('Reset password'))
294 submit = wtforms.SubmitField(_('Reset password'))
297 ignore_labels = ['submit']
295 ignore_labels = ['submit']
298 css_classes = {'submit': 'btn btn-primary'}
296 css_classes = {'submit': 'btn btn-primary'}
299
297
300
298
301 class ChangePasswordForm(ReactorForm):
299 class ChangePasswordForm(ReactorForm):
302 old_password = wtforms.PasswordField(
300 old_password = wtforms.PasswordField(
303 'Old Password',
301 'Old Password',
304 filters=[strip_filter],
302 filters=[strip_filter],
305 validators=[old_password_validator,
303 validators=[old_password_validator,
306 wtforms.validators.DataRequired()])
304 wtforms.validators.DataRequired()])
307
305
308 new_password = wtforms.PasswordField(
306 new_password = wtforms.PasswordField(
309 'New Password',
307 'New Password',
310 filters=[strip_filter],
308 filters=[strip_filter],
311 validators=[wtforms.validators.Length(min=4),
309 validators=[wtforms.validators.Length(min=4),
312 wtforms.validators.DataRequired()])
310 wtforms.validators.DataRequired()])
313 new_password_confirm = wtforms.PasswordField(
311 new_password_confirm = wtforms.PasswordField(
314 'Confirm Password',
312 'Confirm Password',
315 filters=[strip_filter],
313 filters=[strip_filter],
316 validators=[wtforms.validators.EqualTo('new_password'),
314 validators=[wtforms.validators.EqualTo('new_password'),
317 wtforms.validators.DataRequired()])
315 wtforms.validators.DataRequired()])
318 submit = wtforms.SubmitField('Change Password')
316 submit = wtforms.SubmitField('Change Password')
319 ignore_labels = ['submit']
317 ignore_labels = ['submit']
320 css_classes = {'submit': 'btn btn-primary'}
318 css_classes = {'submit': 'btn btn-primary'}
321
319
322
320
323 class CheckPasswordForm(ReactorForm):
321 class CheckPasswordForm(ReactorForm):
324 password = wtforms.PasswordField(
322 password = wtforms.PasswordField(
325 'Password',
323 'Password',
326 filters=[strip_filter],
324 filters=[strip_filter],
327 validators=[old_password_validator,
325 validators=[old_password_validator,
328 wtforms.validators.DataRequired()])
326 wtforms.validators.DataRequired()])
329
327
330
328
331 class NewPasswordForm(ReactorForm):
329 class NewPasswordForm(ReactorForm):
332 new_password = wtforms.PasswordField(
330 new_password = wtforms.PasswordField(
333 'New Password',
331 'New Password',
334 filters=[strip_filter],
332 filters=[strip_filter],
335 validators=[wtforms.validators.Length(min=4),
333 validators=[wtforms.validators.Length(min=4),
336 wtforms.validators.DataRequired()])
334 wtforms.validators.DataRequired()])
337 new_password_confirm = wtforms.PasswordField(
335 new_password_confirm = wtforms.PasswordField(
338 'Confirm Password',
336 'Confirm Password',
339 filters=[strip_filter],
337 filters=[strip_filter],
340 validators=[wtforms.validators.EqualTo('new_password'),
338 validators=[wtforms.validators.EqualTo('new_password'),
341 wtforms.validators.DataRequired()])
339 wtforms.validators.DataRequired()])
342 submit = wtforms.SubmitField('Set Password')
340 submit = wtforms.SubmitField('Set Password')
343 ignore_labels = ['submit']
341 ignore_labels = ['submit']
344 css_classes = {'submit': 'btn btn-primary'}
342 css_classes = {'submit': 'btn btn-primary'}
345
343
346
344
347 class CORSTextAreaField(wtforms.StringField):
345 class CORSTextAreaField(wtforms.StringField):
348 """
346 """
349 This field represents an HTML ``<textarea>`` and can be used to take
347 This field represents an HTML ``<textarea>`` and can be used to take
350 multi-line input.
348 multi-line input.
351 """
349 """
352 widget = wtforms.widgets.TextArea()
350 widget = wtforms.widgets.TextArea()
353
351
354 def process_formdata(self, valuelist):
352 def process_formdata(self, valuelist):
355 self.data = []
353 self.data = []
356 if valuelist:
354 if valuelist:
357 data = [x.strip() for x in valuelist[0].split('\n')]
355 data = [x.strip() for x in valuelist[0].split('\n')]
358 for d in data:
356 for d in data:
359 if not d:
357 if not d:
360 continue
358 continue
361 if d.startswith('www.'):
359 if d.startswith('www.'):
362 d = d[4:]
360 d = d[4:]
363 if data:
361 if data:
364 self.data.append(d)
362 self.data.append(d)
365 else:
363 else:
366 self.data = []
364 self.data = []
367 self.data = '\n'.join(self.data)
365 self.data = '\n'.join(self.data)
368
366
369
367
370 class ApplicationCreateForm(ReactorForm):
368 class ApplicationCreateForm(ReactorForm):
371 resource_name = wtforms.StringField(
369 resource_name = wtforms.StringField(
372 _('Application name'),
370 _('Application name'),
373 filters=[strip_filter],
371 filters=[strip_filter],
374 validators=[wtforms.validators.Length(min=1),
372 validators=[wtforms.validators.Length(min=1),
375 wtforms.validators.DataRequired()])
373 wtforms.validators.DataRequired()])
376
374
377 domains = CORSTextAreaField(
375 domains = CORSTextAreaField(
378 _('Domain names for CORS headers '),
376 _('Domain names for CORS headers '),
379 validators=[wtforms.validators.Length(min=1),
377 validators=[wtforms.validators.Length(min=1),
380 wtforms.validators.Optional()],
378 wtforms.validators.Optional()],
381 description='Required for Javascript error '
379 description='Required for Javascript error '
382 'tracking (one line one domain, skip http:// part)')
380 'tracking (one line one domain, skip http:// part)')
383
381
384 submit = wtforms.SubmitField(_('Create Application'))
382 submit = wtforms.SubmitField(_('Create Application'))
385
383
386 ignore_labels = ['submit']
384 ignore_labels = ['submit']
387 css_classes = {'submit': 'btn btn-primary'}
385 css_classes = {'submit': 'btn btn-primary'}
388 html_attrs = {'resource_name': {'placeholder': 'Application Name'},
386 html_attrs = {'resource_name': {'placeholder': 'Application Name'},
389 'uptime_url': {'placeholder': 'http://somedomain.com'}}
387 'uptime_url': {'placeholder': 'http://somedomain.com'}}
390
388
391
389
392 class ApplicationUpdateForm(ApplicationCreateForm):
390 class ApplicationUpdateForm(ApplicationCreateForm):
393 default_grouping = wtforms.SelectField(
391 default_grouping = wtforms.SelectField(
394 _('Default grouping for errors'),
392 _('Default grouping for errors'),
395 choices=[('url_type', 'Error Type + location',),
393 choices=[('url_type', 'Error Type + location',),
396 ('url_traceback', 'Traceback + location',),
394 ('url_traceback', 'Traceback + location',),
397 ('traceback_server', 'Traceback + Server',)],
395 ('traceback_server', 'Traceback + Server',)],
398 default='url_traceback')
396 default='url_traceback')
399
397
400 error_report_threshold = wtforms.IntegerField(
398 error_report_threshold = wtforms.IntegerField(
401 _('Alert on error reports'),
399 _('Alert on error reports'),
402 validators=[
400 validators=[
403 wtforms.validators.NumberRange(min=1),
401 wtforms.validators.NumberRange(min=1),
404 wtforms.validators.DataRequired()
402 wtforms.validators.DataRequired()
405 ],
403 ],
406 description='Application requires to send at least this amount of '
404 description='Application requires to send at least this amount of '
407 'error reports per minute to open alert'
405 'error reports per minute to open alert'
408 )
406 )
409
407
410 slow_report_threshold = wtforms.IntegerField(
408 slow_report_threshold = wtforms.IntegerField(
411 _('Alert on slow reports'),
409 _('Alert on slow reports'),
412 validators=[wtforms.validators.NumberRange(min=1),
410 validators=[wtforms.validators.NumberRange(min=1),
413 wtforms.validators.DataRequired()],
411 wtforms.validators.DataRequired()],
414 description='Application requires to send at least this amount of '
412 description='Application requires to send at least this amount of '
415 'slow reports per minute to open alert')
413 'slow reports per minute to open alert')
416
414
417 allow_permanent_storage = wtforms.BooleanField(
415 allow_permanent_storage = wtforms.BooleanField(
418 _('Permanent logs'),
416 _('Permanent logs'),
419 false_values=FALSE_VALUES,
417 false_values=FALSE_VALUES,
420 description=_(
418 description=_(
421 'Allow permanent storage of logs in separate DB partitions'))
419 'Allow permanent storage of logs in separate DB partitions'))
422
420
423 submit = wtforms.SubmitField(_('Create Application'))
421 submit = wtforms.SubmitField(_('Create Application'))
424
422
425
423
426 class UserSearchSchemaForm(ReactorForm):
424 class UserSearchSchemaForm(ReactorForm):
427 user_name = wtforms.StringField('User Name',
425 user_name = wtforms.StringField('User Name',
428 filters=[strip_filter], )
426 filters=[strip_filter], )
429
427
430 submit = wtforms.SubmitField(_('Search User'))
428 submit = wtforms.SubmitField(_('Search User'))
431 ignore_labels = ['submit']
429 ignore_labels = ['submit']
432 css_classes = {'submit': 'btn btn-primary'}
430 css_classes = {'submit': 'btn btn-primary'}
433
431
434 '<li class="user_exists"><span></span></li>'
432 '<li class="user_exists"><span></span></li>'
435
433
436
434
437 class YesNoForm(ReactorForm):
435 class YesNoForm(ReactorForm):
438 no = wtforms.SubmitField('No', default='')
436 no = wtforms.SubmitField('No', default='')
439 yes = wtforms.SubmitField('Yes', default='')
437 yes = wtforms.SubmitField('Yes', default='')
440 ignore_labels = ['submit']
438 ignore_labels = ['submit']
441 css_classes = {'submit': 'btn btn-primary'}
439 css_classes = {'submit': 'btn btn-primary'}
442
440
443
441
444 status_codes = [('', 'All',), ('500', '500',), ('404', '404',)]
442 status_codes = [('', 'All',), ('500', '500',), ('404', '404',)]
445
443
446 priorities = [('', 'All',)]
444 priorities = [('', 'All',)]
447 for i in range(1, 11):
445 for i in range(1, 11):
448 priorities.append((str(i), str(i),))
446 priorities.append((str(i), str(i),))
449
447
450 report_status_choices = [('', 'All',),
448 report_status_choices = [('', 'All',),
451 ('never_reviewed', 'Never revieved',),
449 ('never_reviewed', 'Never revieved',),
452 ('reviewed', 'Revieved',),
450 ('reviewed', 'Revieved',),
453 ('public', 'Public',),
451 ('public', 'Public',),
454 ('fixed', 'Fixed',), ]
452 ('fixed', 'Fixed',), ]
455
453
456
454
457 class ReportBrowserForm(ReactorForm):
455 class ReportBrowserForm(ReactorForm):
458 applications = wtforms.SelectMultipleField('Applications',
456 applications = wtforms.SelectMultipleField('Applications',
459 widget=select_multi_checkbox)
457 widget=select_multi_checkbox)
460 http_status = wtforms.SelectField('HTTP Status', choices=status_codes)
458 http_status = wtforms.SelectField('HTTP Status', choices=status_codes)
461 priority = wtforms.SelectField('Priority', choices=priorities, default='')
459 priority = wtforms.SelectField('Priority', choices=priorities, default='')
462 start_date = wtforms.DateField('Start Date')
460 start_date = wtforms.DateField('Start Date')
463 end_date = wtforms.DateField('End Date')
461 end_date = wtforms.DateField('End Date')
464 error = wtforms.StringField('Error')
462 error = wtforms.StringField('Error')
465 url_path = wtforms.StringField('URL Path')
463 url_path = wtforms.StringField('URL Path')
466 url_domain = wtforms.StringField('URL Domain')
464 url_domain = wtforms.StringField('URL Domain')
467 report_status = wtforms.SelectField('Report status',
465 report_status = wtforms.SelectField('Report status',
468 choices=report_status_choices,
466 choices=report_status_choices,
469 default='')
467 default='')
470 submit = wtforms.SubmitField('<span class="glyphicon glyphicon-search">'
468 submit = wtforms.SubmitField('<span class="glyphicon glyphicon-search">'
471 '</span> Filter results',
469 '</span> Filter results',
472 widget=button_widget)
470 widget=button_widget)
473
471
474 ignore_labels = ['submit']
472 ignore_labels = ['submit']
475 css_classes = {'submit': 'btn btn-primary'}
473 css_classes = {'submit': 'btn btn-primary'}
476
474
477
475
478 slow_report_status_choices = [('', 'All',),
476 slow_report_status_choices = [('', 'All',),
479 ('never_reviewed', 'Never revieved',),
477 ('never_reviewed', 'Never revieved',),
480 ('reviewed', 'Revieved',),
478 ('reviewed', 'Revieved',),
481 ('public', 'Public',), ]
479 ('public', 'Public',), ]
482
480
483
481
484 class BulkOperationForm(ReactorForm):
482 class BulkOperationForm(ReactorForm):
485 applications = wtforms.SelectField('Applications')
483 applications = wtforms.SelectField('Applications')
486 start_date = wtforms.DateField(
484 start_date = wtforms.DateField(
487 'Start Date',
485 'Start Date',
488 default=lambda: datetime.datetime.utcnow() - datetime.timedelta(
486 default=lambda: datetime.datetime.utcnow() - datetime.timedelta(
489 days=90))
487 days=90))
490 end_date = wtforms.DateField('End Date')
488 end_date = wtforms.DateField('End Date')
491 confirm = wtforms.BooleanField(
489 confirm = wtforms.BooleanField(
492 'Confirm operation',
490 'Confirm operation',
493 validators=[wtforms.validators.DataRequired()])
491 validators=[wtforms.validators.DataRequired()])
494
492
495
493
496 class LogBrowserForm(ReactorForm):
494 class LogBrowserForm(ReactorForm):
497 applications = wtforms.SelectMultipleField('Applications',
495 applications = wtforms.SelectMultipleField('Applications',
498 widget=select_multi_checkbox)
496 widget=select_multi_checkbox)
499 start_date = wtforms.DateField('Start Date')
497 start_date = wtforms.DateField('Start Date')
500 log_level = wtforms.StringField('Log level')
498 log_level = wtforms.StringField('Log level')
501 message = wtforms.StringField('Message')
499 message = wtforms.StringField('Message')
502 namespace = wtforms.StringField('Namespace')
500 namespace = wtforms.StringField('Namespace')
503 submit = wtforms.SubmitField(
501 submit = wtforms.SubmitField(
504 '<span class="glyphicon glyphicon-search"></span> Filter results',
502 '<span class="glyphicon glyphicon-search"></span> Filter results',
505 widget=button_widget)
503 widget=button_widget)
506 ignore_labels = ['submit']
504 ignore_labels = ['submit']
507 css_classes = {'submit': 'btn btn-primary'}
505 css_classes = {'submit': 'btn btn-primary'}
508
506
509
507
510 class CommentForm(ReactorForm):
508 class CommentForm(ReactorForm):
511 body = wtforms.TextAreaField('Comment', validators=[
509 body = wtforms.TextAreaField('Comment', validators=[
512 wtforms.validators.Length(min=1),
510 wtforms.validators.Length(min=1),
513 wtforms.validators.DataRequired()
511 wtforms.validators.DataRequired()
514 ])
512 ])
515 submit = wtforms.SubmitField('Comment', )
513 submit = wtforms.SubmitField('Comment', )
516 ignore_labels = ['submit']
514 ignore_labels = ['submit']
517 css_classes = {'submit': 'btn btn-primary'}
515 css_classes = {'submit': 'btn btn-primary'}
518
516
519
517
520 class EmailChannelCreateForm(ReactorForm):
518 class EmailChannelCreateForm(ReactorForm):
521 email = wtforms.StringField(_('Email Address'),
519 email = wtforms.StringField(_('Email Address'),
522 filters=[strip_filter],
520 filters=[strip_filter],
523 validators=[email_validator,
521 validators=[email_validator,
524 unique_alert_email_validator,
522 unique_alert_email_validator,
525 wtforms.validators.DataRequired()])
523 wtforms.validators.DataRequired()])
526 submit = wtforms.SubmitField('Add email channel', )
524 submit = wtforms.SubmitField('Add email channel', )
527 ignore_labels = ['submit']
525 ignore_labels = ['submit']
528 css_classes = {'submit': 'btn btn-primary'}
526 css_classes = {'submit': 'btn btn-primary'}
529
527
530
528
531 def gen_user_profile_form():
529 def gen_user_profile_form():
532 class UserProfileForm(ReactorForm):
530 class UserProfileForm(ReactorForm):
533 email = wtforms.StringField(
531 email = wtforms.StringField(
534 _('Email Address'),
532 _('Email Address'),
535 validators=[email_validator, wtforms.validators.DataRequired()])
533 validators=[email_validator, wtforms.validators.DataRequired()])
536 first_name = wtforms.StringField(_('First Name'))
534 first_name = wtforms.StringField(_('First Name'))
537 last_name = wtforms.StringField(_('Last Name'))
535 last_name = wtforms.StringField(_('Last Name'))
538 company_name = wtforms.StringField(_('Company Name'))
536 company_name = wtforms.StringField(_('Company Name'))
539 company_address = wtforms.TextAreaField(_('Company Address'))
537 company_address = wtforms.TextAreaField(_('Company Address'))
540 zip_code = wtforms.StringField(_('ZIP code'))
538 zip_code = wtforms.StringField(_('ZIP code'))
541 city = wtforms.StringField(_('City'))
539 city = wtforms.StringField(_('City'))
542 notifications = wtforms.BooleanField('Account notifications',
540 notifications = wtforms.BooleanField('Account notifications',
543 false_values=FALSE_VALUES)
541 false_values=FALSE_VALUES)
544 submit = wtforms.SubmitField(_('Update Account'))
542 submit = wtforms.SubmitField(_('Update Account'))
545 ignore_labels = ['submit']
543 ignore_labels = ['submit']
546 css_classes = {'submit': 'btn btn-primary'}
544 css_classes = {'submit': 'btn btn-primary'}
547
545
548 return UserProfileForm
546 return UserProfileForm
549
547
550
548
551 class PurgeAppForm(ReactorForm):
549 class PurgeAppForm(ReactorForm):
552 resource_id = wtforms.HiddenField(
550 resource_id = wtforms.HiddenField(
553 'App Id',
551 'App Id',
554 validators=[wtforms.validators.DataRequired()])
552 validators=[wtforms.validators.DataRequired()])
555 days = wtforms.IntegerField(
553 days = wtforms.IntegerField(
556 'Days',
554 'Days',
557 validators=[wtforms.validators.DataRequired()])
555 validators=[wtforms.validators.DataRequired()])
558 password = wtforms.PasswordField(
556 password = wtforms.PasswordField(
559 'Admin Password',
557 'Admin Password',
560 validators=[old_password_validator, wtforms.validators.DataRequired()])
558 validators=[old_password_validator, wtforms.validators.DataRequired()])
561 submit = wtforms.SubmitField(_('Purge Data'))
559 submit = wtforms.SubmitField(_('Purge Data'))
562 ignore_labels = ['submit']
560 ignore_labels = ['submit']
563 css_classes = {'submit': 'btn btn-primary'}
561 css_classes = {'submit': 'btn btn-primary'}
564
562
565
563
566 class IntegrationRepoForm(ReactorForm):
564 class IntegrationRepoForm(ReactorForm):
567 host_name = wtforms.StringField("Service Host", default='')
565 host_name = wtforms.StringField("Service Host", default='')
568 user_name = wtforms.StringField(
566 user_name = wtforms.StringField(
569 "User Name",
567 "User Name",
570 filters=[strip_filter],
568 filters=[strip_filter],
571 validators=[wtforms.validators.DataRequired(),
569 validators=[wtforms.validators.DataRequired(),
572 wtforms.validators.Length(min=1)])
570 wtforms.validators.Length(min=1)])
573 repo_name = wtforms.StringField(
571 repo_name = wtforms.StringField(
574 "Repo Name",
572 "Repo Name",
575 filters=[strip_filter],
573 filters=[strip_filter],
576 validators=[wtforms.validators.DataRequired(),
574 validators=[wtforms.validators.DataRequired(),
577 wtforms.validators.Length(min=1)])
575 wtforms.validators.Length(min=1)])
578
576
579
577
580 class IntegrationBitbucketForm(IntegrationRepoForm):
578 class IntegrationBitbucketForm(IntegrationRepoForm):
581 host_name = wtforms.StringField("Service Host",
579 host_name = wtforms.StringField("Service Host",
582 default='https://bitbucket.org')
580 default='https://bitbucket.org')
583
581
584 def validate_user_name(self, field):
582 def validate_user_name(self, field):
585 try:
583 try:
586 request = pyramid.threadlocal.get_current_request()
584 request = pyramid.threadlocal.get_current_request()
587 client = BitbucketIntegration.create_client(
585 client = BitbucketIntegration.create_client(
588 request,
586 request,
589 self.user_name.data,
587 self.user_name.data,
590 self.repo_name.data)
588 self.repo_name.data)
591 client.get_assignees()
589 client.get_assignees()
592 except IntegrationException as e:
590 except IntegrationException as e:
593 raise wtforms.validators.ValidationError(str(e))
591 raise wtforms.validators.ValidationError(str(e))
594
592
595
593
596 class IntegrationGithubForm(IntegrationRepoForm):
594 class IntegrationGithubForm(IntegrationRepoForm):
597 host_name = wtforms.StringField("Service Host",
595 host_name = wtforms.StringField("Service Host",
598 default='https://github.com')
596 default='https://github.com')
599
597
600 def validate_user_name(self, field):
598 def validate_user_name(self, field):
601 try:
599 try:
602 request = pyramid.threadlocal.get_current_request()
600 request = pyramid.threadlocal.get_current_request()
603 client = GithubIntegration.create_client(
601 client = GithubIntegration.create_client(
604 request,
602 request,
605 self.user_name.data,
603 self.user_name.data,
606 self.repo_name.data)
604 self.repo_name.data)
607 client.get_assignees()
605 client.get_assignees()
608 except IntegrationException as e:
606 except IntegrationException as e:
609 raise wtforms.validators.ValidationError(str(e))
607 raise wtforms.validators.ValidationError(str(e))
610 raise wtforms.validators.ValidationError(str(e))
608 raise wtforms.validators.ValidationError(str(e))
611
609
612
610
613 def filter_rooms(data):
611 def filter_rooms(data):
614 if data is not None:
612 if data is not None:
615 rooms = data.split(',')
613 rooms = data.split(',')
616 return ','.join([r.strip() for r in rooms])
614 return ','.join([r.strip() for r in rooms])
617
615
618
616
619 class IntegrationCampfireForm(ReactorForm):
617 class IntegrationCampfireForm(ReactorForm):
620 account = wtforms.StringField(
618 account = wtforms.StringField(
621 'Account',
619 'Account',
622 filters=[strip_filter],
620 filters=[strip_filter],
623 validators=[wtforms.validators.DataRequired()])
621 validators=[wtforms.validators.DataRequired()])
624 api_token = wtforms.StringField(
622 api_token = wtforms.StringField(
625 'Api Token',
623 'Api Token',
626 filters=[strip_filter],
624 filters=[strip_filter],
627 validators=[wtforms.validators.DataRequired()])
625 validators=[wtforms.validators.DataRequired()])
628 rooms = wtforms.StringField('Room ID list', filters=[filter_rooms])
626 rooms = wtforms.StringField('Room ID list', filters=[filter_rooms])
629
627
630 def validate_api_token(self, field):
628 def validate_api_token(self, field):
631 try:
629 try:
632 client = CampfireIntegration.create_client(self.api_token.data,
630 client = CampfireIntegration.create_client(self.api_token.data,
633 self.account.data)
631 self.account.data)
634 client.get_account()
632 client.get_account()
635 except IntegrationException as e:
633 except IntegrationException as e:
636 raise wtforms.validators.ValidationError(str(e))
634 raise wtforms.validators.ValidationError(str(e))
637
635
638 def validate_rooms(self, field):
636 def validate_rooms(self, field):
639 if not field.data:
637 if not field.data:
640 return
638 return
641 client = CampfireIntegration.create_client(self.api_token.data,
639 client = CampfireIntegration.create_client(self.api_token.data,
642 self.account.data)
640 self.account.data)
643
641
644 try:
642 try:
645 room_list = [r['id'] for r in client.get_rooms()]
643 room_list = [r['id'] for r in client.get_rooms()]
646 except IntegrationException as e:
644 except IntegrationException as e:
647 raise wtforms.validators.ValidationError(str(e))
645 raise wtforms.validators.ValidationError(str(e))
648
646
649 rooms = field.data.split(',')
647 rooms = field.data.split(',')
650 if len(rooms) > 3:
648 if len(rooms) > 3:
651 msg = 'You can use up to 3 room ids'
649 msg = 'You can use up to 3 room ids'
652 raise wtforms.validators.ValidationError(msg)
650 raise wtforms.validators.ValidationError(msg)
653 if rooms:
651 if rooms:
654 for room_id in rooms:
652 for room_id in rooms:
655 if int(room_id) not in room_list:
653 if int(room_id) not in room_list:
656 msg = "Room %s doesn't exist"
654 msg = "Room %s doesn't exist"
657 raise wtforms.validators.ValidationError(msg % room_id)
655 raise wtforms.validators.ValidationError(msg % room_id)
658 if not room_id.strip().isdigit():
656 if not room_id.strip().isdigit():
659 msg = 'You must use only integers for room ids'
657 msg = 'You must use only integers for room ids'
660 raise wtforms.validators.ValidationError(msg)
658 raise wtforms.validators.ValidationError(msg)
661
659
662 submit = wtforms.SubmitField(_('Connect to Campfire'))
660 submit = wtforms.SubmitField(_('Connect to Campfire'))
663 ignore_labels = ['submit']
661 ignore_labels = ['submit']
664 css_classes = {'submit': 'btn btn-primary'}
662 css_classes = {'submit': 'btn btn-primary'}
665
663
666
664
667 def filter_rooms(data):
665 def filter_rooms(data):
668 if data is not None:
666 if data is not None:
669 rooms = data.split(',')
667 rooms = data.split(',')
670 return ','.join([r.strip() for r in rooms])
668 return ','.join([r.strip() for r in rooms])
671
669
672
670
673 class IntegrationHipchatForm(ReactorForm):
671 class IntegrationHipchatForm(ReactorForm):
674 api_token = wtforms.StringField(
672 api_token = wtforms.StringField(
675 'Api Token',
673 'Api Token',
676 filters=[strip_filter],
674 filters=[strip_filter],
677 validators=[wtforms.validators.DataRequired()])
675 validators=[wtforms.validators.DataRequired()])
678 rooms = wtforms.StringField(
676 rooms = wtforms.StringField(
679 'Room ID list',
677 'Room ID list',
680 filters=[filter_rooms],
678 filters=[filter_rooms],
681 validators=[wtforms.validators.DataRequired()])
679 validators=[wtforms.validators.DataRequired()])
682
680
683 def validate_rooms(self, field):
681 def validate_rooms(self, field):
684 if not field.data:
682 if not field.data:
685 return
683 return
686 client = HipchatIntegration.create_client(self.api_token.data)
684 client = HipchatIntegration.create_client(self.api_token.data)
687 rooms = field.data.split(',')
685 rooms = field.data.split(',')
688 if len(rooms) > 3:
686 if len(rooms) > 3:
689 msg = 'You can use up to 3 room ids'
687 msg = 'You can use up to 3 room ids'
690 raise wtforms.validators.ValidationError(msg)
688 raise wtforms.validators.ValidationError(msg)
691 if rooms:
689 if rooms:
692 for room_id in rooms:
690 for room_id in rooms:
693 if not room_id.strip().isdigit():
691 if not room_id.strip().isdigit():
694 msg = 'You must use only integers for room ids'
692 msg = 'You must use only integers for room ids'
695 raise wtforms.validators.ValidationError(msg)
693 raise wtforms.validators.ValidationError(msg)
696 try:
694 try:
697 client.send({
695 client.send({
698 "message_format": 'text',
696 "message_format": 'text',
699 "message": "testing for room existence",
697 "message": "testing for room existence",
700 "from": "AppEnlight",
698 "from": "AppEnlight",
701 "room_id": room_id,
699 "room_id": room_id,
702 "color": "green"
700 "color": "green"
703 })
701 })
704 except IntegrationException as exc:
702 except IntegrationException as exc:
705 msg = 'Room id: %s exception: %s'
703 msg = 'Room id: %s exception: %s'
706 raise wtforms.validators.ValidationError(msg % (room_id,
704 raise wtforms.validators.ValidationError(msg % (room_id,
707 exc))
705 exc))
708
706
709
707
710 class IntegrationFlowdockForm(ReactorForm):
708 class IntegrationFlowdockForm(ReactorForm):
711 api_token = wtforms.StringField('API Token',
709 api_token = wtforms.StringField('API Token',
712 filters=[strip_filter],
710 filters=[strip_filter],
713 validators=[
711 validators=[
714 wtforms.validators.DataRequired()
712 wtforms.validators.DataRequired()
715 ], )
713 ], )
716
714
717 def validate_api_token(self, field):
715 def validate_api_token(self, field):
718 try:
716 try:
719 client = FlowdockIntegration.create_client(self.api_token.data)
717 client = FlowdockIntegration.create_client(self.api_token.data)
720 registry = pyramid.threadlocal.get_current_registry()
718 registry = pyramid.threadlocal.get_current_registry()
721 payload = {
719 payload = {
722 "source": registry.settings['mailing.from_name'],
720 "source": registry.settings['mailing.from_name'],
723 "from_address": registry.settings['mailing.from_email'],
721 "from_address": registry.settings['mailing.from_email'],
724 "subject": "Integration test",
722 "subject": "Integration test",
725 "content": "If you can see this it was successful",
723 "content": "If you can see this it was successful",
726 "tags": ["appenlight"],
724 "tags": ["appenlight"],
727 "link": registry.settings['mailing.app_url']
725 "link": registry.settings['mailing.app_url']
728 }
726 }
729 client.send_to_inbox(payload)
727 client.send_to_inbox(payload)
730 except IntegrationException as e:
728 except IntegrationException as e:
731 raise wtforms.validators.ValidationError(str(e))
729 raise wtforms.validators.ValidationError(str(e))
732
730
733
731
734 class IntegrationSlackForm(ReactorForm):
732 class IntegrationSlackForm(ReactorForm):
735 webhook_url = wtforms.StringField(
733 webhook_url = wtforms.StringField(
736 'Reports webhook',
734 'Reports webhook',
737 filters=[strip_filter],
735 filters=[strip_filter],
738 validators=[wtforms.validators.DataRequired()])
736 validators=[wtforms.validators.DataRequired()])
739
737
740 def validate_webhook_url(self, field):
738 def validate_webhook_url(self, field):
741 registry = pyramid.threadlocal.get_current_registry()
739 registry = pyramid.threadlocal.get_current_registry()
742 client = SlackIntegration.create_client(field.data)
740 client = SlackIntegration.create_client(field.data)
743 link = "<%s|%s>" % (registry.settings['mailing.app_url'],
741 link = "<%s|%s>" % (registry.settings['mailing.app_url'],
744 registry.settings['mailing.from_name'])
742 registry.settings['mailing.from_name'])
745 test_data = {
743 test_data = {
746 "username": "AppEnlight",
744 "username": "AppEnlight",
747 "icon_emoji": ":fire:",
745 "icon_emoji": ":fire:",
748 "attachments": [
746 "attachments": [
749 {"fallback": "Testing integration channel: %s" % link,
747 {"fallback": "Testing integration channel: %s" % link,
750 "pretext": "Testing integration channel: %s" % link,
748 "pretext": "Testing integration channel: %s" % link,
751 "color": "good",
749 "color": "good",
752 "fields": [
750 "fields": [
753 {
751 {
754 "title": "Status",
752 "title": "Status",
755 "value": "Integration is working fine",
753 "value": "Integration is working fine",
756 "short": False
754 "short": False
757 }
755 }
758 ]}
756 ]}
759 ]
757 ]
760 }
758 }
761 try:
759 try:
762 client.make_request(data=test_data)
760 client.make_request(data=test_data)
763 except IntegrationException as exc:
761 except IntegrationException as exc:
764 raise wtforms.validators.ValidationError(str(exc))
762 raise wtforms.validators.ValidationError(str(exc))
765
763
766
764
767 class IntegrationWebhooksForm(ReactorForm):
765 class IntegrationWebhooksForm(ReactorForm):
768 reports_webhook = wtforms.StringField(
766 reports_webhook = wtforms.StringField(
769 'Reports webhook',
767 'Reports webhook',
770 filters=[strip_filter],
768 filters=[strip_filter],
771 validators=[wtforms.validators.DataRequired()])
769 validators=[wtforms.validators.DataRequired()])
772 alerts_webhook = wtforms.StringField(
770 alerts_webhook = wtforms.StringField(
773 'Alerts webhook',
771 'Alerts webhook',
774 filters=[strip_filter],
772 filters=[strip_filter],
775 validators=[wtforms.validators.DataRequired()])
773 validators=[wtforms.validators.DataRequired()])
776 submit = wtforms.SubmitField(_('Setup webhooks'))
774 submit = wtforms.SubmitField(_('Setup webhooks'))
777 ignore_labels = ['submit']
775 ignore_labels = ['submit']
778 css_classes = {'submit': 'btn btn-primary'}
776 css_classes = {'submit': 'btn btn-primary'}
779
777
780
778
781 class IntegrationJiraForm(ReactorForm):
779 class IntegrationJiraForm(ReactorForm):
782 host_name = wtforms.StringField(
780 host_name = wtforms.StringField(
783 'Server URL',
781 'Server URL',
784 filters=[strip_filter],
782 filters=[strip_filter],
785 validators=[wtforms.validators.DataRequired()])
783 validators=[wtforms.validators.DataRequired()])
786 user_name = wtforms.StringField(
784 user_name = wtforms.StringField(
787 'Username',
785 'Username',
788 filters=[strip_filter],
786 filters=[strip_filter],
789 validators=[wtforms.validators.DataRequired()])
787 validators=[wtforms.validators.DataRequired()])
790 password = wtforms.PasswordField(
788 password = wtforms.PasswordField(
791 'Password',
789 'Password',
792 filters=[strip_filter],
790 filters=[strip_filter],
793 validators=[wtforms.validators.DataRequired()])
791 validators=[wtforms.validators.DataRequired()])
794 project = wtforms.StringField(
792 project = wtforms.StringField(
795 'Project key',
793 'Project key',
796 filters=[uppercase_filter, strip_filter],
794 filters=[uppercase_filter, strip_filter],
797 validators=[wtforms.validators.DataRequired()])
795 validators=[wtforms.validators.DataRequired()])
798
796
799 def validate_project(self, field):
797 def validate_project(self, field):
800 if not field.data:
798 if not field.data:
801 return
799 return
802 try:
800 try:
803 client = JiraClient(self.user_name.data,
801 client = JiraClient(self.user_name.data,
804 self.password.data,
802 self.password.data,
805 self.host_name.data,
803 self.host_name.data,
806 self.project.data)
804 self.project.data)
807 except Exception as exc:
805 except Exception as exc:
808 raise wtforms.validators.ValidationError(str(exc))
806 raise wtforms.validators.ValidationError(str(exc))
809
807
810 room_list = [r.key.upper() for r in client.get_projects()]
808 room_list = [r.key.upper() for r in client.get_projects()]
811 if field.data.upper() not in room_list:
809 if field.data.upper() not in room_list:
812 msg = "Project %s doesn\t exist in your Jira Instance"
810 msg = "Project %s doesn\t exist in your Jira Instance"
813 raise wtforms.validators.ValidationError(msg % field.data)
811 raise wtforms.validators.ValidationError(msg % field.data)
814
812
815
813
816 def get_deletion_form(resource):
814 def get_deletion_form(resource):
817 class F(ReactorForm):
815 class F(ReactorForm):
818 application_name = wtforms.StringField(
816 application_name = wtforms.StringField(
819 'Application Name',
817 'Application Name',
820 filters=[strip_filter],
818 filters=[strip_filter],
821 validators=[wtforms.validators.AnyOf([resource.resource_name])])
819 validators=[wtforms.validators.AnyOf([resource.resource_name])])
822 resource_id = wtforms.HiddenField(default=resource.resource_id)
820 resource_id = wtforms.HiddenField(default=resource.resource_id)
823 submit = wtforms.SubmitField(_('Delete my application'))
821 submit = wtforms.SubmitField(_('Delete my application'))
824 ignore_labels = ['submit']
822 ignore_labels = ['submit']
825 css_classes = {'submit': 'btn btn-danger'}
823 css_classes = {'submit': 'btn btn-danger'}
826
824
827 return F
825 return F
828
826
829
827
830 class ChangeApplicationOwnerForm(ReactorForm):
828 class ChangeApplicationOwnerForm(ReactorForm):
831 password = wtforms.PasswordField(
829 password = wtforms.PasswordField(
832 'Password',
830 'Password',
833 filters=[strip_filter],
831 filters=[strip_filter],
834 validators=[old_password_validator,
832 validators=[old_password_validator,
835 wtforms.validators.DataRequired()])
833 wtforms.validators.DataRequired()])
836
834
837 user_name = wtforms.StringField(
835 user_name = wtforms.StringField(
838 'New owners username',
836 'New owners username',
839 filters=[strip_filter],
837 filters=[strip_filter],
840 validators=[found_username_validator,
838 validators=[found_username_validator,
841 wtforms.validators.DataRequired()])
839 wtforms.validators.DataRequired()])
842 submit = wtforms.SubmitField(_('Transfer ownership of application'))
840 submit = wtforms.SubmitField(_('Transfer ownership of application'))
843 ignore_labels = ['submit']
841 ignore_labels = ['submit']
844 css_classes = {'submit': 'btn btn-danger'}
842 css_classes = {'submit': 'btn btn-danger'}
845
843
846
844
847 def default_filename():
845 def default_filename():
848 return 'Invoice %s' % datetime.datetime.utcnow().strftime('%Y/%m')
846 return 'Invoice %s' % datetime.datetime.utcnow().strftime('%Y/%m')
849
847
850
848
851 class FileUploadForm(ReactorForm):
849 class FileUploadForm(ReactorForm):
852 title = wtforms.StringField('File Title',
850 title = wtforms.StringField('File Title',
853 default=default_filename,
851 default=default_filename,
854 validators=[wtforms.validators.DataRequired()])
852 validators=[wtforms.validators.DataRequired()])
855 file = wtforms.FileField('File')
853 file = wtforms.FileField('File')
856
854
857 def validate_file(self, field):
855 def validate_file(self, field):
858 if not hasattr(field.data, 'file'):
856 if not hasattr(field.data, 'file'):
859 raise wtforms.ValidationError('File is missing')
857 raise wtforms.ValidationError('File is missing')
860
858
861 submit = wtforms.SubmitField(_('Upload'))
859 submit = wtforms.SubmitField(_('Upload'))
862
860
863
861
864 def get_partition_deletion_form(es_indices, pg_indices):
862 def get_partition_deletion_form(es_indices, pg_indices):
865 class F(ReactorForm):
863 class F(ReactorForm):
866 es_index = wtforms.SelectMultipleField('Elasticsearch',
864 es_index = wtforms.SelectMultipleField('Elasticsearch',
867 choices=[(ix, '') for ix in
865 choices=[(ix, '') for ix in
868 es_indices])
866 es_indices])
869 pg_index = wtforms.SelectMultipleField('pg',
867 pg_index = wtforms.SelectMultipleField('pg',
870 choices=[(ix, '') for ix in
868 choices=[(ix, '') for ix in
871 pg_indices])
869 pg_indices])
872 confirm = wtforms.TextField('Confirm',
870 confirm = wtforms.TextField('Confirm',
873 filters=[uppercase_filter, strip_filter],
871 filters=[uppercase_filter, strip_filter],
874 validators=[
872 validators=[
875 wtforms.validators.AnyOf(['CONFIRM']),
873 wtforms.validators.AnyOf(['CONFIRM']),
876 wtforms.validators.DataRequired()])
874 wtforms.validators.DataRequired()])
877 ignore_labels = ['submit']
875 ignore_labels = ['submit']
878 css_classes = {'submit': 'btn btn-danger'}
876 css_classes = {'submit': 'btn btn-danger'}
879
877
880 return F
878 return F
881
879
882
880
883 class GroupCreateForm(ReactorForm):
881 class GroupCreateForm(ReactorForm):
884 group_name = wtforms.StringField(
882 group_name = wtforms.StringField(
885 _('Group Name'),
883 _('Group Name'),
886 filters=[strip_filter],
884 filters=[strip_filter],
887 validators=[
885 validators=[
888 wtforms.validators.Length(min=2, max=50),
886 wtforms.validators.Length(min=2, max=50),
889 unique_groupname_validator,
887 unique_groupname_validator,
890 wtforms.validators.DataRequired()
888 wtforms.validators.DataRequired()
891 ])
889 ])
892 description = wtforms.StringField(_('Group description'))
890 description = wtforms.StringField(_('Group description'))
893
891
894
892
895 time_choices = [(k, v['label'],) for k, v in h.time_deltas.items()]
893 time_choices = [(k, v['label'],) for k, v in h.time_deltas.items()]
896
894
897
895
898 class AuthTokenCreateForm(ReactorForm):
896 class AuthTokenCreateForm(ReactorForm):
899 description = wtforms.StringField(_('Token description'))
897 description = wtforms.StringField(_('Token description'))
900 expires = wtforms.SelectField('Expires',
898 expires = wtforms.SelectField('Expires',
901 coerce=lambda x: x,
899 coerce=lambda x: x,
902 choices=time_choices,
900 choices=time_choices,
903 validators=[wtforms.validators.Optional()])
901 validators=[wtforms.validators.Optional()])
General Comments 0
You need to be logged in to leave comments. Login now