aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pysite/views/wiki/delete.py2
-rw-r--r--pysite/views/wiki/move.py86
-rw-r--r--templates/wiki/base.html14
-rw-r--r--templates/wiki/page_delete.html33
-rw-r--r--templates/wiki/page_move.html26
5 files changed, 143 insertions, 18 deletions
diff --git a/pysite/views/wiki/delete.py b/pysite/views/wiki/delete.py
index 0e3bcbbf..47759a87 100644
--- a/pysite/views/wiki/delete.py
+++ b/pysite/views/wiki/delete.py
@@ -10,7 +10,7 @@ from pysite.decorators import csrf, require_roles
from pysite.mixins import DBMixin
-class EditView(RouteView, DBMixin):
+class DeleteView(RouteView, DBMixin):
path = "/delete/<path:page>" # "path" means that it accepts slashes
name = "delete"
table_name = "wiki"
diff --git a/pysite/views/wiki/move.py b/pysite/views/wiki/move.py
new file mode 100644
index 00000000..081ae56a
--- /dev/null
+++ b/pysite/views/wiki/move.py
@@ -0,0 +1,86 @@
+import datetime
+
+import requests
+from flask import redirect, url_for, request
+from werkzeug.exceptions import NotFound, BadRequest
+
+from pysite.base_route import RouteView
+from pysite.constants import EDITOR_ROLES, WIKI_AUDIT_WEBHOOK
+from pysite.decorators import csrf, require_roles
+from pysite.mixins import DBMixin
+
+
+class MoveView(RouteView, DBMixin):
+ path = "/move/<path:page>" # "path" means that it accepts slashes
+ name = "move"
+ table_name = "wiki"
+ revision_table_name = "wiki_revisions"
+
+ @require_roles(*EDITOR_ROLES)
+ def get(self, page):
+ obj = self.db.get(self.table_name, page)
+
+ if obj:
+ title = obj.get("title", "")
+
+ if obj.get("lock_expiry") and obj.get("lock_user") != self.user_data.get("user_id"):
+ lock_time = datetime.datetime.fromtimestamp(obj["lock_expiry"])
+ if datetime.datetime.utcnow() < lock_time:
+ return self.render("wiki/page_in_use.html", page=page)
+
+ return self.render("wiki/page_move.html", page=page, title=title)
+ else:
+ raise NotFound()
+
+ @require_roles(*EDITOR_ROLES)
+ @csrf
+ def post(self, page):
+ location = request.form.get("location")
+
+ if not location or not location.strip():
+ raise BadRequest()
+
+ obj = self.db.get(self.table_name, page)
+
+ if not obj:
+ raise NotFound()
+
+ title = obj.get("title", "")
+ other_obj = self.db.get(self.table_name, location)
+
+ if other_obj:
+ return self.render(
+ "wiki/page_move.html", page=page, title=title,
+ message=f"There's already a page at {location} - please pick a different location"
+ )
+
+ self.db.delete(self.table_name, page)
+
+ obj["slug"] = location
+
+ self.db.insert(self.table_name, obj, conflict="update")
+
+ self.audit_log(obj)
+
+ return redirect(url_for("wiki.page", page=location), code=303) # Redirect, ensuring a GET
+
+ def audit_log(self, obj):
+ if WIKI_AUDIT_WEBHOOK: # If the audit webhook is not configured there is no point processing it
+ audit_payload = {
+ "username": "Wiki Updates",
+ "embeds": [
+ {
+ "title": "Page Move",
+ "description": f"**{obj['title']}** was moved by "
+ f"**{self.user_data.get('username')}** to "
+ f"**{obj['slug']}**",
+ "color": 4165079,
+ "timestamp": datetime.datetime.utcnow().isoformat(),
+ "thumbnail": {
+ "url": "https://pythondiscord.com/static/logos/logo_discord.png"
+ }
+ }
+ ]
+ }
+
+ requests.post(WIKI_AUDIT_WEBHOOK, json=audit_payload)
diff --git a/templates/wiki/base.html b/templates/wiki/base.html
index eec0ecb8..a71f09e6 100644
--- a/templates/wiki/base.html
+++ b/templates/wiki/base.html
@@ -104,6 +104,20 @@
</li>
{% endif %}
+ {% if current_page == "move" %}
+ <li>
+ <a href="{{ url_for("wiki.page", page=page) }}">
+ <i class="uk-icon fas fa-fw fa-arrow-left"></i> &nbsp;Back
+ </a>
+ </li>
+ {% else %}
+ <li>
+ <a href="{{ url_for("wiki.move", page=page) }}">
+ <i class="uk-icon fas fa-fw fa-arrow-right"></i> &nbsp;Move
+ </a>
+ </li>
+ {% endif %}
+
{% if current_page == "history.show" %}
<li>
<a href="{{ url_for("wiki.page", page=page) }}">
diff --git a/templates/wiki/page_delete.html b/templates/wiki/page_delete.html
index f4d52653..27c4b406 100644
--- a/templates/wiki/page_delete.html
+++ b/templates/wiki/page_delete.html
@@ -2,25 +2,24 @@
{% block title %}Wiki | Delete: {{ page }}{% endblock %}
{% block og_title %}Wiki | Delete: {{ page }}{% endblock %}
{% block og_description %}{% endblock %}
-{% block extra_head %}
-<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.3.3/ace.js" type="application/javascript"></script>
-{% endblock %}
{% block content %}
- <div uk-alert class="uk-alert-danger">
- <h3>Delete Page: {{ page }}</h3>
- <p>
- Are you sure you want to delete this page?
- </p>
+ <div class="uk-container uk-container-small">
+ <div uk-alert class="uk-alert-danger">
+ <h3>Delete Page: {{ page }}</h3>
+ <p>
+ Are you sure you want to delete this page?
+ </p>
- <form uk-grid class="uk-grid-small" action="{{ url_for("wiki.delete", page=page) }}" method="post">
- <div class="uk-width-1-2">
- <a href="{{ url_for("wiki.page", page=page) }}" class="uk-button uk-button-primary uk-width-1-1" type="button" value="Cancel" id="cancel">Cancel</a>
- </div>
- <div class="uk-width-1-2">
- <input class="uk-button uk-button-secondary uk-width-1-1" type="submit" id="delete" value="Delete" />
- </div>
+ <form uk-grid class="uk-grid-small" action="{{ url_for("wiki.delete", page=page) }}" method="post">
+ <div class="uk-width-1-2">
+ <a href="{{ url_for("wiki.page", page=page) }}" class="uk-button uk-button-primary uk-width-1-1" type="button" id="cancel">Cancel</a>
+ </div>
+ <div class="uk-width-1-2">
+ <input class="uk-button uk-button-secondary uk-width-1-1" type="submit" id="delete" value="Delete" />
+ </div>
- <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
- </form>
+ <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
+ </form>
+ </div>
</div>
{% endblock %}
diff --git a/templates/wiki/page_move.html b/templates/wiki/page_move.html
new file mode 100644
index 00000000..e2d52807
--- /dev/null
+++ b/templates/wiki/page_move.html
@@ -0,0 +1,26 @@
+{% extends "wiki/base.html" %}
+{% block title %}Wiki | Move: {{ page }}{% endblock %}
+{% block og_title %}Wiki | Move: {{ page }}{% endblock %}
+{% block og_description %}{% endblock %}
+{% block content %}
+ <div class="uk-container uk-container-small">
+ {% if message is defined %}
+ <div uk-alert class="uk-alert-danger">
+ <p>{{ message }}</p>
+ </div>
+ {% endif %}
+
+ <h3>Move Page: {{ page }}</h3>
+ <form uk-grid class="uk-grid-small" action="{{ url_for("wiki.move", page=page) }}" method="post">
+ <input type="text" class="uk-width-1-1 uk-input" placeholder="{{ page }}" id="location" name="location" style="margin-left: 15px;" required>
+ <div class="uk-width-1-2">
+ <a href="{{ url_for("wiki.page", page=page) }}" class="uk-button uk-button-primary uk-width-1-1" type="button" id="cancel">Cancel</a>
+ </div>
+ <div class="uk-width-1-2">
+ <input class="uk-button uk-button-secondary uk-width-1-1" type="submit" id="move" value="Move" />
+ </div>
+
+ <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
+ </form>
+ </div>
+{% endblock %}