From 6fa8e170a3bd573e7ef174584b6c90da83a1f6c9 Mon Sep 17 00:00:00 2001 From: Martin Mares <mj@ucw.cz> Date: Sun, 16 Jan 2022 01:06:42 +0100 Subject: [PATCH] =?UTF-8?q?Implementov=C3=A1no=20maz=C3=A1n=C3=AD=20u?= =?UTF-8?q?=C5=BEivatel=C5=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zatím je dostupné pouze správci a umí vyřešit pouze triviální případy. --- mo/web/org_users.py | 90 +++++++++++++++++++++++++++ mo/web/templates/org_org.html | 1 + mo/web/templates/org_user.html | 1 + mo/web/templates/org_user_delete.html | 28 +++++++++ 4 files changed, 120 insertions(+) create mode 100644 mo/web/templates/org_user_delete.html diff --git a/mo/web/org_users.py b/mo/web/org_users.py index 683c0f79..47b79919 100644 --- a/mo/web/org_users.py +++ b/mo/web/org_users.py @@ -664,3 +664,93 @@ def org_orgs_import(): year=mo.config.CURRENT_YEAR if form.only_this_year.data else None ) return generic_import_page(form, imp, url_for('org_orgs_import'), template='org_global_orgs_import.html') + + +class ConfirmDeleteForm(FlaskForm): + delete = SubmitField('Potvrdit smazání') + + +@app.route('/org/user/<int:user_id>/delete', methods=('GET', 'POST')) +def org_user_delete(user_id: int): + if not g.user.is_admin: + raise werkzeug.exceptions.Forbidden() + + sess = db.get_session() + user = sess.query(db.User).get(user_id) + if not user: + raise werkzeug.exceptions.NotFound() + + warnings = [] + errors = [] + + pants = sess.query(db.Participant).filter_by(user=user).all() + for pant in pants: + warnings.append(f'Účastní se {pant.year}. ročníku') + + pions = (sess.query(db.Participation) + .filter_by(user=user) + # .options(joinedload(db.Participation.contest, db.Participation.contest.round)) + .all()) + for pion in pions: + warnings.append(f'Účastní se kola {pion.contest.round.round_code()}') + + num_roles = sess.query(db.UserRole).filter_by(user=user).count() + if num_roles > 0: + warnings.append(f'Má přidělené role ({num_roles})') + + sols = (sess.query(db.Solution) + .filter_by(user=user) + # .options(joinedload(db.Solution.task, db.Solution.task.round)) + .all()) + for sol in sols: + errors.append(f'Odevzdal úlohu {sol.task.code} v kole {sol.task.round.round_code()}') + + num_papers = sess.query(db.Paper).filter_by(for_user_obj=user).count() + if num_papers: + errors.append(f'Patří mu řešení/opravy ({num_papers})') + + num_uploads = sess.query(db.Paper).filter_by(uploaded_by_obj=user).count() + if num_uploads: + errors.append(f'Nahrál řešení/opravy ({num_uploads})') + + logs = sess.query(db.Log).filter_by(user=user).all() + num_good_logs = 0 + num_bad_logs = 0 + for log in logs: + if log.details.get('reason', "") == 'user-join': + num_good_logs += 1 + else: + num_bad_logs += 1 + if num_good_logs > 0: + warnings.append(f'Vlastní záznamy v logu z registrace ({num_good_logs})') + if num_bad_logs > 0: + errors.append(f'Vlastní záznamy v logu ({num_bad_logs})') + + form = ConfirmDeleteForm() + if form.validate_on_submit() and not errors: + sess.rollback() + + conn = sess.connection() + pant_table = db.Participation.__table__ + pion_table = db.Participant.__table__ + role_table = db.UserRole.__table__ + log_table = db.Log.__table__ + conn.execute(pant_table.delete().where(pant_table.c.user_id == user.user_id)) + conn.execute(pion_table.delete().where(pion_table.c.user_id == user.user_id)) + conn.execute(role_table.delete().where(role_table.c.user_id == user.user_id)) + conn.execute(log_table.delete().where(log_table.c.changed_by == user.user_id)) + sess.commit() + + mo.util.log( + type=db.LogType.user, + what=user.user_id, + details={'action': 'delete', 'user': db.row2dict(user)}, + ) + sess.delete(user) + sess.commit() + + app.logger.info(f"Uživatel #{user.user_id} smazán") + flash('Uživatel smazán.', 'danger') + return redirect(url_for('org_orgs') if user.is_org else url_for('org_users')) + + return render_template('org_user_delete.html', user=user, form=form, warnings=warnings, errors=errors) diff --git a/mo/web/templates/org_org.html b/mo/web/templates/org_org.html index f242e278..9c3c36f3 100644 --- a/mo/web/templates/org_org.html +++ b/mo/web/templates/org_org.html @@ -31,6 +31,7 @@ {% endif %} {% if g.user.is_admin %} <a class="btn btn-default" href="{{ log_url('user', user.user_id) }}">Historie</a> + <a class="btn btn-danger" href="{{ url_for('org_user_delete', user_id=user.user_id) }}">Smazat</a> {% endif %} {% if can_incarnate %} <form action="{{ url_for('incarnate', id=user.user_id) }}" method=POST class='btn-group'> diff --git a/mo/web/templates/org_user.html b/mo/web/templates/org_user.html index edf1f768..965bcb75 100644 --- a/mo/web/templates/org_user.html +++ b/mo/web/templates/org_user.html @@ -39,6 +39,7 @@ {% endif %} {% if g.user.is_admin %} <a class="btn btn-default" href="{{ log_url('user', user.user_id) }}">Historie</a> + <a class="btn btn-danger" href="{{ url_for('org_user_delete', user_id=user.user_id) }}">Smazat</a> {% endif %} {% if can_incarnate %} <form action="{{ url_for('incarnate', id=user.user_id) }}" method=POST class='btn-group'> diff --git a/mo/web/templates/org_user_delete.html b/mo/web/templates/org_user_delete.html new file mode 100644 index 00000000..58678679 --- /dev/null +++ b/mo/web/templates/org_user_delete.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} +{% import "bootstrap/wtf.html" as wtf %} +{% block title %}Smazat uživatele: {{ user.full_name() }}{% endblock %} +{% block body %} + +{% if warnings %} +<h3>Varováni</h3> +<ul> + {% for w in warnings %} + <li>{{ w }} + {% endfor %} +</ul> +{% endif %} + +{% if errors %} +<h3>Chyby</h3> +<ul> + {% for e in errors %} + <li>{{ e }} + {% endfor %} +</ul> +{% endif %} + +{% if form and not errors %} +{{ wtf.quick_form(form, form_type='simple', button_map={'delete': 'danger'}) }} +{% endif %} + +{% endblock %} -- GitLab