mirror of
https://github.com/minetest/contentdb.git
synced 2025-01-03 11:47:28 +01:00
Clean up admin blueprint
This commit is contained in:
parent
cb2d9d4b07
commit
e2708933d3
@ -20,10 +20,11 @@ from typing import List
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
from celery import group
|
from celery import group
|
||||||
from flask import *
|
from flask import redirect, url_for, flash, current_app
|
||||||
from sqlalchemy import or_, and_
|
from sqlalchemy import or_, and_
|
||||||
|
|
||||||
from app.models import *
|
from app.models import PackageRelease, db, Package, PackageState, PackageScreenshot, MetaPackage, User, \
|
||||||
|
NotificationType, PackageUpdateConfig, License, UserRank, PackageType
|
||||||
from app.tasks.forumtasks import importTopicList, checkAllForumAccounts
|
from app.tasks.forumtasks import importTopicList, checkAllForumAccounts
|
||||||
from app.tasks.importtasks import importRepoScreenshot, checkZipRelease, check_for_updates
|
from app.tasks.importtasks import importRepoScreenshot, checkZipRelease, check_for_updates
|
||||||
from app.utils import addNotification, get_system_user
|
from app.utils import addNotification, get_system_user
|
||||||
@ -31,6 +32,7 @@ from app.utils.image import get_image_size
|
|||||||
|
|
||||||
actions = {}
|
actions = {}
|
||||||
|
|
||||||
|
|
||||||
def action(title: str):
|
def action(title: str):
|
||||||
def func(f):
|
def func(f):
|
||||||
name = f.__name__
|
name = f.__name__
|
||||||
@ -43,13 +45,15 @@ def action(title: str):
|
|||||||
|
|
||||||
return func
|
return func
|
||||||
|
|
||||||
|
|
||||||
@action("Delete stuck releases")
|
@action("Delete stuck releases")
|
||||||
def del_stuck_releases():
|
def del_stuck_releases():
|
||||||
PackageRelease.query.filter(PackageRelease.task_id != None).delete()
|
PackageRelease.query.filter(PackageRelease.task_id.isnot(None)).delete()
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for("admin.admin_page"))
|
return redirect(url_for("admin.admin_page"))
|
||||||
|
|
||||||
@action("Check releases")
|
|
||||||
|
@action("Check ZIP releases")
|
||||||
def check_releases():
|
def check_releases():
|
||||||
releases = PackageRelease.query.filter(PackageRelease.url.like("/uploads/%")).all()
|
releases = PackageRelease.query.filter(PackageRelease.url.like("/uploads/%")).all()
|
||||||
|
|
||||||
@ -65,10 +69,11 @@ def check_releases():
|
|||||||
|
|
||||||
return redirect(url_for("todo.view_editor"))
|
return redirect(url_for("todo.view_editor"))
|
||||||
|
|
||||||
@action("Reimport packages")
|
|
||||||
|
@action("Check the first release of all packages")
|
||||||
def reimport_packages():
|
def reimport_packages():
|
||||||
tasks = []
|
tasks = []
|
||||||
for package in Package.query.filter(Package.state!=PackageState.DELETED).all():
|
for package in Package.query.filter(Package.state != PackageState.DELETED).all():
|
||||||
release = package.releases.first()
|
release = package.releases.first()
|
||||||
if release:
|
if release:
|
||||||
tasks.append(checkZipRelease.s(release.id, release.file_path))
|
tasks.append(checkZipRelease.s(release.id, release.file_path))
|
||||||
@ -81,42 +86,46 @@ def reimport_packages():
|
|||||||
|
|
||||||
return redirect(url_for("todo.view_editor"))
|
return redirect(url_for("todo.view_editor"))
|
||||||
|
|
||||||
@action("Import topic list")
|
|
||||||
|
@action("Import forum topic list")
|
||||||
def import_topic_list():
|
def import_topic_list():
|
||||||
task = importTopicList.delay()
|
task = importTopicList.delay()
|
||||||
return redirect(url_for("tasks.check", id=task.id, r=url_for("todo.topics")))
|
return redirect(url_for("tasks.check", id=task.id, r=url_for("todo.topics")))
|
||||||
|
|
||||||
|
|
||||||
@action("Check all forum accounts")
|
@action("Check all forum accounts")
|
||||||
def check_all_forum_accounts():
|
def check_all_forum_accounts():
|
||||||
task = checkAllForumAccounts.delay()
|
task = checkAllForumAccounts.delay()
|
||||||
return redirect(url_for("tasks.check", id=task.id, r=url_for("admin.admin_page")))
|
return redirect(url_for("tasks.check", id=task.id, r=url_for("admin.admin_page")))
|
||||||
|
|
||||||
|
|
||||||
@action("Import screenshots")
|
@action("Import screenshots")
|
||||||
def import_screenshots():
|
def import_screenshots():
|
||||||
packages = Package.query \
|
packages = Package.query \
|
||||||
.filter(Package.state!=PackageState.DELETED) \
|
.filter(Package.state != PackageState.DELETED) \
|
||||||
.outerjoin(PackageScreenshot, Package.id==PackageScreenshot.package_id) \
|
.outerjoin(PackageScreenshot, Package.id == PackageScreenshot.package_id) \
|
||||||
.filter(PackageScreenshot.id==None) \
|
.filter(PackageScreenshot.id.is_(None)) \
|
||||||
.all()
|
.all()
|
||||||
for package in packages:
|
for package in packages:
|
||||||
importRepoScreenshot.delay(package.id)
|
importRepoScreenshot.delay(package.id)
|
||||||
|
|
||||||
return redirect(url_for("admin.admin_page"))
|
return redirect(url_for("admin.admin_page"))
|
||||||
|
|
||||||
@action("Clean uploads")
|
|
||||||
|
@action("Remove unused uploads")
|
||||||
def clean_uploads():
|
def clean_uploads():
|
||||||
upload_dir = app.config['UPLOAD_DIR']
|
upload_dir = current_app.config['UPLOAD_DIR']
|
||||||
|
|
||||||
(_, _, filenames) = next(os.walk(upload_dir))
|
(_, _, filenames) = next(os.walk(upload_dir))
|
||||||
existing_uploads = set(filenames)
|
existing_uploads = set(filenames)
|
||||||
|
|
||||||
if len(existing_uploads) != 0:
|
if len(existing_uploads) != 0:
|
||||||
def getURLsFromDB(column):
|
def get_filenames_from_column(column):
|
||||||
results = db.session.query(column).filter(column != None, column != "").all()
|
results = db.session.query(column).filter(column.isnot(None), column != "").all()
|
||||||
return set([os.path.basename(x[0]) for x in results])
|
return set([os.path.basename(x[0]) for x in results])
|
||||||
|
|
||||||
release_urls = getURLsFromDB(PackageRelease.url)
|
release_urls = get_filenames_from_column(PackageRelease.url)
|
||||||
screenshot_urls = getURLsFromDB(PackageScreenshot.url)
|
screenshot_urls = get_filenames_from_column(PackageScreenshot.url)
|
||||||
|
|
||||||
db_urls = release_urls.union(screenshot_urls)
|
db_urls = release_urls.union(screenshot_urls)
|
||||||
unreachable = existing_uploads.difference(db_urls)
|
unreachable = existing_uploads.difference(db_urls)
|
||||||
@ -135,7 +144,8 @@ def clean_uploads():
|
|||||||
|
|
||||||
return redirect(url_for("admin.admin_page"))
|
return redirect(url_for("admin.admin_page"))
|
||||||
|
|
||||||
@action("Delete metapackages")
|
|
||||||
|
@action("Delete unused metapackages")
|
||||||
def del_meta_packages():
|
def del_meta_packages():
|
||||||
query = MetaPackage.query.filter(~MetaPackage.dependencies.any(), ~MetaPackage.packages.any())
|
query = MetaPackage.query.filter(~MetaPackage.dependencies.any(), ~MetaPackage.packages.any())
|
||||||
count = query.count()
|
count = query.count()
|
||||||
@ -145,6 +155,7 @@ def del_meta_packages():
|
|||||||
flash("Deleted " + str(count) + " unused meta packages", "success")
|
flash("Deleted " + str(count) + " unused meta packages", "success")
|
||||||
return redirect(url_for("admin.admin_page"))
|
return redirect(url_for("admin.admin_page"))
|
||||||
|
|
||||||
|
|
||||||
@action("Delete removed packages")
|
@action("Delete removed packages")
|
||||||
def del_removed_packages():
|
def del_removed_packages():
|
||||||
query = Package.query.filter_by(state=PackageState.DELETED)
|
query = Package.query.filter_by(state=PackageState.DELETED)
|
||||||
@ -157,24 +168,6 @@ def del_removed_packages():
|
|||||||
flash("Deleted {} soft deleted packages packages".format(count), "success")
|
flash("Deleted {} soft deleted packages packages".format(count), "success")
|
||||||
return redirect(url_for("admin.admin_page"))
|
return redirect(url_for("admin.admin_page"))
|
||||||
|
|
||||||
@action("Add update config")
|
|
||||||
def add_update_config():
|
|
||||||
added = 0
|
|
||||||
for pkg in Package.query.filter(Package.repo != None, Package.releases.any(), Package.update_config == None).all():
|
|
||||||
pkg.update_config = PackageUpdateConfig()
|
|
||||||
pkg.update_config.auto_created = True
|
|
||||||
|
|
||||||
release: PackageRelease = pkg.releases.first()
|
|
||||||
if release and release.commit_hash:
|
|
||||||
pkg.update_config.last_commit = release.commit_hash
|
|
||||||
|
|
||||||
db.session.add(pkg.update_config)
|
|
||||||
added += 1
|
|
||||||
|
|
||||||
db.session.commit()
|
|
||||||
|
|
||||||
flash("Added {} update configs".format(added), "success")
|
|
||||||
return redirect(url_for("admin.admin_page"))
|
|
||||||
|
|
||||||
@action("Run update configs")
|
@action("Run update configs")
|
||||||
def run_update_config():
|
def run_update_config():
|
||||||
@ -183,6 +176,7 @@ def run_update_config():
|
|||||||
flash("Started update configs", "success")
|
flash("Started update configs", "success")
|
||||||
return redirect(url_for("admin.admin_page"))
|
return redirect(url_for("admin.admin_page"))
|
||||||
|
|
||||||
|
|
||||||
def _package_list(packages: List[str]):
|
def _package_list(packages: List[str]):
|
||||||
# Who needs translations?
|
# Who needs translations?
|
||||||
if len(packages) >= 3:
|
if len(packages) >= 3:
|
||||||
@ -192,14 +186,15 @@ def _package_list(packages: List[str]):
|
|||||||
packages_list = " and ".join(packages)
|
packages_list = " and ".join(packages)
|
||||||
return packages_list
|
return packages_list
|
||||||
|
|
||||||
|
|
||||||
@action("Send WIP package notification")
|
@action("Send WIP package notification")
|
||||||
def remind_wip():
|
def remind_wip():
|
||||||
users = User.query.filter(User.packages.any(or_(Package.state==PackageState.WIP, Package.state==PackageState.CHANGES_NEEDED)))
|
users = User.query.filter(User.packages.any(or_(Package.state == PackageState.WIP, Package.state == PackageState.CHANGES_NEEDED)))
|
||||||
system_user = get_system_user()
|
system_user = get_system_user()
|
||||||
for user in users:
|
for user in users:
|
||||||
packages = db.session.query(Package.title).filter(
|
packages = db.session.query(Package.title).filter(
|
||||||
Package.author_id==user.id,
|
Package.author_id == user.id,
|
||||||
or_(Package.state==PackageState.WIP, Package.state==PackageState.CHANGES_NEEDED)) \
|
or_(Package.state == PackageState.WIP, Package.state==PackageState.CHANGES_NEEDED)) \
|
||||||
.all()
|
.all()
|
||||||
|
|
||||||
packages = [pkg[0] for pkg in packages]
|
packages = [pkg[0] for pkg in packages]
|
||||||
@ -213,6 +208,7 @@ def remind_wip():
|
|||||||
url_for('todo.view_user', username=user.username))
|
url_for('todo.view_user', username=user.username))
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
@action("Send outdated package notification")
|
@action("Send outdated package notification")
|
||||||
def remind_outdated():
|
def remind_outdated():
|
||||||
users = User.query.filter(User.maintained_packages.any(
|
users = User.query.filter(User.maintained_packages.any(
|
||||||
@ -233,6 +229,7 @@ def remind_outdated():
|
|||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
|
||||||
@action("Import licenses from SPDX")
|
@action("Import licenses from SPDX")
|
||||||
def import_licenses():
|
def import_licenses():
|
||||||
renames = {
|
renames = {
|
||||||
@ -283,7 +280,8 @@ def import_licenses():
|
|||||||
|
|
||||||
@action("Delete inactive users")
|
@action("Delete inactive users")
|
||||||
def delete_inactive_users():
|
def delete_inactive_users():
|
||||||
users = User.query.filter(User.is_active==False, User.packages==None, User.forum_topics==None, User.rank==UserRank.NOT_JOINED).all()
|
users = User.query.filter(User.is_active == False, User.packages.is_(None), User.forum_topics.is_(None),
|
||||||
|
User.rank == UserRank.NOT_JOINED).all()
|
||||||
for user in users:
|
for user in users:
|
||||||
db.session.delete(user)
|
db.session.delete(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@ -313,7 +311,7 @@ def remind_video_url():
|
|||||||
|
|
||||||
|
|
||||||
@action("Update screenshot sizes")
|
@action("Update screenshot sizes")
|
||||||
def remind_video_url():
|
def update_screenshot_sizes():
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
for screenshot in PackageScreenshot.query.all():
|
for screenshot in PackageScreenshot.query.all():
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from flask import *
|
from flask import redirect, render_template, url_for, request, flash
|
||||||
from flask_login import current_user, login_user
|
from flask_login import current_user, login_user
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import *
|
from wtforms import StringField, SubmitField
|
||||||
from wtforms.validators import InputRequired, Length
|
from wtforms.validators import InputRequired, Length
|
||||||
from app.utils import rank_required, addAuditLog, addNotification, get_system_user
|
from app.utils import rank_required, addAuditLog, addNotification, get_system_user
|
||||||
from . import bp
|
from . import bp
|
||||||
@ -48,9 +48,10 @@ def admin_page():
|
|||||||
else:
|
else:
|
||||||
flash("Unknown action: " + action, "danger")
|
flash("Unknown action: " + action, "danger")
|
||||||
|
|
||||||
deleted_packages = Package.query.filter(Package.state==PackageState.DELETED).all()
|
deleted_packages = Package.query.filter(Package.state == PackageState.DELETED).all()
|
||||||
return render_template("admin/list.html", deleted_packages=deleted_packages, actions=actions)
|
return render_template("admin/list.html", deleted_packages=deleted_packages, actions=actions)
|
||||||
|
|
||||||
|
|
||||||
class SwitchUserForm(FlaskForm):
|
class SwitchUserForm(FlaskForm):
|
||||||
username = StringField("Username")
|
username = StringField("Username")
|
||||||
submit = SubmitField("Switch")
|
submit = SubmitField("Switch")
|
||||||
@ -69,14 +70,13 @@ def switch_user():
|
|||||||
else:
|
else:
|
||||||
flash("Unable to login as user", "danger")
|
flash("Unable to login as user", "danger")
|
||||||
|
|
||||||
|
|
||||||
# Process GET or invalid POST
|
# Process GET or invalid POST
|
||||||
return render_template("admin/switch_user.html", form=form)
|
return render_template("admin/switch_user.html", form=form)
|
||||||
|
|
||||||
|
|
||||||
class SendNotificationForm(FlaskForm):
|
class SendNotificationForm(FlaskForm):
|
||||||
title = StringField("Title", [InputRequired(), Length(1, 300)])
|
title = StringField("Title", [InputRequired(), Length(1, 300)])
|
||||||
url = StringField("URL", [InputRequired(), Length(1, 100)], default="/")
|
url = StringField("URL", [InputRequired(), Length(1, 100)], default="/")
|
||||||
submit = SubmitField("Send")
|
submit = SubmitField("Send")
|
||||||
|
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ def send_bulk_notification():
|
|||||||
form = SendNotificationForm(request.form)
|
form = SendNotificationForm(request.form)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
addAuditLog(AuditSeverity.MODERATION, current_user,
|
addAuditLog(AuditSeverity.MODERATION, current_user,
|
||||||
"Sent bulk notification", None, None, form.title.data)
|
"Sent bulk notification", url_for("admin.admin_page"), None, form.title.data)
|
||||||
|
|
||||||
users = User.query.filter(User.rank >= UserRank.NEW_MEMBER).all()
|
users = User.query.filter(User.rank >= UserRank.NEW_MEMBER).all()
|
||||||
addNotification(users, get_system_user(), NotificationType.OTHER, form.title.data, form.url.data, None)
|
addNotification(users, get_system_user(), NotificationType.OTHER, form.title.data, form.url.data, None)
|
||||||
@ -121,5 +121,10 @@ def restore():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(package.getURL("packages.view"))
|
return redirect(package.getURL("packages.view"))
|
||||||
|
|
||||||
deleted_packages = Package.query.filter(Package.state==PackageState.DELETED).join(Package.author).order_by(db.asc(User.username), db.asc(Package.name)).all()
|
deleted_packages = Package.query \
|
||||||
return render_template("admin/restore.html", deleted_packages=deleted_packages)
|
.filter(Package.state == PackageState.DELETED) \
|
||||||
|
.join(Package.author) \
|
||||||
|
.order_by(db.asc(User.username), db.asc(Package.name)) \
|
||||||
|
.all()
|
||||||
|
|
||||||
|
return render_template("admin/restore.html", deleted_packages=deleted_packages)
|
||||||
|
@ -41,6 +41,6 @@ def audit():
|
|||||||
|
|
||||||
@bp.route("/admin/audit/<int:id>/")
|
@bp.route("/admin/audit/<int:id>/")
|
||||||
@rank_required(UserRank.MODERATOR)
|
@rank_required(UserRank.MODERATOR)
|
||||||
def audit_view(id):
|
def audit_view(id_):
|
||||||
entry = AuditLogEntry.query.get(id)
|
entry = AuditLogEntry.query.get(id_)
|
||||||
return render_template("admin/audit_view.html", entry=entry)
|
return render_template("admin/audit_view.html", entry=entry)
|
||||||
|
@ -14,18 +14,17 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from flask import request, abort, url_for, redirect, render_template, flash
|
||||||
from flask import *
|
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import *
|
from wtforms import TextAreaField, SubmitField, StringField
|
||||||
from wtforms.validators import *
|
from wtforms.validators import InputRequired, Length
|
||||||
|
|
||||||
from app.markdown import render_markdown
|
from app.markdown import render_markdown
|
||||||
from app.models import *
|
|
||||||
from app.tasks.emails import send_user_email
|
from app.tasks.emails import send_user_email
|
||||||
from app.utils import rank_required, addAuditLog
|
from app.utils import rank_required, addAuditLog
|
||||||
from . import bp
|
from . import bp
|
||||||
|
from ...models import UserRank, User, AuditSeverity
|
||||||
|
|
||||||
|
|
||||||
class SendEmailForm(FlaskForm):
|
class SendEmailForm(FlaskForm):
|
||||||
@ -67,11 +66,11 @@ def send_bulk_email():
|
|||||||
form = SendEmailForm(request.form)
|
form = SendEmailForm(request.form)
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
addAuditLog(AuditSeverity.MODERATION, current_user,
|
addAuditLog(AuditSeverity.MODERATION, current_user,
|
||||||
"Sent bulk email", None, None, form.text.data)
|
"Sent bulk email", url_for("admin.admin_page"), None, form.text.data)
|
||||||
|
|
||||||
text = form.text.data
|
text = form.text.data
|
||||||
html = render_markdown(text)
|
html = render_markdown(text)
|
||||||
for user in User.query.filter(User.email != None).all():
|
for user in User.query.filter(User.email.isnot(None)).all():
|
||||||
send_user_email.delay(user.email, user.locale or "en", form.subject.data, text, html)
|
send_user_email.delay(user.email, user.locale or "en", form.subject.data, text, html)
|
||||||
|
|
||||||
return redirect(url_for("admin.admin_page"))
|
return redirect(url_for("admin.admin_page"))
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from flask import *
|
from flask import redirect, render_template, abort, url_for, request, flash
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import *
|
from wtforms import StringField, BooleanField, SubmitField
|
||||||
from wtforms.fields.html5 import URLField
|
from wtforms.fields.html5 import URLField
|
||||||
from wtforms.validators import *
|
from wtforms.validators import InputRequired, Length, Optional
|
||||||
|
|
||||||
from app.models import *
|
|
||||||
from app.utils import rank_required, nonEmptyOrNone
|
from app.utils import rank_required, nonEmptyOrNone
|
||||||
from . import bp
|
from . import bp
|
||||||
|
from ...models import UserRank, License, db
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/licenses/")
|
@bp.route("/licenses/")
|
||||||
@ -31,11 +31,13 @@ from . import bp
|
|||||||
def license_list():
|
def license_list():
|
||||||
return render_template("admin/licenses/list.html", licenses=License.query.order_by(db.asc(License.name)).all())
|
return render_template("admin/licenses/list.html", licenses=License.query.order_by(db.asc(License.name)).all())
|
||||||
|
|
||||||
|
|
||||||
class LicenseForm(FlaskForm):
|
class LicenseForm(FlaskForm):
|
||||||
name = StringField("Name", [InputRequired(), Length(3,100)])
|
name = StringField("Name", [InputRequired(), Length(3, 100)])
|
||||||
is_foss = BooleanField("Is FOSS")
|
is_foss = BooleanField("Is FOSS")
|
||||||
url = URLField("URL", [Optional], filters=[nonEmptyOrNone])
|
url = URLField("URL", [Optional], filters=[nonEmptyOrNone])
|
||||||
submit = SubmitField("Save")
|
submit = SubmitField("Save")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/licenses/new/", methods=["GET", "POST"])
|
@bp.route("/licenses/new/", methods=["GET", "POST"])
|
||||||
@bp.route("/licenses/<name>/edit/", methods=["GET", "POST"])
|
@bp.route("/licenses/<name>/edit/", methods=["GET", "POST"])
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from flask import *
|
from flask import redirect, render_template, abort, url_for, request
|
||||||
from flask_login import current_user, login_required
|
from flask_login import current_user, login_required
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import *
|
from wtforms import StringField, TextAreaField, BooleanField, SubmitField
|
||||||
from wtforms.validators import *
|
from wtforms.validators import InputRequired, Length, Optional, Regexp
|
||||||
|
|
||||||
from app.models import *
|
|
||||||
from . import bp
|
from . import bp
|
||||||
|
from ...models import Permission, Tag, db
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/tags/")
|
@bp.route("/tags/")
|
||||||
@ -40,12 +40,14 @@ def tag_list():
|
|||||||
|
|
||||||
return render_template("admin/tags/list.html", tags=query.all())
|
return render_template("admin/tags/list.html", tags=query.all())
|
||||||
|
|
||||||
|
|
||||||
class TagForm(FlaskForm):
|
class TagForm(FlaskForm):
|
||||||
title = StringField("Title", [InputRequired(), Length(3,100)])
|
title = StringField("Title", [InputRequired(), Length(3, 100)])
|
||||||
description = TextAreaField("Description", [Optional(), Length(0, 500)])
|
description = TextAreaField("Description", [Optional(), Length(0, 500)])
|
||||||
name = StringField("Name", [Optional(), Length(1, 20), Regexp("^[a-z0-9_]", 0, "Lower case letters (a-z), digits (0-9), and underscores (_) only")])
|
name = StringField("Name", [Optional(), Length(1, 20), Regexp("^[a-z0-9_]", 0, "Lower case letters (a-z), digits (0-9), and underscores (_) only")])
|
||||||
is_protected = BooleanField("Is Protected")
|
is_protected = BooleanField("Is Protected")
|
||||||
submit = SubmitField("Save")
|
submit = SubmitField("Save")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/tags/new/", methods=["GET", "POST"])
|
@bp.route("/tags/new/", methods=["GET", "POST"])
|
||||||
@bp.route("/tags/<name>/edit/", methods=["GET", "POST"])
|
@bp.route("/tags/<name>/edit/", methods=["GET", "POST"])
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from flask import *
|
from flask import redirect, render_template, abort, url_for, request, flash
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import *
|
from wtforms import StringField, IntegerField, SubmitField
|
||||||
from wtforms.validators import *
|
from wtforms.validators import InputRequired, Length
|
||||||
|
|
||||||
from app.models import *
|
|
||||||
from app.utils import rank_required
|
from app.utils import rank_required
|
||||||
from . import bp
|
from . import bp
|
||||||
|
from ...models import UserRank, MinetestRelease, db
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/versions/")
|
@bp.route("/versions/")
|
||||||
@ -30,10 +30,12 @@ from . import bp
|
|||||||
def version_list():
|
def version_list():
|
||||||
return render_template("admin/versions/list.html", versions=MinetestRelease.query.order_by(db.asc(MinetestRelease.id)).all())
|
return render_template("admin/versions/list.html", versions=MinetestRelease.query.order_by(db.asc(MinetestRelease.id)).all())
|
||||||
|
|
||||||
|
|
||||||
class VersionForm(FlaskForm):
|
class VersionForm(FlaskForm):
|
||||||
name = StringField("Name", [InputRequired(), Length(3,100)])
|
name = StringField("Name", [InputRequired(), Length(3, 100)])
|
||||||
protocol = IntegerField("Protocol")
|
protocol = IntegerField("Protocol")
|
||||||
submit = SubmitField("Save")
|
submit = SubmitField("Save")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/versions/new/", methods=["GET", "POST"])
|
@bp.route("/versions/new/", methods=["GET", "POST"])
|
||||||
@bp.route("/versions/<name>/edit/", methods=["GET", "POST"])
|
@bp.route("/versions/<name>/edit/", methods=["GET", "POST"])
|
||||||
|
@ -15,14 +15,14 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
from flask import *
|
from flask import redirect, render_template, abort, url_for, request, flash
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import *
|
from wtforms import StringField, TextAreaField, SubmitField
|
||||||
from wtforms.validators import *
|
from wtforms.validators import InputRequired, Length, Optional, Regexp
|
||||||
|
|
||||||
from app.models import *
|
|
||||||
from app.utils import rank_required
|
from app.utils import rank_required
|
||||||
from . import bp
|
from . import bp
|
||||||
|
from ...models import UserRank, ContentWarning, db
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/admin/warnings/")
|
@bp.route("/admin/warnings/")
|
||||||
@ -30,11 +30,14 @@ from . import bp
|
|||||||
def warning_list():
|
def warning_list():
|
||||||
return render_template("admin/warnings/list.html", warnings=ContentWarning.query.order_by(db.asc(ContentWarning.title)).all())
|
return render_template("admin/warnings/list.html", warnings=ContentWarning.query.order_by(db.asc(ContentWarning.title)).all())
|
||||||
|
|
||||||
|
|
||||||
class WarningForm(FlaskForm):
|
class WarningForm(FlaskForm):
|
||||||
title = StringField("Title", [InputRequired(), Length(3,100)])
|
title = StringField("Title", [InputRequired(), Length(3, 100)])
|
||||||
description = TextAreaField("Description", [Optional(), Length(0, 500)])
|
description = TextAreaField("Description", [Optional(), Length(0, 500)])
|
||||||
name = StringField("Name", [Optional(), Length(1, 20), Regexp("^[a-z0-9_]", 0, "Lower case letters (a-z), digits (0-9), and underscores (_) only")])
|
name = StringField("Name", [Optional(), Length(1, 20),
|
||||||
submit = SubmitField("Save")
|
Regexp("^[a-z0-9_]", 0, "Lower case letters (a-z), digits (0-9), and underscores (_) only")])
|
||||||
|
submit = SubmitField("Save")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/admin/warnings/new/", methods=["GET", "POST"])
|
@bp.route("/admin/warnings/new/", methods=["GET", "POST"])
|
||||||
@bp.route("/admin/warnings/<name>/edit/", methods=["GET", "POST"])
|
@bp.route("/admin/warnings/<name>/edit/", methods=["GET", "POST"])
|
||||||
|
Loading…
Reference in New Issue
Block a user