Permalink
Browse files

bug 797470 - email and url in report list/index, r=rhelmer

  • Loading branch information...
1 parent e779743 commit f6b87710342cd24f1732f28a8f0bf2e20b93233b @peterbe peterbe committed Oct 10, 2012
@@ -45,7 +45,8 @@ class SocorroCommon(object):
# default cache expiration time if applicable
cache_seconds = 60 * 60
- def fetch(self, url, headers=None, method='get', data=None):
+ def fetch(self, url, headers=None, method='get', data=None,
+ expect_json=True):
if url.startswith('/'):
url = self._complete_url(url)
@@ -86,7 +87,10 @@ def fetch(self, url, headers=None, method='get', data=None):
cache_file = os.path.join(cache_file,
_clean_query(split.query))
- cache_file = os.path.join(cache_file, '%s.json' % cache_key)
+ if expect_json:
+ cache_file = os.path.join(cache_file, '%s.json' % cache_key)
+ else:
+ cache_file = os.path.join(cache_file, '%s.dump' % cache_key)
if os.path.isfile(cache_file):
# but is it fresh enough?
@@ -96,7 +100,10 @@ def fetch(self, url, headers=None, method='get', data=None):
os.remove(cache_file)
else:
logging.debug("CACHE FILE HIT %s" % url)
- return json.load(open(cache_file))
+ if expect_json:
+ return json.load(open(cache_file))
+ else:
+ return open(cache_file).read()
if method == 'post':
request_method = requests.post
@@ -109,14 +116,19 @@ def fetch(self, url, headers=None, method='get', data=None):
if not resp.status_code == 200:
raise BadStatusCodeError('%s: on: %s' % (resp.status_code, url))
- result = json.loads(resp.content)
+ result = resp.content
+ if expect_json:
+ result = json.loads(result)
if cache_key:
cache.set(cache_key, result, self.cache_seconds)
if cache_file:
if not os.path.isdir(os.path.dirname(cache_file)):
os.makedirs(os.path.dirname(cache_file))
- json.dump(result, open(cache_file, 'w'), indent=2)
+ if expect_json:
+ json.dump(result, open(cache_file, 'w'), indent=2)
+ else:
+ open(cache_file, 'w').write(result)
return result
@@ -313,13 +325,14 @@ def get(self, crash_id):
class RawCrash(SocorroMiddleware):
- def get(self, crash_id):
+ def get(self, crash_id, format='meta'):
params = {
'crash_id': crash_id,
+ 'format': format,
}
self.urlencode_params(params)
- url = '/crash/meta/by/uuid/%(crash_id)s' % params
- return self.fetch(url)
+ url = '/crash/%(format)s/by/uuid/%(crash_id)s' % params
+ return self.fetch(url, expect_json=format != 'raw_crash')
class CommentsBySignature(SocorroMiddleware):
@@ -117,9 +117,27 @@
<th>Crash Address</th>
<td>{{ report.address }}</td>
</tr>
+ {% if request.user.is_active %}
+ <tr>
+ <th>Email Address</th>
+ <td>
+ {% if report.email %}
+ <a href="mailto:{{ report.email }}">{{ report.email }}</a> - Super Sensitive! Don't mess around!
+ {% endif %}
+ </td>
+ </tr>
+ <tr>
+ <th>URL</th>
+ <td>
+ {% if report.url %}
+ <a href="{{ report.url }}" title="{{ report.url }}">{{ report.url }}</a> - Super Sensitive! Don't mess around!
+ {% endif %}
+ </td>
+ </tr>
+ {% endif %}
<tr>
<th>User Comments</th>
- <td></td>
+ <td>{{ report.user_comments }}</td>
</tr>
{% if report.app_notes %}
<tr>
@@ -358,6 +376,13 @@
<div class="code">
{{ report.dump }}
</div>
+
+ {% if request.user.is_active %}
+ <h3>Download the Raw Dump</h3>
+ {% for url in raw_dump_urls %}
+ <p><a href="{{ url }}">{{ url }}</a></p>
+ {% endfor %}
+ {% endif %}
</div><!-- /rawdump -->
<div id="extensions" class="ui-tabs-hide">
@@ -387,11 +412,14 @@
{% if comments.total > 0 %}
{% for comment in comments.hits %}
<p class="crash_comments">
- {{ comment.user_comments }}
+ {{ comment.user_comments|nl2br }}
</p>
<p class="crash_comments">
- <a href="/report/index/{{ comment.uuid }}">Submitted: {{ comment.date_processed }}</a>
+ <a href="{{ url('crashstats.report_index', comment.uuid) }}">Submitted: {{ comment.date_processed }}</a>
</p>
+ {% if request.user.is_active %}
+ <p class="crash_comments">Email: {% if comment.email %}<a href="mailto:{{ comment.email }}">{{ comment.email }}</a>{% endif %}</p>
+ {% endif %}
<hr>
{% endfor %}
{% else %}
@@ -261,9 +261,12 @@ <h3 id="by_platform_graph">Crashes By Build Date</h3>
</div>
<div id="comments" class="ui-tabs-hide">
<h2>Comments</h2>
- {% for c in comments %}
- <p class="crash_comments">{{ c[0] }}
- <p class="crash_comments"><a href="{{ url('crashstats.report_index', c[1]) }}">Submitted: {{ c[2] }}</a></p>
+ {% for comment in comments.hits %}
+ <p class="crash_comments">{{ comment.user_comments|nl2br}}</p>
+ <p class="crash_comments"><a href="{{ url('crashstats.report_index', comment.uuid) }}">Submitted: {{ comment.date_processed }}</a></p>
+ {% if request.user.is_active %}
+ <p class="crash_comments">Email: {% if comment.email %}<a href="mailto:{{ comment.email }}">{{ comment.email }}</a>{% endif %}</p>
+ {% endif %}
<hr>
{% endfor %}
</div>
@@ -883,6 +883,7 @@ def mocked_get(**options):
def test_report_index(self, rget, rpost):
dump = "OS|Mac OS X|10.6.8 10K549\\nCPU|amd64|family 6 mod"
comment0 = "This is a comment"
+ email0 = "some@emailaddress.com"
def mocked_get(url, **options):
if 'crash/meta' in url:
@@ -903,13 +904,13 @@ def mocked_get(url, **options):
{
"user_comments": "%s",
"date_processed": "2012-08-21T11:17:28-07:00",
- "email": "socorro-12109@restmail.net",
+ "email": "%s",
"uuid": "469bde48-0e8f-3586-d486-b98810120830"
}
],
"total": 1
}
- """ % comment0)
+ """ % (comment0, email0))
if 'crash/processed' in url:
return Response("""
@@ -964,6 +965,14 @@ def mocked_post(url, **options):
ok_('FakeSignature1' in response.content)
ok_('11cb72f5-eb28-41e1-a8e4-849982120611' in response.content)
ok_(comment0 in response.content)
+ ok_(email0 not in response.content)
+
+ # the email address will appear if we log in
+ User.objects.create_user('test', 'test@mozilla.com', 'secret')
+ assert self.client.login(username='test', password='secret')
+ response = self.client.get(url)
+ eq_(response.status_code, 200)
+ ok_(email0 in response.content)
@mock.patch('requests.post')
@mock.patch('requests.get')
@@ -1034,6 +1043,21 @@ def mocked_get(url, **options):
"total": 2
}
""")
+ if '/crashes/comments/' in url:
+ return Response("""
+ {
+ "hits": [
+ {
+ "user_comments": "I LOVE CHEESE",
+ "date_processed": "2012-08-21T11:17:28-07:00",
+ "email": "bob@uncle.com",
+ "uuid": "469bde48-0e8f-3586-d486-b98810120830"
+ }
+ ],
+ "total": 1
+ }
+ """)
+
raise NotImplementedError(url)
rget.side_effect = mocked_get
@@ -1049,6 +1073,8 @@ def mocked_get(url, **options):
eq_(response.status_code, 200)
ok_('0xdeadbeef' in response.content)
+ ok_('I LOVE CHEESE' in response.content)
+ ok_('bob@uncle.com' not in response.content)
@mock.patch('requests.post')
@mock.patch('requests.get')
@@ -1168,6 +1194,22 @@ def mocked_get(url, **options):
"total": 2
}
""")
+
+ if '/crashes/comments/' in url:
+ return Response("""
+ {
+ "hits": [
+ {
+ "user_comments": "I LOVE CHEESE",
+ "date_processed": "2012-08-21T11:17:28-07:00",
+ "email": "bob@uncle.com",
+ "uuid": "469bde48-0e8f-3586-d486-b98810120830"
+ }
+ ],
+ "total": 1
+ }
+ """)
+
raise NotImplementedError(url)
rget.side_effect = mocked_get
@@ -1176,6 +1218,7 @@ def mocked_get(url, **options):
response = self.client.get(url, {'range_value': 3})
eq_(response.status_code, 200)
ok_('http://farm.ville' not in response.content)
+ ok_('bob@uncle.com' not in response.content)
User.objects.create_user('test', 'test@mozilla.com', 'secret')
assert self.client.login(username='test', password='secret')
@@ -1185,5 +1228,57 @@ def mocked_get(url, **options):
eq_(response.status_code, 200)
# now it suddenly appears when we're logged in
ok_('http://farm.ville' in response.content)
+ ok_('bob@uncle.com' in response.content)
# not too long...
ok_(really_long_url[:80 - 3] + '...' in response.content)
+
+ @mock.patch('requests.get')
+ def test_raw_data(self, rget):
+
+ def mocked_get(url, **options):
+ if 'crash/meta/by/uuid' in url:
+ return Response("""
+ {"foo": "bar",
+ "stuff": 123}
+ """)
+ if 'crash/raw_crash/by/uuid' in url:
+ return Response("""
+ bla bla bla
+ """.strip())
+ raise NotImplementedError(url)
+
+ rget.side_effect = mocked_get
+
+ crash_id = '176bcd6c-c2ec-4b0c-9d5f-dadea2120531'
+ json_url = reverse('crashstats.raw_data', args=(crash_id, 'json'))
+ response = self.client.get(json_url)
+ eq_(response.status_code, 403)
+
+ User.objects.create_user('test', 'test@mozilla.com', 'secret')
+ assert self.client.login(username='test', password='secret')
+ response = self.client.get(json_url)
+ eq_(response.status_code, 200)
+ eq_(response['Content-Type'], 'application/json')
+ eq_(json.loads(response.content),
+ {"foo": "bar", "stuff": 123})
+
+ dump_url = reverse('crashstats.raw_data', args=(crash_id, 'dump'))
+ response = self.client.get(dump_url)
+ eq_(response.status_code, 200)
+ eq_(response['Content-Type'], 'application/octet-stream')
+ ok_('bla bla bla' in response.content)
+
+ # dump files are cached.
+ # check the mock function and expect no change
+ def different_mocked_get(url, **options):
+ if 'crash/raw_crash/by/uuid' in url:
+ return Response("""
+ SOMETHING DIFFERENT
+ """.strip())
+ raise NotImplementedError(url)
+
+ rget.side_effect = different_mocked_get
+
+ response = self.client.get(dump_url)
+ eq_(response.status_code, 200)
+ ok_('bla bla bla' in response.content) # still. good.
@@ -98,6 +98,9 @@
url(r'^signature_summary/json_data$',
views.signature_summary,
name='crashstats.signature_summary'),
+ url(r'^rawdumps/(?P<crash_id>[\w-]{36}).(?P<extension>json|dump)$',
+ views.raw_data,
+ name='crashstats.raw_data'),
# if we do a permanent redirect, the browser will "cache" the redirect and
# it will make it very hard to ever change the DEFAULT_PRODUCT
url(r'^$',
@@ -730,6 +730,11 @@ def report_index(request, crash_id):
data['hang_id']
)
+ data['raw_dump_urls'] = [
+ reverse('crashstats.raw_data', args=(crash_id, 'dump')),
+ reverse('crashstats.raw_data', args=(crash_id, 'json'))
+ ]
+
return render(request, 'crashstats/report_index.html', data)
@@ -764,7 +769,6 @@ def report_list(request):
data['report_list'] = api.get(signature, product_version,
start_date, results_per_page,
result_offset)
-
current_query = request.GET.copy()
if 'page' in current_query:
del current_query['page']
@@ -814,11 +818,6 @@ def report_list(request):
else:
data['table'][buildid][os_name] += 1
- if report['user_comments']:
- data['comments'].append((report['user_comments'],
- report['uuid'],
- report['date_processed']))
-
# signature URLs only if you're logged in
data['signature_urls'] = None
if request.user.is_active:
@@ -832,6 +831,10 @@ def report_list(request):
)
data['signature_urls'] = sigurls['hits']
+ comments_api = models.CommentsBySignature()
+ data['comments'] = comments_api.get(data['signature'],
+ start_date, end_date)
+
bugs_api = models.Bugs()
data['bug_associations'] = bugs_api.get(
[data['signature']]
@@ -1176,3 +1179,27 @@ def item_description(self, item):
def item_pubdate(self, item):
return datetime.datetime.strptime(item['date'], '%Y-%m-%d')
+
+
+def raw_data(request, crash_id, extension):
+ if not request.user.is_active:
+ return http.HttpResponseForbidden("Must be logged in")
+
+ api = models.RawCrash()
+ if extension == 'json':
+ format = 'meta'
+ content_type = 'application/json'
+ elif extension == 'dump':
+ format = 'raw_crash'
+ content_type = 'application/octet-stream'
+ else:
+ raise NotImplementedError(extension)
+
+ data = api.get(crash_id, format)
+ response = http.HttpResponse(content_type=content_type)
+
+ if extension == 'json':
+ response.write(json.dumps(data))
+ else:
+ response.write(data)
+ return response

0 comments on commit f6b8771

Please sign in to comment.