authentic/src/authentic2/app_settings.py

356 lines
15 KiB
Python

# authentic2 - versatile identity manager
# Copyright (C) 2010-2019 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 sys
import six
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ImproperlyConfigured
class Setting(object):
SENTINEL = object()
def __init__(self, default=SENTINEL, definition='', names=None):
self.names = names or []
if isinstance(self.names, six.string_types):
self.names = [self.names]
self.names = set(self.names)
self.default = default
self.definition = definition
def has_default(self):
return self.default != self.SENTINEL
class AppSettings(object):
def __init__(self, defaults):
self.defaults = defaults
@property
def settings(self):
if not hasattr(self, '_settings'):
from django.conf import settings
self._settings = settings
return self._settings
@property
def REALMS(self):
realms = {}
if self.A2_REGISTRATION_REALM:
realms[self.A2_REGISTRATION_REALM] = self.A2_REGISTRATION_REALM
def add_realms(new_realms):
for realm in new_realms:
if not isinstance(realm, (tuple, list)):
realms[realm] = realm
else:
realms[realm[0]] = realm[1]
from django.contrib.auth import get_backends
for backend in get_backends():
if hasattr(backend, 'get_realms'):
add_realms(backend.get_realms())
if self.A2_REALMS:
add_realms(self.A2_REALMS)
return realms.items()
@property
def A2_USER_CAN_RESET_PASSWORD(self):
if hasattr(self.settings, 'A2_USER_CAN_RESET_PASSWORD'):
return self.settings.A2_USER_CAN_RESET_PASSWORD
if hasattr(self.settings, 'A2_CAN_RESET_PASSWORD'):
return self.settings.A2_CAN_RESET_PASSWORD
return self.defaults['A2_USER_CAN_RESET_PASSWORD'].default
def __getattr__(self, key):
if key not in self.defaults:
raise AttributeError('unknown key %s' % key)
if hasattr(self.settings, key):
return getattr(self.settings, key)
if self.defaults[key].names:
for other_key in self.defaults[key].names:
if hasattr(self.settings, other_key):
return getattr(self.settings, other_key)
if self.defaults[key].has_default():
return self.defaults[key].default
raise ImproperlyConfigured(
'missing setting %s(%s) is mandatory' % (key, self.defaults[key].description))
default_settings = dict(
ATTRIBUTE_BACKENDS=Setting(
names=('A2_ATTRIBUTE_BACKENDS',),
default=(
'authentic2.attributes_ng.sources.format',
'authentic2.attributes_ng.sources.function',
'authentic2.attributes_ng.sources.django_user',
'authentic2.attributes_ng.sources.ldap',
'authentic2.attributes_ng.sources.service_roles',
),
definition='List of attribute backend classes or modules',
),
CAFILE=Setting(
names=('AUTHENTIC2_CAFILE', 'CAFILE'),
default=None,
definition='File containing certificate chains as PEM certificates'),
A2_REGISTRATION_CAN_DELETE_ACCOUNT=Setting(
default=True,
definition='Can user self delete their account and all their data'),
A2_REGISTRATION_CAN_CHANGE_PASSWORD=Setting(
default=True,
definition='Allow user to change its own password'),
A2_REGISTRATION_EMAIL_BLACKLIST=Setting(
default=[],
definition='List of forbidden email wildcards, ex.: ^.*@ville.fr$'),
A2_REGISTRATION_REDIRECT=Setting(
default=None,
definition='Forced redirection after each redirect, NEXT_URL substring is replaced'
' by the original next_url passed to /accounts/register/'),
A2_PROFILE_CAN_CHANGE_EMAIL=Setting(
default=True,
definition='Can user self change their email'),
A2_PROFILE_CAN_EDIT_PROFILE=Setting(
default=True,
definition='Can user self edit their profile'),
A2_PROFILE_CAN_MANAGE_FEDERATION=Setting(
default=True,
definition='Can user manage its federations'),
A2_PROFILE_CAN_MANAGE_SERVICE_AUTHORIZATIONS=Setting(
default=True,
definition='Allow user to revoke granted services access to its account profile data'),
A2_PROFILE_DISPLAY_EMPTY_FIELDS=Setting(
default=False,
definition='Include empty fields in profile view'),
A2_HOMEPAGE_URL=Setting(
default=None,
definition='IdP has no homepage, redirect to this one.'),
A2_USER_CAN_RESET_PASSWORD=Setting(
default=None,
definition='Allow online reset of passwords'),
A2_EMAIL_IS_UNIQUE=Setting(
default=False,
definition='Email of users must be unique'),
A2_REGISTRATION_EMAIL_IS_UNIQUE=Setting(
default=False,
definition='Email of registererd accounts must be unique'),
A2_REGISTRATION_FORM_USERNAME_REGEX=Setting(
default=r'^[\w.@+-]+$',
definition='Regex to validate usernames'),
A2_REGISTRATION_FORM_USERNAME_HELP_TEXT=Setting(
default=_('Required. At most 30 characters. Letters, digits, and @/./+/-/_ only.')),
A2_REGISTRATION_FORM_USERNAME_LABEL=Setting(
default=_('Username')),
A2_REGISTRATION_REALM=Setting(
default=None,
definition='Default realm to assign to self-registrated users'),
A2_REGISTRATION_GROUPS=Setting(
default=(),
definition='Default groups for self-registered users'),
A2_PROFILE_FIELDS=Setting(
default=(),
definition='Fields to show to the user in the profile page'),
A2_REGISTRATION_FIELDS=Setting(
default=(),
definition='Fields from the user model that must appear on the registration form'),
A2_REQUIRED_FIELDS=Setting(
default=(),
definition='User fields that are required'),
A2_REGISTRATION_REQUIRED_FIELDS=Setting(
default=(),
definition='Fields from the registration form that must be required'),
A2_PRE_REGISTRATION_FIELDS=Setting(
default=(),
definition='User fields to ask with email'),
A2_REALMS=Setting(
default=(),
definition='List of realms to search user accounts'),
A2_USERNAME_REGEX=Setting(
default=None,
definition='Regex that username must validate'),
A2_USERNAME_LABEL=Setting(
default=None,
definition='Alternate username label for the login form'),
A2_USERNAME_HELP_TEXT=Setting(
default=None,
definition='Help text to explain validation rules of usernames'),
A2_USERNAME_IS_UNIQUE=Setting(
default=True,
definition='Check username uniqueness'),
A2_LOGIN_FORM_OU_SELECTOR=Setting(
default=False,
definition='Whether to add an OU selector to the login form'),
A2_LOGIN_FORM_OU_SELECTOR_LABEL=Setting(
default=None,
definition='Label of OU field on login page'),
A2_REGISTRATION_USERNAME_IS_UNIQUE=Setting(
default=True,
definition='Check username uniqueness on registration'),
IDP_BACKENDS=(),
AUTH_FRONTENDS=(),
AUTH_FRONTENDS_KWARGS={},
VALID_REFERERS=Setting(
default=(),
definition='List of prefix to match referers'),
A2_OPENED_SESSION_COOKIE_NAME=Setting(
default='A2_OPENED_SESSION',
definition='Authentic session open'),
A2_OPENED_SESSION_COOKIE_DOMAIN=Setting(
default=None),
A2_OPENED_SESSION_COOKIE_SECURE=Setting(
default=False),
A2_ATTRIBUTE_KINDS=Setting(
default=(),
definition='List of other attribute kinds'),
A2_ATTRIBUTE_KIND_PROFILE_IMAGE_SIZE=Setting(
default=200,
definition='Width and height for a profile image'),
A2_VALIDATE_EMAIL=Setting(
default=False,
definition='Validate user email server by doing an RCPT command'),
A2_VALIDATE_EMAIL_DOMAIN=Setting(
default=True,
definition='Validate user email domain'),
A2_PASSWORD_POLICY_MIN_CLASSES=Setting(
default=3,
definition='Minimum number of characters classes to be present in passwords'),
A2_PASSWORD_POLICY_MIN_LENGTH=Setting(
default=8,
definition='Minimum number of characters in a password'),
A2_PASSWORD_POLICY_REGEX=Setting(
default=None,
definition='Regular expression for validating passwords'),
A2_PASSWORD_POLICY_REGEX_ERROR_MSG=Setting(
default=None,
definition='Error message to show when the password do not validate the regular expression'),
A2_PASSWORD_POLICY_CLASS=Setting(
default='authentic2.passwords.DefaultPasswordChecker',
definition='path of a class to validate passwords'),
A2_PASSWORD_POLICY_SHOW_LAST_CHAR=Setting(
default=False,
definition='Show last character in password fields'),
A2_AUTH_PASSWORD_ENABLE=Setting(
default=True,
definition='Activate login/password authentication', names=('AUTH_PASSWORD',)),
A2_SUGGESTED_EMAIL_DOMAINS=Setting(
default=['gmail.com', 'msn.com', 'hotmail.com', 'hotmail.fr',
'wanadoo.fr', 'yahoo.fr', 'yahoo.com', 'laposte.fr',
'free.fr', 'orange.fr', 'numericable.fr'],
definition='List of suggested email domains'),
A2_LOGIN_FAILURE_COUNT_BEFORE_WARNING=Setting(
default=0,
definition='Failure count before logging a warning to '
'authentic2.user_login_failure. No warning will be send if value is '
'0.'),
PUSH_PROFILE_UPDATES=Setting(
default=False,
definition='Push profile update to linked services'),
TEMPLATE_VARS=Setting(
default={},
definition='Variable to pass to templates'),
A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_FACTOR=Setting(
default=1.8,
definition='exponential backoff factor duration as seconds until '
'next try after a login failure'),
A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_DURATION=Setting(
default=0,
definition='exponential backoff base factor duration as secondss '
'until next try after a login failure'),
A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_MAX_DURATION=Setting(
default=3600,
definition='maximum exponential backoff maximum duration as seconds until '
'next try after a login failure'),
A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_MIN_DURATION=Setting(
default=10,
definition='minimum exponential backoff maximum duration as seconds until '
'next try after a login failure'),
A2_VERIFY_SSL=Setting(
default=True,
definition='Verify SSL certificate in HTTP requests'),
A2_ATTRIBUTE_KIND_TITLE_CHOICES=Setting(
default=(),
definition='Choices for the title attribute kind'),
A2_CORS_WHITELIST=Setting(
default=(),
definition='List of origin URL to whitelist, must be scheme://netloc[:port]'),
A2_EMAIL_CHANGE_TOKEN_LIFETIME=Setting(
default=7200,
definition='Lifetime in seconds of the token sent to verify email adresses'),
A2_DELETION_REQUEST_LIFETIME=Setting(
default=48*3600,
definition='Lifetime in seconds of the user account deletion request'),
A2_REDIRECT_WHITELIST=Setting(
default=(),
definition='List of origins which are authorized to ask for redirection.'),
A2_API_USERS_REQUIRED_FIELDS=Setting(
default=(),
definition='List of fields to require on user\'s API, override other settings'),
A2_USER_FILTER=Setting(
default={},
definition='Filters (as in QuerySet.filter() to apply to User queryset before '
'authentication'),
A2_USER_EXCLUDE=Setting(
default={},
definition='Exclusion filter (as in QuerySet.exclude() to apply to User queryset before '
'authentication'),
A2_USER_REMEMBER_ME=Setting(
default=None,
definition='Session duration as seconds when using the remember me '
'checkbox. Truthiness activates the checkbox.'),
A2_LOGIN_REDIRECT_AUTHENTICATED_USERS_TO_HOMEPAGE=Setting(
default=False,
definition='Redirect authenticated users to homepage'),
A2_LOGIN_DISPLAY_A_CANCEL_BUTTON=Setting(
default=False,
definition='Display a cancel button.'
'This is only applicable for Liberty single sign on requests'),
A2_SET_RANDOM_PASSWORD_ON_RESET=Setting(
default=True,
definition='Set a random password on request to reset the password from the front-office'),
A2_ACCOUNTS_URL=Setting(
default=None,
definition='IdP has no account page, redirect to this one.'),
A2_CACHE_ENABLED=Setting(
default=True,
definition='Disable all cache decorators for testing purpose.'),
A2_ACCEPT_EMAIL_AUTHENTICATION=Setting(
default=True,
definition='Enable authentication by email'),
A2_EMAILS_IP_RATELIMIT=Setting(
default='10/h',
definition='Maximum rate of email sendings triggered by the same IP address.'),
A2_EMAILS_ADDRESS_RATELIMIT=Setting(
default='3/d',
definition='Maximum rate of emails sent to the same email address.'),
A2_USER_DELETED_KEEP_DATA=Setting(
default=['email', 'uuid'],
definition='User data to keep after deletion'),
A2_USER_DELETED_KEEP_DATA_DAYS=Setting(
default=365,
definition='Number of days to keep data on deleted users'),
A2_TOKEN_EXISTS_WARNING=Setting(
default=True,
definition='If an active token exists, warn user before generating a new one.'),
A2_DUPLICATES_THRESHOLD=Setting(
default=0.7,
definition='Trigram similarity threshold for considering user as duplicate.'),
A2_DUPLICATES_BIRTHDATE_BONUS=Setting(
default=0.3,
definition='Bonus in case of birthdate match (no bonus is 0, max is 1).'),
)
app_settings = AppSettings(default_settings)
app_settings.__name__ = __name__
sys.modules[__name__] = app_settings