示例#1
0
class Role(models.Model):
    ALUMNI_ROLES_HRID = (
        'x',
        'master',
        'phd',
        'bachelor',
        'executive',
        'graduate',
        'masterspe',
    )
    system = models.BooleanField(_("system role"),
                                 default=False,
                                 editable=False)
    hrid = models.SlugField(_("human-readable identifier"), unique=True)
    display = UnboundedCharField(_("display name"))

    class Meta:
        verbose_name = _("role")
        verbose_name_plural = _("roles")

    def __str__(self):
        return self.hrid

    @classmethod
    def get_admin(cls):
        return cls.objects.get(hrid=ADMIN_ROLE_HRID)
示例#2
0
class GoogleAppsPassword(models.Model):
    """Password for the associated Google Apps account"""
    user = models.OneToOneField(User,
                                on_delete=models.CASCADE,
                                primary_key=True,
                                related_name='gapps_password',
                                verbose_name=_("user"))
    password = UnboundedCharField(_("password"))
    last_update = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = _("Google Apps password")
        verbose_name_plural = _("Google Apps passwords")
示例#3
0
class Role(models.Model):
    system = models.BooleanField(_("system role"),
                                 default=False,
                                 editable=False)
    hrid = models.SlugField(_("human-readable identifier"), unique=True)
    display = UnboundedCharField(_("display name"), unique=True)

    class Meta:
        verbose_name = _("role")
        verbose_name_plural = _("roles")

    def __str__(self):
        return self.hrid

    @classmethod
    def get_admin(cls):
        return cls.objects.get(hrid=ADMIN_ROLE_HRID)
示例#4
0
class User(base_user.AbstractBaseUser):
    MALE = 'male'
    FEMALE = 'female'
    SEX = (
        (MALE, _("Male")),
        (FEMALE, _("Female")),
    )

    uid = models.UUIDField("UUID", default=uuid.uuid4, editable=False)
    hrid = DottedSlugField(
        _("username"),
        unique=True,
        max_length=255,
        help_text=_(
            "Human-readable identifier, usually firstname.lastname.study-year")
    )
    fullname = UnboundedCharField(
        _("full name"), help_text=_("Name to display to other users"))
    preferred_name = UnboundedCharField(
        _("preferred name"), help_text=_("Name used when addressing the user"))
    firstname = UnboundedCharField(_("first name"), blank=True, null=True)
    lastname = UnboundedCharField(_("last name"), blank=True, null=True)
    sex = models.CharField(_("sex"),
                           max_length=6,
                           choices=SEX,
                           blank=True,
                           null=True)
    main_email = models.EmailField(_("email"), unique=True)
    roles = models.ManyToManyField(Role,
                                   related_name='members',
                                   blank=True,
                                   verbose_name=_("roles"))
    axid = models.CharField(_("AX ID"),
                            max_length=20,
                            blank=True,
                            null=True,
                            unique=True,
                            help_text=_("Identification in AX directory"))
    schoolid = models.CharField(
        _("School ID"),
        max_length=20,
        blank=True,
        null=True,
        unique=True,
        help_text=_("Identification defined by the School"))
    xorgdb_uid = models.IntegerField(
        _("Polytechnique.org database user ID"),
        blank=True,
        null=True,
        unique=True,
        help_text=_("User ID in Polytechnique.org database"))
    alumnforce_id = models.CharField(
        _("AlumnForce ID"),
        max_length=20,
        blank=True,
        null=True,
        unique=True,
        help_text=_("User ID in ax.polytechnique.org database"))
    study_year = UnboundedCharField(
        _("study year"),
        blank=True,
        null=True,
        help_text=_(
            "Kind and main year of the study ('X1829' means 'entered the school in 1829 "
            "but 'M2005' means 'graduated in 2005')"))
    grad_year = models.IntegerField(_("graduation year"),
                                    blank=True,
                                    null=True,
                                    help_text=_("Year of the graduation"))
    is_active = models.BooleanField(_('active'),
                                    default=True,
                                    help_text=_('Active user'))
    birth_date = models.DateField(_("birthdate"), blank=True, null=True)
    is_dead = models.BooleanField(_("dead"), default=False)
    death_date = models.DateField(_("death date"), blank=True, null=True)
    ax_contributor = models.NullBooleanField(
        _('AX contributor'), help_text=_('Paid a contribution to AX'))
    axjr_subscriber = models.NullBooleanField(
        _('J&R subscriber'), help_text=_('Subscribed to La Jaune et la Rouge'))
    ax_last_synced = models.DateField(_("last sync with AX"),
                                      blank=True,
                                      null=True)

    objects = UserManager()

    class Meta:
        verbose_name = _("user account")
        verbose_name_plural = _("user accounts")

    # base_user.AbstractBaseUser bridge

    EMAIL_FIELD = 'main_email'
    USERNAME_FIELD = 'hrid'
    REQUIRED_FIELDS = ['fullname', 'preferred_name', 'main_email']

    def get_username(self):
        return self.hrid

    def get_full_name(self):
        return self.fullname

    def get_short_name(self):
        return self.preferred_name

    @property
    def is_staff(self):
        """Staff members are defined by the admin role"""
        return self.roles.filter(hrid=ADMIN_ROLE_HRID).count() > 0

    @property
    def email(self):
        """Hack to work around a bug in django-oidc-provider"""
        field_name = self.get_email_field_name()
        return getattr(self, field_name)

    def has_module_perms(self, app_label):
        # staff members have every right
        if self.is_staff:
            return True
        # FIXME implement permissions for other user kinds
        return False

    def has_perm(self, perm, obj=None):
        # staff members have every right
        if self.is_staff:
            return True
        # FIXME implement permissions for other user kinds
        return False

    def is_x_alumni(self):
        """The user is an alumni of Ecole Polytechnique (not an external account)"""
        return self.roles.filter(hrid__in=Role.ALUMNI_ROLES_HRID).exists()

    def clean(self):
        # If the death date is filled, the user is dead
        if self.death_date is not None and not self.is_dead:
            self.is_dead = True

        # Make sure the human-readable identifier is in lowercase
        if self.hrid != self.hrid.lower():
            raise ValidationError({
                'hrid':
                ValidationError(_("Enter a human-readable ID in lowercase.")),
            })

        # Make sure the email address is in lowercase
        if self.main_email != self.main_email.lower():
            raise ValidationError({
                'main_email':
                ValidationError(_("Enter an email address in lowercase.")),
            })
