diff --git a/modules/installed/system/templates/users_add.html b/modules/installed/system/templates/users_add.html
new file mode 100644
index 000000000..3a5c7feab
--- /dev/null
+++ b/modules/installed/system/templates/users_add.html
@@ -0,0 +1,54 @@
+{% extends "login_nav.html" %}
+{% comment %}
+#
+# 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
Adding a user via this administrative -interface might create a system user. For example, if -you provide a user with ssh access, she will need a system account. -If you don't know what that means, don't worry about it.
diff --git a/modules/installed/system/templates/users_edit.html b/modules/installed/system/templates/users_edit.html new file mode 100644 index 000000000..3f4714984 --- /dev/null +++ b/modules/installed/system/templates/users_edit.html @@ -0,0 +1,59 @@ +{% extends "login_nav.html" %} +{% comment %} +# +# 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, seeClick on a user's name to go to a screen for editing that user's -account.
- -Check the box next to a users' names and then click "Delete User" -to remove users from {{ cfg.product_name }} and the {{ cfg.box_name }} -system.
- -Deleting users is permanent!
diff --git a/modules/installed/system/templates/wan.html b/modules/installed/system/templates/wan.html index d04aaae1f..254eca97f 100644 --- a/modules/installed/system/templates/wan.html +++ b/modules/installed/system/templates/wan.html @@ -32,5 +32,4 @@ {% endif %} - {% endblock %} diff --git a/modules/installed/system/users.py b/modules/installed/system/users.py index bc0e7cd43..1b7550405 100644 --- a/modules/installed/system/users.py +++ b/modules/installed/system/users.py @@ -1,20 +1,20 @@ import cherrypy +from django import forms +from django.core import validators from gettext import gettext as _ -from auth import require, add_user -from plugin_mount import PagePlugin, FormPlugin +import auth +from auth import require +from plugin_mount import PagePlugin import cfg -from forms import Form from model import User import util -class users(PagePlugin): +class Users(PagePlugin): order = 20 # order of running init in PagePlugins def __init__(self, *args, **kwargs): PagePlugin.__init__(self, *args, **kwargs) self.register_page("sys.users") - self.register_page("sys.users.add") - self.register_page("sys.users.edit") @staticmethod @cherrypy.expose @@ -32,101 +32,141 @@ class users(PagePlugin): sidebar_right=sidebar_right) -class add(FormPlugin, PagePlugin): - url = ["/sys/users/add"] +class UserAddForm(forms.Form): # pylint: disable-msg=W0232 + """Form to add a new user""" + + username = forms.CharField( + label=_('Username'), + help_text=_('Must be lower case alphanumeric and start with \ +and alphabet'), + validators=[ + validators.RegexValidator(r'^[a-z][a-z0-9]*$', + _('Invalid username'))]) + + password = forms.CharField(label=_('Password'), + widget=forms.PasswordInput()) + full_name = forms.CharField(label=_('Full name'), required=False) + email = forms.EmailField(label=_('Email'), required=False) + + +class UserAdd(PagePlugin): + """Add user page""" order = 30 - @staticmethod - def sidebar_right(**kwargs): - """Return rendered string for sidebar on the right""" - del kwargs # Unused + def __init__(self, *args, **kwargs): + PagePlugin.__init__(self, *args, **kwargs) - return util.render_template(template='users_add_sidebar') + self.register_page('sys.users.add') - def main(self, username='', name='', email='', message=None, *args, **kwargs): - form = Form(title="Add User", - action=cfg.server_dir + "/sys/users/add/index", - name="add_user_form", - message=message) - form.text_input(_("Username"), name="username", value=username) - form.text_input(_("Full name"), name="name", value=name) - form.text_input(_("Email"), name="email", value=email) - form.text_input(_("Password"), name="password", type="password") - form.submit(label=_("Create User"), name="create") - return form.render() + @cherrypy.expose + @require() + def index(self, **kwargs): + """Serve the form""" + form = None + messages = [] - def process_form(self, username=None, name=None, email=None, password=None, **kwargs): - msg = util.Message() - - error = add_user(username, password, name, email, False) - if error: - msg.text = error + if kwargs: + form = UserAddForm(kwargs, prefix='user') + # pylint: disable-msg=E1101 + if form.is_valid(): + self._add_user(form.cleaned_data, messages) + form = UserAddForm(prefix='user') else: - msg.add(_("User %s added" % username)) + form = UserAddForm(prefix='user') - return msg.text - - -class edit(FormPlugin, PagePlugin): - url = ["/sys/users/edit"] - order = 35 + return util.render_template(template='users_add', title=_('Add User'), + form=form, messages=messages) @staticmethod - def sidebar_right(**kwargs): - """Return rendered string for sidebar on the right""" - del kwargs # Unused + def _add_user(data, messages): + """Add a user""" + if cfg.users.exists(data['username']): + messages.append( + ('error', _('User "{username}" already exists').format( + username=data['username']))) + return - return util.render_template(template='users_edit_sidebar') + auth.add_user(data['username'], data['password'], data['full_name'], + data['email'], False) + messages.append( + ('success', _('User "{username}" added').format( + username=data['username']))) + + +class UserEditForm(forms.Form): # pylint: disable-msg=W0232 + """Form to edit/delete a user""" + def __init__(self, *args, **kwargs): + # pylint: disable-msg=E1002 + super(forms.Form, self).__init__(*args, **kwargs) - def main(self, message=None, **kwargs): users = cfg.users.get_all() - add_form = Form(title=_("Edit or Delete User"), - action=cfg.server_dir + "/sys/users/edit", - message=message) - add_form.html('DeleteCould not find a user with username of %s!
") % \ - kwargs['username'] + def __init__(self, *args, **kwargs): + PagePlugin.__init__(self, *args, **kwargs) - user = cfg.users[kwargs['username']] - return _("Edit User '%s'") % user['username'] + self.register_page('sys.users.edit') + + @cherrypy.expose + @require() + def index(self, **kwargs): + """Serve the form""" + form = None + messages = [] + + if kwargs: + form = UserEditForm(kwargs, prefix='user') + # pylint: disable-msg=E1101 + if form.is_valid(): + self._apply_changes(form.cleaned_data, messages) + form = UserEditForm(prefix='user') + else: + form = UserEditForm(prefix='user') + + return util.render_template(template='users_edit', + title=_('Edit or Delete User'), + form=form, messages=messages) + + @staticmethod + def _apply_changes(data, messages): + """Apply form changes""" + for field, value in data.items(): + if not value: + continue + + if not field.startswith('delete_user_'): + continue + + username = field.split('delete_user_')[1] + + cfg.log.info('%s asked to delete %s' % + (cherrypy.session.get(cfg.session_key), username)) + + if username == cfg.users.current(name=True): + messages.append( + ('error', + _('Can not delete current account - "%s"') % username)) + continue + + if not cfg.users.exists(username): + messages.append(('error', + _('User "%s" does not exist') % username)) + continue + + try: + cfg.users.remove(username) + messages.append(('success', _('User "%s" deleted') % username)) + except IOError as exception: + messages.append(('error', _('Error deleting "%s" - %s') % + (username, exception)))