109 lines
3.6 KiB
Python
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
|