]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/views/admin.py
resolves a typo in the source: selfself -> self
[osqa.git] / forum / views / admin.py
index 4ed85925ac8e5b8132415a5859d070cfe0541b66..4823920c1099b6c3f6267a637684ce1bee53fd10 100644 (file)
@@ -1,19 +1,21 @@
 from datetime import datetime, timedelta
 from datetime import datetime, timedelta
-import os, time, csv, random
+import time
 
 
+from django.views.decorators.csrf import csrf_exempt
 from django.shortcuts import render_to_response, get_object_or_404
 from django.core.urlresolvers import reverse
 from django.http import HttpResponseRedirect, HttpResponse, Http404
 from django.shortcuts import render_to_response, get_object_or_404
 from django.core.urlresolvers import reverse
 from django.http import HttpResponseRedirect, HttpResponse, Http404
-from forum.http_responses import HttpResponseUnauthorized
 from django.template import RequestContext
 from django.utils.translation import ugettext as _
 from django.utils import simplejson
 from django.db import models
 from django.template import RequestContext
 from django.utils.translation import ugettext as _
 from django.utils import simplejson
 from django.db import models
+
+from forum.http_responses import HttpResponseUnauthorized
 from forum.settings.base import Setting
 from forum.settings.base import Setting
-from forum.forms import MaintenanceModeForm, PageForm, NodeManFilterForm, CreateUserForm
+from forum.forms import MaintenanceModeForm, PageForm, CreateUserForm
 from forum.settings.forms import SettingsSetForm
 from forum.utils import pagination, html
 from forum.settings.forms import SettingsSetForm
 from forum.utils import pagination, html
-
+from forum.utils.mail import send_template_email
 from forum.models import Question, Answer, User, Node, Action, Page, NodeState, Tag
 from forum.models.node import NodeMetaClass
 from forum.actions import NewPageAction, EditPageAction, PublishAction, DeleteAction, UserJoinsAction, CloseAction
 from forum.models import Question, Answer, User, Node, Action, Page, NodeState, Tag
 from forum.models.node import NodeMetaClass
 from forum.actions import NewPageAction, EditPageAction, PublishAction, DeleteAction, UserJoinsAction, CloseAction
@@ -30,28 +32,47 @@ def super_user_required(fn):
 
     return wrapper
 
 
     return wrapper
 
-def admin_page(fn):
-    @super_user_required
+def staff_user_required(fn):
     def wrapper(request, *args, **kwargs):
     def wrapper(request, *args, **kwargs):
-        res = fn(request, *args, **kwargs)
-        if isinstance(res, HttpResponse):
-            return res
+        if request.user.is_authenticated() and (request.user.is_staff or request.user.is_superuser):
+            return fn(request, *args, **kwargs)
+        else:
+            return HttpResponseUnauthorized(request)
+
+    return wrapper
 
 
-        template, context = res
-        context['basetemplate'] = settings.DJSTYLE_ADMIN_INTERFACE and "osqaadmin/djstyle_base.html" or "osqaadmin/base.html"
-        context['allsets'] = Setting.sets
-        context['othersets'] = sorted(
-                [s for s in Setting.sets.values() if not s.name in
-                ('basic', 'users', 'email', 'paths', 'extkeys', 'repgain', 'minrep', 'voting', 'accept', 'badges', 'about', 'faq', 'sidebar',
-                'form', 'moderation', 'css', 'headandfoot', 'head', 'view', 'urls')]
-                , lambda s1, s2: s1.weight - s2.weight)
+def admin_page_wrapper(fn, request, *args, **kwargs):
+    res = fn(request, *args, **kwargs)
+    if isinstance(res, HttpResponse):
+        return res
 
 
-        context['tools'] = TOOLS
+    template, context = res
+    context['basetemplate'] = settings.DJSTYLE_ADMIN_INTERFACE and "osqaadmin/djstyle_base.html" or "osqaadmin/base.html"
+    context['allsets'] = Setting.sets
+    context['othersets'] = sorted(
+            [s for s in Setting.sets.values() if not s.name in
+            ('basic', 'users', 'email', 'paths', 'extkeys', 'repgain', 'minrep', 'voting', 'accept', 'badges', 'about', 'faq', 'sidebar',
+            'form', 'moderation', 'css', 'headandfoot', 'head', 'view', 'urls')]
+            , lambda s1, s2: s1.weight - s2.weight)
 
 
-        unsaved = request.session.get('previewing_settings', {})
-        context['unsaved'] = set([getattr(settings, s).set.name for s in unsaved.keys() if hasattr(settings, s)])
+    context['tools'] = [(name, fn.label) for name, fn in TOOLS.items()]
 
 
-        return render_to_response(template, context, context_instance=RequestContext(request))
+    unsaved = request.session.get('previewing_settings', {})
+    context['unsaved'] = set([getattr(settings, s).set.name for s in unsaved.keys() if hasattr(settings, s)])
+
+    return render_to_response(template, context, context_instance=RequestContext(request))
+
+def admin_page(fn):
+    @super_user_required
+    def wrapper(request, *args, **kwargs):
+        return admin_page_wrapper(fn, request, *args, **kwargs)
+
+    return wrapper
+
+def moderation_page(fn):
+    @staff_user_required
+    def wrapper(request, *args, **kwargs):
+        return admin_page_wrapper(fn, request, *args, **kwargs)
 
     return wrapper
 
 
     return wrapper
 
