X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=app%2Fmodels.py;h=ade4083594f07c939a65e42c0d75da2c9c7c4b92;hb=bbc89bb2c2a6b74fb36c04659dfe45e75351c58c;hp=3a9ddf491807953539f8943288b8e6836b5411df;hpb=2181e57e428504ee5b8b150fb4aac2b915b7d106;p=cheatdb.git diff --git a/app/models.py b/app/models.py index 3a9ddf4..ade4083 100644 --- a/app/models.py +++ b/app/models.py @@ -1,4 +1,4 @@ -# Content DB +# ContentDB # Copyright (C) 2018 rubenwardy # # This program is free software: you can redistribute it and/or modify @@ -80,6 +80,7 @@ class Permission(enum.Enum): MAKE_RELEASE = "MAKE_RELEASE" DELETE_RELEASE = "DELETE_RELEASE" ADD_SCREENSHOTS = "ADD_SCREENSHOTS" + REIMPORT_META = "REIMPORT_META" APPROVE_SCREENSHOT = "APPROVE_SCREENSHOT" APPROVE_RELEASE = "APPROVE_RELEASE" APPROVE_NEW = "APPROVE_NEW" @@ -90,6 +91,10 @@ class Permission(enum.Enum): EDIT_EDITREQUEST = "EDIT_EDITREQUEST" SEE_THREAD = "SEE_THREAD" CREATE_THREAD = "CREATE_THREAD" + COMMENT_THREAD = "COMMENT_THREAD" + LOCK_THREAD = "LOCK_THREAD" + DELETE_REPLY = "DELETE_REPLY" + EDIT_REPLY = "EDIT_REPLY" UNAPPROVE_PACKAGE = "UNAPPROVE_PACKAGE" TOPIC_DISCARD = "TOPIC_DISCARD" CREATE_TOKEN = "CREATE_TOKEN" @@ -240,23 +245,31 @@ class UserEmailVerification(db.Model): user = db.relationship("User", foreign_keys=[user_id]) class Notification(db.Model): - id = db.Column(db.Integer, primary_key=True) - user_id = db.Column(db.Integer, db.ForeignKey("user.id")) - causer_id = db.Column(db.Integer, db.ForeignKey("user.id")) - user = db.relationship("User", foreign_keys=[user_id]) - causer = db.relationship("User", foreign_keys=[causer_id]) + id = db.Column(db.Integer, primary_key=True) + + user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) + user = db.relationship("User", foreign_keys=[user_id]) + + causer_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) + causer = db.relationship("User", foreign_keys=[causer_id]) + + title = db.Column(db.String(100), nullable=False) + url = db.Column(db.String(200), nullable=True) + + package_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True) + package = db.relationship("Package", foreign_keys=[package_id]) - title = db.Column(db.String(100), nullable=False) - url = db.Column(db.String(200), nullable=True) + created_at = db.Column(db.DateTime, nullable=True, default=datetime.datetime.utcnow) - def __init__(self, us, cau, titl, ur): - if len(titl) > 100: + def __init__(self, user, causer, title, url, package=None): + if len(title) > 100: title = title[:99] + "…" - self.user = us - self.causer = cau - self.title = titl - self.url = ur + self.user = user + self.causer = causer + self.title = title + self.url = url + self.package = package class License(db.Model): @@ -327,7 +340,7 @@ provides = db.Table("provides", db.Column("metapackage_id", db.Integer, db.ForeignKey("meta_package.id"), primary_key=True) ) -tags = db.Table("tags", +Tags = db.Table("tags", db.Column("tag_id", db.Integer, db.ForeignKey("tag.id"), primary_key=True), db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True) ) @@ -346,11 +359,12 @@ class Dependency(db.Model): optional = db.Column(db.Boolean, nullable=False, default=False) __table_args__ = (db.UniqueConstraint("depender_id", "package_id", "meta_package_id", name="_dependency_uc"), ) - def __init__(self, depender=None, package=None, meta=None): + def __init__(self, depender=None, package=None, meta=None, optional=False): if depender is None: return self.depender = depender + self.optional = optional packageProvided = package is not None metaProvided = meta is not None @@ -458,7 +472,7 @@ class Package(db.Model): dependencies = db.relationship("Dependency", backref="depender", lazy="dynamic", foreign_keys=[Dependency.depender_id]) - tags = db.relationship("Tag", secondary=tags, lazy="select", + tags = db.relationship("Tag", secondary=Tags, lazy="select", backref=db.backref("packages", lazy=True)) releases = db.relationship("PackageRelease", backref="package", @@ -480,6 +494,8 @@ class Package(db.Model): self.created_at = package.created_at self.approved = package.approved + self.maintainers.append(self.author) + for e in PackagePropertyKey: setattr(self, e.name, getattr(package, e.name)) @@ -659,6 +675,10 @@ class Package(db.Model): return url_for("packages.remove_self_maintainers", author=self.author.username, name=self.name) + def getUpdateFromReleaseURL(self): + return url_for("packages.update_from_release", + author=self.author.username, name=self.name) + def getReviewURL(self): return url_for('packages.review', author=self.author.username, name=self.name) @@ -691,7 +711,8 @@ class Package(db.Model): elif perm == Permission.MAKE_RELEASE or perm == Permission.ADD_SCREENSHOTS: return isMaintainer - elif perm == Permission.EDIT_PACKAGE or perm == Permission.APPROVE_CHANGES or perm == Permission.APPROVE_RELEASE: + elif perm == Permission.EDIT_PACKAGE or perm == Permission.REIMPORT_META or \ + perm == Permission.APPROVE_CHANGES or perm == Permission.APPROVE_RELEASE: return isMaintainer and user.rank.atLeast(UserRank.MEMBER if self.approved else UserRank.NEW_MEMBER) # Anyone can change the package name when not approved, but only editors when approved @@ -737,6 +758,8 @@ class MetaPackage(db.Model): name = db.Column(db.String(100), unique=True, nullable=False) dependencies = db.relationship("Dependency", backref="meta_package", lazy="dynamic") + mp_name_valid = db.CheckConstraint("name ~* '^[a-z0-9_]+$'") + def __init__(self, name=None): self.name = name @@ -1067,19 +1090,22 @@ class Thread(db.Model): package_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True) package = db.relationship("Package", foreign_keys=[package_id]) - review_id = db.Column(db.Integer, db.ForeignKey("package_review.id"), nullable=True) - review = db.relationship("PackageReview", foreign_keys=[review_id]) + review_id = db.Column(db.Integer, db.ForeignKey("package_review.id"), nullable=True) + review = db.relationship("PackageReview", foreign_keys=[review_id]) author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) title = db.Column(db.String(100), nullable=False) - private = db.Column(db.Boolean, server_default="0") + private = db.Column(db.Boolean, server_default="0", nullable=False) + + locked = db.Column(db.Boolean, server_default="0", nullable=False) created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) - replies = db.relationship("ThreadReply", backref="thread", lazy="dynamic") + replies = db.relationship("ThreadReply", backref="thread", lazy="dynamic", \ + order_by=db.asc("thread_reply_id")) watchers = db.relationship("User", secondary=watchers, lazy="subquery", \ - backref=db.backref("watching", lazy=True)) + backref=db.backref("watching", lazy=True)) def getViewURL(self): return url_for("threads.view", id=self.id) @@ -1092,7 +1118,7 @@ class Thread(db.Model): def checkPerm(self, user, perm): if not user.is_authenticated: - return not self.private + return perm == Permission.SEE_THREAD and not self.private if type(perm) == str: perm = Permission[perm] @@ -1103,8 +1129,16 @@ class Thread(db.Model): if self.package: isMaintainer = isMaintainer or user in self.package.maintainers + canSee = not self.private or isMaintainer or user.rank.atLeast(UserRank.EDITOR) + if perm == Permission.SEE_THREAD: - return not self.private or isMaintainer or user.rank.atLeast(UserRank.EDITOR) + return canSee + + elif perm == Permission.COMMENT_THREAD: + return canSee and (not self.locked or user.rank.atLeast(UserRank.MODERATOR)) + + elif perm == Permission.LOCK_THREAD: + return user.rank.atLeast(UserRank.MODERATOR) else: raise Exception("Permission {} is not related to threads".format(perm.name)) @@ -1116,6 +1150,24 @@ class ThreadReply(db.Model): author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) + def checkPerm(self, user, perm): + if not user.is_authenticated: + return False + + if type(perm) == str: + perm = Permission[perm] + elif type(perm) != Permission: + raise Exception("Unknown permission given to ThreadReply.checkPerm()") + + if perm == Permission.EDIT_REPLY: + return user == self.author and user.rank.atLeast(UserRank.MEMBER) and not self.thread.locked + + elif perm == Permission.DELETE_REPLY: + return user.rank.atLeast(UserRank.MODERATOR) and self.thread.replies[0] != self + + else: + raise Exception("Permission {} is not related to threads".format(perm.name)) + class PackageReview(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -1144,6 +1196,58 @@ class PackageReview(db.Model): name=self.package.name) +class AuditSeverity(enum.Enum): + NORMAL = 0 # Normal user changes + EDITOR = 1 # Editor changes + MODERATION = 2 # Destructive / moderator changes + + def __str__(self): + return self.name + + def getTitle(self): + return self.name.replace("_", " ").title() + + @classmethod + def choices(cls): + return [(choice, choice.getTitle()) for choice in cls] + + @classmethod + def coerce(cls, item): + return item if type(item) == AuditSeverity else AuditSeverity[item] + + + +class AuditLogEntry(db.Model): + id = db.Column(db.Integer, primary_key=True) + + created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) + + causer_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) + causer = db.relationship("User", foreign_keys=[causer_id]) + + severity = db.Column(db.Enum(AuditSeverity), nullable=False) + + title = db.Column(db.String(100), nullable=False) + url = db.Column(db.String(200), nullable=True) + + package_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True) + package = db.relationship("Package", foreign_keys=[package_id]) + + description = db.Column(db.Text, nullable=True, default=None) + + def __init__(self, causer, severity, title, url, package=None, description=None): + if len(title) > 100: + title = title[:99] + "…" + + self.causer = causer + self.severity = severity + self.title = title + self.url = url + self.package = package + self.description = description + + + REPO_BLACKLIST = [".zip", "mediafire.com", "dropbox.com", "weebly.com", \ "minetest.net", "dropboxusercontent.com", "4shared.com", \