示例#5
0
class AuthGroupeXClient(models.Model):
    privkey = models.CharField(
        _("private key"),
        unique=True,
        max_length=40,
        help_text=_("Secret key shared with the client"))
    name = UnboundedCharField(_("name"),
                              unique=True,
                              help_text=_("Name of the client"))
    data_fields = UnboundedCharField(
        _("data fields"), help_text=_("Fields requested by the client"))
    return_urls = UnboundedCharField(
        _("return URLs"),
        help_text=_("Regular expression pattern of the allowed return URLs"))
    last_used = models.DateField(
        _("last used"),
        null=True,
        help_text=_("Date of the last use of this client"))
    allow_xnet = models.BooleanField(
        _("allow xnet"),
        default=False,
        help_text=_(
            "Allow account with type 'xnet' (external) to log in to this client"
        ))

    objects = AuthGroupeXClientManager()

    class Meta:
        verbose_name = _("AuthGroupeX client")
        verbose_name_plural = _("AuthGroupeX clients")

    def __str__(self):
        return self.name

    def match_return_url(self, url):
        """Match the given url against the pattern for return URLS"""
        pattern = self.return_urls.strip()
        # PHP's preg_match uses a special character at the beginning and the end
        # of the pattern
        if pattern and pattern[0] == pattern[-1] == '#':
            pattern = pattern[1:-1]
        return re.match(pattern, url)

    def match_signed_challenge(self, gpex_challenge, gpex_pass):
        """Verify that the challenge has been signed with the right key"""
        try:
            computed_pass = hashlib.md5(
                (gpex_challenge + self.privkey).encode('ascii')).hexdigest()
        except UnicodeEncodeError:
            return
        return compare_digest(computed_pass, gpex_pass)

    def add_response_data(self, ext_url_params, user, gpex_challenge,
                          gpex_group):
        """Add user response data into the returned parameters"""
        try:
            hashed_val = ('1' + gpex_challenge + self.privkey).encode('ascii')
        except UnicodeEncodeError:
            return False
        for data_field in self.data_fields.split(','):
            val = None
            if data_field == 'perms':
                val = 'admin' if user.is_staff else 'user'
            elif data_field == 'forlife':
                val = user.hrid
            elif data_field in ('prenom', 'firstname'):
                val = user.firstname
            elif data_field in ('nom', 'lastname'):
                val = user.lastname
            elif data_field == 'sex':
                val = user.sex
            elif data_field == 'matricule_ax':
                val = user.axid
            elif data_field == 'matricule':
                val = user.schoolid
            elif data_field == 'uid':
                val = str(user.xorgdb_uid or '')
            elif data_field == 'username':
                val = user.main_email
            elif data_field in ('promo', 'entry_year'):
                val = user.study_year
                while val and not '0' <= val[0] <= '9':
                    val = val[1:]
            elif data_field == 'full_promo':
                val = user.study_year
            elif data_field in ('promo_sortie', 'grad_year'):
                val = str(user.grad_year)
            elif data_field == 'grpauth' and gpex_group:
                try:
                    grp_membership = user.groups.get(
                        group__shortname=gpex_group)
                    val = grp_membership.perms
                    if val == 'member':
                        val = 'membre'
                except ObjectDoesNotExist:
                    pass

            if not val:
                val = ''
            ext_url_params[data_field] = val
            try:
                hashed_val += val.encode('utf-8')
            except UnicodeEncodeError:
                return False

        # Sign the values
        auth = hashlib.md5(hashed_val + b'1').hexdigest()
        ext_url_params['auth'] = auth
        return True
