Skip to content
This repository has been archived by the owner on Jul 14, 2023. It is now read-only.

Commit

Permalink
use pyaml to display non-string values in the submissions page.
Browse files Browse the repository at this point in the history
  • Loading branch information
fiatjaf committed Jan 10, 2018
1 parent 9b24823 commit e89c30c
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 8 deletions.
21 changes: 14 additions & 7 deletions formspree/forms/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import requests
import datetime
import pyaml
import io

from flask import request, url_for, render_template, redirect, \
Expand Down Expand Up @@ -504,22 +505,28 @@ def form_submissions(hashid, format=None):
else:
return redirect(url_for('dashboard'))

submissions = form.submissions

if not format:
# normal request.
if request_wants_json():
return jsonify({
'host': form.host,
'email': form.email,
'submissions': [dict(s.data, date=s.submitted_at.isoformat()) for s in submissions]
'submissions': [dict(s.data, date=s.submitted_at.isoformat()) for s in form.submissions]
})
else:
fields = set()
for s in submissions:
for s in form.submissions:
fields.update(s.data.keys())
fields -= EXCLUDE_KEYS

submissions = []
for sub in form.submissions:
for f in fields:
value = sub.data.get(f, '')
typ = type(value)
sub.data[f] = value if typ is unicode or typ is str else pyaml.dump(value)
submissions.append(sub)

return render_template('forms/submissions.html',
form=form,
fields=sorted(fields),
Expand All @@ -532,7 +539,7 @@ def form_submissions(hashid, format=None):
json.dumps({
'host': form.host,
'email': form.email,
'submissions': [dict(s.data, date=s.submitted_at.isoformat()) for s in submissions]
'submissions': [dict(s.data, date=s.submitted_at.isoformat()) for s in form.submissions]
}, sort_keys=True, indent=2),
mimetype='application/json',
headers={
Expand All @@ -542,12 +549,12 @@ def form_submissions(hashid, format=None):
)
elif format == 'csv':
out = io.BytesIO()
fieldnames = set(field for sub in submissions for field in sub.data.keys())
fieldnames = set(field for sub in form.submissions for field in sub.data.keys())
fieldnames = ['date'] + sorted(fieldnames)

w = csv.DictWriter(out, fieldnames=fieldnames, encoding='utf-8')
w.writeheader()
for sub in submissions:
for sub in form.submissions:
w.writerow(dict(sub.data, date=sub.submitted_at.isoformat()))

return Response(
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ redis==2.10.5
requests==2.1.0
stripe==1.55.0
structlog==16.1.0
unicodecsv==0.14.1
unicodecsv==0.14.1
pyaml==17.12.1

7 comments on commit e89c30c

@fiatjaf
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this to solve an issue a client was having for a long time.
JSON submissions were being stored as JSON and caused an exception at render time (the template renderer for the submissions page expected all values to be strings). Now I'm transforming them into nicely-formatted strings before passing them to the template.

Should we apply the same rationale to email templates?

@rohitdatta
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you storing things as YAML now?

@fiatjaf
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Submissions were already being stored as JSON (JSONB, actually) on Postgres. Nothing is changed there.

@fiatjaf
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My previous comment was confusing. Sorry. The short version is: nothing is changed, except non-string values are now turned into pretty YAML representations before they are rendered in the submissions page templates.

@colevscode
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. Yaml might not be safe or UGC. Does pyYaml allow execution of arbitrary code? What's to keep someone from sending a special json blob that includes python code, which we then run on our server?

@fiatjaf
Copy link
Contributor Author

@fiatjaf fiatjaf commented on e89c30c Feb 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's serious. I didn't know about that. Sorry.
PyYAML has a "safe" mode, which "pyaml" can use. I'll enable that.

@fiatjaf
Copy link
Contributor Author

@fiatjaf fiatjaf commented on e89c30c Feb 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.