@@ -327,7 +348,7 @@ def maintenance(request):
                                            })
 
 
                                            })
 
 
-@admin_page
+@moderation_page
 def flagged_posts(request):
     return ('osqaadmin/flagged_posts.html', {
     'flagged_posts': get_flagged_posts(),
 def flagged_posts(request):
     return ('osqaadmin/flagged_posts.html', {
     'flagged_posts': get_flagged_posts(),
@@ -381,6 +402,12 @@ def edit_page(request, id=None):
     'published': published
     })
 
     'published': published
     })
 
+@admin_page
+def delete_page(request, id=None):
+    page = get_object_or_404(Page, id=id)
+    page.delete()
+    return HttpResponseRedirect(reverse('admin_static_pages'))
+
 @admin_tools_page(_('createuser'), _("Create new user"))
 def create_user(request):
     if request.POST:
 @admin_tools_page(_('createuser'), _("Create new user"))
 def create_user(request):
     if request.POST:
@@ -412,122 +439,151 @@ class NodeManagementPaginatorContext(pagination.PaginatorContext):
         super (NodeManagementPaginatorContext, self).__init__(id, sort_methods=(
             (_('added_at'), pagination.SimpleSort(_('added_at'), '-added_at', "")),
             (_('added_at_asc'), pagination.SimpleSort(_('added_at_asc'), 'added_at', "")),
         super (NodeManagementPaginatorContext, self).__init__(id, sort_methods=(
             (_('added_at'), pagination.SimpleSort(_('added_at'), '-added_at', "")),
             (_('added_at_asc'), pagination.SimpleSort(_('added_at_asc'), 'added_at', "")),
+            (_('author'), pagination.SimpleSort(_('author'), '-author__username', "")),
+            (_('author_asc'), pagination.SimpleSort(_('author_asc'), 'author__username', "")),
             (_('score'), pagination.SimpleSort(_('score'), '-score', "")),
             (_('score_asc'), pagination.SimpleSort(_('score_asc'), 'score', "")),
             (_('act_at'), pagination.SimpleSort(_('act_at'), '-last_activity_at', "")),
             (_('act_at_asc'), pagination.SimpleSort(_('act_at_asc'), 'last_activity_at', "")),
             (_('score'), pagination.SimpleSort(_('score'), '-score', "")),
             (_('score_asc'), pagination.SimpleSort(_('score_asc'), 'score', "")),
             (_('act_at'), pagination.SimpleSort(_('act_at'), '-last_activity_at', "")),
             (_('act_at_asc'), pagination.SimpleSort(_('act_at_asc'), 'last_activity_at', "")),
+            (_('act_by'), pagination.SimpleSort(_('act_by'), '-last_activity_by__username', "")),
+            (_('act_by_asc'), pagination.SimpleSort(_('act_by_asc'), 'last_activity_by__username', "")),
         ), pagesizes=(default_pagesize,), force_sort='added_at', default_pagesize=default_pagesize, prefix=prefix)
 
         ), pagesizes=(default_pagesize,), force_sort='added_at', default_pagesize=default_pagesize, prefix=prefix)
 
-@admin_tools_page(_("nodeman"), _("Node management"))
+@admin_tools_page(_("nodeman"), _("Bulk management"))
 def node_management(request):
 def node_management(request):
