mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[FR] Enable restrictions on allowed domains for signup (#4172)
* [FR] Enable restrictions on allowed domains for signup Fixes #4168 * raise permission errors * add setting to page * move checks to clean_email * remove unneeded check * simplify * log error to database * factor settings fnc call out * Add validation before setting save * add before_save to accepted tokens
This commit is contained in:
parent
41318e4056
commit
be859183a5
@ -215,9 +215,35 @@ class RegistratonMixin:
|
|||||||
return super().is_open_for_signup(request, *args, **kwargs)
|
return super().is_open_for_signup(request, *args, **kwargs)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def clean_email(self, email):
|
||||||
|
"""Check if the mail is valid to the pattern in LOGIN_SIGNUP_MAIL_RESTRICTION (if enabled in settings)."""
|
||||||
|
mail_restriction = InvenTreeSetting.get_setting('LOGIN_SIGNUP_MAIL_RESTRICTION', None)
|
||||||
|
if not mail_restriction:
|
||||||
|
return super().clean_email(email)
|
||||||
|
|
||||||
|
split_email = email.split('@')
|
||||||
|
if len(split_email) != 2:
|
||||||
|
logger.error(f'The user {email} has an invalid email address')
|
||||||
|
raise forms.ValidationError(_('The provided primary email address is not valid.'))
|
||||||
|
|
||||||
|
mailoptions = mail_restriction.split(',')
|
||||||
|
for option in mailoptions:
|
||||||
|
if not option.startswith('@'):
|
||||||
|
log_error('LOGIN_SIGNUP_MAIL_RESTRICTION is not configured correctly')
|
||||||
|
raise forms.ValidationError(_('The provided primary email address is not valid.'))
|
||||||
|
else:
|
||||||
|
if split_email[1] == option[1:]:
|
||||||
|
return super().clean_email(email)
|
||||||
|
|
||||||
|
logger.info(f'The provided email domain for {email} is not approved')
|
||||||
|
raise forms.ValidationError(_('The provided email domain is not approved.'))
|
||||||
|
|
||||||
def save_user(self, request, user, form, commit=True):
|
def save_user(self, request, user, form, commit=True):
|
||||||
"""Check if a default group is set in settings."""
|
"""Check if a default group is set in settings."""
|
||||||
|
# Create the user
|
||||||
user = super().save_user(request, user, form)
|
user = super().save_user(request, user, form)
|
||||||
|
|
||||||
|
# Check if a default group is set in settings
|
||||||
start_group = InvenTreeSetting.get_setting('SIGNUP_GROUP')
|
start_group = InvenTreeSetting.get_setting('SIGNUP_GROUP')
|
||||||
if start_group:
|
if start_group:
|
||||||
try:
|
try:
|
||||||
|
@ -11,6 +11,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
@ -81,19 +82,33 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
self.clean(**kwargs)
|
self.clean(**kwargs)
|
||||||
self.validate_unique(**kwargs)
|
self.validate_unique(**kwargs)
|
||||||
|
|
||||||
|
# Execute before_save action
|
||||||
|
self._call_settings_function('before_save', args, kwargs)
|
||||||
|
|
||||||
# Update this setting in the cache
|
# Update this setting in the cache
|
||||||
if do_cache:
|
if do_cache:
|
||||||
self.save_to_cache()
|
self.save_to_cache()
|
||||||
|
|
||||||
super().save()
|
super().save()
|
||||||
|
|
||||||
# Get after_save action
|
# Execute after_save action
|
||||||
|
self._call_settings_function('after_save', args, kwargs)
|
||||||
|
|
||||||
|
def _call_settings_function(self, reference: str, args, kwargs):
|
||||||
|
"""Call a function associated with a particular setting.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
reference (str): The name of the function to call
|
||||||
|
args: Positional arguments to pass to the function
|
||||||
|
kwargs: Keyword arguments to pass to the function
|
||||||
|
"""
|
||||||
|
# Get action
|
||||||
setting = self.get_setting_definition(self.key, *args, **kwargs)
|
setting = self.get_setting_definition(self.key, *args, **kwargs)
|
||||||
after_save = setting.get('after_save', None)
|
settings_fnc = setting.get(reference, None)
|
||||||
|
|
||||||
# Execute if callable
|
# Execute if callable
|
||||||
if callable(after_save):
|
if callable(settings_fnc):
|
||||||
after_save(self)
|
settings_fnc(self)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cache_key(self):
|
def cache_key(self):
|
||||||
@ -771,6 +786,19 @@ def update_instance_name(setting):
|
|||||||
site_obj.save()
|
site_obj.save()
|
||||||
|
|
||||||
|
|
||||||
|
def validate_email_domains(setting):
|
||||||
|
"""Validate the email domains setting."""
|
||||||
|
if not setting.value:
|
||||||
|
return
|
||||||
|
|
||||||
|
domains = setting.value.split(',')
|
||||||
|
for domain in domains:
|
||||||
|
if not domain:
|
||||||
|
raise ValidationError(_('An empty domain is not allowed.'))
|
||||||
|
if not re.match(r'^@[a-zA-Z0-9\.\-_]+$', domain):
|
||||||
|
raise ValidationError(_(f'Invalid domain name: {domain}'))
|
||||||
|
|
||||||
|
|
||||||
class InvenTreeSetting(BaseInvenTreeSetting):
|
class InvenTreeSetting(BaseInvenTreeSetting):
|
||||||
"""An InvenTreeSetting object is a key:value pair used for storing single values (e.g. one-off settings values).
|
"""An InvenTreeSetting object is a key:value pair used for storing single values (e.g. one-off settings values).
|
||||||
|
|
||||||
@ -1375,6 +1403,13 @@ class InvenTreeSetting(BaseInvenTreeSetting):
|
|||||||
'validator': bool,
|
'validator': bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'LOGIN_SIGNUP_MAIL_RESTRICTION': {
|
||||||
|
'name': _('Allowed domains'),
|
||||||
|
'description': _('Restrict signup to certain domains (comma-separated, strarting with @)'),
|
||||||
|
'default': '',
|
||||||
|
'before_save': validate_email_domains,
|
||||||
|
},
|
||||||
|
|
||||||
'SIGNUP_GROUP': {
|
'SIGNUP_GROUP': {
|
||||||
'name': _('Group on signup'),
|
'name': _('Group on signup'),
|
||||||
'description': _('Group to which new users are assigned on registration'),
|
'description': _('Group to which new users are assigned on registration'),
|
||||||
|
@ -134,6 +134,7 @@ class SettingsTest(InvenTreeTestCase):
|
|||||||
'units',
|
'units',
|
||||||
'requires_restart',
|
'requires_restart',
|
||||||
'after_save',
|
'after_save',
|
||||||
|
'before_save',
|
||||||
]
|
]
|
||||||
|
|
||||||
for k in setting.keys():
|
for k in setting.keys():
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_MAIL_TWICE" icon="fa-at" %}
|
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_MAIL_TWICE" icon="fa-at" %}
|
||||||
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_PWD_TWICE" icon="fa-user-lock" %}
|
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_PWD_TWICE" icon="fa-user-lock" %}
|
||||||
{% include "InvenTree/settings/setting.html" with key="SIGNUP_GROUP" icon="fa-users" %}
|
{% include "InvenTree/settings/setting.html" with key="SIGNUP_GROUP" icon="fa-users" %}
|
||||||
|
{% include "InvenTree/settings/setting.html" with key="LOGIN_SIGNUP_MAIL_RESTRICTION" icon="fa-sitemap" %}
|
||||||
<tr>
|
<tr>
|
||||||
<th><h5>{% trans 'Single Sign On' %}</h5></th>
|
<th><h5>{% trans 'Single Sign On' %}</h5></th>
|
||||||
<td colspan='4'></td>
|
<td colspan='4'></td>
|
||||||
|
Loading…
Reference in New Issue
Block a user