diff options
author | rubenwardy <rw@rubenwardy.com> | 2018-05-25 18:28:24 +0100 |
---|---|---|
committer | rubenwardy <rw@rubenwardy.com> | 2018-05-25 18:28:24 +0100 |
commit | 8cf5c7204f0ebb787eafb9ffa04c9e61a8d6d3af (patch) | |
tree | 5ef4e040ed428a48319c325d93927508624c99c3 | |
parent | f93394df753b7e2181f2a3eb3c1f3d45835ccc63 (diff) | |
download | cheatdb-8cf5c7204f0ebb787eafb9ffa04c9e61a8d6d3af.tar.xz |
Add package soft deletion
-rw-r--r-- | app/models.py | 7 | ||||
-rw-r--r-- | app/scss/components.scss | 6 | ||||
-rw-r--r-- | app/tasks/importtasks.py | 2 | ||||
-rw-r--r-- | app/templates/admin/list.html | 17 | ||||
-rw-r--r-- | app/templates/packages/delete.html | 18 | ||||
-rw-r--r-- | app/templates/packages/view.html | 3 | ||||
-rw-r--r-- | app/utils.py | 2 | ||||
-rw-r--r-- | app/views/__init__.py | 2 | ||||
-rw-r--r-- | app/views/admin.py | 14 | ||||
-rw-r--r-- | app/views/packages/__init__.py | 35 | ||||
-rw-r--r-- | app/views/packages/todo.py | 2 | ||||
-rw-r--r-- | migrations/versions/c4152f4240ed_.py | 28 |
12 files changed, 120 insertions, 16 deletions
diff --git a/app/models.py b/app/models.py index c0c9a09..9118f78 100644 --- a/app/models.py +++ b/app/models.py @@ -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 diff --git a/app/scss/components.scss b/app/scss/components.scss index 3a145bc..226ef6b 100644 --- a/app/scss/components.scss +++ b/app/scss/components.scss @@ -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 { diff --git a/app/tasks/importtasks.py b/app/tasks/importtasks.py index 352736e..a20bbee 100644 --- a/app/tasks/importtasks.py +++ b/app/tasks/importtasks.py @@ -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 diff --git a/app/templates/admin/list.html b/app/templates/admin/list.html index 7b66458..373f18b 100644 --- a/app/templates/admin/list.html +++ b/app/templates/admin/list.html @@ -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 %} diff --git a/app/templates/packages/delete.html b/app/templates/packages/delete.html new file mode 100644 index 0000000..95709c3 --- /dev/null +++ b/app/templates/packages/delete.html @@ -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 %} diff --git a/app/templates/packages/view.html b/app/templates/packages/view.html index c3dbb34..8d329ef 100644 --- a/app/templates/packages/view.html +++ b/app/templates/packages/view.html @@ -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> diff --git a/app/utils.py b/app/utils.py index e42c3cc..9be70d6 100644 --- a/app/utils.py +++ b/app/utils.py @@ -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) diff --git a/app/views/__init__.py b/app/views/__init__.py index a296e5d..abaacd7 100644 --- a/app/views/__init__.py +++ b/app/views/__init__.py @@ -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) diff --git a/app/views/admin.py b/app/views/admin.py index d0dcf73..6c8c4ef 100644 --- a/app/views/admin.py +++ b/app/views/admin.py @@ -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") diff --git a/app/views/packages/__init__.py b/app/views/packages/__init__.py index c280666..340dab7 100644 --- a/app/views/packages/__init__.py +++ b/app/views/packages/__init__.py @@ -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 diff --git a/app/views/packages/todo.py b/app/views/packages/todo.py index 53fec73..63f843b 100644 --- a/app/views/packages/todo.py +++ b/app/views/packages/todo.py @@ -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: diff --git a/migrations/versions/c4152f4240ed_.py b/migrations/versions/c4152f4240ed_.py new file mode 100644 index 0000000..de729a8 --- /dev/null +++ b/migrations/versions/c4152f4240ed_.py @@ -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 ### |