]> git.openstreetmap.org Git - osqa.git/blob - forum/views/admin.py
2b3426efac14622346f92d6474f2f2fd975dd6af
[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_state(deleted=False).filter(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_state(deleted=False).filter(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(canceled=False, 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_state(deleted=False).count(),
153         'questions_last_24': Question.objects.filter_state(deleted=False).filter(added_at__gt=(datetime.now() - timedelta(days=1))).count(),
154         'total_answers': Answer.objects.filter_state(deleted=False).count(),
155         'answers_last_24': Answer.objects.filter_state(deleted=False).filter(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_CREATE_TAGS.set_value(0)
195     settings.REP_TO_CLOSE_OWN.set_value(60)
196     settings.REP_TO_REOPEN_OWN.set_value(120)
197     settings.REP_TO_RETAG.set_value(150)
198     settings.REP_TO_EDIT_WIKI.set_value(200)
199     settings.REP_TO_EDIT_OTHERS.set_value(400)
200     settings.REP_TO_CLOSE_OTHERS.set_value(600)
201     settings.REP_TO_DELETE_COMMENTS.set_value(400)
202     settings.REP_TO_VIEW_FLAGS.set_value(30)
203
204     settings.INITIAL_REP.set_value(1)
205     settings.MAX_REP_BY_UPVOTE_DAY.set_value(300)
206     settings.REP_GAIN_BY_UPVOTED.set_value(15)
207     settings.REP_LOST_BY_DOWNVOTED.set_value(1)
208     settings.REP_LOST_BY_DOWNVOTING.set_value(0)
209     settings.REP_GAIN_BY_ACCEPTED.set_value(25)
210     settings.REP_GAIN_BY_ACCEPTING.set_value(5)
211     settings.REP_LOST_BY_FLAGGED.set_value(2)
212     settings.REP_LOST_BY_FLAGGED_3_TIMES.set_value(30)
213     settings.REP_LOST_BY_FLAGGED_5_TIMES.set_value(100)
214
215     settings.SETTINGS_PACK.set_value("bootstrap")
216
217     request.user.message_set.create(message=_('Bootstrap mode enabled'))
218     return HttpResponseRedirect(reverse('admin_index'))
219
220 @super_user_required
221 def go_defaults(request):
222     for setting in Setting.sets['badges']:
223         setting.to_default()
224     for setting in Setting.sets['minrep']:
225         setting.to_default()
226     for setting in Setting.sets['repgain']:
227         setting.to_default()
228
229     settings.SETTINGS_PACK.set_value("default")
230
231     request.user.message_set.create(message=_('All values reverted to defaults'))
232     return HttpResponseRedirect(reverse('admin_index'))
233
234
235 @super_user_required
236 def recalculate_denormalized(request):
237     for n in Node.objects.all():
238         n = n.leaf
239         n.score = n.votes.aggregate(score=Sum('value'))['score']
240         if not n.score: n.score = 0
241         n.save()
242
243     for u in User.objects.all():
244         u.reputation = u.reputes.aggregate(reputation=Sum('value'))['reputation']
245         u.save()
246
247     request.user.message_set.create(message=_('All values recalculated'))
248     return HttpResponseRedirect(reverse('admin_index'))
249
250 @admin_page
251 def maintenance(request):
252     if request.POST:
253         if 'close' in request.POST or 'adjust' in request.POST:
254             form = MaintenanceModeForm(request.POST)
255
256             if form.is_valid():
257                 settings.MAINTAINANCE_MODE.set_value({
258                     'allow_ips': form.cleaned_data['ips'],
259                     'message': form.cleaned_data['message']})
260
261                 if 'close' in request.POST:
262                     message = _('Maintenance mode enabled')
263                 else:
264                     message = _('Settings adjusted')
265
266                 request.user.message_set.create(message=message)
267
268                 return HttpResponseRedirect(reverse('admin_maintenance'))
269         elif 'open' in request.POST:
270             settings.MAINTAINANCE_MODE.set_value(None)
271             request.user.message_set.create(message=_("Your site is now running normally"))
272             return HttpResponseRedirect(reverse('admin_maintenance'))
273     else:
274         form = MaintenanceModeForm(initial={'ips': request.META['REMOTE_ADDR'],
275                                             'message': _('Currently down for maintenance. We\'ll be back soon')})
276
277     return ('osqaadmin/maintenance.html', {'form': form, 'in_maintenance': settings.MAINTAINANCE_MODE.value is not None})
278
279
280 @admin_page
281 def flagged_posts(request):
282     return ('osqaadmin/flagged_posts.html', {
283         'flagged_posts': get_flagged_posts(),
284     })
285
286