authentic/src/authentic2/apps/authenticators/models.py

109 lines
3.6 KiB
Python

# authentic2 - versatile identity manager
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
import logging
import uuid
from django.db import models
from django.shortcuts import render, reverse
from django.utils.formats import date_format
from django.utils.translation import ugettext_lazy as _
from authentic2.utils.evaluate import evaluate_condition
from .query import AuthenticatorManager
logger = logging.getLogger(__name__)
class BaseAuthenticator(models.Model):
uuid = models.CharField(max_length=255, unique=True, default=uuid.uuid4, editable=False)
name = models.CharField(_('Name'), max_length=128)
slug = models.SlugField(unique=True)
ou = models.ForeignKey(
verbose_name=_('organizational unit'),
to='a2_rbac.OrganizationalUnit',
null=True,
blank=False,
on_delete=models.CASCADE,
)
order = models.IntegerField(_('Order'), default=0)
enabled = models.BooleanField(default=False, editable=False)
show_condition = models.CharField(
_('Show condition'),
max_length=128,
blank=True,
help_text=_(
'Django template controlling authenticator display. For example, "\'backoffice\' in '
'login_hint or remotre_addr == \'1.2.3.4\'" would hide the authenticator from normal users '
'except if they come from the specified IP address. Available variables include '
'service_ou_slug, service_slug, remote_addr, login_hint and headers.'
),
)
objects = models.Manager()
authenticators = AuthenticatorManager()
type = ''
manager_form_class = None
description_fields = ['show_condition']
class Meta:
ordering = ('-enabled', 'name', 'slug', 'ou')
def __str__(self):
if self.name:
return '%s - %s' % (self._meta.verbose_name, self.name)
return str(self._meta.verbose_name)
def get_identifier(self):
return '%s_%s' % (self.type, self.pk)
def get_absolute_url(self):
return reverse('a2-manager-authenticator-detail', kwargs={'pk': self.pk})
def get_short_description(self):
return ''
def get_full_description(self):
for field in self.description_fields:
value = getattr(self, field)
if not value:
continue
if isinstance(value, datetime.datetime):
value = date_format(value, 'DATETIME_FORMAT')
yield _('%(field)s: %(value)s') % {
'field': self._meta.get_field(field).verbose_name.capitalize(),
'value': value,
}
@property
def priority(self):
return self.order
def shown(self, ctx=()):
if not self.show_condition:
return True
ctx = dict(ctx, id=self.slug)
try:
return evaluate_condition(self.show_condition, ctx, on_raise=True)
except Exception as e:
logger.error(e)
return False