notify_comments = forms.BooleanField(required=False, initial=False)
notify_accepted = forms.BooleanField(required=False, initial=False)
-
-class AwardPointsForm(forms.Form):
- points = forms.IntegerField(min_value=1, initial=50, label=_('Points to award'))
- message = forms.CharField(widget=forms.Textarea(), label=_('Message'), required=False)
+from forum.settings import MAINTAINANCE_MODE, APP_LOGO, APP_TITLE\r
+from django.http import HttpResponseGone\r
+from django.template.loader import render_to_string\r
+\r
\r
class RequestUtils(object):\r
def __init__(self):\r
return int(pagesize)\r
\r
def process_request(self, request):\r
+ if MAINTAINANCE_MODE.value is not None and isinstance(MAINTAINANCE_MODE.value.get('allow_ips', None), list):\r
+ ip = request.META['REMOTE_ADDR']\r
+\r
+ if not ip in MAINTAINANCE_MODE.value['allow_ips']:\r
+ return HttpResponseGone(render_to_string('410.html', {\r
+ 'message': MAINTAINANCE_MODE.value.get('message', ''),\r
+ 'app_logo': APP_LOGO,\r
+ 'app_title': APP_TITLE\r
+ }))\r
+\r
self.request = request\r
request.utils = self\r
return None
\ No newline at end of file
OSQA_VERSION = "Development Build"
SVN_REVISION = get_svn_revision(djsettings.SITE_SRC_ROOT)
+MAINTAINANCE_MODE = Setting('MAINTAINANCE_MODE', None)
+
SETTINGS_PACK = Setting('SETTINGS_PACK', "default")
DJSTYLE_ADMIN_INTERFACE = Setting('DJSTYLE_ADMIN_INTERFACE', True)
return self.base_type(value)
except:
pass
- return value
+ return value
+
+class AnyTypeSetting(BaseSetting):
+ def _parse(self, value):
+ return value
class Setting(object):
sets = {}
def __new__(cls, name, default, set=None, field_context=None):
+ if default is None:
+ return AnyTypeSetting(name, default, set, field_context)
+
deftype = type(default)
if deftype in Setting.emulators:
import os
+import socket
from string import strip
from django import forms
from base import Setting
return ', '.join(data[name])
+class IPListField(forms.CharField):
+ def clean(self, value):
+ ips = [ip.strip() for ip in value.strip().strip(',').split(',')]
+ iplist = []
+
+ if len(ips) < 1:
+ raise forms.ValidationError(_('Please input at least one ip address'))
+
+ for ip in ips:
+ try:
+ socket.inet_aton(ip)
+ except socket.error:
+ raise forms.ValidationError(_('Invalid ip address: %s' % ip))
+
+ if not len(ip.split('.')) == 4:
+ raise forms.ValidationError(_('Please use the dotted quad notation for the ip addresses'))
+
+ iplist.append(ip)
+
+ return iplist
+
+class MaintenanceModeForm(forms.Form):
+ ips = IPListField(label=_('Allow ips'),
+ help_text=_('Comma separated list of ips allowed to access the site while in maintenance'),
+ required=True,
+ widget=forms.TextInput(attrs={'class': 'longstring'}))
+
+ message = forms.CharField(label=_('Message'),
+ help_text=_('A message to display to your site visitors while in maintainance mode'),
+ widget=forms.Textarea)
+
label = _("Rep gain by upvoted"),\r
help_text = _("Reputation a user gains for having one of his posts up voted.")))\r
\r
-REP_LOST_BY_UPVOTE_CANCELED = Setting('REP_LOST_BY_UPVOTE_CANCELED', 10, REP_GAIN_SET, dict(\r
-label = _("Rep lost bu upvote canceled"),\r
-help_text = _("Reputation a user loses for having one of the upvotes on his posts canceled.")))\r
-\r
REP_LOST_BY_DOWNVOTED = Setting('REP_LOST_BY_DOWNVOTED', 2, REP_GAIN_SET, dict(\r
label = _("Rep lost by downvoted"),\r
help_text = _("Reputation a user loses for having one of his posts down voted.")))\r
label = _("Rep lost by downvoting"),\r
help_text = _("Reputation a user loses for down voting a post.")))\r
\r
-REP_GAIN_BY_DOWNVOTE_CANCELED = Setting('REP_GAIN_BY_DOWNVOTE_CANCELED', 2, REP_GAIN_SET, dict(\r
-label = _("Rep gain by downvote canceled"),\r
-help_text = _("Reputation a user gains for having one of the downvotes on his posts canceled.")))\r
-\r
-REP_GAIN_BY_CANCELING_DOWNVOTE = Setting('REP_GAIN_BY_CANCELING_DOWNVOTE', 1, REP_GAIN_SET, dict(\r
-label = _("Rep gain by canceling downvote"),\r
-help_text = _("Reputation a user gains for canceling a downvote.")))\r
\r
REP_GAIN_BY_ACCEPTED = Setting('REP_GAIN_BY_ACCEPTED', 15, REP_GAIN_SET, dict(\r
label = _("Rep gain by accepted answer"),\r
help_text = _("Reputation a user gains for having one of his answers accepted.")))\r
\r
-REP_LOST_BY_ACCEPTED_CANCELED = Setting('REP_LOST_BY_ACCEPTED_CANCELED', 15, REP_GAIN_SET, dict(\r
-label = _("Rep lost by accepted canceled"),\r
-help_text = _("Reputation a user loses for having one of his accepted answers canceled.")))\r
-\r
REP_GAIN_BY_ACCEPTING = Setting('REP_GAIN_BY_ACCEPTING', 2, REP_GAIN_SET, dict(\r
label = _("Rep gain by accepting answer"),\r
help_text = _("Reputation a user gains for accepting an answer to one of his questions.")))\r
\r
-REP_LOST_BY_CANCELING_ACCEPTED = Setting('REP_LOST_BY_CANCELING_ACCEPTED', 2, REP_GAIN_SET, dict(\r
-label = _("Rep lost by canceling accepted"),\r
-help_text = _("Reputation a user loses by canceling an accepted answer.")))\r
-\r
REP_LOST_BY_FLAGGED = Setting('REP_LOST_BY_FLAGGED', 2, REP_GAIN_SET, dict(\r
label = _("Rep lost by post flagged"),\r
help_text = _("Reputation a user loses by having one of his posts flagged.")))\r
position: relative;
left: 612px;
}
+
+.admin_message {
+ background-color: #ffffe0;
+ border: 3px double #b8860b;
+ padding: 4px;
+}
\ No newline at end of file
--- /dev/null
+{% load i18n %}
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>{% trans "System down for maintenance" %}</title>
+ <style>
+ #content {
+ margin: auto;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="content">
+ <img src="{{ app_logo }}">
+ <p>{{ app_title }}</p>
+ <h3>{% trans "System down for maintenance" %}</h3>
+ <br/>
+ {{ message }}
+ </div>
+ </body>
+</html>
</div>
<div id="content" class="colMS">
<div id="content-main">
+ {% for message in user_messages %}
+ <p class="admin_message">{{ message }}</p>
+ {% endfor %}
{% block admincontent %}{% endblock %}
</div>
<div id="content-related">
{% endfor %}
</ul>
</div>
- {% comment %}<div id="tools-menu" class="module">
+ <div id="tools-menu" class="module">
<h2>{% trans "Tools" %}</h2>
<ul>
- <li><a href="{% url admin_statistics %}">{% trans "Statistics" %}</a></li>
+ <li><a href="{% url admin_maintenance %}">{% trans "Maintenance mode" %}</a></li>
</ul>
- </div>{% endcomment %}
+ </div>
</div>
</div>
<div id="footer" class="breadcumbs">
--- /dev/null
+{% extends basetemplate %}
+
+{% load i18n %}
+
+{% block subtitle %}{% trans "Maintenance mode" %}{% endblock %}
+{% block pagename %}{% trans "Maintenance mode" %}{% endblock %}
+{% block description %}{% trans "Maintainance mode allows you to close your site for maintainance, allowing only a predetermined set of ip addresses to access it normally." %}{% endblock %}
+
+{% block admincontent %}
+<form method="POST" action="">
+ {% if in_maintenance %}
+ <h1>{% trans "Your site is currently running on maintenance mode." %}</h1>
+ <p>{% trans "You can adjust the settings bellow" %}</p>
+ {% endif %}
+ <table>
+ {{ form.as_table }}
+ </table>
+ {% if in_maintenance %}
+ <input type="submit" name="adjust" value="{% trans "Adjust settings" %}" />
+ <input type="submit" name="open" value="{% trans "Open site" %}" />
+ {% else %}
+ <input type="submit" name="close" value="{% trans "Close for maintenance" %}" />
+ {% endif %}
+</form>
+{% endblock %}
\ No newline at end of file
url(r'^%s%s$' % (_('admin/'), _('denormalize/')), app.admin.recalculate_denormalized, name="admin_denormalize"),
url(r'^%s%s$' % (_('admin/'), _('go_bootstrap/')), app.admin.go_bootstrap, name="admin_go_bootstrap"),
url(r'^%s%s$' % (_('admin/'), _('go_defaults/')), app.admin.go_defaults, name="admin_go_defaults"),
- url(r'^%s(?P<set_name>\w+)/$' % _('admin/'), app.admin.settings_set, name="admin_set"),
- url(r'^%s(?P<set_name>\w+)/(?P<var_name>\w+)/$' % _('admin/'), app.admin.get_default, name="admin_default"),
+ url(r'^%s%s(?P<set_name>\w+)/(?P<var_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.get_default, name="admin_default"),
+ url(r'^%s%s$' % (_('admin/'), _('maintenance/')), app.admin.maintenance, name="admin_maintenance"),
+
+ url(r'^%s%s(?P<set_name>\w+)/$' % (_('admin/'), _('settings/')), app.admin.settings_set, name="admin_set"),
url(r'^feeds/rss/$', RssLastestQuestionsFeed, name="latest_questions_feed"),
)
from django.db.models import Sum
from forum.settings.base import Setting
-from forum.settings.forms import SettingsSetForm
+from forum.settings.forms import SettingsSetForm, MaintenanceModeForm
from forum.models import Question, Answer, User, Node, Action
from forum import settings
settings.INITIAL_REP.set_value(1)
settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
settings.REP_GAIN_BY_UPVOTED.set_value(15)
- settings.REP_LOST_BY_UPVOTE_CANCELED.set_value(15)
settings.REP_LOST_BY_DOWNVOTED.set_value(1)
settings.REP_LOST_BY_DOWNVOTING.set_value(0)
- settings.REP_GAIN_BY_DOWNVOTE_CANCELED.set_value(1)
- settings.REP_GAIN_BY_CANCELING_DOWNVOTE.set_value(0)
settings.REP_GAIN_BY_ACCEPTED.set_value(25)
- settings.REP_LOST_BY_ACCEPTED_CANCELED.set_value(25)
settings.REP_GAIN_BY_ACCEPTING.set_value(5)
- settings.REP_LOST_BY_CANCELING_ACCEPTED.set_value(5)
settings.REP_LOST_BY_FLAGGED.set_value(2)
settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
request.user.message_set.create(message=_('All values recalculated'))
return HttpResponseRedirect(reverse('admin_index'))
+@admin_page
+def maintenance(request):
+ if request.POST:
+ if 'close' in request.POST or 'adjust' in request.POST:
+ form = MaintenanceModeForm(request.POST)
+
+ if form.is_valid():
+ settings.MAINTAINANCE_MODE.set_value({
+ 'allow_ips': form.cleaned_data['ips'],
+ 'message': form.cleaned_data['message']})
+
+ if 'close' in request.POST:
+ message = _('Maintenance mode enabled')
+ else:
+ message = _('Settings adjusted')
+
+ request.user.message_set.create(message=message)
+
+ return HttpResponseRedirect(reverse('admin_maintenance'))
+ elif 'open' in request.POST:
+ settings.MAINTAINANCE_MODE.set_value(None)
+ request.user.message_set.create(message=_("Your site is now running normally"))
+ return HttpResponseRedirect(reverse('admin_maintenance'))
+ else:
+ form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
+ 'message': _('Currently down for maintenance. We\'ll be back soon')})
+
+ return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None})
+
+