2023-08-14 22:48:50 +02:00
|
|
|
# ContentDB
|
|
|
|
# Copyright (C) 2023 rubenwardy
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU Affero General Public License for more details.
|
|
|
|
#
|
|
|
|
# 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/>.
|
|
|
|
|
|
|
|
import datetime
|
|
|
|
|
2023-08-20 22:47:20 +02:00
|
|
|
from flask import url_for, current_app
|
2023-08-14 22:48:50 +02:00
|
|
|
|
|
|
|
from . import db, Permission, User, UserRank
|
|
|
|
|
|
|
|
|
|
|
|
class CollectionPackage(db.Model):
|
|
|
|
package_id = db.Column(db.Integer, db.ForeignKey("package.id"), primary_key=True)
|
|
|
|
package = db.relationship("Package", foreign_keys=[package_id])
|
|
|
|
|
|
|
|
collection_id = db.Column(db.Integer, db.ForeignKey("collection.id"), primary_key=True)
|
|
|
|
collection = db.relationship("Collection", back_populates="items", foreign_keys=[collection_id])
|
|
|
|
|
|
|
|
order = db.Column(db.Integer, nullable=False, default=0)
|
|
|
|
description = db.Column(db.String, nullable=True)
|
|
|
|
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
|
|
|
|
|
|
|
|
collection_description_nonempty = db.CheckConstraint("description = NULL OR description != ''")
|
|
|
|
|
2023-08-20 22:47:20 +02:00
|
|
|
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(),
|
|
|
|
}
|
|
|
|
|
2023-08-14 22:48:50 +02:00
|
|
|
|
|
|
|
class Collection(db.Model):
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
|
|
|
|
|
author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
|
|
|
|
author = db.relationship("User", back_populates="collections", foreign_keys=[author_id])
|
|
|
|
|
|
|
|
name = db.Column(db.Unicode(100), nullable=False)
|
|
|
|
title = db.Column(db.Unicode(100), nullable=False)
|
|
|
|
short_description = db.Column(db.Unicode(200), nullable=False)
|
2023-08-19 03:43:38 +02:00
|
|
|
long_description = db.Column(db.UnicodeText, nullable=True)
|
2023-08-14 22:48:50 +02:00
|
|
|
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
|
|
|
|
private = db.Column(db.Boolean, nullable=False, default=False)
|
2023-11-08 00:06:22 +01:00
|
|
|
pinned = db.Column(db.Boolean, nullable=False, default=False)
|
2023-08-14 22:48:50 +02:00
|
|
|
|
|
|
|
packages = db.relationship("Package", secondary=CollectionPackage.__table__, backref="collections")
|
2023-08-20 23:51:21 +02:00
|
|
|
items = db.relationship("CollectionPackage", back_populates="collection", order_by=db.asc("order"),
|
2023-08-14 23:17:29 +02:00
|
|
|
cascade="all, delete, delete-orphan")
|
2023-08-14 22:48:50 +02:00
|
|
|
|
|
|
|
collection_name_valid = db.CheckConstraint("name ~* '^[a-z0-9_]+$' AND name != '_game'")
|
|
|
|
__table_args__ = (db.UniqueConstraint("author_id", "name", name="_collection_uc"),)
|
|
|
|
|
|
|
|
def get_url(self, endpoint, **kwargs):
|
|
|
|
return url_for(endpoint, author=self.author.username, name=self.name, **kwargs)
|
|
|
|
|
2023-08-20 22:47:20 +02:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
2023-08-14 22:48:50 +02:00
|
|
|
def check_perm(self, user: User, perm):
|
|
|
|
if type(perm) == str:
|
|
|
|
perm = Permission[perm]
|
|
|
|
elif type(perm) != Permission:
|
|
|
|
raise Exception("Unknown permission given to Collection.check_perm()")
|
|
|
|
|
2024-03-30 18:46:54 +01:00
|
|
|
if user is None or not user.is_authenticated:
|
2023-08-14 22:48:50 +02:00
|
|
|
return perm == Permission.VIEW_COLLECTION and not self.private
|
|
|
|
|
|
|
|
can_view = not self.private or self.author == user or user.rank.at_least(UserRank.MODERATOR)
|
|
|
|
if perm == Permission.VIEW_COLLECTION:
|
|
|
|
return can_view
|
|
|
|
elif perm == Permission.EDIT_COLLECTION:
|
|
|
|
return can_view and (self.author == user or user.rank.at_least(UserRank.EDITOR))
|
|
|
|
else:
|
|
|
|
raise Exception("Permission {} is not related to collections".format(perm.name))
|