Add package soft deletion

This commit is contained in:
rubenwardy 2018-05-25 18:28:24 +01:00
parent f93394df75
commit 8cf5c7204f
No known key found for this signature in database
GPG Key ID: A1E29D52FF81513C
12 changed files with 120 additions and 16 deletions

View File

@ -261,6 +261,7 @@ class Package(db.Model):
license_id = db.Column(db.Integer, db.ForeignKey("license.id"))
approved = db.Column(db.Boolean, nullable=False, default=False)
soft_deleted = db.Column(db.Boolean, nullable=False, default=False)
# Downloads
repo = db.Column(db.String(200), nullable=True)
@ -329,6 +330,10 @@ class Package(db.Model):
return url_for("approve_package_page",
author=self.author.username, name=self.name)
def getDeleteURL(self):
return url_for("delete_package_page",
author=self.author.username, name=self.name)
def getNewScreenshotURL(self):
return url_for("create_screenshot_page",
author=self.author.username, name=self.name)
@ -546,7 +551,7 @@ class EditRequestChange(db.Model):
if user is None:
continue
dep = Package.query.filter_by(author=user, name=value).first()
dep = Package.query.filter_by(author=user, name=value, soft_deleted=False).first()
if dep is None:
continue

View File

@ -301,9 +301,9 @@ select:not([multiple]) {
color: #fff;
}
.alert-error {
background: #933;
border: 1px solid #c44;
.alert-error, .button-danger {
background: #933 !important;
border: 1px solid #c44 !important;
}
.alert-warning {

View File

@ -231,7 +231,7 @@ def makeVCSRelease(id, branch):
@celery.task()
def importRepoScreenshot(id):
package = Package.query.get(id)
if package is None:
if package is None or package.soft_deleted:
raise Exception("Unexpected none package")
# Get URL Maker

View File

@ -19,7 +19,22 @@
<option value="importusers" selected>Create users from mod list</option>
<option value="importscreenshots">Import screenshots from VCS</option>
</select>
<input type="submit" value="Start" />
<input type="submit" value="Perform" />
</form>
</div>
<div class="box box_grey">
<h2>Restore Package</h2>
<form method="post" action="" class="box-body">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="hidden" name="action" value="restore" />
<select name="package">
{% for p in deleted_packages %}
<option value={{ p.id }}>{{ p.id}}) {{ p.title }} by {{ p.author.display_name }}</option>
{% endfor %}
</select>
<input type="submit" value="Restore" />
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block title %}
Delete | {{ package.title }}
{% endblock %}
{% block content %}
<form method="POST" action="" class="box box_grey ">
<h3>Delete Package</h3>
<div class="box-body">
<p>This action can be undone by the admin, but he'll be very annoyed!</p>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<input type="submit" value="Delete" class="button-danger" />
</div>
</form>
{% endblock %}

View File

@ -91,6 +91,9 @@
{% if package.checkPerm(current_user, "MAKE_RELEASE") %}
<li><a href="{{ package.getCreateReleaseURL() }}">Create Release</a></li>
{% endif %}
{% if package.checkPerm(current_user, "DELETE_PACKAGE") %}
<li><a href="{{ package.getDeleteURL() }}">Delete</a></li>
{% endif %}
</ul>
</div>
</aside>

View File

@ -116,7 +116,7 @@ def getPackageByInfo(author, name):
if user is None:
abort(404)
package = Package.query.filter_by(name=name, author_id=user.id).first()
package = Package.query.filter_by(name=name, author_id=user.id, soft_deleted=False).first()
if package is None:
abort(404)

View File

@ -38,7 +38,7 @@ def send_upload(path):
@app.route("/")
@menu.register_menu(app, ".", "Home")
def home_page():
query = Package.query.filter_by(approved=True)
query = Package.query.filter_by(approved=True, soft_deleted=False)
count = query.count()
packages = query.order_by(db.desc(Package.created_at)).limit(15).all()
return render_template("index.html", packages=packages, count=count)

View File