-    if request.is_ajax():
-        if request.POST and request.POST.get('filtername', None) and request.GET:
+    if request.POST:
+        params = pagination.generate_uri(request.GET, ('page',))
+
+        if "save_filter" in request.POST:
+            filter_name = request.POST.get('filter_name', _('filter'))
             params = pagination.generate_uri(request.GET, ('page',))
             current_filters = settings.NODE_MAN_FILTERS.value
             params = pagination.generate_uri(request.GET, ('page',))
             current_filters = settings.NODE_MAN_FILTERS.value
-            current_filters.add((request.POST['filtername'], params))
+            current_filters.append((filter_name, params))
             settings.NODE_MAN_FILTERS.set_value(current_filters)
             settings.NODE_MAN_FILTERS.set_value(current_filters)
-            return HttpResponse('OK')
 
 
-        return HttpResponse('ERROR')
+        elif r"execute" in request.POST:
+            selected_nodes = request.POST.getlist('_selected_node')
 
 
-    if request.POST:
-        selected_nodes = request.POST.getlist('_selected_node')
+            if selected_nodes and request.POST.get('action', None):
+                action = str(request.POST['action'])
+                selected_nodes = Node.objects.filter(id__in=selected_nodes)
 
 
-        if selected_nodes and request.POST.get('action', None):
-            action = request.POST['action']
-            selected_nodes = Node.objects.filter(id__in=selected_nodes)
+                message = _("No action performed")
 
 
-            message = _("No action performed")
+                if action == 'delete_selected':
+                    for node in selected_nodes:
+                        if node.node_type in ('question', 'answer', 'comment') and (not node.nis.deleted):
+                            DeleteAction(user=request.user, node=node, ip=request.META['REMOTE_ADDR']).save()
 
 
-            if action == 'delete_selected':
-                for node in selected_nodes:
-                    if node.node_type in ('question', 'answer', 'comment') and (not node.nis.deleted):
-                        DeleteAction(user=request.user, node=node, ip=request.META['REMOTE_ADDR']).save()
-                        
-                message = _("All selected nodes marked as deleted")
+                    message = _("All selected nodes marked as deleted")
 
 
-            if action == "close_selected":
-                for node in selected_nodes:
-                    if node.node_type == "question" and (not node.nis.closed):
-                        CloseAction(node=node.leaf, user=request.user, extra=_("bulk close"), ip=request.META['REMOTE_ADDR']).save()
+                if action == 'undelete_selected':
+                    for node in selected_nodes:
+                        if node.node_type in ('question', 'answer', 'comment') and (node.nis.deleted):
+                            node.nstate.deleted.cancel(ip=request.META['REMOTE_ADDR'])
 
 
-                message = _("Selected questions were closed")
+                    message = _("All selected nodes undeleted")
 
 
-            if action == "hard_delete_selected":
-                ids = [n.id for n in selected_nodes]
+                if action == "close_selected":
+                    for node in selected_nodes:
+                        if node.node_type == "question" and (not node.nis.closed):
+                            CloseAction(node=node.leaf, user=request.user, extra=_("bulk close"), ip=request.META['REMOTE_ADDR']).save()
 
 
-                for id in ids:
-                    try:
-                        node = Node.objects.get(id=id)
-                        node.delete()
-                    except:
-                        pass                        
+                    message = _("Selected questions were closed")
 
 
-                message = _("All selected nodes deleted")
+                if action == "hard_delete_selected":
+                    ids = [n.id for n in selected_nodes]
 
 
-            request.user.message_set.create(message=message)
+                    for id in ids:
+                        try:
+                            node = Node.objects.get(id=id)
+                            node.delete()
+                        except:
+                            pass
 
 
-            params = pagination.generate_uri(request.GET, ('page',))
+                    message = _("All selected nodes deleted")
+
+                request.user.message_set.create(message=message)
+
+                params = pagination.generate_uri(request.GET, ('page',))
+                
             return HttpResponseRedirect(reverse("admin_tools", kwargs={'name': 'nodeman'}) + "?" + params)
 
 
     nodes = Node.objects.all()
 
             return HttpResponseRedirect(reverse("admin_tools", kwargs={'name': 'nodeman'}) + "?" + params)
 
 
     nodes = Node.objects.all()
 
