Tweaked the metadata edit screen to run jsonschema validators against the data.

This commit is contained in:
tilly-Q 2014-05-14 11:51:13 -04:00
parent 65f5714118
commit 0d6550fb05
5 changed files with 57 additions and 40 deletions

View File

@ -15,10 +15,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import wtforms import wtforms
from jsonschema import Draft4Validator
from mediagoblin.tools.text import tag_length_validator from mediagoblin.tools.text import tag_length_validator
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
from mediagoblin.tools.licenses import licenses_as_choices from mediagoblin.tools.licenses import licenses_as_choices
from mediagoblin.tools.metadata import DEFAULT_SCHEMA, DEFAULT_CHECKER
from mediagoblin.auth.tools import normalize_user_or_email_field from mediagoblin.auth.tools import normalize_user_or_email_field
@ -123,11 +125,37 @@ class ChangeEmailForm(wtforms.Form):
description=_( description=_(
"Enter your password to prove you own this account.")) "Enter your password to prove you own this account."))
class MetaDataValidator(object):
"""
Custom validator which runs form data in a MetaDataForm through a jsonschema
validator and passes errors recieved in jsonschema to wtforms.
:param schema The json schema to validate the data against. By
default this uses the DEFAULT_SCHEMA from
mediagoblin.tools.metadata.
:param format_checker The FormatChecker object that limits which types
jsonschema can recognize. By default this uses
DEFAULT_CHECKER from mediagoblin.tools.metadata.
"""
def __init__(self, schema=DEFAULT_SCHEMA, format_checker=DEFAULT_CHECKER):
self.schema = schema
self.format_checker = format_checker
def __call__(self, form, field):
metadata_dict = {field.data:form.value.data}
validator = Draft4Validator(self.schema,
format_checker=self.format_checker)
errors = [e.message
for e in validator.iter_errors(metadata_dict)]
if len(errors) >= 1:
raise wtforms.validators.ValidationError(
errors.pop())
class MetaDataForm(wtforms.Form): class MetaDataForm(wtforms.Form):
identifier = wtforms.TextField(_(u'Identifier')) identifier = wtforms.TextField(_(u'Identifier'),[MetaDataValidator()])
value = wtforms.TextField(_(u'Value')) value = wtforms.TextField(_(u'Value'))
class EditMetaDataForm(wtforms.Form): class EditMetaDataForm(wtforms.Form):
media_metadata = wtforms.FieldList( media_metadata = wtforms.FieldList(
wtforms.FormField(MetaDataForm, label="") wtforms.FormField(MetaDataForm, ""),
) )

View File