@ -37,15 +37,25 @@ def admin_page():
elif action == "importscreenshots":
packages = Package.query \
.outerjoin(PackageScreenshot, Package.id==PackageScreenshot.package_id) \
.filter(PackageScreenshot.id==None).all()
.filter(PackageScreenshot.id==None) \
.filter_by(soft_deleted=False).all()
for package in packages:
importRepoScreenshot.delay(package.id)
return redirect(url_for("admin_page"))
elif action == "restore":
package = Package.query.get(request.form["package"])
if package is None:
flash("Unknown package", "error")
else:
package.soft_deleted = False
db.session.commit()
return redirect(url_for("admin_page"))
else:
flash("Unknown action: " + action, "error")
return render_template("admin/list.html")
deleted_packages = Package.query.filter_by(soft_deleted=True).all()
return render_template("admin/list.html", deleted_packages=deleted_packages)
class SwitchUserForm(FlaskForm):
username = StringField("Username")

View File

@ -43,7 +43,7 @@ def packages_page():
type = PackageType[type.upper()]
title = "Packages"
query = Package.query
query = Package.query.filter_by(soft_deleted=False)
if type is not None:
title = type.value + "s"
@ -107,8 +107,8 @@ class PackageForm(FlaskForm):
type = SelectField("Type", [InputRequired()], choices=PackageType.choices(), coerce=PackageType.coerce, default=PackageType.MOD)
license = QuerySelectField("License", [InputRequired()], query_factory=lambda: License.query, get_pk=lambda a: a.id, get_label=lambda a: a.name)
tags = QuerySelectMultipleField('Tags', query_factory=lambda: Tag.query.order_by(db.asc(Tag.name)), get_pk=lambda a: a.id, get_label=lambda a: a.title)
harddeps = QuerySelectMultipleField('Dependencies', query_factory=lambda: Package.query.join(User).order_by(db.asc(Package.title), db.asc(User.display_name)), get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
softdeps = QuerySelectMultipleField('Soft Dependencies', query_factory=lambda: Package.query.join(User).order_by(db.asc(Package.title), db.asc(User.display_name)), get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
harddeps = QuerySelectMultipleField('Dependencies', query_factory=lambda: Package.query.join(User).filter_by(soft_deleted=False,approved=True).order_by(db.asc(Package.title), db.asc(User.display_name)), get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
softdeps = QuerySelectMultipleField('Soft Dependencies', query_factory=lambda: Package.query.join(User).filter_by(soft_deleted=False,approved=True).order_by(db.asc(Package.title), db.asc(User.display_name)), get_pk=lambda a: a.id, get_label=lambda a: a.title + " by " + a.author.display_name)
repo = StringField("Repo URL", [Optional(), URL()])
website = StringField("Website URL", [Optional(), URL()])
issueTracker = StringField("Issue Tracker URL", [Optional(), URL()])
@ -151,8 +151,11 @@ def create_edit_package_page(author=None, name=None):
if not package:
package = Package.query.filter_by(name=form["name"].data, author_id=author.id).first()
if package is not None:
flash("Package already exists!", "error")
return redirect(url_for("create_edit_package_page"))
if package.soft_deleted:
package.delete()
else:
flash("Package already exists!", "error")
return redirect(url_for("create_edit_package_page"))
package = Package()
package.author = author
@ -198,4 +201,26 @@ def approve_package_page(package):
return redirect(package.getDetailsURL())
@app.route("/packages/<author>/<name>/delete/", methods=["GET", "POST"])
@login_required
@is_package_page
def delete_package_page(package):
if request.method == "GET":
return render_template("packages/delete.html", package=package)
if not package.checkPerm(current_user, Permission.DELETE_PACKAGE):
flash("You don't have permission to do that.", "error")
package.soft_deleted = True
url = url_for("user_profile_page", username=package.author.username)
triggerNotif(package.author, current_user,
"{} deleted".format(package.title), url)
db.session.commit()
flash("Deleted package", "success")
return redirect(url)
from . import todo, screenshots, editrequests, releases

View File

@ -29,7 +29,7 @@ def todo_page():
packages = None
if canApproveNew:
packages = Package.query.filter_by(approved=False).all()
packages = Package.query.filter_by(approved=False, soft_deleted=False).all()
releases = None
if canApproveRel:

View File

@ -0,0 +1,28 @@
"""empty message
Revision ID: c4152f4240ed
Revises: 3f4d7cd8401f
Create Date: 2018-05-25 18:27:16.953305
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'c4152f4240ed'
down_revision = '3f4d7cd8401f'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('package', sa.Column('soft_deleted', sa.Boolean(), nullable=False))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('package', 'soft_deleted')
# ### end Alembic commands ###