models.py 3.97 KB
Newer Older
cahrens committed
1 2 3 4
"""
Table for storing information about whether or not Studio users have course creation privileges.
"""
from django.db import models
cahrens committed
5
from django.db.models.signals import post_init, post_save
6
from django.dispatch import receiver, Signal
7
from django.contrib.auth.models import User
cahrens committed
8

9
from django.utils import timezone
10
from django.utils.translation import ugettext as _
cahrens committed
11

12
# A signal that will be sent when users should be added or removed from the creator group
13 14 15 16 17 18 19
update_creator_state = Signal(providing_args=["caller", "user", "state"])

# A signal that will be sent when admin should be notified of a pending user request
send_admin_notification = Signal(providing_args=["user"])

# A signal that will be sent when user should be notified of change in course creator privileges
send_user_notification = Signal(providing_args=["user", "state"])
cahrens committed
20

cahrens committed
21

cahrens committed
22
class CourseCreator(models.Model):
cahrens committed
23 24 25
    """
    Creates the database table model.
    """
26 27 28 29 30 31
    UNREQUESTED = 'unrequested'
    PENDING = 'pending'
    GRANTED = 'granted'
    DENIED = 'denied'

    # Second value is the "human-readable" version.
cahrens committed
32
    STATES = (
33 34 35 36
        (UNREQUESTED, _(u'unrequested')),
        (PENDING, _(u'pending')),
        (GRANTED, _(u'granted')),
        (DENIED, _(u'denied')),
cahrens committed
37
    )
cahrens committed
38

39
    user = models.ForeignKey(User, help_text=_("Studio user"), unique=True)
cahrens committed
40
    state_changed = models.DateTimeField('state last updated', auto_now_add=True,
41 42 43 44 45
                                         help_text=_("The date when state was last updated"))
    state = models.CharField(max_length=24, blank=False, choices=STATES, default=UNREQUESTED,
                             help_text=_("Current course creator state"))
    note = models.CharField(max_length=512, blank=True, help_text=_("Optional notes about this user (for example, "
                                                                    "why course creation access was denied)"))
cahrens committed
46 47

    def __unicode__(self):
48
        return u"{0} | {1} [{2}]".format(self.user, self.state, self.state_changed)
cahrens committed
49

cahrens committed
50 51

@receiver(post_init, sender=CourseCreator)
52
def post_init_callback(sender, **kwargs):
53
    """
54
    Extend to store previous state.
55
    """
cahrens committed
56
    instance = kwargs['instance']
57
    instance.orig_state = instance.state
cahrens committed
58

cahrens committed
59 60

@receiver(post_save, sender=CourseCreator)
61
def post_save_callback(sender, **kwargs):
62
    """
63
    Extend to update state_changed time and fire event to update course creator group, if appropriate.
64
    """
cahrens committed
65 66 67 68
    instance = kwargs['instance']
    # We only wish to modify the state_changed time if the state has been modified. We don't wish to
    # modify it for changes to the notes field.
    if instance.state != instance.orig_state:
69
        granted_state_change = instance.state == CourseCreator.GRANTED or instance.orig_state == CourseCreator.GRANTED
70 71
        # If either old or new state is 'granted', we must manipulate the course creator
        # group maintained by authz. That requires staff permissions (stored admin).
72
        if granted_state_change:
73
            assert hasattr(instance, 'admin'), 'Must have stored staff user to change course creator group'
74 75 76 77
            update_creator_state.send(
                sender=sender,
                caller=instance.admin,
                user=instance.user,
78
                state=instance.state
79
            )
80

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
        # If user has been denied access, granted access, or previously granted access has been
        # revoked, send a notification message to the user.
        if instance.state == CourseCreator.DENIED or granted_state_change:
            send_user_notification.send(
                sender=sender,
                user=instance.user,
                state=instance.state
            )

        # If the user has gone into the 'pending' state, send a notification to interested admin.
        if instance.state == CourseCreator.PENDING:
            send_admin_notification.send(
                sender=sender,
                user=instance.user
            )

97 98 99
        instance.state_changed = timezone.now()
        instance.orig_state = instance.state
        instance.save()