models.py 3.76 KB
Newer Older
1
"""
2 3 4 5 6 7 8 9 10 11
Models for embargoing visits to certain courses by IP address.

WE'RE USING MIGRATIONS!

If you make changes to this model, be sure to create an appropriate migration
file and check it in at the same time as your model changes. To do that,

1. Go to the edx-platform dir
2. ./manage.py lms schemamigration embargo --auto description_of_your_change
3. Add the migration file created in edx-platform/common/djangoapps/embargo/migrations/
12
"""
13 14 15

import ipaddr

16 17 18
from django.db import models

from config_models.models import ConfigurationModel
19
from xmodule_django.models import CourseKeyField, NoneToEmptyManager
20 21


22 23 24 25
class EmbargoedCourse(models.Model):
    """
    Enable course embargo on a course-by-course basis.
    """
26 27
    objects = NoneToEmptyManager()

28
    # The course to embargo
29
    course_id = CourseKeyField(max_length=255, db_index=True, unique=True)
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

    # Whether or not to embargo
    embargoed = models.BooleanField(default=False)

    @classmethod
    def is_embargoed(cls, course_id):
        """
        Returns whether or not the given course id is embargoed.

        If course has not been explicitly embargoed, returns False.
        """
        try:
            record = cls.objects.get(course_id=course_id)
            return record.embargoed
        except cls.DoesNotExist:
            return False

    def __unicode__(self):
        not_em = "Not "
        if self.embargoed:
            not_em = ""
51 52
        # pylint: disable=no-member
        return u"Course '{}' is {}Embargoed".format(self.course_id.to_deprecated_string(), not_em)
53 54 55


class EmbargoedState(ConfigurationModel):
56
    """
57
    Register countries to be embargoed.
58
    """
59
    # The countries to embargo
60 61 62 63 64
    embargoed_countries = models.TextField(
        blank=True,
        help_text="A comma-separated list of country codes that fall under U.S. embargo restrictions"
    )

65 66 67 68 69
    @property
    def embargoed_countries_list(self):
        """
        Return a list of upper case country codes
        """
70 71
        if self.embargoed_countries == '':
            return []
72 73 74
        return [country.strip().upper() for country in self.embargoed_countries.split(',')]  # pylint: disable=no-member


75
class IPFilter(ConfigurationModel):
76 77 78 79 80 81 82 83 84
    """
    Register specific IP addresses to explicitly block or unblock.
    """
    whitelist = models.TextField(
        blank=True,
        help_text="A comma-separated list of IP addresses that should not fall under embargo restrictions."
    )

    blacklist = models.TextField(
85
        blank=True,
86
        help_text="A comma-separated list of IP addresses that should fall under embargo restrictions."
87 88
    )

89 90 91 92 93 94 95 96 97 98
    class IPFilterList(object):
        """
        Represent a list of IP addresses with support of networks.
        """

        def __init__(self, ips):
            self.networks = [ipaddr.IPNetwork(ip) for ip in ips]

        def __iter__(self):
            for network in self.networks:
99
                yield network
100 101 102 103 104 105 106 107 108 109 110 111 112

        def __contains__(self, ip):
            try:
                ip = ipaddr.IPAddress(ip)
            except ValueError:
                return False

            for network in self.networks:
                if network.Contains(ip):
                    return True

            return False

113
    @property
114
    def whitelist_ips(self):
115
        """
116
        Return a list of valid IP addresses to whitelist
117
        """
118 119
        if self.whitelist == '':
            return []
120
        return self.IPFilterList([addr.strip() for addr in self.whitelist.split(',')])  # pylint: disable=no-member
121 122

    @property
123
    def blacklist_ips(self):
124
        """
125
        Return a list of valid IP addresses to blacklist
126
        """
127 128
        if self.blacklist == '':
            return []
129
        return self.IPFilterList([addr.strip() for addr in self.blacklist.split(',')])  # pylint: disable=no-member