From 76414cb5ba96a4ed75fc67e09f2f3f819f961d63 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 29 Jul 2023 21:34:23 +0100 Subject: [PATCH] Add page to transfer packages --- app/blueprints/admin/admin.py | 57 +++++++++++++++++++++++++++-- app/blueprints/packages/packages.py | 4 +- app/templates/admin/list.html | 1 + app/templates/admin/transfer.html | 19 ++++++++++ 4 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 app/templates/admin/transfer.html diff --git a/app/blueprints/admin/admin.py b/app/blueprints/admin/admin.py index dc8a8615..77bceeb0 100644 --- a/app/blueprints/admin/admin.py +++ b/app/blueprints/admin/admin.py @@ -18,11 +18,11 @@ from flask import redirect, render_template, url_for, request, flash from flask_login import current_user, login_user from flask_wtf import FlaskForm from wtforms import StringField, SubmitField -from wtforms.validators import InputRequired, Length -from app.utils import rank_required, add_audit_log, add_notification, get_system_user +from wtforms.validators import InputRequired, Length, Optional +from app.utils import rank_required, add_audit_log, add_notification, get_system_user, nonempty_or_none from . import bp from .actions import actions -from app.models import UserRank, Package, db, PackageState, User, AuditSeverity, NotificationType +from app.models import UserRank, Package, db, PackageState, User, AuditSeverity, NotificationType, PackageAlias @bp.route("/admin/", methods=["GET", "POST"]) @@ -118,3 +118,54 @@ def restore(): .all() return render_template("admin/restore.html", deleted_packages=deleted_packages) + + +class TransferPackageForm(FlaskForm): + old_username = StringField("Old Username", [InputRequired()]) + new_username = StringField("New Username", [InputRequired()]) + package = StringField("Package", [Optional()]) + submit = SubmitField("Transfer") + + +def perform_transfer(form: TransferPackageForm): + query = Package.query.filter(Package.author.has(username=form.old_username.data)) + if nonempty_or_none(form.package.data): + query = query.filter_by(name=form.package.data) + + packages = query.all() + if len(packages) == 0: + flash("Unable to find package(s)", "danger") + return + + new_user = User.query.filter_by(username=form.new_username.data).first() + if new_user is None: + flash("Unable to find new user", "danger") + return + + for package in packages: + package.author = new_user + package.maintainers.append(new_user) + package.aliases.append(PackageAlias(form.old_username.data, package.name)) + + add_audit_log(AuditSeverity.MODERATION, current_user, + f"Transferred {form.old_username.data}/{package.name} to {form.new_username.data}", + package.get_url("packages.view"), package) + + db.session.commit() + + flash("Transferred " + ", ".join([x.name for x in packages]), "success") + + return redirect(url_for("admin.transfer")) + + +@bp.route("/admin/transfer/", methods=["GET", "POST"]) +@rank_required(UserRank.MODERATOR) +def transfer(): + form = TransferPackageForm(formdata=request.form) + if form.validate_on_submit(): + ret = perform_transfer(form) + if ret is not None: + return ret + + # Process GET or invalid POST + return render_template("admin/transfer.html", form=form) diff --git a/app/blueprints/packages/packages.py b/app/blueprints/packages/packages.py index c5342dc1..abf5ed4b 100644 --- a/app/blueprints/packages/packages.py +++ b/app/blueprints/packages/packages.py @@ -592,7 +592,7 @@ class PackageAliasForm(FlaskForm): @bp.route("/packages///aliases/") -@rank_required(UserRank.EDITOR) +@rank_required(UserRank.ADMIN) @is_package_page def alias_list(package: Package): return render_template("packages/alias_list.html", package=package) @@ -600,7 +600,7 @@ def alias_list(package: Package): @bp.route("/packages///aliases/new/", methods=["GET", "POST"]) @bp.route("/packages///aliases//", methods=["GET", "POST"]) -@rank_required(UserRank.EDITOR) +@rank_required(UserRank.ADMIN) @is_package_page def alias_create_edit(package: Package, alias_id: int = None): alias = None diff --git a/app/templates/admin/list.html b/app/templates/admin/list.html index 0b5b9718..f29358fb 100644 --- a/app/templates/admin/list.html +++ b/app/templates/admin/list.html @@ -10,6 +10,7 @@
User list Restore package + Transfer package(s) Tag Editor License Editor Version Editor diff --git a/app/templates/admin/transfer.html b/app/templates/admin/transfer.html new file mode 100644 index 00000000..3ca31064 --- /dev/null +++ b/app/templates/admin/transfer.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block title %} + Transfer Package(s) +{% endblock %} + +{% block content %} +

Transfer Package(s)

+ + {% from "macros/forms.html" import render_field, render_submit_field %} +
+ {{ form.hidden_tag() }} + + {{ render_field(form.old_username) }} + {{ render_field(form.new_username) }} + {{ render_field(form.package, hint="Leave blank to transfer all packages") }} + {{ render_submit_field(form.submit) }} +
+{% endblock %}