Merge pull request #330 from tmuncks/add-user-edit

Add option to edit users from the comfort of the UI
This commit is contained in:
Khanh Ngo 2018-08-14 08:52:20 +07:00 committed by GitHub
commit 7b5c74cc7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 143 additions and 22 deletions

View File

@ -328,6 +328,36 @@ class User(db.Model):
db.session.commit()
return {'status': True, 'msg': 'Created user successfully'}
def update_local_user(self):
"""
Update local user
"""
# Sanity check - account name
if self.username == "":
return {'status': False, 'msg': 'No user name specified'}
# read user and check that it exists
user = User.query.filter(User.username == self.username).first()
if not user:
return {'status': False, 'msg': 'User does not exist'}
# check if new email exists (only if changed)
if user.email != self.email:
checkuser = User.query.filter(User.email == self.email).first()
if checkuser:
return {'status': False, 'msg': 'New email address is already in use'}
user.firstname = self.firstname
user.lastname = self.lastname
user.email = self.email
# store new password hash (only if changed)
if self.plain_text_password != "":
user.password = self.get_hashed_password(self.plain_text_password).decode("utf-8")
db.session.commit()
return {'status': True, 'msg': 'User updated successfully'}
def update_profile(self, enable_otp=None):
"""
Update user profile

View File

@ -1,17 +1,17 @@
{% extends "base.html" %}
{% block title %}<title>DNS Control Panel - Create User</title>{% endblock %}
{% block title %}<title>DNS Control Panel - Edit User</title>{% endblock %}
{% block dashboard_stat %}
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
User
<small>Create new</small>
<small>{% if create %}New user{% else %}{{ user.username }}{% endif %}</small>
</h1>
<ol class="breadcrumb">
<li><a href="{{ url_for('dashboard') }}"><i class="fa fa-dashboard"></i>Home</a></li>
<li><a href="{{ url_for('dashboard') }}">Admin</a></li>
<li class="active">Create user</li>
<li class="active">{% if create %}Add{% else %}Edit{% endif %} user</li>
</ol>
</section>
{% endblock %}
@ -22,11 +22,12 @@
<div class="col-md-4">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Create new user</h3>
<h3 class="box-title">{% if create %}Add{% else %}Edit{% endif %} user</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<form role="form" method="post" action="{{ url_for('admin_createuser') }}">
<form role="form" method="post" action="{% if create %}{{ url_for('admin_edituser') }}{% else %}{{ url_for('admin_edituser', user_username=user.username) }}{% endif %}">
<input type="hidden" name="create" value="{{ create }}">
<div class="box-body">
{% if error %}
<div class="alert alert-danger alert-dismissible">
@ -58,12 +59,12 @@
<div class="form-group has-feedback">
<label class="control-label" for="username">Username</label>
<input type="text" class="form-control" placeholder="Username"
name="username" {% if user %}value={{ user.username }}{% endif %}> <span
name="username" {% if user %}value={{ user.username }}{% endif %} {% if not create %}disabled{% endif %}> <span
class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-feedback {% if blank_password %}has-error{% endif %}">
<label class="control-label" for="username">Password</label>
<input type="password" class="form-control" placeholder="Password"
<input type="password" class="form-control" placeholder="Password {% if create %}(Required){% else %}(Leave blank to keep unchanged){% endif %}"
name="password"> <span
class="glyphicon glyphicon-lock form-control-feedback"></span>
{% if blank_password %}
@ -72,22 +73,81 @@
</div>
</div>
<div class="box-footer">
<button type="submit" class="btn btn-flat btn-primary">Create User</button>
<button type="submit" class="btn btn-flat btn-primary">{% if create %}Create{% else %}Update{% endif %} User</button>
</div>
</form>
</div>
{% if not create %}
<div class="box box-secondary">
<div class="box-header with-border">
<h3 class="box-title">Two Factor Authentication</h3>
</div>
<div class="box-body">
<p>If two factor authentication was configured and is causing problems due to a lost device or technical issue, it can be disabled here.</p>
<p>The user will need to reconfigure two factor authentication, to re-enable it.</p>
<p><strong>Beware: This could compromise security!</strong></p>
</div>
<div class="box-footer">
<button type="button" class="btn btn-flat btn-warning button_otp_disable" id="{{ user.username }}" {% if not user.otp_secret %}disabled{% endif %}>Disable Two Factor Authentication</button>
</div>
</div>
{% endif %}
</div>
<div class="col-md-8">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Help with creating a new user</h3>
<h3 class="box-title">Help with {% if create %}creating a new{% else%}updating a{% endif %} user</h3>
</div>
<div class="box-body">
<p>Fill in all the fields to the in the form to the left.</p>
{% if create %}
<p><strong>Newly created users do not have access to any domains.</strong> You will need to grant access to the user once it is created via the domain management buttons on the dashboard.</p>
{% else %}
<p><strong>Password</strong> can be left empty to keep the current password.</p>
<p><strong>Username</strong> cannot be changed.</p>
{% endif %}
</div>
</div>
</div>
</div>
</section>
{% endblock %}
{% block extrascripts %}
<script>
// handle disabling two factor authentication
$(document.body).on('click', '.button_otp_disable', function() {
var modal = $("#modal_otp_disable");
var username = $(this).prop('id');
var info = "Are you sure you want to disable two factor authentication for user " + username + "?";
modal.find('.modal-body p').text(info);
modal.find('#button_otp_disable_confirm').click(function() {
var postdata = {'action': 'user_otp_disable', 'data': username}
applyChanges(postdata, $SCRIPT_ROOT + '/admin/manageuser', false, true);
})
modal.modal('show');
});
</script>
{% endblock %}
{% block modals %}
<div class="modal fade modal-warning" id="modal_otp_disable">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Confirmation</h4>
</div>
<div class="modal-body">
<p></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-flat btn-default pull-left"
data-dismiss="modal">Close</button>
<button type="button" class="btn btn-flat btn-danger" id="button_otp_disable_confirm">Disable Two Factor Authentication</button>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -20,7 +20,7 @@
<h3 class="box-title">User Management</h3>
</div>
<div class="box-body">
<a href="{{ url_for('admin_createuser') }}">
<a href="{{ url_for('admin_edituser') }}">
<button type="button" class="btn btn-flat btn-primary pull-left button_add_user">
Add User&nbsp;<i class="fa fa-plus"></i>
</button>
@ -36,7 +36,7 @@
<th>Email</th>
<th>Admin</th>
<th>Privileges</th>
<th>Deletion</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@ -54,7 +54,10 @@
Revoke&nbsp;<i class="fa fa-lock"></i>
</button>
</td>
<td width="6%">
<td width="15%">
<button type="button" class="btn btn-flat btn-success button_edit" onclick="window.location.href='{{ url_for('admin_edituser', user_username=user.username) }}'">
Edit&nbsp;<i class="fa fa-lock"></i>
</button>
<button type="button" class="btn btn-flat btn-danger button_delete" id="{{ user.username }}" {% if user.username==current_user.username %}disabled{% endif %}>
Delete&nbsp;<i class="fa fa-trash"></i>
</button>

View File

@ -1156,26 +1156,44 @@ def admin():
return render_template('admin.html', domains=domains, users=users, configs=configs, statistics=statistics, uptime=uptime, history_number=history_number)
@app.route('/admin/user/create', methods=['GET', 'POST'])
@app.route('/admin/user/edit/<user_username>', methods=['GET', 'POST'])
@app.route('/admin/user/edit', methods=['GET', 'POST'])
@login_required
@admin_role_required
def admin_createuser():
def admin_edituser(user_username=None):
if request.method == 'GET':
return render_template('admin_createuser.html')
if not user_username:
return render_template('admin_edituser.html', create=1)
if request.method == 'POST':
else:
user = User.query.filter(User.username == user_username).first()
return render_template('admin_edituser.html', user=user, create=0)
elif request.method == 'POST':
fdata = request.form
user = User(username=fdata['username'], plain_text_password=fdata['password'], firstname=fdata['firstname'], lastname=fdata['lastname'], email=fdata['email'])
if not user_username:
user_username = fdata['username']
user = User(username=user_username, plain_text_password=fdata['password'], firstname=fdata['firstname'], lastname=fdata['lastname'], email=fdata['email'], reload_info=False)
create = int(fdata['create'])
if create:
if fdata['password'] == "":
return render_template('admin_createuser.html', user=user, blank_password=True)
return render_template('admin_edituser.html', user=user, create=create, blank_password=True)
result = user.create_local_user()
history = History(msg='Created user {0}'.format(user.username), created_by=current_user.username)
else:
result = user.update_local_user()
history = History(msg='Updated user {0}'.format(user.username), created_by=current_user.username)
result = user.create_local_user();
if result['status']:
history.add()
return redirect(url_for('admin_manageuser'))
return render_template('admin_createuser.html', user=user, error=result['msg'])
return render_template('admin_edituser.html', user=user, create=create, error=result['msg'])
@app.route('/admin/manageuser', methods=['GET', 'POST'])
@ -1195,6 +1213,16 @@ def admin_manageuser():
jdata = request.json
data = jdata['data']
if jdata['action'] == 'user_otp_disable':
user = User(username=data)
result = user.update_profile(enable_otp=False)
if result:
history = History(msg='Two factor authentication disabled for user {0}'.format(data), created_by=current_user.username)
history.add()
return make_response(jsonify( { 'status': 'ok', 'msg': 'Two factor authentication has been disabled for user.' } ), 200)
else:
return make_response(jsonify( { 'status': 'error', 'msg': 'Cannot disable two factor authentication for user.' } ), 500)
if jdata['action'] == 'delete_user':
user = User(username=data)
if user.username == current_user.username: