mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
Merge pull request #47 from DanielGrams/issue/46-edit-user-roles
#46 Edit user roles
This commit is contained in:
commit
0200249fdc
@ -2,6 +2,7 @@ from flask_wtf import FlaskForm
|
||||
from flask_babelex import lazy_gettext
|
||||
from wtforms import TextAreaField, SubmitField
|
||||
from wtforms.validators import Optional
|
||||
from project.forms.widgets import MultiCheckboxField
|
||||
|
||||
|
||||
class AdminSettingsForm(FlaskForm):
|
||||
@ -11,3 +12,8 @@ class AdminSettingsForm(FlaskForm):
|
||||
privacy = TextAreaField(lazy_gettext("Privacy"), validators=[Optional()])
|
||||
|
||||
submit = SubmitField(lazy_gettext("Save"))
|
||||
|
||||
|
||||
class UpdateUserForm(FlaskForm):
|
||||
roles = MultiCheckboxField(lazy_gettext("Roles"))
|
||||
submit = SubmitField(lazy_gettext("Update user"))
|
||||
|
||||
@ -6,20 +6,37 @@ def create_user(email, password):
|
||||
return user_datastore.create_user(email=email, password=hash_password(password))
|
||||
|
||||
|
||||
def add_roles_to_user(email, role_names):
|
||||
def add_roles_to_user(email, roles):
|
||||
user = find_user_by_email(email)
|
||||
|
||||
if user is None:
|
||||
raise ValueError("User with given email does not exist.")
|
||||
|
||||
for role_name in role_names:
|
||||
user_datastore.add_role_to_user(user, role_name)
|
||||
for role in roles:
|
||||
user_datastore.add_role_to_user(user, role)
|
||||
|
||||
|
||||
def add_admin_roles_to_user(email):
|
||||
add_roles_to_user(email, ["admin", "event_verifier"])
|
||||
|
||||
|
||||
def remove_roles_from_user(email, roles):
|
||||
user = find_user_by_email(email)
|
||||
|
||||
for role in roles:
|
||||
user_datastore.remove_role_from_user(user, role)
|
||||
|
||||
|
||||
def remove_all_roles_from_user(email):
|
||||
user = find_user_by_email(email)
|
||||
remove_roles_from_user(email, user.roles)
|
||||
|
||||
|
||||
def set_roles_for_user(email, roles):
|
||||
remove_all_roles_from_user(email)
|
||||
add_roles_to_user(email, roles)
|
||||
|
||||
|
||||
def upsert_user_role(role_name, role_title, permissions):
|
||||
role = user_datastore.find_or_create_role(role_name)
|
||||
role.title = role_title
|
||||
|
||||
@ -19,6 +19,10 @@
|
||||
{{ _('Admin Units') }}
|
||||
<i class="fa fa-caret-right"></i>
|
||||
</a>
|
||||
<a href="{{ url_for('admin_users') }}" class="list-group-item">
|
||||
{{ _('Users') }}
|
||||
<i class="fa fa-caret-right"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
25
project/templates/admin/update_user.html
Normal file
25
project/templates/admin/update_user.html
Normal file
@ -0,0 +1,25 @@
|
||||
{% extends "layout.html" %}
|
||||
{% from "_macros.html" import render_field_with_errors, render_field %}
|
||||
{% block title %}
|
||||
{{ _('Update user') }}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<h1>{{ _('Update user') }}</h1>
|
||||
|
||||
<form action="" method="POST">
|
||||
{{ form.hidden_tag() }}
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
{{ user.email }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ render_field_with_errors(form.roles, ri="multicheckbox") }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ render_field(form.submit) }}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
36
project/templates/admin/users.html
Normal file
36
project/templates/admin/users.html
Normal file
@ -0,0 +1,36 @@
|
||||
{% extends "layout.html" %}
|
||||
{% from "_macros.html" import render_pagination %}
|
||||
{% block title %}
|
||||
{{ _('Users') }}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{{ url_for('admin') }}">{{ _('Admin') }}</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ _('Users') }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ _('Email') }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{ user.email }}</td>
|
||||
<td><a href="{{ url_for('admin_user_update', id=user.id) }}">{{ _('Edit') }}</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="my-4">{{ render_pagination(pagination) }}</div>
|
||||
|
||||
{% endblock %}
|
||||
@ -1,15 +1,18 @@
|
||||
from project import app, db
|
||||
from project.models import AdminUnit
|
||||
from project.models import AdminUnit, User, Role
|
||||
from flask import render_template, flash, url_for, redirect
|
||||
from flask_babelex import gettext
|
||||
from flask_security import roles_required
|
||||
from project.forms.admin import AdminSettingsForm
|
||||
from project.forms.admin import AdminSettingsForm, UpdateUserForm
|
||||
from project.services.admin import upsert_settings
|
||||
from project.services.user import set_roles_for_user
|
||||
from project.views.utils import (
|
||||
flash_errors,
|
||||
handleSqlError,
|
||||
get_pagination_urls,
|
||||
)
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
|
||||
@app.route("/admin")
|
||||
@ -44,3 +47,38 @@ def admin_settings():
|
||||
flash_errors(form)
|
||||
|
||||
return render_template("admin/settings.html", form=form)
|
||||
|
||||
|
||||
@app.route("/admin/users")
|
||||
@roles_required("admin")
|
||||
def admin_users():
|
||||
users = User.query.order_by(func.lower(User.email)).paginate()
|
||||
return render_template(
|
||||
"admin/users.html", users=users.items, pagination=get_pagination_urls(users)
|
||||
)
|
||||
|
||||
|
||||
@app.route("/admin/user/<int:id>/update", methods=("GET", "POST"))
|
||||
@roles_required("admin")
|
||||
def admin_user_update(id):
|
||||
user = User.query.get_or_404(id)
|
||||
|
||||
form = UpdateUserForm()
|
||||
form.roles.choices = [
|
||||
(c.name, gettext(c.title)) for c in Role.query.order_by(Role.id).all()
|
||||
]
|
||||
|
||||
if form.validate_on_submit():
|
||||
set_roles_for_user(user.email, form.roles.data)
|
||||
|
||||
try:
|
||||
db.session.commit()
|
||||
flash(gettext("User successfully updated"), "success")
|
||||
return redirect(url_for("admin_users"))
|
||||
except SQLAlchemyError as e:
|
||||
db.session.rollback()
|
||||
flash(handleSqlError(e), "danger")
|
||||
else:
|
||||
form.roles.data = [c.name for c in user.roles]
|
||||
|
||||
return render_template("admin/update_user.html", user=user, form=form)
|
||||
|
||||
@ -58,3 +58,52 @@ def test_admin_settings(client, seeder, utils, app, mocker, db_error):
|
||||
assert settings.legal_notice == "Mein Impressum"
|
||||
assert settings.contact == "Mein Kontakt"
|
||||
assert settings.privacy == "Mein Datenschutz"
|
||||
|
||||
|
||||
def test_admin_users(client, seeder, utils, app):
|
||||
seeder.create_user(admin=True)
|
||||
user = utils.login()
|
||||
seeder.create_admin_unit(user, "Meine Crew")
|
||||
response = client.get("/admin/users")
|
||||
assert b"test@test.de" in response.data
|
||||
|
||||
|
||||
@pytest.mark.parametrize("db_error", [True, False])
|
||||
def test_admin_user_update(client, seeder, utils, app, mocker, db, db_error):
|
||||
user_id, admin_unit_id = seeder.setup_base(True)
|
||||
other_user_id = seeder.create_user("other@test.de")
|
||||
|
||||
with app.app_context():
|
||||
from project.models import User
|
||||
from project.services.user import set_roles_for_user
|
||||
|
||||
user = User.query.get_or_404(other_user_id)
|
||||
set_roles_for_user(user.email, ["event_verifier"])
|
||||
db.session.commit()
|
||||
|
||||
url = utils.get_url("admin_user_update", id=other_user_id)
|
||||
response = utils.get_ok(url)
|
||||
|
||||
if db_error:
|
||||
utils.mock_db_commit(mocker)
|
||||
|
||||
response = utils.post_form(
|
||||
url,
|
||||
response,
|
||||
{
|
||||
"roles": "admin",
|
||||
},
|
||||
)
|
||||
|
||||
if db_error:
|
||||
utils.assert_response_db_error(response)
|
||||
return
|
||||
|
||||
utils.assert_response_redirect(response, "admin_users")
|
||||
|
||||
with app.app_context():
|
||||
from project.models import User
|
||||
|
||||
user = User.query.get_or_404(other_user_id)
|
||||
assert len(user.roles) == 1
|
||||
assert any(r.name == "admin" for r in user.roles)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user