-    if (request.GET):
-        filter_form = NodeManFilterForm(request.GET)
-    else:
-        filter_form = NodeManFilterForm({'node_type': 'all', 'state_type': 'any'})
+    text = request.GET.get('text', '')
+    text_in = request.GET.get('text_in', 'body')
 
     authors = request.GET.getlist('authors')
     tags = request.GET.getlist('tags')
 
 
     authors = request.GET.getlist('authors')
     tags = request.GET.getlist('tags')
 
-    if filter_form.is_valid():
-        data = filter_form.cleaned_data
+    type_filter = request.GET.getlist('node_type')
+    state_filter = request.GET.getlist('state_type')
+    state_filter_type = request.GET.get('state_filter_type', 'any')
 
 
-        if data['node_type'] != 'all':
-            nodes = nodes.filter(node_type=data['node_type'])
+    if type_filter:
+        nodes = nodes.filter(node_type__in=type_filter)
 
 
-        if (data['state_type'] != 'any'):
-            nodes = nodes.filter_state(**{str(data['state_type']): True})
+    state_types = NodeState.objects.filter(node__in=nodes).values_list('state_type', flat=True).distinct('state_type')
+    state_filter = [s for s in state_filter if s in state_types]
 
 
-        if (authors):
-            nodes = nodes.filter(author__id__in=authors)
-            authors = User.objects.filter(id__in=authors)
+    if state_filter:
+        if state_filter_type == 'all':
+            nodes = nodes.all_states(*state_filter)
+        else:
+            nodes = nodes.any_state(*state_filter)
 
 
-        if (tags):
-            nodes = nodes.filter(tags__id__in=tags)
-            tags = Tag.objects.filter(id__in=tags)
+    if (authors):
+        nodes = nodes.filter(author__id__in=authors)
+        authors = User.objects.filter(id__in=authors)
 
 
-        if data['text']:
-            filter = None
+    if (tags):
+        nodes = nodes.filter(tags__id__in=tags)
+        tags = Tag.objects.filter(id__in=tags)
 
 
-            if data['text_in'] == 'title' or data['text_in'] == 'both':
-                filter = models.Q(title__icontains=data['text'])
+    if text:
+        text_in = request.GET.get('text_in', 'body')
+        filter = None
 
 
-            if data['text_in'] == 'body' or data['text_in'] == 'both':
-                sec_filter = models.Q(body__icontains=data['text'])
-                if filter:
-                    filter = filter | sec_filter
-                else:
-                    filter = sec_filter
+        if text_in == 'title' or text_in == 'both':
+            filter = models.Q(title__icontains=text)
 
 
+        if text_in == 'body' or text_in == 'both':
+            sec_filter = models.Q(body__icontains=text)
             if filter:
             if filter:
-                nodes = nodes.filter(filter)
+                filter = filter | sec_filter
+            else:
+                filter = sec_filter
 
 
-    node_types = [('all', _("all"))] + [(k, n.friendly_name) for k, n in NodeMetaClass.types.items()]
-    state_types = NodeState.objects.filter(node__in=nodes).values_list('state_type', flat=True).distinct('state_type')
+        if filter:
+            nodes = nodes.filter(filter)
+
+    node_types = [(k, n.friendly_name) for k, n in NodeMetaClass.types.items()]
 
     return ('osqaadmin/nodeman.html', pagination.paginated(request, ("nodes", NodeManagementPaginatorContext()), {
     'nodes': nodes,
 
     return ('osqaadmin/nodeman.html', pagination.paginated(request, ("nodes", NodeManagementPaginatorContext()), {
     'nodes': nodes,
+    'text': text,
+    'text_in': text_in,
+    'type_filter': type_filter,
+    'state_filter': state_filter,
+    'state_filter_type': state_filter_type,
     'node_types': node_types,
     'state_types': state_types,
     'node_types': node_types,
     'state_types': state_types,
-    'filter_form': filter_form,
     'authors': authors,
     'tags': tags,
     'hide_menu': True
     }))
 
     'authors': authors,
     'tags': tags,
     'hide_menu': True
     }))
 
+@csrf_exempt
+@super_user_required
+def test_email_settings(request):
+    user = request.user
 
 
+    send_template_email([user,], 'osqaadmin/mail_test.html', { 'user' : user })
 
 
-
-
+    return render_to_response(
+        'osqaadmin/test_email_settings.html',
+        { 'user': user, },
+        RequestContext(request)
+    )
\ No newline at end of file