Admin User Management
New fonctions to manage users for admin.
This commit is contained in:
parent
2e5bf79a8e
commit
95df3228fc
@ -14,6 +14,7 @@ class Config:
|
||||
|
||||
class DevelopmentConfig(Config):
|
||||
DEBUG = True
|
||||
DEBUG_TB_ENABLED = True
|
||||
MAIL_SERVER = 'localhost'
|
||||
MAIL_PORT = 25
|
||||
MAIL_USE_TLS = True
|
||||
|
@ -5,7 +5,7 @@ from wtforms import StringField, PasswordField, BooleanField, SubmitField, \
|
||||
from wtforms.validators import Required, Length, Email, Regexp, EqualTo
|
||||
from ..models import User, Role
|
||||
|
||||
class EditProfileAdminForm(Form):
|
||||
class EditUserAdminForm(Form):
|
||||
email = StringField('Email', validators=[Required(), Length(1, 128),
|
||||
Email()])
|
||||
username = StringField('Username', validators=[
|
||||
@ -13,15 +13,39 @@ class EditProfileAdminForm(Form):
|
||||
'Usernames must have only letters, '
|
||||
'numbers, dots or underscores')])
|
||||
full_name = StringField('Full name', validators=[Required(), Length(1, 255)])
|
||||
role_id = SelectField('Role', coerce=int)
|
||||
role = SelectField('Role', coerce=int)
|
||||
confirmed = BooleanField('Confirmed')
|
||||
|
||||
def __init__(self, user, *args, **kwargs):
|
||||
super(EditProfileAdminForm, self).__init__(*args, **kwargs)
|
||||
self.role_id.choices = [(role.id, role.name)
|
||||
super(EditUserAdminForm, self).__init__(*args, **kwargs)
|
||||
self.role.choices = [(role.id, role.name)
|
||||
for role in Role.query.order_by(Role.name).all()]
|
||||
self.user = user
|
||||
|
||||
def validate_email(self, field):
|
||||
if field.data != self.user.email and \
|
||||
User.query.filter_by(email=field.data).first():
|
||||
raise ValidationError('Email already registered.')
|
||||
|
||||
def validate_username(self, field):
|
||||
if field.data != self.user.username and \
|
||||
User.query.filter_by(username=field.data).first():
|
||||
raise ValidationError('Username already in use.')
|
||||
|
||||
|
||||
class CreateUserAdminForm(Form):
|
||||
email = StringField('Email', validators=[Required(), Length(1, 128),
|
||||
Email()])
|
||||
username = StringField('Username', validators=[
|
||||
Required(), Length(1, 64), Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0,
|
||||
'Usernames must have only letters, '
|
||||
'numbers, dots or underscores')])
|
||||
full_name = StringField('Full name', validators=[Required(), Length(1, 255)])
|
||||
password = PasswordField('Password', validators=[
|
||||
Required(), EqualTo('password2', message='Passwords must match.')])
|
||||
password2 = PasswordField('Confirm password', validators=[Required()])
|
||||
confirmed = BooleanField('Confirmed')
|
||||
|
||||
def validate_email(self, field):
|
||||
if User.query.filter_by(email=field.data).first():
|
||||
raise ValidationError('Email already registered.')
|
||||
@ -29,3 +53,8 @@ class EditProfileAdminForm(Form):
|
||||
def validate_username(self, field):
|
||||
if User.query.filter_by(username=field.data).first():
|
||||
raise ValidationError('Username already in use.')
|
||||
|
||||
|
||||
class DeleteUserAdminForm(Form):
|
||||
confirm = BooleanField('Confirmed', validators=[Required(message='You must confirm to delete.')])
|
||||
|
@ -11,7 +11,8 @@ from .. import db
|
||||
from ..models import User, Role
|
||||
from ..email import send_email
|
||||
from ..decorators import requires_roles
|
||||
from .forms import EditProfileAdminForm
|
||||
from .forms import EditUserAdminForm, CreateUserAdminForm, CreateUserAdminForm, \
|
||||
DeleteUserAdminForm
|
||||
|
||||
@admin.route('/')
|
||||
@login_required
|
||||
@ -28,21 +29,61 @@ def list_users():
|
||||
title="List Users",
|
||||
block_description = "list, edit and delete users")
|
||||
|
||||
@admin.route('/create-user', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@requires_roles("admin")
|
||||
def create_user_admin():
|
||||
form = CreateUserAdminForm()
|
||||
if form.validate_on_submit():
|
||||
r = Role.query.filter_by(default=True).first()
|
||||
user = User(email=form.email.data,
|
||||
username=form.username.data,
|
||||
full_name=form.full_name.data,
|
||||
password=form.password.data,
|
||||
avatar="/static/img/user2-160x160.jpg",
|
||||
created_at=datetime.datetime.now(),
|
||||
role_id=r.id,
|
||||
confirmed=form.confirmed.data)
|
||||
db.session.add(user)
|
||||
db.session.commit()
|
||||
flash('New user created.')
|
||||
return redirect(url_for('.edit_user_admin', id=user.id))
|
||||
return render_template('admin/create_user.html', form=form,
|
||||
title="Create New User",
|
||||
block_description = "fill all the fields to create new user")
|
||||
|
||||
@admin.route('/edit-user/<int:id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@requires_roles("admin")
|
||||
def edit_user_admin(id):
|
||||
user = User.query.get_or_404(id)
|
||||
form = EditProfileAdminForm(user=user)
|
||||
roles = Role.query.filter_by().all()
|
||||
form = EditUserAdminForm(user=user)
|
||||
if form.validate_on_submit():
|
||||
user.email = form.email.data
|
||||
user.username = form.username.data
|
||||
user.full_name = form.full_name.data
|
||||
user.role_id = Role.query.get(form.role.data)
|
||||
user.role = Role.query.get(form.role.data)
|
||||
user.confirmed = form.confirmed.data
|
||||
db.session.add(user)
|
||||
flash('The profile has been updated.')
|
||||
return redirect(url_for('.user', username=user.username))
|
||||
return redirect(url_for('.edit_user_admin', id=user.id))
|
||||
return render_template('admin/edit_user.html', user=user, form=form,
|
||||
roles=roles,
|
||||
title="Edit User",
|
||||
block_description = "edit and update user info")
|
||||
|
||||
@admin.route('/delete-user/<int:id>', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@requires_roles("admin")
|
||||
def delete_user_admin(id):
|
||||
user = User.query.get_or_404(id)
|
||||
form = DeleteUserAdminForm(user=user)
|
||||
if form.validate_on_submit():
|
||||
db.session.delete(user)
|
||||
db.session.commit()
|
||||
flash('The user has been deleted.')
|
||||
return redirect(url_for('.index'))
|
||||
return render_template('admin/delete_user.html', user=user, form=form,
|
||||
title="Delete User",
|
||||
block_description = "delete user confirmation")
|
98
dash/templates/admin/create_user.html
Normal file
98
dash/templates/admin/create_user.html
Normal file
@ -0,0 +1,98 @@
|
||||
{% extends "adminlte/base.html" %}
|
||||
{% import "adminlte/layout.html" as layout with context %}
|
||||
{% import "adminlte/widgets.html" as widgets with context %}
|
||||
{% from "_formhelpers.html" import render_field %}
|
||||
|
||||
{% block title %}Admin - {{ title }}{% endblock %}
|
||||
{% block description %}{{ block_description }}{% endblock %}
|
||||
|
||||
{% block navbar %}
|
||||
|
||||
{% include "navbar.html" %}
|
||||
|
||||
{%- endblock navbar %}
|
||||
|
||||
|
||||
{% block sidebar -%}
|
||||
|
||||
{% include 'sidebar.html' %}
|
||||
|
||||
{% include 'admin/sidebar_menu.html' %}
|
||||
|
||||
{%- endblock sidebar %}
|
||||
|
||||
|
||||
{% block content_header -%}
|
||||
{% include 'admin/content_header.html' %}
|
||||
{%- endblock content_header %}
|
||||
|
||||
{% block content -%}
|
||||
<!-- Main content -->
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="box">
|
||||
<!-- /.box-header -->
|
||||
<div class="register-box-body">
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="form-group has-feedback">
|
||||
<input type="email" name="email" class="form-control" placeholder="User Email" value="{{ request.form['email'] }}">
|
||||
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
|
||||
{% if form.email.errors %}
|
||||
<span class="text-red">{% for error in form.email.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<input type="text" name="username" class="form-control" placeholder="User name" value="{{ request.form['username'] }}">
|
||||
<span class="glyphicon glyphicon-user form-control-feedback"></span>
|
||||
{% if form.username.errors %}
|
||||
<span class="text-red">{% for error in form.username.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<input type="text" name="full_name" class="form-control" placeholder="Full name" value="{{ request.form['full_name'] }}">
|
||||
<span class="glyphicon glyphicon-user form-control-feedback"></span>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<input type="password" name="password" class="form-control" placeholder="Password">
|
||||
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
||||
{% if form.password.errors %}
|
||||
<span class="text-red">{% for error in form.password.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<input type="password" name="password2" class="form-control" placeholder="Retype password">
|
||||
<span class="glyphicon glyphicon-log-in form-control-feedback"></span>
|
||||
{% if form.password2.errors %}
|
||||
<span class="text-red">{% for error in form.password2.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-8 col-xs-offset-0">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="confirmed"> Confirmed?
|
||||
</label>
|
||||
{% if form.confirmed.errors %}
|
||||
<br />
|
||||
<span class="text-red">{% for error in form.confirmed.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-xs-4">
|
||||
<button type="submit" name="submit" class="btn btn-primary btn-block btn-flat" value="Update">Create</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
|
||||
{%- endblock content %}
|
84
dash/templates/admin/delete_user.html
Normal file
84
dash/templates/admin/delete_user.html
Normal file
@ -0,0 +1,84 @@
|
||||
{% extends "adminlte/base.html" %}
|
||||
{% import "adminlte/layout.html" as layout with context %}
|
||||
{% import "adminlte/widgets.html" as widgets with context %}
|
||||
{% from "_formhelpers.html" import render_field %}
|
||||
|
||||
{% block title %}Admin - {{ title }}{% endblock %}
|
||||
{% block description %}{{ block_description }}{% endblock %}
|
||||
|
||||
{% block navbar %}
|
||||
|
||||
{% include "navbar.html" %}
|
||||
|
||||
{%- endblock navbar %}
|
||||
|
||||
|
||||
{% block sidebar -%}
|
||||
|
||||
{% include 'sidebar.html' %}
|
||||
|
||||
{% include 'admin/sidebar_menu.html' %}
|
||||
|
||||
{%- endblock sidebar %}
|
||||
|
||||
|
||||
{% block content_header -%}
|
||||
{% include 'admin/content_header.html' %}
|
||||
{%- endblock content_header %}
|
||||
|
||||
{% block content -%}
|
||||
<!-- Main content -->
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="box">
|
||||
<!-- /.box-header -->
|
||||
<div class="box-header with-border">
|
||||
<i class="fa fa-warning"></i>
|
||||
|
||||
<h3 class="box-title">You are Warned</h3>
|
||||
</div>
|
||||
<!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
<div class="alert alert-danger alert-dismissible">
|
||||
<h4><i class="icon fa fa-ban"></i> User Delete Alert!</h4>
|
||||
Your are about to delete user "{{ user.username }}" from database.
|
||||
You will not able to undo this action.
|
||||
<br />
|
||||
Are you sure you want to delete this user?
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
<div class="register-box-body">
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="row">
|
||||
<div class="col-xs-8 col-xs-offset-0">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="confirm"> I confirm to delete "{{ user.username }}".
|
||||
</label>
|
||||
{% if form.confirm.errors %}
|
||||
<br />
|
||||
<span class="text-red">{% for error in form.confirm.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-xs-4">
|
||||
<button type="submit" name="submit" class="btn btn-danger btn-block btn-flat" value="Update">Delete User</button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!-- /.box-body -->
|
||||
</div>
|
||||
<!-- /.box -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
|
||||
{%- endblock content %}
|
@ -36,40 +36,40 @@
|
||||
<form class="form-horizontal" action="" method="post">
|
||||
{{ form.hidden_tag() }}
|
||||
<div class="form-group has-feedback">
|
||||
<input type="email" name="email" class="form-control" placeholder="Email" value="{{ request.form['email'] }}">
|
||||
<input type="email" name="email" class="form-control" placeholder="New Email" value=" {{ user.email }} ">
|
||||
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
|
||||
{% if form.email.errors %}
|
||||
<span class="text-red">{% for error in form.email.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<input type="text" name="username" class="form-control" placeholder="User name" value="{{ request.form['username'] }}">
|
||||
<input type="text" name="username" class="form-control" placeholder="User name" value="{{ user.username }}">
|
||||
<span class="glyphicon glyphicon-user form-control-feedback"></span>
|
||||
{% if form.username.errors %}
|
||||
<span class="text-red">{% for error in form.username.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<input type="text" name="full_name" class="form-control" placeholder="Full name" value="{{ request.form['full_name'] }}">
|
||||
<input type="text" name="full_name" class="form-control" placeholder="Full name" value="{{ user.full_name}}">
|
||||
<span class="glyphicon glyphicon-user form-control-feedback"></span>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<label>User Role</label>
|
||||
<select class="form-control">
|
||||
<option value="1">Admin</option>
|
||||
<option value="2">Reseller</option>
|
||||
<option value="3" selected>User</option>
|
||||
<select name="role" class="form-control">
|
||||
{% for role in roles %}
|
||||
<option value="{{ role.id }}" {% if role.id == user.role_id %} selected {% endif %} >{{ role.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<span class="glyphicon glyphicon-signal form-control-feedback"></span>
|
||||
{% if form.role_id.errors %}
|
||||
<span class="text-red">{% for error in form.role_id.errors %} {{ error }} {% endfor %}</span>
|
||||
{% if form.role.errors %}
|
||||
<span class="text-red">{% for error in form.role.errors %} {{ error }} {% endfor %}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-8 col-xs-offset-0">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="confirmed"> Confirmed?
|
||||
<input type="checkbox" name="confirmed" {% if user.confirmed %} checked {% endif %} > Confirmed?
|
||||
</label>
|
||||
{% if form.confirmed.errors %}
|
||||
<br />
|
||||
|
@ -53,6 +53,8 @@
|
||||
<td>{{ user.role.name }}</td>
|
||||
<td>
|
||||
<a href="{{ url_for('admin.edit_user_admin', id=user.id) }}">Edit</a>
|
||||
|
|
||||
<a href="{{ url_for('admin.delete_user_admin', id=user.id) }}">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -14,7 +14,7 @@
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li>
|
||||
<a href="">
|
||||
<a href="{{ url_for('admin.create_user_admin') }}">
|
||||
<i class="fa fa-user-plus"></i>
|
||||
Create User
|
||||
</a>
|
||||
|
Loading…
x
Reference in New Issue
Block a user