]> git.openstreetmap.org Git - osqa.git/blob - forum/views/admin.py
Fixing OSQA 258, Original templates can be directly accessed by public viewers.
[osqa.git] / forum / views / admin.py
1 from datetime import datetime, timedelta
2 import time
3
4 from django.shortcuts import render_to_response
5 from django.core.urlresolvers import reverse
6 from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
7 from django.template import RequestContext
8 from django.utils.translation import ugettext as _
9 from django.utils import simplejson
10 from django.db.models import Sum
11 from forum.settings.base import Setting
12 from forum.settings.forms import SettingsSetForm, MaintenanceModeForm
13
14 from forum.models import Question, Answer, User, Node, Action
15 from forum import settings
16
17 def super_user_required(fn):
18     def wrapper(request, *args, **kwargs):
19         if request.user.is_authenticated() and request.user.is_superuser:
20             return fn(request, *args, **kwargs)
21         else:
22             return HttpResponseForbidden()
23
24     return wrapper
25
26 def admin_page(fn):
27     @super_user_required
28     def wrapper(request, *args, **kwargs):
29         res = fn(request, *args, **kwargs)
30         if isinstance(res, tuple):
31             template, context = res
32             context['basetemplate'] = settings.DJSTYLE_ADMIN_INTERFACE and "osqaadmin/djstyle_base.html" or "osqaadmin/base.html"
33             context['allsets'] = Setting.sets
34             context['othersets'] = sorted(
35                     [s for s in Setting.sets.values() if not s.name in
36                     ('basic', 'users', 'email', 'paths', 'extkeys', 'repgain', 'minrep', 'voting', 'badges', 'about', 'faq', 'sidebar',
37                     'form', 'moderation')]
38                     , lambda s1, s2: s1.weight - s2.weight)
39             return render_to_response(template, context, context_instance=RequestContext(request))
40         else:
41             return res
42
43     return wrapper
44
45 @admin_page
46 def dashboard(request):
47     return ('osqaadmin/dashboard.html', {
48         'settings_pack': unicode(settings.SETTINGS_PACK),
49         'statistics': get_statistics(),
50         'recent_activity': get_recent_activity(),
51         'flagged_posts': get_flagged_posts(),
52     })
53
54 @super_user_required
55 def interface_switch(request):
56     if request.GET and request.GET.get('to', None) and request.GET['to'] in ('default', 'djstyle'):
57         settings.DJSTYLE_ADMIN_INTERFACE.set_value(request.GET['to'] == 'djstyle')
58
59     return HttpResponseRedirect(reverse('admin_index'))
60
61 @admin_page
62 def statistics(request):
63     today = datetime.now()
64     last_month = today - timedelta(days=30)
65
66     last_month_questions = Question.objects.filter(deleted=None, added_at__gt=last_month
67                                                   ).order_by('added_at').values_list('added_at', flat=True)
68
69     last_month_n_questions = Question.objects.filter(deleted=None, added_at__lt=last_month).count()
70     qgraph_data = simplejson.dumps([
71             (time.mktime(d.timetuple()) * 1000, i + last_month_n_questions)
72             for i, d in enumerate(last_month_questions)
73     ])
74
75     last_month_users = User.objects.filter(date_joined__gt=last_month
76                                                   ).order_by('date_joined').values_list('date_joined', flat=True)
77
78     last_month_n_users = User.objects.filter(date_joined__lt=last_month).count()
79
80     ugraph_data = simplejson.dumps([
81             (time.mktime(d.timetuple()) * 1000, i + last_month_n_users)
82             for i, d in enumerate(last_month_users)
83     ])
84
85     return 'osqaadmin/statistics.html', {
86         'graphs': [
87             {
88                 'id': 'questions_graph',
89                 'caption': _("Questions Graph"),
90                 'data': qgraph_data
91             },{
92                 'id': 'userss_graph',
93                 'caption': _("Users Graph"),
94                 'data': ugraph_data
95             }
96         ]
97     }
98
99
100 @admin_page
101 def settings_set(request, set_name):
102     set = Setting.sets.get(set_name, None)
103
104     if set is None:
105         raise Http404
106
107     if request.POST:
108         form = SettingsSetForm(set, data=request.POST, files=request.FILES)
109
110         if form.is_valid():
111             form.save()
112             request.user.message_set.create(message=_("'%s' settings saved succesfully") % set_name)
113
114             if set_name in ('minrep', 'badges', 'repgain'):
115                 settings.SETTINGS_PACK.set_value("custom")
116
117             return HttpResponseRedirect(reverse('admin_set', args=[set_name]))
118     else:
119         form = SettingsSetForm(set)
120
121     return 'osqaadmin/set.html', {
122         'form': form,
123         'markdown': set.markdown,
124     }
125
126 @super_user_required
127 def get_default(request, set_name, var_name):
128     set = Setting.sets.get(set_name, None)
129     if set is None: raise Http404
130
131     setting = dict([(s.name, s) for s in set]).get(var_name, None)
132     if setting is None: raise Http404
133
134     setting.to_default()
135
136     if request.is_ajax():
137         return HttpResponse(setting.default)
138     else:
139         return HttpResponseRedirect(reverse('admin_set', kwargs={'set_name': set_name}))
140
141
142 def get_recent_activity():
143     return Action.objects.order_by('-action_date')[0:30]
144
145 def get_flagged_posts():
146     return Action.objects.filter(action_type="flag").order_by('-action_date')[0:30]
147
148 def get_statistics():
149     return {
150         'total_users': User.objects.all().count(),
151         'users_last_24': User.objects.filter(date_joined__gt=(datetime.now() - timedelta(days=1))).count(),
152         'total_questions': Question.objects.filter(deleted=None).count(),
153         'questions_last_24': Question.objects.filter(deleted=None, added_at__gt=(datetime.now() - timedelta(days=1))).count(),
154         'total_answers': Answer.objects.filter(deleted=None).count(),
155         'answers_last_24': Answer.objects.filter(deleted=None, added_at__gt=(datetime.now() - timedelta(days=1))).count(),
156     }
157
158 @super_user_required
159 def go_bootstrap(request):
160     #todo: this is the quick and dirty way of implementing a bootstrap mode
161     try:
162         from forum_modules.default_badges import settings as dbsets
163         dbsets.POPULAR_QUESTION_VIEWS.set_value(100)
164         dbsets.NOTABLE_QUESTION_VIEWS.set_value(200)
165         dbsets.FAMOUS_QUESTION_VIEWS.set_value(300)
166         dbsets.NICE_ANSWER_VOTES_UP.set_value(2)
167         dbsets.NICE_QUESTION_VOTES_UP.set_value(2)
168         dbsets.GOOD_ANSWER_VOTES_UP.set_value(4)
169         dbsets.GOOD_QUESTION_VOTES_UP.set_value(4)
170         dbsets.GREAT_ANSWER_VOTES_UP.set_value(8)
171         dbsets.GREAT_QUESTION_VOTES_UP.set_value(8)
172         dbsets.FAVORITE_QUESTION_FAVS.set_value(1)
173         dbsets.STELLAR_QUESTION_FAVS.set_value(3)
174         dbsets.DISCIPLINED_MIN_SCORE.set_value(3)
175         dbsets.PEER_PRESSURE_MAX_SCORE.set_value(-3)
176         dbsets.CIVIC_DUTY_VOTES.set_value(15)
177         dbsets.PUNDIT_COMMENT_COUNT.set_value(10)
178         dbsets.SELF_LEARNER_UP_VOTES.set_value(2)
179         dbsets.STRUNK_AND_WHITE_EDITS.set_value(10)
180         dbsets.ENLIGHTENED_UP_VOTES.set_value(2)
181         dbsets.GURU_UP_VOTES.set_value(4)
182         dbsets.NECROMANCER_UP_VOTES.set_value(2)
183         dbsets.NECROMANCER_DIF_DAYS.set_value(30)
184         dbsets.TAXONOMIST_USE_COUNT.set_value(5)
185     except:
186         pass
187
188     settings.REP_TO_VOTE_UP.set_value(0)
189     settings.REP_TO_VOTE_DOWN.set_value(15)
190     settings.REP_TO_FLAG.set_value(15)
191     settings.REP_TO_COMMENT.set_value(0)
192     settings.REP_TO_LIKE_COMMENT.set_value(0)
193     settings.REP_TO_UPLOAD.set_value(0)
194     settings.REP_TO_CLOSE_OWN.set_value(60)
195     settings.REP_TO_REOPEN_OWN.set_value(120)
196     settings.REP_TO_RETAG.set_value(150)
197     settings.REP_TO_EDIT_WIKI.set_value(200)
198     settings.REP_TO_EDIT_OTHERS.set_value(400)
199     settings.REP_TO_CLOSE_OTHERS.set_value(600)
200     settings.REP_TO_DELETE_COMMENTS.set_value(400)
201     settings.REP_TO_VIEW_FLAGS.set_value(30)
202
203     settings.INITIAL_REP.set_value(1)
204     settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
205     settings.REP_GAIN_BY_UPVOTED.set_value(15)
206     settings.REP_LOST_BY_DOWNVOTED.set_value(1)
207     settings.REP_LOST_BY_DOWNVOTING.set_value(0)
208     settings.REP_GAIN_BY_ACCEPTED.set_value(25)
209     settings.REP_GAIN_BY_ACCEPTING.set_value(5)
210     settings.REP_LOST_BY_FLAGGED.set_value(2)
211     settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
212     settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
213
214     settings.SETTINGS_PACK.set_value("bootstrap")
215
216     request.user.message_set.create(message=_('Bootstrap mode enabled'))
217     return HttpResponseRedirect(reverse('admin_index'))
218
219 @super_user_required
220 def go_defaults(request):
221     for setting in Setting.sets['badges']:
222         setting.to_default()
223     for setting in Setting.sets['minrep']:
224         setting.to_default()
225     for setting in Setting.sets['repgain']:
226         setting.to_default()
227
228     settings.SETTINGS_PACK.set_value("default")
229
230     request.user.message_set.create(message=_('All values reverted to defaults'))
231     return HttpResponseRedirect(reverse('admin_index'))
232
233
234 @super_user_required
235 def recalculate_denormalized(request):
236     for n in Node.objects.all():
237         n = n.leaf
238         n.score = n.votes.aggregate(score=Sum('value'))['score']
239         if not n.score: n.score = 0
240         n.save()
241
242     for u in User.objects.all():
243         u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
244         u.save()
245
246     request.user.message_set.create(message=_('All values recalculated'))
247     return HttpResponseRedirect(reverse('admin_index'))
248
249 @admin_page
250 def maintenance(request):
251     if request.POST:
252         if 'close' in request.POST or 'adjust' in request.POST:
253             form = MaintenanceModeForm(request.POST)
254
255             if form.is_valid():
256                 settings.MAINTAINANCE_MODE.set_value({
257                     'allow_ips': form.cleaned_data['ips'],
258                     'message': form.cleaned_data['message']})
259
260                 if 'close' in request.POST:
261                     message = _('Maintenance mode enabled')
262                 else:
263                     message = _('Settings adjusted')
264
265                 request.user.message_set.create(message=message)
266
267                 return HttpResponseRedirect(reverse('admin_maintenance'))
268         elif 'open' in request.POST:
269             settings.MAINTAINANCE_MODE.set_value(None)
270             request.user.message_set.create(message=_("Your site is now running normally"))
271             return HttpResponseRedirect(reverse('admin_maintenance'))
272     else:
273         form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
274                                             'message': _('Currently down for maintenance. We\'ll be back soon')})
275
276     return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None})
277
278
279 @admin_page
280 def flagged_posts(request):
281     return ('osqaadmin/flagged_posts.html', {
282         'flagged_posts': get_flagged_posts(),
283     })
284
285