@ -20,6 +20,7 @@ from itsdangerous import BadSignature
from pyld import jsonld from pyld import jsonld
from werkzeug.exceptions import Forbidden from werkzeug.exceptions import Forbidden
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from jsonschema import ValidationError, Draft4Validator
from mediagoblin import messages from mediagoblin import messages
from mediagoblin import mg_globals from mediagoblin import mg_globals
@ -33,7 +34,8 @@ from mediagoblin.decorators import (require_active_login, active_user_from_url,
get_user_collection, user_has_privilege, get_user_collection, user_has_privilege,
user_not_banned) user_not_banned)
from mediagoblin.tools.crypto import get_timed_signer_url from mediagoblin.tools.crypto import get_timed_signer_url
from mediagoblin.tools.metadata import compact_and_validate from mediagoblin.tools.metadata import (compact_and_validate, DEFAULT_CHECKER,
DEFAULT_SCHEMA)
from mediagoblin.tools.mail import email_debug_message from mediagoblin.tools.mail import email_debug_message
from mediagoblin.tools.response import (render_to_response, from mediagoblin.tools.response import (render_to_response,
redirect, redirect_obj, render_404) redirect, redirect_obj, render_404)
@ -444,24 +446,19 @@ def edit_metadata(request, media):
if request.method == "POST" and form.validate(): if request.method == "POST" and form.validate():
metadata_dict = dict([(row['identifier'],row['value']) metadata_dict = dict([(row['identifier'],row['value'])
for row in form.media_metadata.data]) for row in form.media_metadata.data])
json_ld_metadata = None
json_ld_metadata = compact_and_validate(metadata_dict) json_ld_metadata = compact_and_validate(metadata_dict)
media.media_metadata = json_ld_metadata media.media_metadata = json_ld_metadata
media.save() media.save()
return redirect_obj(request, media) return redirect_obj(request, media)
if media.media_metadata: if media.media_metadata and len(form.media_metadata) == 0:
for identifier, value in media.media_metadata.iteritems(): for identifier, value in media.media_metadata.iteritems():
if identifier == "@context": continue if identifier == "@context": continue
form.media_metadata.append_entry({ form.media_metadata.append_entry({
'identifier':identifier, 'identifier':identifier,
'value':value}) 'value':value})
else:
form.media_metadata.append_entry({
'identifier':"",
'value':""})
form.media_metadata.append_entry({
'identifier':"",
'value':""})
return render_to_response( return render_to_response(
request, request,
'mediagoblin/edit/metadata.html', 'mediagoblin/edit/metadata.html',

View File

@ -940,18 +940,13 @@ p.verifier {
/* for the media metadata editing table */ /* for the media metadata editing table */
table.metadata_editor { table.metadata_editor {
margin: 10px auto; margin: 10px auto;
width: 1000px; width: 800px;
}
table.metadata_editor tr th {
width:100px;
} }
table.metadata_editor tr td { table.metadata_editor tr td {
width:300px; width:350px;
} }
table.metadata_editor tr td.form_field_input input { table.metadata_editor tr td.form_field_input input {
width:300px; width:350px;
} }

View File

@ -69,7 +69,7 @@
<form action="" method="POST" id="metadata_form"> <form action="" method="POST" id="metadata_form">
<!-- This table holds all the information about the media entry's metadata --> <!-- This table holds all the information about the media entry's metadata -->
<h3>{% trans %}Data{% endtrans %}</h3> <h3>{% trans %}MetaData{% endtrans %}</h3>
<table class="metadata_editor" id="metadata_list" > <table class="metadata_editor" id="metadata_list" >
{{ wtforms_util.render_fieldlist_as_table_rows(form.media_metadata) }} {{ wtforms_util.render_fieldlist_as_table_rows(form.media_metadata) }}
</table> </table>
@ -77,16 +77,13 @@
<!-- These are the buttons you use to control the form --> <!-- These are the buttons you use to control the form -->
<table class="metadata_editor" id="buttons_bottom"> <table class="metadata_editor" id="buttons_bottom">
<tr> <tr>
<th></th>
<td><input type=button value="{% trans %}Add new Row{% endtrans %}" <td><input type=button value="{% trans %}Add new Row{% endtrans %}"
class="button_action" id="add_new_metadata_row" /> class="button_action" id="add_new_metadata_row" />
</td> </td>
<th></th>
<td><input type=submit value="{% trans %}Update Metadata{% endtrans %}" <td><input type=submit value="{% trans %}Update Metadata{% endtrans %}"
class="button_action_highlight" /></td> class="button_action_highlight" /></td>
</tr> </tr>
<tr> <tr>
<th></th>
<td><input type=button value="{% trans %}Clear empty Rows{% endtrans %}" <td><input type=button value="{% trans %}Clear empty Rows{% endtrans %}"
class="button_action" id="clear_empty_rows" /></td> class="button_action" id="clear_empty_rows" /></td>
</tr> </tr>

View File

@ -77,20 +77,21 @@
{% macro render_form_as_table_row(form) %} {% macro render_form_as_table_row(form) %}
<tr> <tr>
{%- for field in form %} {%- for field in form %}
<th>{{ render_label_p(field) }}</th>
<td class="form_field_input"> <td class="form_field_input">
{{field}} {{field}}
{%- if field.errors -%}
<br />
<ul class="errors">
{% for error in field.errors %}
<li>{{error}}</li>
{%- endfor %}
</ul>
{%- endif -%}
</td> </td>
{%- endfor %} {%- endfor %}
</tr> </tr>
<tr>
{%- for field in form %}
{% for error in field.errors %}
<tr>
<td>
<p class="form_field_error">{{error}}</p>
</td>
</tr>
{%- endfor %}
{%- endfor %}
{%- endmacro %} {%- endmacro %}
{% macro render_field_as_table_row(field) %} {% macro render_field_as_table_row(field) %}
@ -98,16 +99,15 @@
<th>{{ field.label.text }}</th> <th>{{ field.label.text }}</th>
<td> <td>
{{field}} {{field}}
{% if field.errors %}
<br />
<ul class="errors">
{% for error in field.errors %}
<li>{{error}}</li>
{% endfor %}
</ul>
{% endif %}
</td> </td>
</tr> </tr>
{% for error in field.errors %}
<tr>
<td>
<p class="form_field_error">{{error}}</p>
</td>
</tr>
{%- endfor %}
{% endmacro %} {% endmacro %}
{% macro render_fieldlist_as_table_rows(fieldlist) %} {% macro render_fieldlist_as_table_rows(fieldlist) %}