Add Collections API

This commit is contained in:
rubenwardy 2023-08-20 21:47:20 +01:00
parent c0655eb9e2
commit a2ea6573bd
3 changed files with 102 additions and 2 deletions

@ -779,3 +779,43 @@ def hypertext():
html = render_markdown(html) html = render_markdown(html)
return jsonify(html_to_minetest(html, formspec_version, include_images)) return jsonify(html_to_minetest(html, formspec_version, include_images))
@bp.route("/api/collections/")
@cors_allowed
def collection_list():
if "author" in request.args:
user = User.query.filter_by(username=request.args["author"]).one_or_404()
query = user.collections
else:
query = Collection.query.order_by(db.asc(Collection.title))
if "package" in request.args:
id_ = request.args["package"]
package = Package.get_by_key(id_)
if package is None:
error(404, f"Package {id_} not found")
query = query.filter(Collection.packages.contains(package))
collections = [x.as_short_dict() for x in query.all() if not x.private]
return jsonify(collections)
@bp.route("/api/collections/<author>/<name>/")
@cors_allowed
def collection_view(author, name):
collection = Collection.query \
.filter(Collection.name == name, Collection.author.has(username=author)) \
.one_or_404()
if not collection.check_perm(current_user, Permission.VIEW_COLLECTION):
error(404, "Collection not found")
items = collection.items
if collection.check_perm(current_user, Permission.EDIT_COLLECTION):
items = [x for x in items if x.package.check_perm(current_user, Permission.VIEW_PACKAGE)]
ret = collection.as_dict()
ret["items"] = [x.as_dict() for x in items]
return jsonify(ret)

@ -413,6 +413,36 @@ Supported query parameters:
* `show_discarded`: Show topics marked as discarded. * `show_discarded`: Show topics marked as discarded.
* `limit`: Return at most `limit` topics. * `limit`: Return at most `limit` topics.
## Collections
* GET `/api/collections/`
* Query args:
* `author`: collection author username.
* `package`: collections that contain the package.
* Returns JSON array of collection entries:
* `author`: author username.
* `name`: collection name.
* `title`
* `short_description`
* `created_at`: creation time in iso format.
* `private`: whether collection is private, boolean.
* `package_count`: number of packages, integer.
* GET `/api/collections/<username>/<name>/`
* Returns JSON object for collection:
* `author`: author username.
* `name`: collection name.
* `title`
* `short_description`
* `long_description`
* `created_at`: creation time in iso format.
* `private`: whether collection is private, boolean.
* `items`: array of item objects:
* `package`: short info about the package.
* `description`: custom short description.
* `created_at`: when the package was added to the collection.
* `order`: integer.
## Types ## Types
### Tags ### Tags

@ -16,7 +16,7 @@
import datetime import datetime
from flask import url_for from flask import url_for, current_app
from . import db, Permission, User, UserRank from . import db, Permission, User, UserRank
@ -34,6 +34,14 @@ class CollectionPackage(db.Model):
collection_description_nonempty = db.CheckConstraint("description = NULL OR description != ''") collection_description_nonempty = db.CheckConstraint("description = NULL OR description != ''")
def as_dict(self):
return {
"package": self.package.as_short_dict(current_app.config["BASE_URL"]),
"order": self.order,
"description": self.description,
"created_at": self.created_at.isoformat(),
}
class Collection(db.Model): class Collection(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
@ -58,6 +66,28 @@ class Collection(db.Model):
def get_url(self, endpoint, **kwargs): def get_url(self, endpoint, **kwargs):
return url_for(endpoint, author=self.author.username, name=self.name, **kwargs) return url_for(endpoint, author=self.author.username, name=self.name, **kwargs)
def as_short_dict(self):
return {
"author": self.author.username,
"name": self.name,
"title": self.title,
"short_description": self.short_description,
"created_at": self.created_at.isoformat(),
"private": self.private,
"package_count": len(self.packages)
}
def as_dict(self):
return {
"author": self.author.username,
"name": self.name,
"title": self.title,
"short_description": self.short_description,
"long_description": self.long_description,
"created_at": self.created_at.isoformat(),
"private": self.private,
}
def check_perm(self, user: User, perm): def check_perm(self, user: User, perm):
if type(perm) == str: if type(perm) == str:
perm = Permission[perm] perm = Permission[perm]