示例#6
0
class User(base_user.AbstractBaseUser):
    MALE = 'male'
    FEMALE = 'female'
    SEX = (
        (MALE, _("Male")),
        (FEMALE, _("Female")),
    )

    uid = models.UUIDField("UUID", default=uuid.uuid4, editable=False)
    hrid = DottedSlugField(
        _("username"),
        unique=True,
        max_length=255,
        help_text=_(
            "Human-readable identifier, usually firstname.lastname.study-year")
    )
    fullname = UnboundedCharField(
        _("full name"), help_text=_("Name to display to other users"))
    preferred_name = UnboundedCharField(
        _("preferred name"), help_text=_("Name used when addressing the user"))
    firstname = UnboundedCharField(_("first name"), null=True)
    lastname = UnboundedCharField(_("last name"), null=True)
    sex = models.CharField(_("sex"), max_length=6, choices=SEX, null=True)
    main_email = models.EmailField(_("email"), unique=True)
    roles = models.ManyToManyField(Role,
                                   related_name='members',
                                   blank=True,
                                   verbose_name=_("roles"))
    axid = UnboundedCharField(_("AX ID"),
                              blank=True,
                              null=True,
                              help_text=_("Identification in AX directory"))
    schoolid = UnboundedCharField(
        _("School ID"),
        blank=True,
        null=True,
        unique=True,
        help_text=_("Identification defined by the School"))
    xorgdb_uid = models.IntegerField(
        _("Polytechnique.org database user ID"),
        null=True,
        unique=True,
        help_text=_("User ID in Polytechnique.org database"))
    study_year = UnboundedCharField(
        _("study year"),
        blank=True,
        null=True,
        help_text=
        _("Kind and main year of the study ('X1829' means 'entered the school in 1829 "
          + "but 'M2005' means 'graduated in 2005')"))
    grad_year = models.IntegerField(_("graduation year"),
                                    blank=True,
                                    null=True,
                                    help_text=_("Year of the graduation"))

    objects = UserManager()

    class Meta:
        verbose_name = _("user account")
        verbose_name_plural = _("user accounts")

    # base_user.AbstractBaseUser bridge

    EMAIL_FIELD = 'main_email'
    USERNAME_FIELD = 'hrid'
    REQUIRED_FIELDS = ['fullname', 'preferred_name', 'main_email']

    def get_username(self):
        return self.hrid

    def get_full_name(self):
        return self.fullname

    def get_short_name(self):
        return self.preferred_name

    @property
    def is_staff(self):
        """Staff members are defined by the admin role"""
        return self.roles.filter(hrid=ADMIN_ROLE_HRID).count() > 0

    @property
    def email(self):
        """Hack to work around a bug in django-oidc-provider"""
        field_name = self.get_email_field_name()
        return getattr(self, field_name)

    def has_module_perms(self, app_label):
        # staff members have every right
        if self.is_staff:
            return True
        # FIXME implement permissions for other user kinds
        return False

    def has_perm(self, perm, obj=None):
        # staff members have every right
        if self.is_staff:
            return True
        # FIXME implement permissions for other user kinds
        return False