Clean up database constraints

This commit is contained in:
rubenwardy 2020-12-10 16:49:37 +00:00
parent 70ac8fa6ab
commit 8d8577a941
7 changed files with 78 additions and 25 deletions

@ -35,16 +35,17 @@ from .threads import *
class APIToken(db.Model):
id = db.Column(db.Integer, primary_key=True)
access_token = db.Column(db.String(34), unique=True)
access_token = db.Column(db.String(34), unique=True, nullable=False)
name = db.Column(db.String(100), nullable=False)
owner_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
owner = db.relationship("User", back_populates="tokens", foreign_keys=[owner_id])
owner = db.relationship("User", foreign_keys=[owner_id], back_populates="tokens")
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
package_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=True)
package = db.relationship("Package", foreign_keys=[package_id])
package = db.relationship("Package", foreign_keys=[package_id], back_populates="tokens")
def canOperateOnPackage(self, package):
if self.package and self.package != package:
@ -80,7 +81,7 @@ class AuditLogEntry(db.Model):
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
causer_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=True)
causer = db.relationship("User", back_populates="", foreign_keys=[causer_id])
causer = db.relationship("User", foreign_keys=[causer_id], back_populates="audit_log_entries")
severity = db.Column(db.Enum(AuditSeverity), nullable=False)
@ -88,7 +89,7 @@ class AuditLogEntry(db.Model):
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])
package = db.relationship("Package", foreign_keys=[package_id], back_populates="audit_log_entries")
description = db.Column(db.Text, nullable=True, default=None)
@ -104,15 +105,15 @@ class AuditLogEntry(db.Model):
self.description = description
REPO_BLACKLIST = [".zip", "mediafire.com", "dropbox.com", "weebly.com",
"minetest.net", "dropboxusercontent.com", "4shared.com",
"digitalaudioconcepts.com", "hg.intevation.org", "www.wtfpl.net",
"imageshack.com", "imgur.com"]
class ForumTopic(db.Model):
topic_id = db.Column(db.Integer, primary_key=True, autoincrement=False)
author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
author = db.relationship("User")

@ -143,26 +143,31 @@ class PackagePropertyKey(enum.Enum):
else:
return str(value)
provides = db.Table("provides",
db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True),
db.Column("metapackage_id", db.Integer, db.ForeignKey("meta_package.id"), primary_key=True)
)
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)
)
ContentWarnings = db.Table("content_warnings",
db.Column("content_warning_id", db.Integer, db.ForeignKey("content_warning.id"), primary_key=True),
db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True)
)
maintainers = db.Table("maintainers",
db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True),
db.Column("package_id", db.Integer, db.ForeignKey("package.id"), primary_key=True)
)
class Dependency(db.Model):
id = db.Column(db.Integer, primary_key=True)
@ -252,14 +257,14 @@ class Package(db.Model):
id = db.Column(db.Integer, primary_key=True)
# Basic details
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
author_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
author = db.relationship("User", back_populates="packages", foreign_keys=[author_id])
name = db.Column(db.Unicode(100), nullable=False)
title = db.Column(db.Unicode(100), nullable=False)
short_desc = db.Column(db.Unicode(200), nullable=False)
desc = db.Column(db.UnicodeText, nullable=True)
type = db.Column(db.Enum(PackageType))
type = db.Column(db.Enum(PackageType), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
approved_at = db.Column(db.DateTime, nullable=True, default=None)
@ -273,7 +278,7 @@ class Package(db.Model):
media_license_id = db.Column(db.Integer, db.ForeignKey("license.id"), nullable=False, default=1)
media_license = db.relationship("License", foreign_keys=[media_license_id])
state = db.Column(db.Enum(PackageState), default=PackageState.WIP)
state = db.Column(db.Enum(PackageState), nullable=False, default=PackageState.WIP)
@property
def approved(self):
@ -284,7 +289,7 @@ class Package(db.Model):
downloads = db.Column(db.Integer, nullable=False, default=0)
review_thread_id = db.Column(db.Integer, db.ForeignKey("thread.id"), nullable=True, default=None)
review_thread = db.relationship("Thread", foreign_keys=[review_thread_id], back_populates="is_review_thread")
review_thread = db.relationship("Thread", uselist=False, foreign_keys=[review_thread_id], back_populates="is_review_thread")
# Downloads
repo = db.Column(db.String(200), nullable=True)
@ -321,6 +326,9 @@ class Package(db.Model):
audit_log_entries = db.relationship("AuditLogEntry", foreign_keys="AuditLogEntry.package_id", back_populates="package",
order_by=db.desc("audit_log_entry_created_at"), lazy="dynamic")
notifications = db.relationship("Notification", foreign_keys="Notification.package_id",
back_populates="package", cascade="all, delete, delete-orphan")
tokens = db.relationship("APIToken", foreign_keys="APIToken.package_id", back_populates="package",
lazy="dynamic", cascade="all, delete, delete-orphan")
@ -625,7 +633,6 @@ class Package(db.Model):
return True
def getNextStates(self, user):
states = []
@ -635,7 +642,6 @@ class Package(db.Model):
return states
def getScoreDict(self):
return {
"author": self.author.username,
@ -872,7 +878,7 @@ class PackageRelease(db.Model):
class PackageScreenshot(db.Model):
id = db.Column(db.Integer, primary_key=True)
package_id = db.Column(db.Integer, db.ForeignKey("package.id"))
package_id = db.Column(db.Integer, db.ForeignKey("package.id"), nullable=False)
package = db.relationship("Package", back_populates="screenshots", foreign_keys=[package_id])
order = db.Column(db.Integer, nullable=False, default=0)

@ -22,11 +22,13 @@ from . import db
from .users import Permission, UserRank
from .packages import Package
watchers = db.Table("watchers",
db.Column("user_id", db.Integer, db.ForeignKey("user.id"), primary_key=True),
db.Column("thread_id", db.Integer, db.ForeignKey("thread.id"), primary_key=True)
)
class Thread(db.Model):
id = db.Column(db.Integer, primary_key=True)
@ -89,6 +91,7 @@ class Thread(db.Model):
else:
raise Exception("Permission {} is not related to threads".format(perm.name))
class ThreadReply(db.Model):
id = db.Column(db.Integer, primary_key=True)
@ -134,7 +137,7 @@ class PackageReview(db.Model):
recommends = db.Column(db.Boolean, nullable=False)
thread = db.relationship("Thread", uselist=False, back_populates="review", cascade="all, delete")
thread = db.relationship("Thread", uselist=False, back_populates="review")
def asSign(self):
return 1 if self.recommends else -1

@ -114,9 +114,11 @@ class Permission(enum.Enum):
return perm.check(user)
def display_name_default(context):
return context.get_current_parameters()["username"]
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
@ -128,7 +130,7 @@ class User(db.Model, UserMixin):
def get_id(self):
return self.username
rank = db.Column(db.Enum(UserRank))
rank = db.Column(db.Enum(UserRank), nullable=False)
# Account linking
github_username = db.Column(db.String(50, collation="NOCASE"), nullable=True, unique=True)
@ -139,7 +141,7 @@ class User(db.Model, UserMixin):
# User email information
email = db.Column(db.String(255), nullable=True, unique=True)
email_confirmed_at = db.Column(db.DateTime())
email_confirmed_at = db.Column(db.DateTime(), nullable=True)
# User information
profile_pic = db.Column(db.String(255), nullable=True, server_default=None)
@ -265,9 +267,9 @@ class User(db.Model, UserMixin):
class UserEmailVerification(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
email = db.Column(db.String(100))
token = db.Column(db.String(32))
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
email = db.Column(db.String(100), nullable=False)
token = db.Column(db.String(32), nullable=True)
user = db.relationship("User", foreign_keys=[user_id])
is_password_reset = db.Column(db.Boolean, nullable=False, default=False)
@ -373,9 +375,9 @@ class Notification(db.Model):
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])
package = db.relationship("Package", foreign_keys=[package_id], back_populates="notifications")
created_at = db.Column(db.DateTime, nullable=True, default=datetime.datetime.utcnow)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
def __init__(self, user, causer, type, title, url, package=None):
if len(title) > 100:

@ -1,14 +1,14 @@
{% extends "base.html" %}
{% block title %}
Delete thread in {{ thread.title }}
{{ _('Delete "%(title)s" by %(author)s', title=thread.title, author=thread.author.display_name) }}
{% endblock %}
{% block content %}
<form method="POST" action="" class="card box_grey">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<h3 class="card-header">Delete {{ thread.title }} by {{ thread.author.display_name }}</h3>
<h3 class="card-header">{{ self.title() }}</h3>
<div class="card-body">
{{ thread.replies[0].comment | markdown }}
</div>

@ -0,0 +1,41 @@
"""empty message
Revision ID: a9c1c08bf956
Revises: 43dc7dbf64c8
Create Date: 2020-12-10 16:42:28.086146
"""
from alembic import op
# revision identifiers, used by Alembic.
revision = 'a9c1c08bf956'
down_revision = '43dc7dbf64c8'
branch_labels = None
def upgrade():
op.alter_column('api_token', 'access_token', nullable=False)
op.alter_column('package', 'author_id', nullable=False)
op.execute("""UPDATE package SET "state"='WIP' WHERE "state" IS NULL""")
op.alter_column('package', 'state', nullable=False)
op.alter_column('package_screenshot', 'package_id', nullable=False)
op.alter_column('user', 'rank', nullable=False)
op.alter_column('user_email_verification', 'user_id', nullable=False)
op.alter_column('user_email_verification', 'email', nullable=False)
op.alter_column('user_email_verification', 'token', nullable=False)
op.execute("UPDATE notification SET created_at=NOW() WHERE created_at IS NULL")
op.alter_column('notification', 'created_at', nullable=False)
def downgrade():
op.alter_column('api_token', 'access_token', nullable=True)
op.alter_column('package', 'author_id', nullable=True)
op.alter_column('package', 'state', nullable=True)
op.alter_column('package_screenshot', 'package_id', nullable=True)
op.alter_column('user', 'rank', nullable=True)
op.alter_column('user_email_verification', 'user_id', nullable=True)
op.alter_column('user_email_verification', 'email', nullable=True)
op.alter_column('user_email_verification', 'token', nullable=True)
op.alter_column('notification', 'created_at', nullable=True)
depends_on = None

@ -2,7 +2,7 @@
# Create a database migration, and copy it back to the host.
docker exec contentdb_app_1 sh -c "FLASK_CONFIG=../config.cfg FLASK_APP=app/__init__.py flask db migrate"
docker exec contentdb_app_1 sh -c "FLASK_CONFIG=../config.cfg FLASK_APP=app/__init__.py flask db revision"
docker exec -u root contentdb_app_1 sh -c "cp /home/cdb/migrations/versions/* /source/migrations/versions/"
USER=$(whoami)