Add page to transfer packages

This commit is contained in:
rubenwardy 2023-07-29 21:34:23 +01:00
parent 6d184e0320
commit 76414cb5ba
4 changed files with 76 additions and 5 deletions

@ -18,11 +18,11 @@ from flask import redirect, render_template, url_for, request, flash
from flask_login import current_user, login_user from flask_login import current_user, login_user
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField from wtforms import StringField, SubmitField
from wtforms.validators import InputRequired, Length from wtforms.validators import InputRequired, Length, Optional
from app.utils import rank_required, add_audit_log, add_notification, get_system_user from app.utils import rank_required, add_audit_log, add_notification, get_system_user, nonempty_or_none
from . import bp from . import bp
from .actions import actions 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"]) @bp.route("/admin/", methods=["GET", "POST"])
@ -118,3 +118,54 @@ def restore():
.all() .all()
return render_template("admin/restore.html", deleted_packages=deleted_packages) 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)

@ -592,7 +592,7 @@ class PackageAliasForm(FlaskForm):
@bp.route("/packages/<author>/<name>/aliases/") @bp.route("/packages/<author>/<name>/aliases/")
@rank_required(UserRank.EDITOR) @rank_required(UserRank.ADMIN)
@is_package_page @is_package_page
def alias_list(package: Package): def alias_list(package: Package):
return render_template("packages/alias_list.html", package=package) return render_template("packages/alias_list.html", package=package)
@ -600,7 +600,7 @@ def alias_list(package: Package):
@bp.route("/packages/<author>/<name>/aliases/new/", methods=["GET", "POST"]) @bp.route("/packages/<author>/<name>/aliases/new/", methods=["GET", "POST"])
@bp.route("/packages/<author>/<name>/aliases/<int:alias_id>/", methods=["GET", "POST"]) @bp.route("/packages/<author>/<name>/aliases/<int:alias_id>/", methods=["GET", "POST"])
@rank_required(UserRank.EDITOR) @rank_required(UserRank.ADMIN)
@is_package_page @is_package_page
def alias_create_edit(package: Package, alias_id: int = None): def alias_create_edit(package: Package, alias_id: int = None):
alias = None alias = None

@ -10,6 +10,7 @@
<div class="list-group"> <div class="list-group">
<a class="list-group-item list-group-item-action" href="{{ url_for('users.list_all') }}">User list</a> <a class="list-group-item list-group-item-action" href="{{ url_for('users.list_all') }}">User list</a>
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.restore') }}">Restore package</a> <a class="list-group-item list-group-item-action" href="{{ url_for('admin.restore') }}">Restore package</a>
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.transfer') }}">Transfer package(s)</a>
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.tag_list') }}">Tag Editor</a> <a class="list-group-item list-group-item-action" href="{{ url_for('admin.tag_list') }}">Tag Editor</a>
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.license_list') }}">License Editor</a> <a class="list-group-item list-group-item-action" href="{{ url_for('admin.license_list') }}">License Editor</a>
<a class="list-group-item list-group-item-action" href="{{ url_for('admin.version_list') }}">Version Editor</a> <a class="list-group-item list-group-item-action" href="{{ url_for('admin.version_list') }}">Version Editor</a>

@ -0,0 +1,19 @@
{% extends "base.html" %}
{% block title %}
Transfer Package(s)
{% endblock %}
{% block content %}
<h2>Transfer Package(s)</h2>
{% from "macros/forms.html" import render_field, render_submit_field %}
<form method="POST" action="">
{{ 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) }}
</form>
{% endblock %}