diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index bfee815..d71b7e0 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -20,7 +20,7 @@ from sqlalchemy.sql.expression import func from app import csrf from app.utils.markdown import render_markdown -from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, MinetestRelease, APIToken, PackageScreenshot, License +from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, MinetestRelease, APIToken, PackageScreenshot, License, ContentWarning from app.querybuilder import QueryBuilder from app.utils import is_package_page from . import bp @@ -317,6 +317,11 @@ def tags(): return jsonify([tag.getAsDictionary() for tag in Tag.query.all() ]) +@bp.route("/api/content_warnings/") +def content_warnings(): + return jsonify([warning.getAsDictionary() for warning in ContentWarning.query.all() ]) + + @bp.route("/api/licenses/") def licenses(): return jsonify([ { "name": license.name, "is_foss": license.is_foss } \ diff --git a/app/flatpages/help/api.md b/app/flatpages/help/api.md index 962c2ed..0d9022c 100644 --- a/app/flatpages/help/api.md +++ b/app/flatpages/help/api.md @@ -63,7 +63,7 @@ Examples: # Edit packages curl -X PUT http://localhost:5123/api/packages/username/name/ \ -H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \ - -d '{ "title": "Foo bar", "tags": ["pvp", "survival"], "license": "wtfpl" }' + -d '{ "title": "Foo bar", "tags": ["pvp", "survival"], "license": "WTFPL" }' # Remove website URL curl -X PUT http://localhost:5123/api/packages/username/name/ \ diff --git a/app/flatpages/help/package_config.md b/app/flatpages/help/package_config.md index c518e89..97d269f 100644 --- a/app/flatpages/help/package_config.md +++ b/app/flatpages/help/package_config.md @@ -38,6 +38,40 @@ and for mods only: * `name` - the mod technical name. + +## .cdb.json + +You can include a `.cdb.json` file in the root of your content directory (ie: next to a .conf) +to update the package meta. + +It should be a JSON dictionary with one or more of the following optional keys. + +* `type`: One of `GAME`, `MOD`, `TXP`. +* `title`: Human-readable title. +* `name`: Technical name (needs permission if already approved). +* `short_description` +* `tags`: List of tag names, see [/api/tags/](/api/tags/). +* `content_Warnings`: List of content warning names, see [/api/content_warnings/](/api/content_warnings/). +* `license`: A license name, see [/api/licenses/](/api/licenses/). +* `media_license`: A license name. +* `desc`: Long markdown description. +* `repo`: Git repo URL. +* `website`: Website URL. +* `issue_tracker`: Issue tracker URL. +* `forums`: forum topic ID. + +Use `null` to unset fields where relevant. + +Example: + +```json +{ + "title": "Foo bar", + "tags": ["pvp", "survival"], + "license": "WTFPL" +} +``` + ## Controlling Release Creation ### Git-based Releases and Submodules diff --git a/app/logic/packages.py b/app/logic/packages.py index c00f290..cf7bd70 100644 --- a/app/logic/packages.py +++ b/app/logic/packages.py @@ -15,11 +15,12 @@ # along with this program. If not, see . -import re, validators +import re +import validators from app.logic.LogicError import LogicError -from app.models import User, Package, PackageType, MetaPackage, Tag, ContentWarning, db, Permission, NotificationType, AuditSeverity, License -from app.utils import addNotification, addAuditLog +from app.models import User, Package, PackageType, MetaPackage, Tag, ContentWarning, db, Permission, AuditSeverity, License +from app.utils import addAuditLog def check(cond: bool, msg: str): @@ -152,9 +153,6 @@ def do_edit_package(user: User, package: Package, was_new: bool, data: dict, rea else: msg = "Edited {} ({})".format(package.title, reason) - addNotification(package.maintainers, user, NotificationType.PACKAGE_EDIT, - msg, package.getDetailsURL(), package) - severity = AuditSeverity.NORMAL if user in package.maintainers else AuditSeverity.EDITOR addAuditLog(severity, user, msg, package.getDetailsURL(), package) diff --git a/app/models/packages.py b/app/models/packages.py index 9e743a7..499757d 100644 --- a/app/models/packages.py +++ b/app/models/packages.py @@ -727,6 +727,10 @@ class ContentWarning(db.Model): regex = re.compile("[^a-z_]") self.name = regex.sub("", self.title.lower().replace(" ", "_")) + def getAsDictionary(self): + description = self.description if self.description != "" else None + return { "name": self.name, "title": self.title, "description": description } + class Tag(db.Model): id = db.Column(db.Integer, primary_key=True) diff --git a/app/tasks/importtasks.py b/app/tasks/importtasks.py index aeee25e..86a70a9 100644 --- a/app/tasks/importtasks.py +++ b/app/tasks/importtasks.py @@ -13,8 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - - +import json import os, shutil, gitdb from zipfile import ZipFile from git import GitCommandError @@ -23,9 +22,11 @@ from kombu import uuid from app.models import * from app.tasks import celery, TaskError -from app.utils import randomString, post_bot_message, addSystemNotification, addSystemAuditLog +from app.utils import randomString, post_bot_message, addSystemNotification, addSystemAuditLog, get_system_user from app.utils.git import clone_repo, get_latest_tag, get_latest_commit, get_temp_dir from .minetestcheck import build_tree, MinetestCheckError, ContentType +from ..logic.LogicError import LogicError +from ..logic.packages import do_edit_package @celery.task() @@ -90,13 +91,21 @@ def postReleaseCheckUpdate(self, release, path): db.session.add(Dependency(package, meta=meta, optional=True)) # Update min/max - if tree.meta.get("min_minetest_version"): release.min_rel = MinetestRelease.get(tree.meta["min_minetest_version"], None) if tree.meta.get("max_minetest_version"): release.max_rel = MinetestRelease.get(tree.meta["max_minetest_version"], None) + try: + with open(os.path.join(tree.baseDir, ".cdb.json"), "r") as f: + data = json.loads(f.read()) + do_edit_package(package.author, package, False, data, "Post release hook") + except LogicError as e: + raise TaskError(e.message) + except IOError: + pass + return tree except MinetestCheckError as err: diff --git a/app/utils/models.py b/app/utils/models.py index 8fb07b9..d11f359 100644 --- a/app/utils/models.py +++ b/app/utils/models.py @@ -85,23 +85,23 @@ def clearNotifications(url): Notification.query.filter_by(user=current_user, url=url).delete() db.session.commit() -def addSystemNotification(target, type: NotificationType, title: str, url: str, package: Package = None): + +def get_system_user(): system_user = User.query.filter_by(username="ContentDB").first() assert system_user + return system_user - return addNotification(target, system_user, type, title, url, package) + +def addSystemNotification(target, type: NotificationType, title: str, url: str, package: Package = None): + return addNotification(target, get_system_user(), type, title, url, package) def addSystemAuditLog(severity: AuditSeverity, title: str, url: str, package=None, description=None): - system_user = User.query.filter_by(username="ContentDB").first() - assert system_user - - return addAuditLog(severity, system_user, title, url, package, description) + return addAuditLog(severity, get_system_user(), title, url, package, description) def post_bot_message(package: Package, title: str, message: str): - system_user = User.query.filter_by(username="ContentDB").first() - assert system_user + system_user = get_system_user() thread = package.threads.filter_by(author=system_user).first() if not thread: