From ebe9724f143f61eed233ad8ab2206045129a21a9 Mon Sep 17 00:00:00 2001 From: SvyatoslavArtymovych Date: Thu, 1 Jun 2023 17:01:45 +0300 Subject: [PATCH] small refactor, add position fields --- app/models/collection.py | 1 + app/models/section.py | 1 + migrations/versions/79e8c7bff9c9_init.py | 695 ++++++++++++------- migrations/versions/96995454b90d_ordering.py | 38 + tests/test_permissions.py | 99 +-- tests/utils.py | 96 ++- 6 files changed, 575 insertions(+), 355 deletions(-) create mode 100644 migrations/versions/96995454b90d_ordering.py diff --git a/app/models/collection.py b/app/models/collection.py index 6c631e9..9d1d113 100644 --- a/app/models/collection.py +++ b/app/models/collection.py @@ -11,6 +11,7 @@ class Collection(BaseModel): about = db.Column(db.Text, unique=False, nullable=True) is_root = db.Column(db.Boolean, default=False) is_leaf = db.Column(db.Boolean, default=False) + position = db.Column(db.Integer, default=-1, nullable=True) # Foreign keys version_id = db.Column(db.ForeignKey("book_versions.id")) diff --git a/app/models/section.py b/app/models/section.py index 16ea606..fa6e027 100644 --- a/app/models/section.py +++ b/app/models/section.py @@ -18,6 +18,7 @@ class Section(BaseModel): user_id = db.Column(db.ForeignKey("users.id")) version_id = db.Column(db.ForeignKey("book_versions.id")) selected_interpretation_id = db.Column(db.Integer, nullable=True) + position = db.Column(db.Integer, default=-1, nullable=True) # Relationships collection = db.relationship("Collection", viewonly=True) diff --git a/migrations/versions/79e8c7bff9c9_init.py b/migrations/versions/79e8c7bff9c9_init.py index 092b528..7a4c682 100644 --- a/migrations/versions/79e8c7bff9c9_init.py +++ b/migrations/versions/79e8c7bff9c9_init.py @@ -1,7 +1,7 @@ """init Revision ID: 79e8c7bff9c9 -Revises: +Revises: Create Date: 2023-06-01 15:31:33.635236 """ @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '79e8c7bff9c9' +revision = "79e8c7bff9c9" down_revision = None branch_labels = None depends_on = None @@ -18,294 +18,463 @@ depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.create_table('permissions', - sa.Column('access', sa.Integer(), nullable=True), - sa.Column('entity_type', sa.Enum('UNKNOWN', 'BOOK', 'COLLECTION', 'SECTION', 'INTERPRETATION', 'COMMENT', name='entity'), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.PrimaryKeyConstraint('id') + op.create_table( + "permissions", + sa.Column("access", sa.Integer(), nullable=True), + sa.Column( + "entity_type", + sa.Enum( + "UNKNOWN", + "BOOK", + "COLLECTION", + "SECTION", + "INTERPRETATION", + "COMMENT", + name="entity", + ), + nullable=True, + ), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('tags', - sa.Column('name', sa.String(length=32), nullable=False), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') + op.create_table( + "tags", + sa.Column("name", sa.String(length=32), nullable=False), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("name"), ) - op.create_table('users', - sa.Column('username', sa.String(length=64), nullable=True), - sa.Column('password_hash', sa.String(length=256), nullable=True), - sa.Column('is_activated', sa.Boolean(), nullable=True), - sa.Column('wallet_id', sa.String(length=64), nullable=True), - sa.Column('avatar_img', sa.Text(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('username') + op.create_table( + "users", + sa.Column("username", sa.String(length=64), nullable=True), + sa.Column("password_hash", sa.String(length=256), nullable=True), + sa.Column("is_activated", sa.Boolean(), nullable=True), + sa.Column("wallet_id", sa.String(length=64), nullable=True), + sa.Column("avatar_img", sa.Text(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("username"), ) - op.create_table('books', - sa.Column('label', sa.String(length=256), nullable=False), - sa.Column('about', sa.Text(), nullable=True), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "books", + sa.Column("label", sa.String(length=256), nullable=False), + sa.Column("about", sa.Text(), nullable=True), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('access_groups', - sa.Column('name', sa.String(length=32), nullable=False), - sa.Column('book_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['book_id'], ['books.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "access_groups", + sa.Column("name", sa.String(length=32), nullable=False), + sa.Column("book_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["book_id"], + ["books.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('book_contributors', - sa.Column('role', sa.Enum('UNKNOWN', 'MODERATOR', 'EDITOR', name='roles'), nullable=True), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('book_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['book_id'], ['books.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "book_contributors", + sa.Column( + "role", + sa.Enum("UNKNOWN", "MODERATOR", "EDITOR", name="roles"), + nullable=True, + ), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("book_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["book_id"], + ["books.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('book_tags', - sa.Column('tag_id', sa.Integer(), nullable=True), - sa.Column('book_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['book_id'], ['books.id'], ), - sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "book_tags", + sa.Column("tag_id", sa.Integer(), nullable=True), + sa.Column("book_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["book_id"], + ["books.id"], + ), + sa.ForeignKeyConstraint( + ["tag_id"], + ["tags.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('book_versions', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('semver', sa.String(length=16), nullable=False), - sa.Column('exported', sa.Boolean(), nullable=True), - sa.Column('updated_at', sa.DateTime(), nullable=True), - sa.Column('derivative_id', sa.Integer(), nullable=True), - sa.Column('book_id', sa.Integer(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['book_id'], ['books.id'], ), - sa.ForeignKeyConstraint(['derivative_id'], ['book_versions.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "book_versions", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("semver", sa.String(length=16), nullable=False), + sa.Column("exported", sa.Boolean(), nullable=True), + sa.Column("updated_at", sa.DateTime(), nullable=True), + sa.Column("derivative_id", sa.Integer(), nullable=True), + sa.Column("book_id", sa.Integer(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["book_id"], + ["books.id"], + ), + sa.ForeignKeyConstraint( + ["derivative_id"], + ["book_versions.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('books_stars', - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('book_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['book_id'], ['books.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "books_stars", + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("book_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["book_id"], + ["books.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('books_access_groups', - sa.Column('book_id', sa.Integer(), nullable=True), - sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['access_group_id'], ['access_groups.id'], ), - sa.ForeignKeyConstraint(['book_id'], ['books.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "books_access_groups", + sa.Column("book_id", sa.Integer(), nullable=True), + sa.Column("access_group_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["access_group_id"], + ["access_groups.id"], + ), + sa.ForeignKeyConstraint( + ["book_id"], + ["books.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('collections', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('label', sa.String(length=256), nullable=False), - sa.Column('about', sa.Text(), nullable=True), - sa.Column('is_root', sa.Boolean(), nullable=True), - sa.Column('is_leaf', sa.Boolean(), nullable=True), - sa.Column('version_id', sa.Integer(), nullable=True), - sa.Column('parent_id', sa.Integer(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['parent_id'], ['collections.id'], ), - sa.ForeignKeyConstraint(['version_id'], ['book_versions.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "collections", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("label", sa.String(length=256), nullable=False), + sa.Column("about", sa.Text(), nullable=True), + sa.Column("is_root", sa.Boolean(), nullable=True), + sa.Column("is_leaf", sa.Boolean(), nullable=True), + sa.Column("version_id", sa.Integer(), nullable=True), + sa.Column("parent_id", sa.Integer(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["parent_id"], + ["collections.id"], + ), + sa.ForeignKeyConstraint( + ["version_id"], + ["book_versions.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('permissions_access_groups', - sa.Column('permission_id', sa.Integer(), nullable=True), - sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['access_group_id'], ['access_groups.id'], ), - sa.ForeignKeyConstraint(['permission_id'], ['permissions.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "permissions_access_groups", + sa.Column("permission_id", sa.Integer(), nullable=True), + sa.Column("access_group_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["access_group_id"], + ["access_groups.id"], + ), + sa.ForeignKeyConstraint( + ["permission_id"], + ["permissions.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('users_access_groups', - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['access_group_id'], ['access_groups.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "users_access_groups", + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("access_group_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["access_group_id"], + ["access_groups.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('collections_access_groups', - sa.Column('collection_id', sa.Integer(), nullable=True), - sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['access_group_id'], ['access_groups.id'], ), - sa.ForeignKeyConstraint(['collection_id'], ['collections.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "collections_access_groups", + sa.Column("collection_id", sa.Integer(), nullable=True), + sa.Column("access_group_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["access_group_id"], + ["access_groups.id"], + ), + sa.ForeignKeyConstraint( + ["collection_id"], + ["collections.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('sections', - sa.Column('label', sa.String(length=256), nullable=False), - sa.Column('collection_id', sa.Integer(), nullable=True), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('version_id', sa.Integer(), nullable=True), - sa.Column('selected_interpretation_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['collection_id'], ['collections.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.ForeignKeyConstraint(['version_id'], ['book_versions.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "sections", + sa.Column("label", sa.String(length=256), nullable=False), + sa.Column("collection_id", sa.Integer(), nullable=True), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("version_id", sa.Integer(), nullable=True), + sa.Column("selected_interpretation_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["collection_id"], + ["collections.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.ForeignKeyConstraint( + ["version_id"], + ["book_versions.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('interpretations', - sa.Column('text', sa.Text(), nullable=False), - sa.Column('plain_text', sa.Text(), nullable=True), - sa.Column('approved', sa.Boolean(), nullable=True), - sa.Column('marked', sa.Boolean(), nullable=True), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('section_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['section_id'], ['sections.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "interpretations", + sa.Column("text", sa.Text(), nullable=False), + sa.Column("plain_text", sa.Text(), nullable=True), + sa.Column("approved", sa.Boolean(), nullable=True), + sa.Column("marked", sa.Boolean(), nullable=True), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("section_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["section_id"], + ["sections.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('section_tags', - sa.Column('tag_id', sa.Integer(), nullable=True), - sa.Column('section_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['section_id'], ['sections.id'], ), - sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "section_tags", + sa.Column("tag_id", sa.Integer(), nullable=True), + sa.Column("section_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["section_id"], + ["sections.id"], + ), + sa.ForeignKeyConstraint( + ["tag_id"], + ["tags.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('sections_access_groups', - sa.Column('section_id', sa.Integer(), nullable=True), - sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['access_group_id'], ['access_groups.id'], ), - sa.ForeignKeyConstraint(['section_id'], ['sections.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "sections_access_groups", + sa.Column("section_id", sa.Integer(), nullable=True), + sa.Column("access_group_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["access_group_id"], + ["access_groups.id"], + ), + sa.ForeignKeyConstraint( + ["section_id"], + ["sections.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('comments', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('text', sa.Text(), nullable=False), - sa.Column('approved', sa.Boolean(), nullable=True), - sa.Column('marked', sa.Boolean(), nullable=True), - sa.Column('edited', sa.Boolean(), nullable=True), - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('parent_id', sa.Integer(), nullable=True), - sa.Column('interpretation_id', sa.Integer(), nullable=True), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['interpretation_id'], ['interpretations.id'], ), - sa.ForeignKeyConstraint(['parent_id'], ['comments.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "comments", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("text", sa.Text(), nullable=False), + sa.Column("approved", sa.Boolean(), nullable=True), + sa.Column("marked", sa.Boolean(), nullable=True), + sa.Column("edited", sa.Boolean(), nullable=True), + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("parent_id", sa.Integer(), nullable=True), + sa.Column("interpretation_id", sa.Integer(), nullable=True), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["interpretation_id"], + ["interpretations.id"], + ), + sa.ForeignKeyConstraint( + ["parent_id"], + ["comments.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('interpretation_tags', - sa.Column('tag_id', sa.Integer(), nullable=True), - sa.Column('interpretation_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['interpretation_id'], ['interpretations.id'], ), - sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "interpretation_tags", + sa.Column("tag_id", sa.Integer(), nullable=True), + sa.Column("interpretation_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["interpretation_id"], + ["interpretations.id"], + ), + sa.ForeignKeyConstraint( + ["tag_id"], + ["tags.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('interpretation_votes', - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('interpretation_id', sa.Integer(), nullable=True), - sa.Column('positive', sa.Boolean(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['interpretation_id'], ['interpretations.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "interpretation_votes", + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("interpretation_id", sa.Integer(), nullable=True), + sa.Column("positive", sa.Boolean(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["interpretation_id"], + ["interpretations.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('interpretations_access_groups', - sa.Column('interpretation_id', sa.Integer(), nullable=True), - sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['access_group_id'], ['access_groups.id'], ), - sa.ForeignKeyConstraint(['interpretation_id'], ['interpretations.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "interpretations_access_groups", + sa.Column("interpretation_id", sa.Integer(), nullable=True), + sa.Column("access_group_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["access_group_id"], + ["access_groups.id"], + ), + sa.ForeignKeyConstraint( + ["interpretation_id"], + ["interpretations.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('comment_tags', - sa.Column('tag_id', sa.Integer(), nullable=True), - sa.Column('comment_id', sa.Integer(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['comment_id'], ['comments.id'], ), - sa.ForeignKeyConstraint(['tag_id'], ['tags.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "comment_tags", + sa.Column("tag_id", sa.Integer(), nullable=True), + sa.Column("comment_id", sa.Integer(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["comment_id"], + ["comments.id"], + ), + sa.ForeignKeyConstraint( + ["tag_id"], + ["tags.id"], + ), + sa.PrimaryKeyConstraint("id"), ) - op.create_table('comment_votes', - sa.Column('user_id', sa.Integer(), nullable=True), - sa.Column('comment_id', sa.Integer(), nullable=True), - sa.Column('positive', sa.Boolean(), nullable=True), - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('created_at', sa.DateTime(), nullable=True), - sa.Column('is_deleted', sa.Boolean(), nullable=True), - sa.ForeignKeyConstraint(['comment_id'], ['comments.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), - sa.PrimaryKeyConstraint('id') + op.create_table( + "comment_votes", + sa.Column("user_id", sa.Integer(), nullable=True), + sa.Column("comment_id", sa.Integer(), nullable=True), + sa.Column("positive", sa.Boolean(), nullable=True), + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("created_at", sa.DateTime(), nullable=True), + sa.Column("is_deleted", sa.Boolean(), nullable=True), + sa.ForeignKeyConstraint( + ["comment_id"], + ["comments.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), ) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('comment_votes') - op.drop_table('comment_tags') - op.drop_table('interpretations_access_groups') - op.drop_table('interpretation_votes') - op.drop_table('interpretation_tags') - op.drop_table('comments') - op.drop_table('sections_access_groups') - op.drop_table('section_tags') - op.drop_table('interpretations') - op.drop_table('sections') - op.drop_table('collections_access_groups') - op.drop_table('users_access_groups') - op.drop_table('permissions_access_groups') - op.drop_table('collections') - op.drop_table('books_access_groups') - op.drop_table('books_stars') - op.drop_table('book_versions') - op.drop_table('book_tags') - op.drop_table('book_contributors') - op.drop_table('access_groups') - op.drop_table('books') - op.drop_table('users') - op.drop_table('tags') - op.drop_table('permissions') + op.drop_table("comment_votes") + op.drop_table("comment_tags") + op.drop_table("interpretations_access_groups") + op.drop_table("interpretation_votes") + op.drop_table("interpretation_tags") + op.drop_table("comments") + op.drop_table("sections_access_groups") + op.drop_table("section_tags") + op.drop_table("interpretations") + op.drop_table("sections") + op.drop_table("collections_access_groups") + op.drop_table("users_access_groups") + op.drop_table("permissions_access_groups") + op.drop_table("collections") + op.drop_table("books_access_groups") + op.drop_table("books_stars") + op.drop_table("book_versions") + op.drop_table("book_tags") + op.drop_table("book_contributors") + op.drop_table("access_groups") + op.drop_table("books") + op.drop_table("users") + op.drop_table("tags") + op.drop_table("permissions") # ### end Alembic commands ### + + +"" diff --git a/migrations/versions/96995454b90d_ordering.py b/migrations/versions/96995454b90d_ordering.py new file mode 100644 index 0000000..76e6445 --- /dev/null +++ b/migrations/versions/96995454b90d_ordering.py @@ -0,0 +1,38 @@ +"""ordering + +Revision ID: 96995454b90d +Revises: 79e8c7bff9c9 +Create Date: 2023-06-01 17:01:00.877443 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "96995454b90d" +down_revision = "79e8c7bff9c9" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("collections", schema=None) as batch_op: + batch_op.add_column(sa.Column("position", sa.Integer(), nullable=True)) + + with op.batch_alter_table("sections", schema=None) as batch_op: + batch_op.add_column(sa.Column("position", sa.Integer(), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("sections", schema=None) as batch_op: + batch_op.drop_column("position") + + with op.batch_alter_table("collections", schema=None) as batch_op: + batch_op.drop_column("position") + + # ### end Alembic commands ### diff --git a/tests/test_permissions.py b/tests/test_permissions.py index cf01678..274b61b 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1,96 +1,15 @@ -from random import randint - from flask import current_app as Response from app import models as m -from tests.utils import login, logout - - -def create_book(client): - random_id = randint(1, 100) - BOOK_NAME = f"TBook {random_id}" - response: Response = client.post( - "/book/create", - data=dict(label=BOOK_NAME), - follow_redirects=True, - ) - - assert response.status_code == 200 - assert b"Book added!" in response.data - - book: m.Book = m.Book.query.filter_by(label=BOOK_NAME).first() - - assert book - assert book.versions - assert len(book.versions) == 1 - assert book.access_groups - assert len(book.access_groups) == 2 - - root_collection: m.Collection = book.last_version.collections[0] - assert root_collection - assert root_collection.access_groups - assert len(root_collection.access_groups) == 2 - - return book - - -def create_collection(client, book_id): - random_id = randint(1, 100) - LABEL = f"TCollection {random_id}" - response: Response = client.post( - f"/book/{book_id}/create_collection", - data=dict(label=LABEL), - follow_redirects=True, - ) - - assert response.status_code == 200 - collection: m.Collection = m.Collection.query.filter_by(label=LABEL).first() - - return collection, response - - -def create_section(client, book_id, collection_id): - random_id = randint(1, 100) - LABEL = f"TSection {random_id}" - response: Response = client.post( - f"/book/{book_id}/{collection_id}/create_section", - data=dict(collection_id=collection_id, label=LABEL), - follow_redirects=True, - ) - - section: m.Section = m.Section.query.filter_by( - label=LABEL, collection_id=collection_id - ).first() - return section, response - - -def create_interpretation(client, book_id, section_id): - random_id = randint(1, 100) - LABEL = f"TInterpretation {random_id}" - response: Response = client.post( - f"/book/{book_id}/{section_id}/create_interpretation", - data=dict(section_id=section_id, text=LABEL), - follow_redirects=True, - ) - interpretation: m.Interpretation = m.Interpretation.query.filter_by( - section_id=section_id, text=LABEL - ).first() - return interpretation, response - - -def create_comment(client, book_id, interpretation_id): - random_id = randint(1, 100) - TEXT = f"TComment {random_id}" - response: Response = client.post( - f"/book/{book_id}/{interpretation_id}/create_comment", - data=dict( - text=TEXT, - interpretation_id=interpretation_id, - ), - follow_redirects=True, - ) - comment: m.Comment = m.Comment.query.filter_by(text=TEXT).first() - return comment, response +from tests.utils import ( + login, + logout, + create_book, + create_collection, + create_section, + create_interpretation, + create_comment, +) def test_editor_access_to_entire_book(client): diff --git a/tests/utils.py b/tests/utils.py index f4e148c..f7e7518 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,11 +1,13 @@ +from random import randint + +from flask import current_app as Response + from app import models as m from app.controllers.create_access_groups import ( create_editor_group, create_moderator_group, ) -from random import randint - TEST_ADMIN_NAME = "bob" TEST_ADMIN_EMAIL = "bob@test.com" TEST_ADMIN_PASSWORD = "password" @@ -184,3 +186,93 @@ def check_if_nested_comment_entities_is_deleted( for child in comment.children: child: m.Comment assert child.is_deleted == is_deleted + + +# book entities: + + +def create_book(client): + random_id = randint(1, 100) + BOOK_NAME = f"TBook {random_id}" + response: Response = client.post( + "/book/create", + data=dict(label=BOOK_NAME), + follow_redirects=True, + ) + + assert response.status_code == 200 + assert b"Book added!" in response.data + + book: m.Book = m.Book.query.filter_by(label=BOOK_NAME).first() + + assert book + assert book.versions + assert len(book.versions) == 1 + assert book.access_groups + assert len(book.access_groups) == 2 + + root_collection: m.Collection = book.last_version.collections[0] + assert root_collection + assert root_collection.access_groups + assert len(root_collection.access_groups) == 2 + + return book + + +def create_collection(client, book_id): + random_id = randint(1, 100) + LABEL = f"TCollection {random_id}" + response: Response = client.post( + f"/book/{book_id}/create_collection", + data=dict(label=LABEL), + follow_redirects=True, + ) + + assert response.status_code == 200 + collection: m.Collection = m.Collection.query.filter_by(label=LABEL).first() + + return collection, response + + +def create_section(client, book_id, collection_id): + random_id = randint(1, 100) + LABEL = f"TSection {random_id}" + response: Response = client.post( + f"/book/{book_id}/{collection_id}/create_section", + data=dict(collection_id=collection_id, label=LABEL), + follow_redirects=True, + ) + + section: m.Section = m.Section.query.filter_by( + label=LABEL, collection_id=collection_id + ).first() + return section, response + + +def create_interpretation(client, book_id, section_id): + random_id = randint(1, 100) + LABEL = f"TInterpretation {random_id}" + response: Response = client.post( + f"/book/{book_id}/{section_id}/create_interpretation", + data=dict(section_id=section_id, text=LABEL), + follow_redirects=True, + ) + interpretation: m.Interpretation = m.Interpretation.query.filter_by( + section_id=section_id, text=LABEL + ).first() + return interpretation, response + + +def create_comment(client, book_id, interpretation_id): + random_id = randint(1, 100) + TEXT = f"TComment {random_id}" + response: Response = client.post( + f"/book/{book_id}/{interpretation_id}/create_comment", + data=dict( + text=TEXT, + interpretation_id=interpretation_id, + ), + follow_redirects=True, + ) + comment: m.Comment = m.Comment.query.filter_by(text=TEXT).first() + return comment, response