+ forums = db.Column(db.Integer, nullable=False)
+
+ tags = db.relationship("Tag", secondary=tags, lazy="subquery",
+ backref=db.backref("packages", lazy=True))
+
+ harddeps = db.relationship("Package",
+ secondary=harddeps,
+ primaryjoin=id==harddeps.c.package_id,
+ secondaryjoin=id==harddeps.c.dependency_id,
+ backref="dependents")
+
+ softdeps = db.relationship("Package",
+ secondary=softdeps,
+ primaryjoin=id==softdeps.c.package_id,
+ secondaryjoin=id==softdeps.c.dependency_id,
+ backref="softdependents")
+
+ releases = db.relationship("PackageRelease", backref="package",
+ lazy="dynamic", order_by=db.desc("package_release_releaseDate"))
+
+ screenshots = db.relationship("PackageScreenshot", backref="package",
+ lazy="dynamic")
+
+ requests = db.relationship("EditRequest", backref="package",
+ lazy="dynamic")
+
+ def getAsDictionary(self, base_url):
+ return {
+ "name": self.name,
+ "title": self.title,
+ "author": self.author.display_name,
+ "shortDesc": self.shortDesc,
+ "type": self.type.toName(),
+ "license": self.license.name,
+ "repo": self.repo,
+ "url": base_url + self.getDownloadURL(),
+ "release": self.getDownloadRelease().id if self.getDownloadRelease() is not None else None,
+ "screenshots": [base_url + ss.url for ss in self.screenshots]
+ }
+
+ def getDetailsURL(self):
+ return url_for("package_page",
+ author=self.author.username, name=self.name)
+
+ def getEditURL(self):
+ return url_for("create_edit_package_page",
+ author=self.author.username, name=self.name)
+
+ def getApproveURL(self):
+ return url_for("approve_package_page",
+ author=self.author.username, name=self.name)
+
+ def getNewScreenshotURL(self):
+ return url_for("create_screenshot_page",
+ author=self.author.username, name=self.name)
+
+ def getCreateReleaseURL(self):
+ return url_for("create_release_page",
+ author=self.author.username, name=self.name)
+
+ def getCreateEditRequestURL(self):
+ return url_for("create_edit_editrequest_page",
+ author=self.author.username, name=self.name)
+
+ def getDownloadURL(self):
+ return url_for("package_download_page",
+ author=self.author.username, name=self.name)
+
+ def getMainScreenshotURL(self):
+ screenshot = self.screenshots.first()
+ return screenshot.url if screenshot is not None else None
+
+ def getDownloadRelease(self):
+ for rel in self.releases:
+ if rel.approved:
+ return rel
+
+ return None
+
+ 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 Package.checkPerm()")
+
+ isOwner = user == self.author
+
+ # Members can edit their own packages, and editors can edit any packages
+ if perm == Permission.MAKE_RELEASE:
+ return isOwner or user.rank.atLeast(UserRank.EDITOR)
+
+ if perm == Permission.EDIT_PACKAGE or perm == Permission.APPROVE_CHANGES:
+ return user.rank.atLeast(UserRank.MEMBER if isOwner else UserRank.EDITOR)
+
+ # Editors can change authors, approve new packages, and approve releases
+ elif perm == Permission.CHANGE_AUTHOR or perm == Permission.APPROVE_NEW \
+ or perm == Permission.APPROVE_RELEASE:
+ return user.rank.atLeast(UserRank.EDITOR)
+
+ # Moderators can delete packages
+ elif perm == Permission.DELETE_PACKAGE or perm == Permission.CHANGE_RELEASE_URL:
+ return user.rank.atLeast(UserRank.MODERATOR)
+
+ else:
+ raise Exception("Permission {} is not related to packages".format(perm.name))
+
+class Tag(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.String(100), unique=True, nullable=False)
+ title = db.Column(db.String(100), nullable=False)
+ backgroundColor = db.Column(db.String(6), nullable=False)
+ textColor = db.Column(db.String(6), nullable=False)
+
+ def __init__(self, title, backgroundColor="000000", textColor="ffffff"):
+ self.title = title
+ self.backgroundColor = backgroundColor
+ self.textColor = textColor
+
+ import re
+ regex = re.compile("[^a-z_]")
+ self.name = regex.sub("", self.title.lower().replace(" ", "_"))
+
+class PackageRelease(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+
+ package_id = db.Column(db.Integer, db.ForeignKey("package.id"))
+ title = db.Column(db.String(100), nullable=False)
+ releaseDate = db.Column(db.DateTime, nullable=False)
+ url = db.Column(db.String(200), nullable=False)
+ approved = db.Column(db.Boolean, nullable=False, default=False)
+ task_id = db.Column(db.String(37), nullable=True)
+
+
+ def getEditURL(self):
+ return url_for("edit_release_page",
+ author=self.package.author.username,
+ name=self.package.name,
+ id=self.id)
+
+ def __init__(self):
+ self.releaseDate = datetime.now()
+
+class PackageScreenshot(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ package_id = db.Column(db.Integer, db.ForeignKey("package.id"))
+ title = db.Column(db.String(100), nullable=False)
+ url = db.Column(db.String(100), nullable=False)
+
+ def getThumbnailURL(self):
+ return self.url # TODO
+
+class EditRequest(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+
+ package_id = db.Column(db.Integer, db.ForeignKey("package.id"))
+ author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
+
+ title = db.Column(db.String(100), nullable=False)
+ desc = db.Column(db.String(1000), nullable=True)
+
+ # 0 - open
+ # 1 - merged
+ # 2 - rejected
+ status = db.Column(db.Integer, nullable=False, default=0)
+
+ changes = db.relationship("EditRequestChange", backref="request",
+ lazy="dynamic")
+
+ def getURL(self):
+ return url_for("view_editrequest_page",
+ author=self.package.author.username,
+ name=self.package.name,
+ id=self.id)
+
+ def getApproveURL(self):
+ return url_for("approve_editrequest_page",
+ author=self.package.author.username,
+ name=self.package.name,
+ id=self.id)
+
+ def getRejectURL(self):
+ return url_for("reject_editrequest_page",
+ author=self.package.author.username,
+ name=self.package.name,
+ id=self.id)
+
+ def getEditURL(self):
+ return url_for("create_edit_editrequest_page",
+ author=self.package.author.username,
+ name=self.package.name,
+ id=self.id)
+
+ def applyAll(self, package):
+ for change in self.changes:
+ change.apply(package)
+
+
+ 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 EditRequest.checkPerm()")
+
+ isOwner = user == self.author
+
+ # Members can edit their own packages, and editors can edit any packages
+ if perm == Permission.EDIT_EDITREQUEST:
+ return isOwner or user.rank.atLeast(UserRank.EDITOR)
+
+ else:
+ raise Exception("Permission {} is not related to packages".format(perm.name))
+
+
+
+
+class EditRequestChange(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+
+ request_id = db.Column(db.Integer, db.ForeignKey("edit_request.id"))
+ key = db.Column(db.Enum(PackagePropertyKey), nullable=False)
+
+ # TODO: make diff instead
+ oldValue = db.Column(db.Text, nullable=True)
+ newValue = db.Column(db.Text, nullable=True)
+
+ def apply(self, package):
+ if self.key == PackagePropertyKey.tags:
+ package.tags.clear()
+ for tagTitle in self.newValue.split(","):
+ tag = Tag.query.filter_by(title=tagTitle.strip()).first()
+ package.tags.append(tag)
+ else:
+ setattr(package, self.key.name, self.newValue)