mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-27 10:44:33 +00:00
users: Refactor valid user name checking for reuse
- Supress output from getent - More accurate message
This commit is contained in:
parent
c8c6bc377b
commit
e719966c4b
@ -35,31 +35,18 @@ from plinth import cfg
|
||||
from plinth.errors import ActionError, DomainRegistrationError
|
||||
from plinth.modules.pagekite.utils import PREDEFINED_SERVICES, run
|
||||
from plinth.modules.security import set_restricted_access
|
||||
from plinth.modules.users.forms import GROUP_CHOICES, RESTRICTED_USERNAMES
|
||||
from plinth.modules.users.forms import GROUP_CHOICES, ValidNewUsernameCheckMixin
|
||||
from plinth.utils import format_lazy
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class State1Form(auth.forms.UserCreationForm):
|
||||
class State1Form(ValidNewUsernameCheckMixin, auth.forms.UserCreationForm):
|
||||
"""Firstboot state 1: create a new user."""
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.request = kwargs.pop('request')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
"""Check for username collisions with system users."""
|
||||
username = self.cleaned_data['username']
|
||||
try:
|
||||
subprocess.run(['getent', 'passwd', username], check=True)
|
||||
# Exit code 0 means that the username is already in use.
|
||||
raise ValidationError(_('Username is reserved'))
|
||||
except subprocess.CalledProcessError:
|
||||
if username in RESTRICTED_USERNAMES:
|
||||
raise ValidationError(_('Username is reserved'))
|
||||
|
||||
return super().clean()
|
||||
|
||||
def save(self, commit=True):
|
||||
"""Create and log the user in."""
|
||||
user = super().save(commit=commit)
|
||||
|
||||
@ -28,7 +28,7 @@ from plinth import actions
|
||||
from plinth.errors import ActionError
|
||||
|
||||
# Usernames used by optional services (that might not be installed yet).
|
||||
RESTRICTED_USERNAMES = [
|
||||
RESERVED_USERNAMES = [
|
||||
'debian-deluged',
|
||||
'Debian-minetest',
|
||||
'debian-tor',
|
||||
@ -50,7 +50,33 @@ GROUP_CHOICES = (
|
||||
)
|
||||
|
||||
|
||||
class CreateUserForm(UserCreationForm):
|
||||
class ValidNewUsernameCheckMixin(object):
|
||||
"""Mixin to check if a username is valid for created new user."""
|
||||
def clean(self):
|
||||
"""Check for username collisions with system users."""
|
||||
if not self.is_valid_new_username():
|
||||
raise ValidationError(_('Username is taken or is reserved'))
|
||||
|
||||
return super().clean()
|
||||
|
||||
def is_valid_new_username(self):
|
||||
"""Check for username collisions with system users."""
|
||||
username = self.cleaned_data['username']
|
||||
try:
|
||||
subprocess.run(['getent', 'passwd', username],
|
||||
stdout=subprocess.DEVNULL, check=True)
|
||||
# Exit code 0 means that the username is already in use.
|
||||
return False
|
||||
except subprocess.CalledProcessError:
|
||||
pass
|
||||
|
||||
if username in RESERVED_USERNAMES:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm):
|
||||
"""Custom user create form.
|
||||
|
||||
Include options to add user to groups.
|
||||
@ -75,19 +101,6 @@ class CreateUserForm(UserCreationForm):
|
||||
self.request = request
|
||||
super(CreateUserForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
"""Check for username collisions with system users."""
|
||||
username = self.cleaned_data['username']
|
||||
try:
|
||||
subprocess.run(['getent', 'passwd', username], check=True)
|
||||
# Exit code 0 means that the username is already in use.
|
||||
raise ValidationError(_('Username is reserved'))
|
||||
except subprocess.CalledProcessError:
|
||||
if username in RESTRICTED_USERNAMES:
|
||||
raise ValidationError(_('Username is reserved'))
|
||||
|
||||
return super().clean()
|
||||
|
||||
def save(self, commit=True):
|
||||
"""Save the user model and create LDAP user if required."""
|
||||
user = super(CreateUserForm, self).save(commit)
|
||||
@ -119,7 +132,7 @@ class CreateUserForm(UserCreationForm):
|
||||
return user
|
||||
|
||||
|
||||
class UserUpdateForm(forms.ModelForm):
|
||||
class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm):
|
||||
"""When user info is changed, also updates LDAP user."""
|
||||
ssh_keys = forms.CharField(
|
||||
label=ugettext_lazy('SSH Keys'),
|
||||
@ -149,19 +162,6 @@ class UserUpdateForm(forms.ModelForm):
|
||||
self.username = username
|
||||
super(UserUpdateForm, self).__init__(*args, **kwargs)
|
||||
|
||||
def clean(self):
|
||||
"""Check for username collisions with system users."""
|
||||
username = self.cleaned_data['username']
|
||||
try:
|
||||
subprocess.run(['getent', 'passwd', username], check=True)
|
||||
# Exit code 0 means that the username is already in use.
|
||||
raise ValidationError(_('Username is reserved'))
|
||||
except subprocess.CalledProcessError:
|
||||
if username in RESTRICTED_USERNAMES:
|
||||
raise ValidationError(_('Username is reserved'))
|
||||
|
||||
return super().clean()
|
||||
|
||||
def save(self, commit=True):
|
||||
"""Update LDAP user name and groups after saving user model."""
|
||||
user = super(UserUpdateForm, self).save(commit)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user