mirror of
https://github.com/minetest/contentdb.git
synced 2025-01-08 22:17:34 +01:00
Add package soft deletion
This commit is contained in:
parent
f93394df75
commit
8cf5c7204f
@ -261,6 +261,7 @@ class Package(db.Model):
|
|||||||
license_id = db.Column(db.Integer, db.ForeignKey("license.id"))
|
license_id = db.Column(db.Integer, db.ForeignKey("license.id"))
|
||||||
|
|
||||||
approved = db.Column(db.Boolean, nullable=False, default=False)
|
approved = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
soft_deleted = db.Column(db.Boolean, nullable=False, default=False)
|
||||||
|
|
||||||
# Downloads
|
# Downloads
|
||||||
repo = db.Column(db.String(200), nullable=True)
|
repo = db.Column(db.String(200), nullable=True)
|
||||||
@ -329,6 +330,10 @@ class Package(db.Model):
|
|||||||
return url_for("approve_package_page",
|
return url_for("approve_package_page",
|
||||||
author=self.author.username, name=self.name)
|
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):
|
def getNewScreenshotURL(self):
|
||||||
return url_for("create_screenshot_page",
|
return url_for("create_screenshot_page",
|
||||||
author=self.author.username, name=self.name)
|
author=self.author.username, name=self.name)
|
||||||
@ -546,7 +551,7 @@ class EditRequestChange(db.Model):
|
|||||||
if user is None:
|
if user is None:
|
||||||
continue
|
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:
|
if dep is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -301,9 +301,9 @@ select:not([multiple]) {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-error {
|
.alert-error, .button-danger {
|
||||||
background: #933;
|
background: #933 !important;
|
||||||
border: 1px solid #c44;
|
border: 1px solid #c44 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-warning {
|
.alert-warning {
|
||||||
|
@ -231,7 +231,7 @@ def makeVCSRelease(id, branch):
|
|||||||
@celery.task()
|
@celery.task()
|
||||||
def importRepoScreenshot(id):
|
def importRepoScreenshot(id):
|
||||||
package = Package.query.get(id)
|
package = Package.query.get(id)
|
||||||
if package is None:
|
if package is None or package.soft_deleted:
|
||||||
raise Exception("Unexpected none package")
|
raise Exception("Unexpected none package")
|
||||||
|
|
||||||
# Get URL Maker
|
# Get URL Maker
|
||||||
|
@ -19,7 +19,22 @@
|
|||||||
<option value="importusers" selected>Create users from mod list</option>
|
<option value="importusers" selected>Create users from mod list</option>
|
||||||
<option value="importscreenshots">Import screenshots from VCS</option>
|
<option value="importscreenshots">Import screenshots from VCS</option>
|
||||||
</select>
|
</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>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
18
app/templates/packages/delete.html
Normal file
18
app/templates/packages/delete.html
Normal 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 %}
|
@ -91,6 +91,9 @@
|
|||||||
{% if package.checkPerm(current_user, "MAKE_RELEASE") %}
|
{% if package.checkPerm(current_user, "MAKE_RELEASE") %}
|
||||||
<li><a href="{{ package.getCreateReleaseURL() }}">Create Release</a></li>
|
<li><a href="{{ package.getCreateReleaseURL() }}">Create Release</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if package.checkPerm(current_user, "DELETE_PACKAGE") %}
|
||||||
|
<li><a href="{{ package.getDeleteURL() }}">Delete</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
@ -116,7 +116,7 @@ def getPackageByInfo(author, name):
|
|||||||
if user is None:
|
if user is None:
|
||||||
abort(404)
|
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:
|
if package is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ def send_upload(path):
|
|||||||
@app.route("/")
|
@app.route("/")
|
||||||
@menu.register_menu(app, ".", "Home")
|
@menu.register_menu(app, ".", "Home")
|
||||||
def home_page():
|
def home_page():
|
||||||
query = Package.query.filter_by(approved=True)
|
query = Package.query.filter_by(approved=True, soft_deleted=False)
|
||||||
count = query.count()
|
count = query.count()
|
||||||
packages = query.order_by(db.desc(Package.created_at)).limit(15).all()
|
packages = query.order_by(db.desc(Package.created_at)).limit(15).all()
|
||||||
return render_template("index.html", packages=packages, count=count)
|
return render_template("index.html", packages=packages, count=count)
|
||||||
|
@ -37,15 +37,25 @@ def admin_page():
|
|||||||
elif action == "importscreenshots":
|
elif action == "importscreenshots":
|
||||||
packages = Package.query \
|
packages = Package.query \
|
||||||
.outerjoin(PackageScreenshot, Package.id==PackageScreenshot.package_id) \
|
.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:
|
for package in packages:
|
||||||
importRepoScreenshot.delay(package.id)
|
importRepoScreenshot.delay(package.id)
|
||||||
|
|
||||||
return redirect(url_for("admin_page"))
|
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:
|
else:
|
||||||
flash("Unknown action: " + action, "error")
|
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):
|
class SwitchUserForm(FlaskForm):
|
||||||
username = StringField("Username")
|
username = StringField("Username")
|
||||||
|
@ -43,7 +43,7 @@ def packages_page():
|
|||||||
type = PackageType[type.upper()]
|
type = PackageType[type.upper()]
|
||||||
|
|
||||||
title = "Packages"
|
title = "Packages"
|
||||||
query = Package.query
|
query = Package.query.filter_by(soft_deleted=False)
|
||||||
|
|
||||||
if type is not None:
|
if type is not None:
|
||||||
title = type.value + "s"
|
title = type.value + "s"
|
||||||
@ -107,8 +107,8 @@ class PackageForm(FlaskForm):
|
|||||||
type = SelectField("Type", [InputRequired()], choices=PackageType.choices(), coerce=PackageType.coerce, default=PackageType.MOD)
|
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)
|
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)
|
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)
|
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).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()])
|
repo = StringField("Repo URL", [Optional(), URL()])
|
||||||
website = StringField("Website URL", [Optional(), URL()])
|
website = StringField("Website URL", [Optional(), URL()])
|
||||||
issueTracker = StringField("Issue Tracker 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:
|
if not package:
|
||||||
package = Package.query.filter_by(name=form["name"].data, author_id=author.id).first()
|
package = Package.query.filter_by(name=form["name"].data, author_id=author.id).first()
|
||||||
if package is not None:
|
if package is not None:
|
||||||
flash("Package already exists!", "error")
|
if package.soft_deleted:
|
||||||
return redirect(url_for("create_edit_package_page"))
|
package.delete()
|
||||||
|
else:
|
||||||
|
flash("Package already exists!", "error")
|
||||||
|
return redirect(url_for("create_edit_package_page"))
|
||||||
|
|
||||||
package = Package()
|
package = Package()
|
||||||
package.author = author
|
package.author = author
|
||||||
@ -198,4 +201,26 @@ def approve_package_page(package):
|
|||||||
|
|
||||||
return redirect(package.getDetailsURL())
|
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
|
from . import todo, screenshots, editrequests, releases
|
||||||
|
@ -29,7 +29,7 @@ def todo_page():
|
|||||||
|
|
||||||
packages = None
|
packages = None
|
||||||
if canApproveNew:
|
if canApproveNew:
|
||||||
packages = Package.query.filter_by(approved=False).all()
|
packages = Package.query.filter_by(approved=False, soft_deleted=False).all()
|
||||||
|
|
||||||
releases = None
|
releases = None
|
||||||
if canApproveRel:
|
if canApproveRel:
|
||||||
|
28
migrations/versions/c4152f4240ed_.py
Normal file
28
migrations/versions/c4152f4240ed_.py
Normal 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 ###
|
Loading…
Reference in New Issue
Block a user