Skip to content

Commit

Permalink
Hash settings to prevent overwriting of someone else's changes
Browse files Browse the repository at this point in the history
Signed-off-by: Jannis Leidel <jannis@leidel.info>
  • Loading branch information
Bouke authored and jezdez committed Nov 27, 2014
1 parent 395924a commit d0fc64b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 12 deletions.
37 changes: 29 additions & 8 deletions constance/admin.py
@@ -1,5 +1,6 @@
from datetime import datetime, date, time
from decimal import Decimal
import hashlib
from operator import itemgetter
import six

Expand All @@ -13,7 +14,12 @@
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from django.utils.formats import localize
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy as _

try:
from django.utils.encoding import smart_bytes
except ImportError:
from django.utils.encoding import smart_str as smart_bytes

try:
from django.conf.urls import patterns, url
Expand Down Expand Up @@ -54,22 +60,37 @@


class ConstanceForm(forms.Form):
def __init__(self, *args, **kwargs):
super(ConstanceForm, self).__init__(*args, **kwargs)
version = forms.CharField(widget=forms.HiddenInput)

def __init__(self, initial, *args, **kwargs):
super(ConstanceForm, self).__init__(*args, initial=initial, **kwargs)
version_hash = hashlib.md5()

for name, (default, help_text) in settings.CONFIG.items():
config_type = type(default)
if config_type not in FIELDS:
raise ImproperlyConfigured("Constance doesn't support "
"config values of the type %s. "
"Please fix the value of '%s'."
raise ImproperlyConfigured(_("Constance doesn't support "
"config values of the type %s. "
"Please fix the value of '%s'.")
% (config_type, name))
field_class, kwargs = FIELDS[config_type]
self.fields[name] = field_class(label=name, **kwargs)

version_hash.update(smart_bytes(initial.get(name, '')))
self.initial['version'] = version_hash.hexdigest()

def save(self):
for name in self.cleaned_data:
for name in settings.CONFIG:
setattr(config, name, self.cleaned_data[name])

def clean_version(self):
value = self.cleaned_data['version']
if value != self.initial['version']:
raise forms.ValidationError(_('The settings have been modified '
'by someone else. Please reload the '
'form and resubmit your changes.'))
return value


class ConstanceAdmin(admin.ModelAdmin):

Expand All @@ -96,7 +117,7 @@ def changelist_view(self, request, extra_context=None):
**dict(config._backend.mget(settings.CONFIG.keys())))
form = ConstanceForm(initial=initial)
if request.method == 'POST':
form = ConstanceForm(request.POST)
form = ConstanceForm(data=request.POST, initial=initial)
if form.is_valid():
form.save()
# In django 1.5 this can be replaced with self.message_user
Expand Down
16 changes: 12 additions & 4 deletions constance/templates/admin/constance/change_list.html
Expand Up @@ -36,6 +36,14 @@
<div id="content-main">
<div class="module" id="changelist">
<form id="changelist-form" action="" method="post">{% csrf_token %}
<ul class="errorlist">
{% for field in form.hidden_fields %}
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
{{ field }}
{% endfor %}
</ul>
<table cellspacing="0" id="result_list">
<thead>
<tr>
Expand All @@ -47,15 +55,15 @@
</thead>
{% for item in config %}
<tr class="{% cycle 'row1' 'row2' %}">
<th>{{item.name}}
<div class="help">{{item.help_text}}</div>
<th>{{ item.name }}
<div class="help">{{ item.help_text }}</div>
</th>
<td>
{{ item.default }}
</td>
<td>
{{item.form_field.errors}}
{{item.form_field}}
{{ item.form_field.errors }}
{{ item.form_field }}
</td>
<td>
{% if item.modified %}
Expand Down

0 comments on commit d0fc64b

Please sign in to comment.