diff options
-rw-r--r-- | Pipfile | 4 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | docker/Dockerfile.base | 2 | ||||
-rw-r--r-- | pysite/database/table_init/hiphopify_namelist.json | 4 | ||||
-rw-r--r-- | pysite/views/wiki/delete.py | 67 | ||||
-rw-r--r-- | pysite/views/wiki/history/compare.py | 4 | ||||
-rw-r--r-- | pysite/views/wiki/special/__init__.py | 1 | ||||
-rw-r--r-- | pysite/views/wiki/special/all_pages.py | 27 | ||||
-rw-r--r-- | pysite/views/wiki/special/index.py | 10 | ||||
-rw-r--r-- | static/style.css | 2 | ||||
-rw-r--r-- | templates/wiki/base.html | 105 | ||||
-rw-r--r-- | templates/wiki/page_delete.html | 26 | ||||
-rw-r--r-- | templates/wiki/page_edit.html | 2 | ||||
-rw-r--r-- | templates/wiki/special.html | 17 | ||||
-rw-r--r-- | templates/wiki/special_all.html | 26 |
15 files changed, 247 insertions, 52 deletions
@@ -41,3 +41,7 @@ start = "gunicorn -w 12 -b 0.0.0.0:10012 -c gunicorn_config.py --log-level info lint = "python -m flake8" test = "py.test app_test.py --cov pysite --cov-report term-missing -v" clean = "rm -rf __pycache__ htmlcov .coverage .pytest_cache" +build = "docker build -t pythondiscord/site:latest -f docker/Dockerfile ." +push = "docker push pythondiscord/site:latest" +buildbase = "docker build -t pythondiscord/site-base:latest -f docker/Dockerfile.base ." +pushbase = "docker push pythondiscord/site-base:latest" @@ -1,6 +1,6 @@ # Python Discord website -[](https://travis-ci.org/discord-python/site) [](https://coveralls.io/github/discord-python/site?branch=master) +[](https://travis-ci.org/discord-python/site) [](https://coveralls.io/github/discord-python/site?branch=master) [](https://discord.gg/2B963hn) ### See the wiki for details diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index 87c6fd73..a09a04e8 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -1,4 +1,4 @@ -FROM python:3.6-alpine +FROM python:3.6-alpine3.7 RUN apk add --update tini RUN apk add --update git diff --git a/pysite/database/table_init/hiphopify_namelist.json b/pysite/database/table_init/hiphopify_namelist.json index 28d6242a..6d90a4a2 100644 --- a/pysite/database/table_init/hiphopify_namelist.json +++ b/pysite/database/table_init/hiphopify_namelist.json @@ -1977,7 +1977,7 @@ }, { "name": "Isaiah Rashad", - "image_url": "http://www.rehabonlinemag.com/wp-content/uploads/2015/09/5854_12.jpg" + "image_url": "http://okp-cdn.okayplayer.com/wp-content/uploads/2014/06/xxl-freshman-2014-cypher-drama-cannon-lead.jpg" }, { "name": "Iyanya", @@ -2777,7 +2777,7 @@ }, { "name": "Lloyd Banks", - "image_url": "http://www.streetgangs.com/wp-content/uploads/2010/01/promoter2.jpg" + "image_url": "https://www.bet.com/music/2018/03/17/lloyd-banks/_jcr_content/image.large2x1image.dimg/__1521337827454__1521335807971/031718-music-lloyd-banks.jpg" }, { "name": "Locksmith", diff --git a/pysite/views/wiki/delete.py b/pysite/views/wiki/delete.py new file mode 100644 index 00000000..0e3bcbbf --- /dev/null +++ b/pysite/views/wiki/delete.py @@ -0,0 +1,67 @@ +import datetime + +import requests +from flask import redirect, url_for +from werkzeug.exceptions import NotFound + +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 EditView(RouteView, DBMixin): + path = "/delete/<path:page>" # "path" means that it accepts slashes + name = "delete" + 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_delete.html", page=page, title=title) + else: + raise NotFound() + + @require_roles(*EDITOR_ROLES) + @csrf + def post(self, page): + obj = self.db.get(self.table_name, page) + + if not obj: + raise NotFound() + + self.db.delete(self.table_name, page) + self.db.delete(self.revision_table_name, page) + + self.audit_log(obj) + + return redirect(url_for("wiki.page", page="home"), 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 Deletion", + "description": f"**{obj['title']}** was deleted by **{self.user_data.get('username')}**", + "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/pysite/views/wiki/history/compare.py b/pysite/views/wiki/history/compare.py index 6296f734..6411ab30 100644 --- a/pysite/views/wiki/history/compare.py +++ b/pysite/views/wiki/history/compare.py @@ -50,7 +50,9 @@ class CompareView(RouteView, DBMixin): diff = highlight(diff, DiffLexer(), HtmlFormatter()) return self.render("wiki/compare_revision.html", title=after["post"]["title"], - diff=diff, slug=before["slug"], + page=before["slug"], + diff=diff, + slug=before["slug"], can_edit=self.is_staff()) def is_staff(self): diff --git a/pysite/views/wiki/special/__init__.py b/pysite/views/wiki/special/__init__.py new file mode 100644 index 00000000..9bad5790 --- /dev/null +++ b/pysite/views/wiki/special/__init__.py @@ -0,0 +1 @@ +# coding=utf-8 diff --git a/pysite/views/wiki/special/all_pages.py b/pysite/views/wiki/special/all_pages.py new file mode 100644 index 00000000..d2e02a72 --- /dev/null +++ b/pysite/views/wiki/special/all_pages.py @@ -0,0 +1,27 @@ +from pysite.base_route import RouteView +from pysite.mixins import DBMixin + + +class PageView(RouteView, DBMixin): + path = "/special/all_pages" + name = "special.all_pages" + table_name = "wiki" + + def get(self): + pages = self.db.pluck(self.table_name, "title", "slug") + pages = sorted(pages, key=lambda d: d.get("title", "No Title")) + + letters = {} + + for page in pages: + if "title" not in page: + page["title"] = "No Title" + + letter = page["title"][0].upper() + + if letter not in letters: + letters[letter] = [] + + letters[letter].append(page) + + return self.render("wiki/special_all.html", letters=letters) diff --git a/pysite/views/wiki/special/index.py b/pysite/views/wiki/special/index.py new file mode 100644 index 00000000..15c0a649 --- /dev/null +++ b/pysite/views/wiki/special/index.py @@ -0,0 +1,10 @@ +from pysite.base_route import RouteView +from pysite.mixins import DBMixin + + +class PageView(RouteView, DBMixin): + path = "/special" + name = "special" + + def get(self): + return self.render("wiki/special.html") diff --git a/static/style.css b/static/style.css index fd182b03..78f2663b 100644 --- a/static/style.css +++ b/static/style.css @@ -140,7 +140,7 @@ img.navbar-logo { } #wiki-nav .uk-nav-divider { - min-width: 7rem; + min-width: 8.0rem; } /* Resource page styling */ diff --git a/templates/wiki/base.html b/templates/wiki/base.html index c6f8deca..eec0ecb8 100644 --- a/templates/wiki/base.html +++ b/templates/wiki/base.html @@ -69,32 +69,48 @@ <li><a href="{{ url_for("wiki.page", page="minecraft") }}"> <i class="uk-icon fas fa-fw fa-cube"></i> Minecraft </a></li> -{# <li class="uk-active"><a href="#">active</a></li>#} -{# <li class="uk-parent">#} -{# <a href="#">Contributing</a>#} -{# <ul class="uk-nav-sub">#} -{# <li><a href="#">Sub item</a></li>#} -{# <li><a href="#">Sub item</a></li>#} -{# </ul>#} -{# </li>#} - <li class="uk-nav-divider"></li> - {% if (can_edit or debug) and current_page != "edit" %} - <li> - <a href="{{ url_for("wiki.edit", page=page) }}"> - <i class="uk-icon fas fa-fw fa-pencil-alt"></i> Edit - </a> - </li> - {% elif current_page == "edit" %} - <li> - <a href="{{ url_for("wiki.page", page=page) }}"> - <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back - </a> - </li> - {% endif %} + {% set ACTIONABLE_PAGES = ["page", "edit", "history.show", "history.compare", "source", "delete"] %} + {% set actionable = current_page in ACTIONABLE_PAGES %} + + {% if actionable %} + <li class="uk-nav-divider"></li> - {% if current_page != "history.show" %} - {% if current_page == "history.compare" %} + {% if current_page == "edit" %} + <li> + <a href="{{ url_for("wiki.page", page=page) }}"> + <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back + </a> + </li> + {% else %} + <li> + <a href="{{ url_for("wiki.edit", page=page) }}"> + <i class="uk-icon fas fa-fw fa-pencil-alt"></i> Edit + </a> + </li> + {% endif %} + + {% if current_page == "delete" %} + <li> + <a href="{{ url_for("wiki.page", page=page) }}"> + <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back + </a> + </li> + {% else %} + <li> + <a href="{{ url_for("wiki.delete", page=page) }}"> + <i class="uk-icon fas fa-fw fa-trash"></i> Delete + </a> + </li> + {% endif %} + + {% if current_page == "history.show" %} + <li> + <a href="{{ url_for("wiki.page", page=page) }}"> + <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back + </a> + </li> + {% elif current_page == "history.compare" %} <li> <a href="{{ url_for("wiki.history.show", page=slug) }}"> <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back @@ -107,30 +123,29 @@ </a> </li> {% endif %} - {% else %} - <li> - <a href="{{ url_for("wiki.page", page=page) }}"> - <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back - </a> - </li> - {% endif %} - - {% if current_page != "source" %} - <li> - <a href="{{ url_for("wiki.source", page=page) }}"> - <i class="uk-icon fas fa-fw fa-code"></i> Source - </a> - </li> - {% else %} - <li> - <a href="{{ url_for("wiki.page", page=page) }}"> - <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back - </a> - </li> + {% if current_page == "source" %} + <li> + <a href="{{ url_for("wiki.page", page=page) }}"> + <i class="uk-icon fas fa-fw fa-arrow-left"></i> Back + </a> + </li> + {% else %} + <li> + <a href="{{ url_for("wiki.source", page=page) }}"> + <i class="uk-icon fas fa-fw fa-code"></i> Source + </a> + </li> + {% endif %} {% endif %} + <li class="uk-nav-divider"></li> - <li><a href="{{ url_for("wiki.page", page="help") }}"><i class="fas fa-fw fa-question-circle"></i> Help</a></li> + <li><a href="{{ url_for("wiki.special") }}"> + <i class="uk-icon fas fa-fw fa-ellipsis-h"></i> Special Pages + </a></li> + <li><a href="{{ url_for("wiki.page", page="help") }}"> + <i class="fas fa-fw fa-question-circle"></i> Help + </a></li> </ul> </div> <div class="uk-section" style="flex-grow: 1; margin: 0 1rem 1rem;"> diff --git a/templates/wiki/page_delete.html b/templates/wiki/page_delete.html new file mode 100644 index 00000000..f4d52653 --- /dev/null +++ b/templates/wiki/page_delete.html @@ -0,0 +1,26 @@ +{% extends "wiki/base.html" %} +{% 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> + + <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> + + <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> + </form> + </div> +{% endblock %} diff --git a/templates/wiki/page_edit.html b/templates/wiki/page_edit.html index a2d709e2..51ce70db 100644 --- a/templates/wiki/page_edit.html +++ b/templates/wiki/page_edit.html @@ -1,7 +1,7 @@ {% extends "wiki/base.html" %} {% block title %}Wiki | Edit: {{ page }}{% endblock %} {% block og_title %}Wiki | Edit: {{ page }}{% endblock %} -{% block og_description %}Landing page for the wiki{% 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 %} diff --git a/templates/wiki/special.html b/templates/wiki/special.html new file mode 100644 index 00000000..12e9cb18 --- /dev/null +++ b/templates/wiki/special.html @@ -0,0 +1,17 @@ +{% extends "wiki/base.html" %} +{% block title %}Wiki | Special Pages{% endblock %} +{% block og_title %}Wiki | Special Pages{% endblock %} +{% block og_description %}Wiki special pages, non-article informational pages{% endblock %} +{% block content %} + <div class="uk-container uk-container-small"> + <h2 class="uk-title"> + Special Pages + </h2> + + <ul> + <li><a href="{{ url_for("wiki.special.all_pages") }}"> + Special: All Pages + </a></li> + </ul> + </div> +{% endblock %}
\ No newline at end of file diff --git a/templates/wiki/special_all.html b/templates/wiki/special_all.html new file mode 100644 index 00000000..92aa12a4 --- /dev/null +++ b/templates/wiki/special_all.html @@ -0,0 +1,26 @@ +{% extends "wiki/base.html" %} +{% block title %}Wiki | Special: All Pages{% endblock %} +{% block og_title %}Wiki | Special: All Pages{% endblock %} +{% block og_description %}A listing for all pages on the wiki{% endblock %} +{% block content %} + <div class="uk-container uk-container-small"> + <h2 class="uk-title"> + Special: All Pages + </h2> + <p class="uk-text-meta"> + A listing for all pages on the wiki + </p> + + {% for letter, pages in letters.items() %} + <h3 class="uk-heading-divider">{{ letter }}</h3> + + <ul> + {% for page in pages %} + <li><a href="{{ url_for("wiki.page", page=page.slug) }}"> + {{ page.title }} (<span style="font-family: monospace;">{{ page.slug }}</span>) + </a></li> + {% endfor %} + </ul> + {% endfor %} + </div> +{% endblock %}
\ No newline at end of file |