src/cm/security.py
author gibus
Tue, 25 Jun 2013 11:56:01 +0200
changeset 504 b2e0186daa5b
parent 470 077be006891e
child 522 c9c2148f09c9
permissions -rw-r--r--
Adds a category to comments, painted with colored vertical bar.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     1
from django.conf import settings
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     2
from django.contrib.auth import REDIRECT_FIELD_NAME
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     3
from django.contrib.auth.models import Permission
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     4
from django.contrib.contenttypes.models import ContentType
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     5
from django.shortcuts import get_object_or_404
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     6
from django.core.urlresolvers import reverse
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     7
from django.http import HttpResponseRedirect
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     8
from django.utils.http import urlquote
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     9
from django.db.models import Q
287
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
    10
from piston.utils import rc
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    11
import logging
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    12
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    13
from cm.models import *
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    14
from cm import cm_settings
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    15
from cm.exception import UnauthorizedException
449
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
    16
from cm.cm_settings import DECORATED_CREATORS
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    17
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    18
def get_request_user(request):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    19
    if request and request.user and not request.user.is_anonymous():
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    20
        user = request.user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    21
    else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    22
        user = None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    23
    return user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    24
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    25
## Permission functions
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    26
class FakeRequest(object):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    27
    def __init__(self, user):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    28
        self.user = user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    29
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    30
def user_has_perm(user, perm_name, text=None):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    31
    return has_perm(FakeRequest(user),perm_name, text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    32
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    33
def has_perm(request, perm_name, text=None):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    34
    # bypass sec if NO_SECURITY
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    35
    if cm_settings.NO_SECURITY:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    36
        return True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    37
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    38
    # make sure perm exist
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    39
    assert Permission.objects.get(codename=perm_name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    40
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    41
    user = get_request_user(request)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    42
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    43
    if user and user.is_staff:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    44
        return True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    45
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    46
    if not text:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    47
        return UserRole.objects.filter(user=user, text=None).filter(Q(role__permissions__codename__exact=perm_name)).count() != 0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    48
    else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    49
        # local role only ADDS permissions:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    50
        # either a global or a local role with appropriate permissions
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    51
        #return UserRole.objects.filter(user=user).filter(Q(text=text) | Q(text=None)).filter(Q(role__permissions__codename__exact=perm_name)).count() != 0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    52
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    53
        # local role OVERRIDES global role:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    54
        if UserRole.objects.filter(Q(user=user),Q(text=text),~Q(role=None)): # if non void local role
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    55
            return UserRole.objects.filter(user=user).filter(text=text).filter(Q(role__permissions__codename__exact=perm_name)).count() != 0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    56
        else:
210
e4715ab65e2d fix security pb (too restrictive): logged users should inherit anon roles (if no text role is defined)
raph
parents: 102
diff changeset
    57
            # local role for anon users
e4715ab65e2d fix security pb (too restrictive): logged users should inherit anon roles (if no text role is defined)
raph
parents: 102
diff changeset
    58
            # OR global role for anon users
e4715ab65e2d fix security pb (too restrictive): logged users should inherit anon roles (if no text role is defined)
raph
parents: 102
diff changeset
    59
            # OR global role for this user
e4715ab65e2d fix security pb (too restrictive): logged users should inherit anon roles (if no text role is defined)
raph
parents: 102
diff changeset
    60
            return UserRole.objects.filter(Q(user=user) | Q(user=None)).filter(Q(text=None) | Q(text=text)).filter(Q(role__permissions__codename__exact=perm_name)).count() != 0            
e4715ab65e2d fix security pb (too restrictive): logged users should inherit anon roles (if no text role is defined)
raph
parents: 102
diff changeset
    61
            #return UserRole.objects.filter(user=user).filter(text=None).filter(Q(role__permissions__codename__exact=perm_name)).count() != 0
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    62
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    63
def has_own_perm(request, perm_name, text, comment):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    64
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    65
    user = get_request_user(request)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    66
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    67
    if not user:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    68
        return False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    69
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    70
    # bypass sec if NO_SECURITY
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    71
    if cm_settings.NO_SECURITY:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    72
        return True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    73
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    74
    # make sure perm exist
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    75
    assert Permission.objects.get(codename=perm_name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    76
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    77
    # 2 special cases for comment own edition:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    78
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    79
    # 1
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    80
    # if perm = can_edit_own_comment and 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    81
    # text is a priori moderated and
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    82
    # comment is approved and
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    83
    # don't have moderation rights and
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    84
    if comment and comment.state == 'approved' and \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    85
       perm_name == 'can_edit_comment_own' and \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    86
       text.last_text_version.mod_posteriori == False and \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    87
       not has_perm(request, 'can_manage_text', text=text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    88
        return False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    89
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    90
    # 2       
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    91
    # if perm = can_edit_own_comment and and 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    92
    # text is a posteriori moderated and
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    93
    # there is a reply
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    94
    # don't have moderation rights and
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    95
    if comment and comment.state == 'approved' and \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    96
       perm_name == 'can_edit_comment_own' and \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    97
       text.last_text_version.mod_posteriori == True and \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    98
       comment.comment_set.count() != 0 and \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    99
       not has_perm(request, 'can_manage_text', text=text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   100
        return False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   101
    
355
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   102
    actual_own_user = False
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   103
    if comment.user == request.user:
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   104
      if DECORATED_CREATORS:
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   105
        if request.GET.get('name', None) == comment.get_name():
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   106
          actual_own_user = True
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   107
      else:
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   108
        actual_own_user = True
c926868cf7e6 if DECORATED_CREATORS take into account the "fake" username if has_own_perm()
gibus
parents: 295
diff changeset
   109
    return (actual_own_user and has_perm(request, perm_name, text=text)) 
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   110
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   111
def is_authenticated(request):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   112
    # We customize this to be able to monkey patch it if needed
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   113
    return request.user.is_authenticated()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   114
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   115
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   116
## Content access functions
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   117
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   118
def get_texts_with_perm(request, perm_name):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   119
    assert Permission.objects.get(codename=perm_name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   120
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   121
    user = get_request_user(request)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   122
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   123
    if user and user.is_staff:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   124
        return Text.objects.all()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   125
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   126
    # local role only ADDS permissions:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   127
    ## global perm
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   128
    # if UserRole.objects.filter(text=None).filter(role__permissions__codename__exact=perm_name).filter(Q(user=user) | Q(user=None) ).count() != 0:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   129
    #    return Text.objects.all().distinct()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   130
    ## only texts with role with perm
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   131
    #else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   132
    #    return Text.objects.filter(Q(userrole__role__permissions__codename__exact=perm_name), Q(userrole__user=user) | Q(userrole__user=None)).distinct()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   133
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   134
    # local role OVERRIDES global role:
102
f5d3ea4bd03c fix permissions in get_text_with_perms
raph
parents: 81
diff changeset
   135
    texts_with_local_role = Text.objects.filter(userrole__in=UserRole.objects.filter(Q(user=user) | Q(user=None)).filter(~Q(role=None)))
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   136
    #Text.objects.filter(Q(userrole__user=user) & ~Q(userrole__role=None))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   137
    texts_without_local_role = Text.objects.exclude(id__in=texts_with_local_role)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   138
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   139
    texts_with_local_role_with_perm = Text.objects.filter(id__in=texts_with_local_role).filter(Q(userrole__role__permissions__codename__exact=perm_name), Q(userrole__user=user) | Q(userrole__user=None)).distinct()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   140
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   141
    # global perm?
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   142
    if UserRole.objects.filter(text=None).filter(role__permissions__codename__exact=perm_name).filter(Q(user=user) | Q(user=None) ).count() != 0:    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   143
        texts_without_local_role_with_perm = Text.objects.filter(id__in=texts_without_local_role)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   144
    else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   145
        texts_without_local_role_with_perm = []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   146
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   147
    ids = set([t.id for t in texts_with_local_role_with_perm]).union(set([t.id for t in texts_without_local_role_with_perm]))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   148
    return Text.objects.filter(id__in=ids)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   149
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   150
def get_viewable_comments(request, comments, text, order_by=('created',)):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   151
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   152
    Get comments visibles by user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   153
    comments: queryset
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   154
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   155
    user = get_request_user(request)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   156
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   157
    if user and has_perm(request, 'can_view_unapproved_comment', text=text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   158
        return list(comments.order_by(*order_by))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   159
    else:
449
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   160
        # Fetch role_model to process specific behaviour for role_teacher model
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   161
        from cm.models import ApplicationConfiguration
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   162
        role_model = ApplicationConfiguration.get_key('workspace_role_model')
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   163
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   164
        if has_perm(request, 'can_view_approved_comment', text=text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   165
            visible_comments = comments.filter(state = 'approved').order_by(*order_by)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   166
            # filter comments with a non visible (i.e. moderated) comment in the above thread 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   167
            comments_thread_viewable = [c for c in visible_comments if c.is_thread_full_visible()]
449
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   168
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   169
            # for role_teacher role model, do not show 'individual student' comments
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   170
            if (role_model == 'teacher'):
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   171
              unfiltered_comments = list(comments_thread_viewable)
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   172
              for c in unfiltered_comments:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   173
                if c.user_id and c.user_id != 1:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   174
                  try:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   175
                    userrole = UserRole.objects.get(user=c.user, text=text)
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   176
                  except:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   177
                    userrole = UserRole.objects.get(user=None, text=None)
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   178
                  if userrole.role_id == None:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   179
                    role = c.user.get_profile().global_userrole().role
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   180
                  else:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   181
                    role = userrole.role
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   182
                  if role.name == 'Individual student':
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   183
                    comments_thread_viewable.remove(c)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   184
            return comments_thread_viewable 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   185
        elif user and has_perm(request, 'can_view_comment_own', text=text):
449
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   186
            if DECORATED_CREATORS:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   187
              visible_comments = comments.filter(name=request.GET.get('name', None)).order_by(*order_by)
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   188
            else:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   189
              visible_comments = comments.filter(user=user).order_by(*order_by)
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   190
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   191
            # for role_teacher role model, add 'teacher' comments
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   192
            if (role_model == 'teacher'):
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   193
              with_teachers = []
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   194
              for u in list(User.objects.filter(userrole__role__name = 'Teacher')):
470
077be006891e Fix filtering of teachers' comments for individual students in role_teacher role model when using DECORATED_CREATORS.
gibus
parents: 449
diff changeset
   195
                with_teachers.append(u.id)
449
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   196
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   197
              # add admin and current user
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   198
              admin =  User.objects.get(id=1)
470
077be006891e Fix filtering of teachers' comments for individual students in role_teacher role model when using DECORATED_CREATORS.
gibus
parents: 449
diff changeset
   199
              with_teachers.append(admin.id)
449
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   200
              if DECORATED_CREATORS:
470
077be006891e Fix filtering of teachers' comments for individual students in role_teacher role model when using DECORATED_CREATORS.
gibus
parents: 449
diff changeset
   201
                myself = request.GET.get('name', None)
077be006891e Fix filtering of teachers' comments for individual students in role_teacher role model when using DECORATED_CREATORS.
gibus
parents: 449
diff changeset
   202
                visible_comments = comments.filter(Q(user__id__in=with_teachers) | Q(name=myself)).order_by(*order_by)
449
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   203
              else:
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   204
                with_teachers.append(user.id)
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   205
                visible_comments = comments.filter(user__id__in=with_teachers).order_by(*order_by)
5387c032df35 In role_teacher model, individual students can see their own comments but also teacher's ones, whereas individual students' comments cannot be seen by students.
gibus
parents: 355
diff changeset
   206
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   207
            # filter comments with a non visible (i.e. moderated) comment in the above thread 
16
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 0
diff changeset
   208
            comments_thread_viewable = [c for c in visible_comments if c.is_thread_full_visible(own_user=user)]
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   209
            return comments_thread_viewable                
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   210
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   211
            return []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   212
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   213
def get_viewable_activities(request=None, act_types={}, text=None):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   214
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   215
    Get activities user in request is allowed to see
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   216
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   217
    from cm.security import has_perm, get_texts_with_perm, get_viewable_comments
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   218
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   219
    selected_activities = reduce(list.__add__,[Activity.VIEWABLE_ACTIVITIES[k] for k in act_types.keys() if act_types[k]], [])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   220
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   221
    activities = Activity.objects.filter(type__in=selected_activities)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   222
    if text:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   223
        activities = activities.filter(text=text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   224
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   225
    if not has_perm(request, 'can_manage_workspace'):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   226
        texts = get_texts_with_perm(request, 'can_view_text')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   227
        activities = activities.filter(Q(text__in=texts))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   228
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   229
        comments = [] 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   230
        [comments.extend(get_viewable_comments(request, t.last_text_version.comment_set.all(), t)) for t in texts]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   231
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   232
        activities = activities.filter(Q(comment__in=comments) | Q(comment=None))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   233
    return activities.order_by('-created')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   234
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   235
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   236
# won't need to be overridden, should it be moved to another file ? 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   237
def list_viewable_comments(request, comments_list, text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   238
    ret = []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   239
    for comment in comments_list :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   240
        ret += [comment] + list_viewable_comments(request, get_viewable_comments(request, comment.comment_set, text), text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   241
    return ret
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   242
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   243
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   244
# decorators (simple wrappers around above functions)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   245
def has_global_perm(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   246
    def _dec(view_func):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   247
        def _check_global_perm(request, *args, **kwargs):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   248
            if must_be_logged_in and not is_authenticated(request):
284
730dd9fb2c77 simplification of security check: all unauthorized exceptions are dealt with by context processors
raph
parents: 210
diff changeset
   249
                raise UnauthorizedException('Should be logged in')
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   250
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   251
            if has_perm(request, perm_name, text=None): 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   252
                return view_func(request, *args, **kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   253
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   254
            raise UnauthorizedException('No global perm %s' % perm_name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   255
        _check_global_perm.__doc__ = view_func.__doc__
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   256
        _check_global_perm.__dict__ = view_func.__dict__
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   257
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   258
        return _check_global_perm
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   259
    return _dec    
287
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   260
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   261
def has_perm_on_text_api(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME):    
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   262
    return _has_perm_on_text(perm_name, must_be_logged_in, redirect_field_name, api=True)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   263
    
287
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   264
def has_perm_on_text(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME, api=False):
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   265
    return _has_perm_on_text(perm_name, must_be_logged_in, redirect_field_name, api)
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   266
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   267
def _has_perm_on_text(perm_name, must_be_logged_in=False, redirect_field_name=REDIRECT_FIELD_NAME, api=False):    
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   268
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   269
    decorator protection checking for perm for logged in user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   270
    force logged in (i.e. redirect to connection screen if not if must_be_logged_in 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   271
    """    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   272
    def _dec(view_func):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   273
        def _check_local_perm(request, *args, **kwargs):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   274
            if cm_settings.NO_SECURITY:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   275
                return view_func(request, *args, **kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   276
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   277
            if must_be_logged_in and not is_authenticated(request):
287
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   278
                if not api:
295
7c40b98f627f Merge with b8672f57ba3cd4e876277a13c69621446b940052
raph
parents: 287 284
diff changeset
   279
                    raise UnauthorizedException('Should be logged in')
287
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   280
                else:
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   281
                    return rc.FORBIDDEN
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   282
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   283
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   284
            if 'key' in kwargs: 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   285
                text = get_object_or_404(Text, key=kwargs['key'])                
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   286
            else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   287
                raise Exception('no security check possible')
287
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   288
                
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   289
            # in api, the view has an object as first parameter, request is args[0]
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   290
            if not api:                
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   291
                req = request
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   292
            else:                    
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   293
                req = args[0]     
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   294
            if has_perm(req, perm_name, text=text): 
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   295
                return view_func(request, *args, **kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   296
            #else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   297
                # TODO: (? useful ?) if some user have the perm and not logged-in : redirect to login
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   298
                #if not request.user.is_authenticated() and number_has_perm_on_text(permission, text_id) > 0:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   299
                #    return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, urlquote(request.get_full_path())))                    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   300
            # else : unauthorized
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   301
            
287
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   302
            if not api:
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   303
                raise UnauthorizedException('No perm %s' % perm_name)
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   304
            else:
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   305
                return rc.FORBIDDEN
fc5ed157ebfe add api: basic auth / unit tests / online doc (based on django-piston)
raph
parents: 210
diff changeset
   306
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   307
        _check_local_perm.__doc__ = view_func.__doc__
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   308
        _check_local_perm.__dict__ = view_func.__dict__
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   309
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   310
        return _check_local_perm
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   311
    return _dec
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   312
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   313
def has_perm_on_comment(perm_name):    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   314
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   315
    decorator protection checking for perm for logged in user on to comment
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   316
    perm_name: 'virtual' permission name 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   317
    """    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   318
    def _dec(view_func):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   319
        def _check_local_perm(request, *args, **kwargs):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   320
            if cm_settings.NO_SECURITY:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   321
                return view_func(request, *args, **kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   322
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   323
            if 'key' in kwargs: 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   324
                text = get_object_or_404(Text, key=kwargs['key'])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   325
                # first try permission on text                
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   326
                if has_perm(request, perm_name, text=text) :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   327
                    return view_func(request, *args, **kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   328
                if 'comment_key' in kwargs:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   329
                    comment = get_object_or_404(Comment, key=kwargs['comment_key'])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   330
                    if has_own_perm(request, perm_name + "_own", text, comment) :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   331
                        return view_func(request, *args, **kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   332
                else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   333
                    raise Exception('no security check possible: no comment key')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   334
            else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   335
                raise Exception('no security check possible: no text key')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   336
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   337
            raise UnauthorizedException('No perm %s on comment' % perm_name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   338
        _check_local_perm.__doc__ = view_func.__doc__
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   339
        _check_local_perm.__dict__ = view_func.__dict__
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   340
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   341
        return _check_local_perm
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   342
    return _dec        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   343
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   344
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   345