diff --git a/actions/disable-user b/actions/disable-user
new file mode 100755
index 000000000..013ddbc39
--- /dev/null
+++ b/actions/disable-user
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# This file is part of Plinth.
+#
+# 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 .
+#
+
+# Must be run as root.
+
+username="$1"
+
+usermod --expiredate 1 "$username"
+if [ $? -ne 0 ]; then
+ echo "Failed"
+fi
diff --git a/actions/enable-user b/actions/enable-user
new file mode 100755
index 000000000..7cfe857a8
--- /dev/null
+++ b/actions/enable-user
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# This file is part of Plinth.
+#
+# 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 .
+#
+
+# Must be run as root.
+
+username="$1"
+
+usermod --expiredate "" "$username"
+if [ $? -ne 0 ]; then
+ echo "Failed"
+fi
diff --git a/plinth/modules/users/forms.py b/plinth/modules/users/forms.py
index 11a1c73ac..aeaf54271 100644
--- a/plinth/modules/users/forms.py
+++ b/plinth/modules/users/forms.py
@@ -16,6 +16,7 @@
#
from django import forms
+from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, SetPasswordForm
from gettext import gettext as _
@@ -41,6 +42,26 @@ class CreateUserForm(UserCreationForm):
return user
+class UserUpdateForm(forms.ModelForm):
+ """When user is enabled/disabled, also enables/disables the POSIX user."""
+
+ class Meta:
+ fields = ('username', 'groups', 'is_active')
+ model = User
+ widgets = {
+ 'groups': forms.widgets.CheckboxSelectMultiple(),
+ }
+
+ def save(self, commit=True):
+ user = super(UserUpdateForm, self).save(commit)
+ if commit:
+ if user.is_active:
+ actions.superuser_run('enable-user', [user.username])
+ else:
+ actions.superuser_run('disable-user', [user.username])
+ return user
+
+
class UserChangePasswordForm(SetPasswordForm):
"""Custom form that also updates password for POSIX users."""
diff --git a/plinth/modules/users/views.py b/plinth/modules/users/views.py
index 8fa9eb4ba..21b841cb2 100644
--- a/plinth/modules/users/views.py
+++ b/plinth/modules/users/views.py
@@ -15,7 +15,6 @@
# along with this program. If not, see .
#
-from django import forms
from django.contrib import messages
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.models import User
@@ -26,7 +25,7 @@ from django.views.generic.edit import (CreateView, DeleteView, UpdateView,
from django.views.generic import ListView
from gettext import gettext as _
-from .forms import CreateUserForm, UserChangePasswordForm
+from .forms import CreateUserForm, UserUpdateForm, UserChangePasswordForm
subsubmenu = [{'url': reverse_lazy('users:index'),
@@ -65,19 +64,11 @@ class UserList(ContextMixin, ListView):
class UserUpdate(ContextMixin, SuccessMessageMixin, UpdateView):
"""View to update a user's details."""
template_name = 'users_update.html'
- fields = ('username', 'groups', 'is_active')
model = User
+ form_class = UserUpdateForm
slug_field = 'username'
success_message = _('User %(username)s updated.')
title = _('Edit User')
- widgets = {
- 'groups': forms.widgets.CheckboxSelectMultiple(),
- }
-
- def get_form_class(self):
- """Return a form class generated from user model."""
- return forms.models.modelform_factory(self.model, fields=self.fields,
- widgets=self.widgets)
def get_success_url(self):
"""Return the URL to redirect to in case of successful updation."""