Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: sitescripts/formmail/web/formmail2.py

Issue 29374647: Issue 4814 - Adds csv log to formmail2 (Closed) Base URL: https://hg.adblockplus.org/sitescripts
Patch Set: Created March 18, 2017, 4:13 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 # This file is part of the Adblock Plus web scripts, 1 # This file is part of the Adblock Plus web scripts,
2 # Copyright (C) 2006-2016 Eyeo GmbH 2 # Copyright (C) 2006-2016 Eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details. 11 # GNU General Public License for more details.
12 # 12 #
13 # You should have received a copy of the GNU General Public License 13 # You should have received a copy of the GNU General Public License
14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
15 15 import os
16 import datetime 16 import datetime
17 import collections 17 import collections
18 from csv import DictWriter, DictReader
18 19
19 from sitescripts.utils import (get_config, sendMail, encode_email_address, 20 from sitescripts.utils import (get_config, sendMail, encode_email_address,
20 get_template) 21 get_template)
21 from sitescripts.web import registerUrlHandler, form_handler 22 from sitescripts.web import registerUrlHandler, form_handler
22 23
23 24
24 def get_config_items(): 25 def get_config_items():
25 config = get_config() 26 config = get_config()
26 default_keys = set(config.defaults()) 27 default_keys = set(config.defaults())
27 for name, value in config.items('formmail2'): 28 for name, value in config.items('formmail2'):
(...skipping 18 matching lines...) Expand all
46 store_value(conf_dict, path, value) 47 store_value(conf_dict, path, value)
47 return conf_dict 48 return conf_dict
48 49
49 50
50 def make_error(spec, check_type, default_message): 51 def make_error(spec, check_type, default_message):
51 if check_type in spec: 52 if check_type in spec:
52 return spec[check_type].value 53 return spec[check_type].value
53 return default_message 54 return default_message
54 55
55 56
57 def log_formfield_error(parameters, log_path):
58 err_file = os.path.basename(log_path) + '_error'
59 err_path = os.path.join(os.path.dirname(log_path), err_file)
60 if os.path.isfile(err_path):
61 with open(err_path, 'a') as error_log:
62 writer = DictWriter(error_log, fieldnames=parameters.keys())
63 writer.writerow(parameters)
64 raise Exception('Field names have changed, error log '
65 'appended to ' + err_path)
66 with open(err_path, 'w') as error_log:
67 writer = DictWriter(error_log, fieldnames=parameters.keys())
68 writer.writeheader()
69 writer.writerow(parameters)
70 raise Exception('Field names have changed, error log '
71 'written to ' + err_path)
72
73
74 def log_formdata(params, path):
75 if os.path.isfile(path):
76 with open(path, 'ab+') as formlog:
77 formlog.seek(0)
78 reader = DictReader(formlog)
79 if reader.fieldnames != params.keys():
Jon Sonesen 2017/03/22 09:23:30 I think this is incorrect, after some local testin
Jon Sonesen 2017/03/22 14:28:21 Done.
80 log_formfield_error(params, path)
81 formlog.seek(os.SEEK_END)
82 writer = DictWriter(formlog, fieldnames=params.keys())
83 writer.writerow(params)
84 return
85 with open(path, 'w') as new_formlog:
86 writer = DictWriter(new_formlog, fieldnames=params.keys())
87 writer.writeheader()
88 writer.writerow(params)
89 return
90
91
92 def validate_fields(fields, params):
93 errors = []
94 for field, spec in fields.items():
95 if 'mandatory' in spec.value:
96 if field not in params.keys():
97 errors.append(make_error(spec, 'mandatory',
98 'No {} entered'.format(field)))
99 if 'email' in spec.value and field in params.keys():
100 try:
101 params[field] = encode_email_address(params[field])
102 except ValueError:
103 errors.append(make_error(spec, 'email', 'Invalid email'))
104 return errors
105
106
56 def make_handler(name, config): 107 def make_handler(name, config):
57 try: 108 try:
58 url = config['url'].value 109 url = config['url'].value
Jon Sonesen 2017/03/22 15:50:34 while parametrizing the tests which cover config e
59 except (KeyError, AttributeError): 110 except (KeyError, AttributeError):
60 raise Exception('No URL configured for form handler: ' + name) 111 raise Exception('No URL configured for form handler: ' + name)
61 try: 112 try:
62 template = config['template'].value 113 template = config['template'].value
63 get_template(template, autoescape=False) 114 get_template(template, autoescape=False)
Jon Sonesen 2017/03/22 15:50:34 Currently we are letting this raise jinjas Templat
64 except (KeyError, AttributeError): 115 except (KeyError, AttributeError):
65 raise Exception('No template configured for form handler: ' + name) 116 raise Exception('No template configured for form handler: ' + name)
66 try: 117 try:
67 fields = config['fields'] 118 fields = config['fields']
68 for field, spec in fields.items(): 119 for field, spec in fields.items():
69 spec.value = {s.strip() for s in spec.value.split(',')} 120 spec.value = {s.strip() for s in spec.value.split(',')}
70 except KeyError: 121 except KeyError:
71 raise Exception('No fields configured for form handler: ' + name) 122 raise Exception('No fields configured for form handler: ' + name)
72 if len(fields) == 0: 123 if len(fields) == 0:
73 raise Exception('No fields configured for form handler: ' + name) 124 raise Exception('No fields configured for form handler: ' + name)
74 125
75 @form_handler 126 @form_handler
76 def handler(environ, start_response, params): 127 def handler(environ, start_response, params):
77 response_headers = [('Content-Type', 'text/plain; charset=utf-8')] 128 response_headers = [('Content-Type', 'text/plain; charset=utf-8')]
78 errors = [] 129 errors = validate_fields(fields, params)
79 for field, spec in fields.items():
80 if 'mandatory' in spec.value:
81 if field not in params.keys():
82 errors.append(make_error(spec, 'mandatory',
83 'No {} entered'.format(field)))
84 if 'email' in spec.value and field in params.keys():
85 try:
86 params[field] = encode_email_address(params[field])
87 except ValueError:
88 errors.append(make_error(spec, 'email', 'Invalid email'))
89 if errors: 130 if errors:
90 start_response('400 Bad Request', response_headers) 131 start_response('400 Bad Request', response_headers)
91 return '\n'.join(errors) 132 return '\n'.join(errors)
92 133 time = datetime.datetime.now()
93 template_args = { 134 template_args = {
94 'time': datetime.datetime.now(), 135 'time': time,
95 'fields': {field: params.get(field, '') for field in fields} 136 'fields': {field: params.get(field, '') for field in fields}
96 } 137 }
97 sendMail(template, template_args) 138 try:
139 sendMail(template, template_args)
140 except:
141 start_response('500 Server Error', response_headers)
Vasily Kuznetsov 2017/03/21 14:00:35 I wonder if we could log the stacktrace here someh
Jon Sonesen 2017/03/22 14:28:21 Done.
142 return ''
143 finally:
144 if 'csv_log' in config:
145 params = {field: params.get(field, '').encode('utf8')
146 for field in fields}
147 params['time'] = time
148 log_formdata(params, config['csv_log'].value)
98 start_response('200 OK', response_headers) 149 start_response('200 OK', response_headers)
99 return '' 150 return ''
100 151
101 return url, handler 152 return url, handler
102 153
103 154
104 conf_dict = conf_parse(get_config_items()) 155 conf_dict = conf_parse(get_config_items())
105 for name, config in conf_dict.items(): 156 for name, config in conf_dict.items():
106 url, handler = make_handler(name, config) 157 url, handler = make_handler(name, config)
107 registerUrlHandler(url, handler) 158 registerUrlHandler(url, handler)
OLDNEW

Powered by Google App Engine
This is Rietveld