mirror of https://github.com/logos-co/open-law.git
commit
87a2670c82
|
@ -1,4 +1,3 @@
|
|||
import click
|
||||
from flask import Flask
|
||||
from app import models as m
|
||||
from app import db, forms
|
||||
|
@ -16,23 +15,23 @@ def init(app: Flask):
|
|||
if app.config["ENV"] != "production":
|
||||
|
||||
@app.cli.command()
|
||||
@click.option("--count", default=100, type=int)
|
||||
def db_populate(count: int):
|
||||
def db_populate():
|
||||
"""Fill DB by dummy data."""
|
||||
from tests.db import populate
|
||||
from tests.db.create_dummy_data import create_dummy_data
|
||||
|
||||
populate(count)
|
||||
print(f"DB populated by {count} instancies")
|
||||
create_dummy_data()
|
||||
print("Dummy data added")
|
||||
|
||||
@app.cli.command("create-admin")
|
||||
def create_admin():
|
||||
"""Create super admin account"""
|
||||
if m.User.query.filter_by(email=app.config["ADMIN_EMAIL"]).first():
|
||||
print(f"User with e-mail: [{app.config['ADMIN_EMAIL']}] already exists")
|
||||
if m.User.query.filter_by(username=app.config["ADMIN_USERNAME"]).first():
|
||||
print(
|
||||
f"User with username: [{app.config['ADMIN_USERNAME']}] already exists"
|
||||
)
|
||||
return
|
||||
m.User(
|
||||
username=app.config["ADMIN_USERNAME"],
|
||||
email=app.config["ADMIN_EMAIL"],
|
||||
password=app.config["ADMIN_PASSWORD"],
|
||||
).save()
|
||||
print("admin created")
|
||||
|
|
|
@ -6,7 +6,7 @@ from wtforms import (
|
|||
ValidationError,
|
||||
BooleanField,
|
||||
)
|
||||
from wtforms.validators import DataRequired, Email, Length, EqualTo
|
||||
from wtforms.validators import DataRequired, Length, EqualTo
|
||||
|
||||
from app import models as m
|
||||
|
||||
|
@ -14,7 +14,6 @@ from app import models as m
|
|||
class UserForm(FlaskForm):
|
||||
next_url = StringField("next_url")
|
||||
user_id = StringField("user_id", [DataRequired()])
|
||||
email = StringField("email", [DataRequired(), Email()])
|
||||
activated = BooleanField("activated")
|
||||
username = StringField("Username", [DataRequired()])
|
||||
password = PasswordField("Password", validators=[DataRequired(), Length(6, 30)])
|
||||
|
@ -36,18 +35,8 @@ class UserForm(FlaskForm):
|
|||
):
|
||||
raise ValidationError("This username is taken.")
|
||||
|
||||
def validate_email(self, field):
|
||||
if (
|
||||
m.User.query.filter_by(email=field.data)
|
||||
.filter(m.User.id != int(self.user_id.data))
|
||||
.first()
|
||||
is not None
|
||||
):
|
||||
raise ValidationError("This email is already registered.")
|
||||
|
||||
|
||||
class NewUserForm(FlaskForm):
|
||||
email = StringField("email", [DataRequired(), Email()])
|
||||
activated = BooleanField("activated")
|
||||
username = StringField("Username", [DataRequired()])
|
||||
password = PasswordField("Password", validators=[DataRequired(), Length(6, 30)])
|
||||
|
@ -63,7 +52,3 @@ class NewUserForm(FlaskForm):
|
|||
def validate_username(self, field):
|
||||
if m.User.query.filter_by(username=field.data).first() is not None:
|
||||
raise ValidationError("This username is taken.")
|
||||
|
||||
def validate_email(self, field):
|
||||
if m.User.query.filter_by(email=field.data).first() is not None:
|
||||
raise ValidationError("This email is already registered.")
|
||||
|
|
|
@ -1,2 +1,15 @@
|
|||
# flake8: noqa F401
|
||||
from .user import User, AnonymousUser, gen_password_reset_id
|
||||
from .book import Book
|
||||
from .books_stars import BookStar
|
||||
from .book_contributor import BookContributor
|
||||
from .book_version import BookVersion
|
||||
from .collection import Collection
|
||||
from .section import Section
|
||||
from .interpretation import Interpretation
|
||||
from .comment import Comment
|
||||
from .comment_vote import CommentVote
|
||||
from .interpretation_vote import InterpretationVote
|
||||
from .tag import Tag
|
||||
from .interpretation_tag import InterpretationTag
|
||||
from .comment_tag import CommentTags
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class Book(BaseModel):
|
||||
__tablename__ = "books"
|
||||
|
||||
label = db.Column(db.String(1024), unique=False, nullable=False)
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.ForeignKey("users.id"))
|
||||
|
||||
# Relationships
|
||||
owner = db.relationship("User", viewonly=True)
|
||||
stars = db.relationship("User", secondary="books_stars", back_populates="stars")
|
||||
contributors = db.relationship("BookContributor")
|
||||
versions = db.relationship("BookVersion")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.label}>"
|
|
@ -0,0 +1,26 @@
|
|||
from enum import IntEnum
|
||||
|
||||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class BookContributor(BaseModel):
|
||||
__tablename__ = "book_contributors"
|
||||
|
||||
class Roles(IntEnum):
|
||||
UNKNOWN = 10
|
||||
MODERATOR = 1
|
||||
EDITOR = 2
|
||||
|
||||
role = db.Column(db.Enum(Roles), default=Roles.MODERATOR)
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||
book_id = db.Column(db.Integer, db.ForeignKey("books.id"))
|
||||
|
||||
# Relationships
|
||||
user = db.relationship("User", viewonly=True)
|
||||
book = db.relationship("Book", viewonly=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.label}>"
|
|
@ -0,0 +1,26 @@
|
|||
from datetime import datetime
|
||||
|
||||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class BookVersion(BaseModel):
|
||||
__tablename__ = "book_versions"
|
||||
|
||||
# need to redeclare id to use it in the derivative relationship
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
semver = db.Column(db.String(1024), unique=False, nullable=False)
|
||||
exported = db.Column(db.Boolean, default=False)
|
||||
updated_at = db.Column(db.DateTime, default=datetime.now)
|
||||
|
||||
# Foreign keys
|
||||
derivative_id = db.Column(db.Integer, db.ForeignKey("book_versions.id"))
|
||||
book_id = db.Column(db.Integer, db.ForeignKey("books.id"))
|
||||
|
||||
# Relationships
|
||||
book = db.relationship("Book", viewonly=True)
|
||||
derivative = db.relationship("BookVersion", remote_side=[id])
|
||||
sections = db.relationship("Section", viewonly=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.semver}>"
|
|
@ -0,0 +1,17 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class BookStar(BaseModel):
|
||||
__tablename__ = "books_stars"
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||
book_id = db.Column(db.Integer, db.ForeignKey("books.id"))
|
||||
|
||||
# Relationships
|
||||
user = db.relationship("User", viewonly=True)
|
||||
book = db.relationship("Book", viewonly=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.user} to {self.book}>"
|
|
@ -0,0 +1,28 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class Collection(BaseModel):
|
||||
__tablename__ = "collections"
|
||||
|
||||
# need to redeclare id to use it in the parrent relationship
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
label = db.Column(db.String(1024), unique=False, nullable=False)
|
||||
about = db.Column(db.Text, unique=False, nullable=False)
|
||||
is_root = db.Column(db.Boolean, default=False)
|
||||
is_leaf = db.Column(db.Boolean, default=False)
|
||||
|
||||
# Foreign keys
|
||||
version_id = db.Column(db.ForeignKey("book_versions.id"))
|
||||
parrent_id = db.Column(db.ForeignKey("collections.id"))
|
||||
|
||||
# Relationships
|
||||
version = db.relationship("BookVersion")
|
||||
parrent = db.relationship("Collection", remote_side=[id])
|
||||
children = db.relationship(
|
||||
"Collection", backref=db.backref("parent", remote_side=[id]), viewonly=True
|
||||
)
|
||||
sections = db.relationship("Section")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.label}>"
|
|
@ -0,0 +1,34 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class Comment(BaseModel):
|
||||
__tablename__ = "comments"
|
||||
|
||||
# need to redeclare id to use it in the parrent relationship
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
text = db.Column(db.Text, unique=False, nullable=False)
|
||||
marked = db.Column(db.Boolean, default=False)
|
||||
included_with_interpreation = db.Column(db.Boolean, default=False)
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.ForeignKey("users.id"))
|
||||
parrent_id = db.Column(db.ForeignKey("comments.id"))
|
||||
interpretation_id = db.Column(db.ForeignKey("interpretations.id"))
|
||||
|
||||
# Relationships
|
||||
user = db.relationship("User")
|
||||
parrent = db.relationship("Comment", remote_side=[id])
|
||||
children = db.relationship(
|
||||
"Comment", backref=db.backref("parent", remote_side=[id]), viewonly=True
|
||||
)
|
||||
interpretation = db.relationship("Interpretation")
|
||||
votes = db.relationship("CommentVote")
|
||||
tags = db.relationship(
|
||||
"Tag",
|
||||
secondary="comment_tags",
|
||||
back_populates="comments",
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.text[:20]}>"
|
|
@ -0,0 +1,13 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class CommentTags(BaseModel):
|
||||
__tablename__ = "comment_tags"
|
||||
|
||||
# Foreign keys
|
||||
tag_id = db.Column(db.Integer, db.ForeignKey("tags.id"))
|
||||
comment_id = db.Column(db.Integer, db.ForeignKey("comments.id"))
|
||||
|
||||
def __repr__(self):
|
||||
return f"<t:{self.tag} to c:{self.comment}"
|
|
@ -0,0 +1,18 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class CommentVote(BaseModel):
|
||||
__tablename__ = "comment_votes"
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||
comment_id = db.Column(db.Integer, db.ForeignKey("comments.id"))
|
||||
possitive = db.Column(db.Boolean, default=True)
|
||||
|
||||
# Relationships
|
||||
user = db.relationship("User", viewonly=True)
|
||||
comment = db.relationship("Comment", viewonly=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.user} to {self.comment} Positive:{self.possitive}>"
|
|
@ -0,0 +1,28 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class Interpretation(BaseModel):
|
||||
__tablename__ = "interpretations"
|
||||
|
||||
label = db.Column(db.String(1024), unique=False, nullable=False)
|
||||
text = db.Column(db.Text, unique=False, nullable=False)
|
||||
marked = db.Column(db.Boolean, default=False)
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.ForeignKey("users.id"))
|
||||
section_id = db.Column(db.ForeignKey("sections.id"))
|
||||
|
||||
# Relationships
|
||||
user = db.relationship("User")
|
||||
section = db.relationship("Section")
|
||||
comments = db.relationship("Comment", viewonly=True)
|
||||
votes = db.relationship("InterpretationVote", viewonly=True)
|
||||
tags = db.relationship(
|
||||
"Tag",
|
||||
secondary="interpretation_tags",
|
||||
back_populates="interpretations",
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.label}>"
|
|
@ -0,0 +1,13 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class InterpretationTag(BaseModel):
|
||||
__tablename__ = "interpretation_tags"
|
||||
|
||||
# Foreign keys
|
||||
tag_id = db.Column(db.Integer, db.ForeignKey("tags.id"))
|
||||
interpretation_id = db.Column(db.Integer, db.ForeignKey("interpretations.id"))
|
||||
|
||||
def __repr__(self):
|
||||
return f"<t:{self.tag_id} to i:{self.interpretation_id}"
|
|
@ -0,0 +1,18 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class InterpretationVote(BaseModel):
|
||||
__tablename__ = "interpretation_votes"
|
||||
|
||||
# Foreign keys
|
||||
user_id = db.Column(db.Integer, db.ForeignKey("users.id"))
|
||||
interpretation_id = db.Column(db.Integer, db.ForeignKey("interpretations.id"))
|
||||
possitive = db.Column(db.Boolean, default=True)
|
||||
|
||||
# Relationships
|
||||
user = db.relationship("User", viewonly=True)
|
||||
interpretation = db.relationship("Interpretation", viewonly=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.user} to {self.interpretation} Positive:{self.possitive}>"
|
|
@ -0,0 +1,24 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class Section(BaseModel):
|
||||
__tablename__ = "sections"
|
||||
|
||||
label = db.Column(db.String(1024), unique=False, nullable=False)
|
||||
about = db.Column(db.Text, unique=False, nullable=True)
|
||||
|
||||
# Foreign keys
|
||||
collection_id = db.Column(db.ForeignKey("collections.id"))
|
||||
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)
|
||||
|
||||
# Relationships
|
||||
collection = db.relationship("Collection", viewonly=True)
|
||||
user = db.relationship("User", viewonly=True)
|
||||
version = db.relationship("BookVersion", viewonly=True)
|
||||
interpretations = db.relationship("Interpretation", viewonly=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.label}>"
|
|
@ -0,0 +1,19 @@
|
|||
from app import db
|
||||
from app.models.utils import BaseModel
|
||||
|
||||
|
||||
class Tag(BaseModel):
|
||||
__tablename__ = "tags"
|
||||
|
||||
name = db.Column(db.String(32), unique=True, nullable=False)
|
||||
|
||||
# Relationships
|
||||
interpretations = db.relationship(
|
||||
"Interpretation", secondary="interpretation_tags", back_populates="tags"
|
||||
)
|
||||
comments = db.relationship(
|
||||
"Comment", secondary="comment_tags", back_populates="tags"
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.name}>"
|
|
@ -1,4 +1,3 @@
|
|||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
|
||||
from flask_login import UserMixin, AnonymousUserMixin
|
||||
|
@ -7,7 +6,7 @@ from sqlalchemy.ext.hybrid import hybrid_property
|
|||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
|
||||
from app import db
|
||||
from app.models.utils import ModelMixin
|
||||
from app.models.utils import BaseModel
|
||||
from app.logger import log
|
||||
from app import schema as s
|
||||
|
||||
|
@ -16,18 +15,15 @@ def gen_password_reset_id() -> str:
|
|||
return str(uuid4())
|
||||
|
||||
|
||||
class User(db.Model, UserMixin, ModelMixin):
|
||||
|
||||
class User(BaseModel, UserMixin):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(60), unique=True, nullable=False)
|
||||
email = db.Column(db.String(255), unique=True, nullable=False)
|
||||
password_hash = db.Column(db.String(255), default="")
|
||||
activated = db.Column(db.Boolean, default=False)
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
unique_id = db.Column(db.String(36), default=gen_password_reset_id)
|
||||
reset_password_uid = db.Column(db.String(64), default=gen_password_reset_id)
|
||||
|
||||
# Relationships
|
||||
stars = db.relationship("Book", secondary="books_stars", back_populates="stars")
|
||||
books = db.relationship("Book")
|
||||
|
||||
@hybrid_property
|
||||
def password(self):
|
||||
|
@ -40,10 +36,7 @@ class User(db.Model, UserMixin, ModelMixin):
|
|||
@classmethod
|
||||
def authenticate(cls, user_id, password):
|
||||
user = cls.query.filter(
|
||||
db.or_(
|
||||
func.lower(cls.username) == func.lower(user_id),
|
||||
func.lower(cls.email) == func.lower(user_id),
|
||||
)
|
||||
).first()
|
||||
if not user:
|
||||
log(log.WARNING, "user:[%s] not found", user_id)
|
||||
|
@ -51,13 +44,8 @@ class User(db.Model, UserMixin, ModelMixin):
|
|||
if user is not None and check_password_hash(user.password, password):
|
||||
return user
|
||||
|
||||
def reset_password(self):
|
||||
self.password_hash = ""
|
||||
self.reset_password_uid = gen_password_reset_id()
|
||||
self.save()
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.id}: {self.username},{self.email}>"
|
||||
return f"<{self.id}: {self.username}>"
|
||||
|
||||
@property
|
||||
def json(self):
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
from datetime import datetime
|
||||
|
||||
from app import db
|
||||
|
||||
|
||||
|
@ -10,4 +12,12 @@ class ModelMixin(object):
|
|||
return self
|
||||
|
||||
|
||||
class BaseModel(db.Model, ModelMixin):
|
||||
__abstract__ = True
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
created_at = db.Column(db.DateTime, default=datetime.now)
|
||||
is_deleted = db.Column(db.Boolean, default=False)
|
||||
|
||||
|
||||
# Add your own utility classes and functions here.
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -27,7 +27,6 @@
|
|||
>
|
||||
<div class="pl-3">
|
||||
<div class="text-base font-semibold">{{ user.username }}</div>
|
||||
<div class="font-normal text-gray-500"><a class="hover:text-blue-500" href="mailto:{{ user.email }}">{{ user.email }}</a></div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="p-4 text-base font-normal text-gray-900 whitespace-nowrap dark:text-white">
|
||||
|
|
|
@ -23,7 +23,7 @@ def get_all():
|
|||
q = request.args.get("q", type=str, default=None)
|
||||
users = m.User.query.order_by(m.User.id)
|
||||
if q:
|
||||
users = users.filter(m.User.username.like(f"{q}%") | m.User.email.like(f"{q}%"))
|
||||
users = users.filter(m.User.username.like(f"{q}%"))
|
||||
|
||||
pagination = create_pagination(total=users.count())
|
||||
|
||||
|
@ -45,7 +45,6 @@ def save():
|
|||
log(log.ERROR, "Not found user by id : [%s]", form.user_id.data)
|
||||
flash("Cannot save user data", "danger")
|
||||
u.username = form.username.data
|
||||
u.email = form.email.data
|
||||
u.activated = form.activated.data
|
||||
if form.password.data.strip("*\n "):
|
||||
u.password = form.password.data
|
||||
|
@ -67,7 +66,6 @@ def create():
|
|||
if form.validate_on_submit():
|
||||
user = m.User(
|
||||
username=form.username.data,
|
||||
email=form.email.data,
|
||||
password=form.password.data,
|
||||
activated=form.activated.data,
|
||||
)
|
||||
|
|
|
@ -18,7 +18,6 @@ class BaseConfig(BaseSettings):
|
|||
|
||||
# Super admin
|
||||
ADMIN_USERNAME: str
|
||||
ADMIN_EMAIL: str
|
||||
ADMIN_PASSWORD: str
|
||||
|
||||
# Pagination
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: 02f6f2ebad1b
|
||||
Revises:
|
||||
Create Date: 2023-04-21 17:26:06.003994
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '02f6f2ebad1b'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
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=60), nullable=False),
|
||||
sa.Column('password_hash', sa.String(length=255), 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=1024), nullable=False),
|
||||
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('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_versions',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('semver', sa.String(length=1024), 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('collections',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('label', sa.String(length=1024), nullable=False),
|
||||
sa.Column('about', sa.Text(), nullable=False),
|
||||
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('parrent_id', sa.Integer(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('is_deleted', sa.Boolean(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['parrent_id'], ['collections.id'], ),
|
||||
sa.ForeignKeyConstraint(['version_id'], ['book_versions.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_table('sections',
|
||||
sa.Column('label', sa.String(length=1024), nullable=False),
|
||||
sa.Column('about', sa.Text(), nullable=True),
|
||||
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('label', sa.String(length=1024), nullable=False),
|
||||
sa.Column('text', sa.Text(), nullable=False),
|
||||
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('comments',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('text', sa.Text(), nullable=False),
|
||||
sa.Column('marked', sa.Boolean(), nullable=True),
|
||||
sa.Column('included_with_interpreation', sa.Boolean(), nullable=True),
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('parrent_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(['parrent_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_votes',
|
||||
sa.Column('user_id', sa.Integer(), nullable=True),
|
||||
sa.Column('interpretation_id', sa.Integer(), nullable=True),
|
||||
sa.Column('possitive', 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('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('possitive', 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('interpretation_votes')
|
||||
op.drop_table('interpretation_tags')
|
||||
op.drop_table('comments')
|
||||
op.drop_table('interpretations')
|
||||
op.drop_table('sections')
|
||||
op.drop_table('collections')
|
||||
op.drop_table('books_stars')
|
||||
op.drop_table('book_versions')
|
||||
op.drop_table('book_contributors')
|
||||
op.drop_table('books')
|
||||
op.drop_table('users')
|
||||
op.drop_table('tags')
|
||||
# ### end Alembic commands ###
|
|
@ -1,40 +0,0 @@
|
|||
"""init
|
||||
|
||||
Revision ID: 766427519c34
|
||||
Revises:
|
||||
Create Date: 2023-04-07 19:36:58.671750
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '766427519c34'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('users',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('username', sa.String(length=60), nullable=False),
|
||||
sa.Column('email', sa.String(length=255), nullable=False),
|
||||
sa.Column('password_hash', sa.String(length=255), nullable=True),
|
||||
sa.Column('activated', sa.Boolean(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('unique_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('reset_password_uid', sa.String(length=64), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
sa.UniqueConstraint('email'),
|
||||
sa.UniqueConstraint('username')
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_table('users')
|
||||
# ### end Alembic commands ###
|
|
@ -21,7 +21,6 @@ LOCAL_WEB_PORT=8080
|
|||
|
||||
# Super admin
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_EMAIL=simple2b.info@gmail.com
|
||||
ADMIN_PASSWORD=admin
|
||||
|
||||
# Pagination
|
||||
|
|
|
@ -97,8 +97,6 @@ function editUser(user: IUser) {
|
|||
input.value = user.username;
|
||||
input = document.querySelector('#user-edit-id');
|
||||
input.value = user.id.toString();
|
||||
input = document.querySelector('#user-edit-email');
|
||||
input.value = user.email;
|
||||
input = document.querySelector('#user-edit-password');
|
||||
input.value = '*******';
|
||||
input = document.querySelector('#user-edit-password_confirmation');
|
||||
|
|
|
@ -50,7 +50,6 @@ def populate(client: FlaskClient):
|
|||
for i in range(NUM_TEST_USERS):
|
||||
m.User(
|
||||
username=f"user{i+1}",
|
||||
email=f"user{i+1}@mail.com",
|
||||
password="password",
|
||||
).save(False)
|
||||
db.session.commit()
|
||||
|
|
|
@ -4,7 +4,6 @@ from sqlalchemy import func
|
|||
from app import db
|
||||
from app import models as m
|
||||
|
||||
|
||||
faker = Faker()
|
||||
|
||||
NUM_TEST_USERS = 100
|
||||
|
@ -34,13 +33,3 @@ def gen_test_items(num_objects: int) -> Generator[str, None, None]:
|
|||
|
||||
# email formatting
|
||||
yield f"{first_name}{i}".lower(), f"{first_name}.{last_name}{i}@{company}.{dns_org}".lower()
|
||||
|
||||
|
||||
def populate(count: int = NUM_TEST_USERS):
|
||||
for username, email in gen_test_items(count):
|
||||
m.User(
|
||||
username=username,
|
||||
email=email,
|
||||
).save(False)
|
||||
|
||||
db.session.commit()
|
||||
|
|
|
@ -0,0 +1,272 @@
|
|||
from app import models as m
|
||||
|
||||
|
||||
def create_dummy_data():
|
||||
user = m.User(username="Dummy User 1", password="Dummy Password").save()
|
||||
user_2 = m.User(username="Dummy User 2", password="Dummy Password").save()
|
||||
user_3 = m.User(username="Dummy User 3", password="Dummy Password").save()
|
||||
user_4 = m.User(username="Dummy User 4", password="Dummy Password").save()
|
||||
|
||||
book = m.Book(label="Dummy Book", user_id=user.id).save()
|
||||
|
||||
m.BookStar(user_id=user.id, book_id=book.id).save()
|
||||
|
||||
moderator = m.User(username="Dummy Moderator", password="Dummy Password").save()
|
||||
m.BookContributor(
|
||||
user_id=moderator.id, book_id=book.id, role=m.BookContributor.Roles.MODERATOR
|
||||
).save()
|
||||
|
||||
editor = m.User(username="Dummy Editor", password="Dummy Password").save()
|
||||
m.BookContributor(
|
||||
user_id=editor.id, book_id=book.id, role=m.BookContributor.Roles.EDITOR
|
||||
).save()
|
||||
|
||||
exported_version = m.BookVersion(
|
||||
semver="1.0.0", book_id=book.id, exported=True
|
||||
).save()
|
||||
unexported_version = m.BookVersion(
|
||||
semver="1.0.1", book_id=book.id, exported=False, derivative=exported_version
|
||||
).save()
|
||||
|
||||
# collections
|
||||
|
||||
# root
|
||||
# - collection 1 (leaf)
|
||||
# - collection 2
|
||||
# - subcollection 2.1 (leaf)
|
||||
|
||||
# root
|
||||
rool_collection = m.Collection(
|
||||
label="Dummy Root Collection Label",
|
||||
about="Dummy Root Collection About",
|
||||
is_root=True,
|
||||
version_id=unexported_version.id,
|
||||
).save()
|
||||
|
||||
collection_1 = m.Collection(
|
||||
label="Dummy Collection 1 Label",
|
||||
about="Dummy Collection 1 About",
|
||||
version_id=unexported_version.id,
|
||||
parrent_id=rool_collection.id,
|
||||
is_leaf=True,
|
||||
).save()
|
||||
|
||||
collection_2 = m.Collection(
|
||||
label="Dummy Collection 2 Label",
|
||||
about="Dummy Collection 2 About",
|
||||
version_id=unexported_version.id,
|
||||
parrent_id=rool_collection.id,
|
||||
).save()
|
||||
|
||||
subcollection_2_1 = m.Collection(
|
||||
label="Dummy SubCollection 2.1 Label",
|
||||
about="Dummy SubCollection 2.1 About",
|
||||
is_leaf=True,
|
||||
version_id=unexported_version.id,
|
||||
parrent_id=collection_2.id,
|
||||
).save()
|
||||
|
||||
# sections
|
||||
|
||||
# root
|
||||
# - collection 1 (leaf)
|
||||
# - section 1.1
|
||||
# - collection 2
|
||||
# - subcollection 2.1 (leaf)
|
||||
# - section 2.1.1
|
||||
# - section 2.1.2
|
||||
|
||||
section_1_1 = m.Section(
|
||||
label="Dummy Section 1.1 Label",
|
||||
about="Dummy Section 1.1 About",
|
||||
collection_id=collection_1.id,
|
||||
version_id=collection_1.version_id,
|
||||
user_id=user.id,
|
||||
).save()
|
||||
|
||||
section_2_1_1 = m.Section(
|
||||
label="Dummy Section 2.1.1 Label",
|
||||
about="Dummy Section 2.1.1 About",
|
||||
collection_id=subcollection_2_1.id,
|
||||
version_id=unexported_version.id,
|
||||
user_id=user.id,
|
||||
).save()
|
||||
|
||||
section_2_1_2 = m.Section(
|
||||
label="Dummy Section 2.1.2 Label",
|
||||
about="Dummy Section 2.1.2 About",
|
||||
collection_id=subcollection_2_1.id,
|
||||
version_id=unexported_version.id,
|
||||
user_id=user.id,
|
||||
).save()
|
||||
|
||||
# root
|
||||
# - collection 1 (leaf)
|
||||
# - section 1.1
|
||||
# - interpretation 1
|
||||
# - collection 2
|
||||
# - subcollection 2.1 (leaf)
|
||||
# - section 2.1.1
|
||||
# - interpretation 2 (marked)
|
||||
# - section 2.1.2
|
||||
# - interpretation 3 (marked)
|
||||
# - interpretation 4
|
||||
|
||||
interpretation_1 = m.Interpretation(
|
||||
label="Dummy Interpretation 1 Label",
|
||||
text="Dummy Interpretation 1 About",
|
||||
section_id=section_1_1.id,
|
||||
user_id=user.id,
|
||||
).save()
|
||||
|
||||
interpretation_2 = m.Interpretation(
|
||||
label="Dummy Interpretation 2 Label",
|
||||
text="Dummy Interpretation 2 About",
|
||||
section_id=section_2_1_1.id,
|
||||
user_id=user.id,
|
||||
marked=True,
|
||||
).save()
|
||||
|
||||
interpretation_3 = m.Interpretation(
|
||||
label="Dummy Interpretation 3 Label",
|
||||
text="Dummy Interpretation 3 About",
|
||||
section_id=section_2_1_2.id,
|
||||
user_id=user.id,
|
||||
marked=True,
|
||||
).save()
|
||||
|
||||
m.Interpretation(
|
||||
label="Dummy Interpretation 4 Label",
|
||||
text="Dummy Interpretation 4 About",
|
||||
section_id=section_2_1_2.id,
|
||||
user_id=user.id,
|
||||
).save()
|
||||
|
||||
# comments
|
||||
# - interpretation 2
|
||||
# - comment 1
|
||||
# - comment 1.1
|
||||
# - comment 1.2 (marked)
|
||||
# - comment 2
|
||||
# - comment 3
|
||||
# - comment 3.1 (marked)
|
||||
# - comment 3.2 (included_with_interpreation)
|
||||
# - comment 3.3
|
||||
|
||||
comment_1 = m.Comment(
|
||||
text="Dummy Comment 1 Text",
|
||||
user_id=user_2.id,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
m.Comment(
|
||||
text="Dummy Comment 1.1 Text",
|
||||
user_id=user_3.id,
|
||||
parrent_id=comment_1.id,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
m.Comment(
|
||||
text="Dummy Comment 1.2 Text",
|
||||
user_id=user_2.id,
|
||||
parrent_id=comment_1.id,
|
||||
marked=True,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
comment_2 = m.Comment(
|
||||
text="Dummy Comment 2 Text",
|
||||
user_id=user_4.id,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
comment_3 = m.Comment(
|
||||
text="Dummy Comment 3 Text",
|
||||
user_id=user.id,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
comment_3_1 = m.Comment(
|
||||
text="Dummy Comment 3.1 Text",
|
||||
user_id=user.id,
|
||||
marked=True,
|
||||
parrent_id=comment_3.id,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
comment_3_2 = m.Comment(
|
||||
text="Dummy Comment 3.2 Text",
|
||||
user_id=user.id,
|
||||
included_with_interpreation=True,
|
||||
parrent_id=comment_3.id,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
comment_3_3 = m.Comment(
|
||||
text="Dummy Comment 3.3 Text",
|
||||
user_id=user.id,
|
||||
parrent_id=comment_3.id,
|
||||
interpretation_id=interpretation_2.id,
|
||||
).save()
|
||||
|
||||
# - comment 3.1 (2 possitive, 2 negative)
|
||||
# - comment 3.2 (1 negative)
|
||||
# - comment 3.3 (1 possitive)
|
||||
m.CommentVote(comment_id=comment_3_1.id, user_id=user.id, possitive=True).save()
|
||||
m.CommentVote(comment_id=comment_3_1.id, user_id=user_2.id, possitive=True).save()
|
||||
m.CommentVote(comment_id=comment_3_1.id, user_id=user_3.id, possitive=False).save()
|
||||
m.CommentVote(comment_id=comment_3_1.id, user_id=user_4.id, possitive=False).save()
|
||||
m.CommentVote(comment_id=comment_3_2.id, user_id=user_2.id, possitive=False).save()
|
||||
m.CommentVote(comment_id=comment_3_3.id, user_id=user_3.id, possitive=True).save()
|
||||
|
||||
# - interpretation 1 (2 possitive, 1 negative)
|
||||
# - interpretation 2 (1 negative)
|
||||
# - interpretation 3 (1 possitive)
|
||||
m.InterpretationVote(
|
||||
interpretation_id=interpretation_1.id, user_id=user.id, possitive=True
|
||||
).save()
|
||||
m.InterpretationVote(
|
||||
interpretation_id=interpretation_1.id, user_id=user_2.id, possitive=True
|
||||
).save()
|
||||
m.InterpretationVote(
|
||||
interpretation_id=interpretation_1.id, user_id=user_3.id, possitive=False
|
||||
).save()
|
||||
m.InterpretationVote(
|
||||
interpretation_id=interpretation_2.id, user_id=user_2.id, possitive=False
|
||||
).save()
|
||||
m.InterpretationVote(
|
||||
interpretation_id=interpretation_3.id, user_id=user_3.id, possitive=True
|
||||
).save()
|
||||
|
||||
# tags
|
||||
tag_1 = m.Tag(name="Dummy Tag 1").save()
|
||||
tag_2 = m.Tag(name="Dummy Tag 2").save()
|
||||
tag_3 = m.Tag(name="Dummy Tag 3").save()
|
||||
|
||||
# interpretation tags
|
||||
|
||||
# - interpretation 1
|
||||
# - tags: 1,
|
||||
# - interpretation 2
|
||||
# - tags: 2, 3
|
||||
# - interpretation 3
|
||||
# - tags: 1, 3
|
||||
m.InterpretationTag(interpretation_id=interpretation_1.id, tag_id=tag_1.id).save()
|
||||
m.InterpretationTag(interpretation_id=interpretation_2.id, tag_id=tag_2.id).save()
|
||||
m.InterpretationTag(interpretation_id=interpretation_2.id, tag_id=tag_3.id).save()
|
||||
m.InterpretationTag(interpretation_id=interpretation_3.id, tag_id=tag_1.id).save()
|
||||
m.InterpretationTag(interpretation_id=interpretation_3.id, tag_id=tag_3.id).save()
|
||||
|
||||
# commen tags
|
||||
|
||||
# - comment 1
|
||||
# - tags: 1,
|
||||
# - comment 2
|
||||
# - tags: 2, 3
|
||||
# - comment 3
|
||||
# - tags: 1, 3
|
||||
m.CommentTags(comment_id=comment_1.id, tag_id=tag_1.id).save()
|
||||
m.CommentTags(comment_id=comment_2.id, tag_id=tag_2.id).save()
|
||||
m.CommentTags(comment_id=comment_2.id, tag_id=tag_3.id).save()
|
||||
m.CommentTags(comment_id=comment_3.id, tag_id=tag_1.id).save()
|
||||
m.CommentTags(comment_id=comment_3.id, tag_id=tag_3.id).save()
|
|
@ -0,0 +1,285 @@
|
|||
from flask.testing import FlaskCliRunner
|
||||
from click.testing import Result
|
||||
from app import models as m
|
||||
|
||||
|
||||
def test_dummy_data(runner: FlaskCliRunner):
|
||||
res: Result = runner.invoke(args=["db-populate"])
|
||||
assert "Dummy data added" in res.output, res.stderr
|
||||
|
||||
user: m.User = m.User.query.filter_by(username="Dummy User 1").first()
|
||||
book: m.Book = m.Book.query.filter_by(label="Dummy Book").first()
|
||||
|
||||
assert user
|
||||
assert user.books
|
||||
assert book in user.books
|
||||
|
||||
# stars
|
||||
book_star: m.BookStar = m.BookStar.query.first()
|
||||
assert book.stars
|
||||
assert user.stars
|
||||
assert book_star
|
||||
assert book_star.user_id == user.id
|
||||
assert book_star.book_id == book.id
|
||||
|
||||
# contributors
|
||||
assert book.contributors
|
||||
assert len(book.contributors) == 2
|
||||
|
||||
moderator: m.User = m.User.query.filter_by(username="Dummy Moderator").first()
|
||||
book_moderator: m.BookContributor = m.BookContributor.query.filter_by(
|
||||
role=m.BookContributor.Roles.MODERATOR
|
||||
).first()
|
||||
|
||||
assert book_moderator
|
||||
assert book_moderator.book_id == book.id
|
||||
assert book_moderator.user_id == moderator.id
|
||||
|
||||
editor: m.User = m.User.query.filter_by(username="Dummy Editor").first()
|
||||
book_editor: m.BookContributor = m.BookContributor.query.filter_by(
|
||||
role=m.BookContributor.Roles.EDITOR
|
||||
).first()
|
||||
assert book_editor
|
||||
assert book_editor.book_id == book.id
|
||||
assert book_editor.user_id == editor.id
|
||||
|
||||
# versions
|
||||
assert book.versions
|
||||
|
||||
exported_version: m.BookVersion = m.BookVersion.query.filter_by(
|
||||
book=book, exported=True
|
||||
).first()
|
||||
assert exported_version.exported
|
||||
assert exported_version.book_id == book.id
|
||||
assert not exported_version.derivative_id
|
||||
|
||||
unexported_version: m.BookVersion = m.BookVersion.query.filter_by(
|
||||
book=book, exported=False
|
||||
).first()
|
||||
assert not unexported_version.exported
|
||||
assert unexported_version.derivative == exported_version
|
||||
assert unexported_version.book_id == book.id
|
||||
|
||||
# collections
|
||||
|
||||
# root
|
||||
# - collection 1 (leaf)
|
||||
# - collection 2
|
||||
# - subcollection 2.1 (leaf)
|
||||
|
||||
root_collection: m.Collection = m.Collection.query.filter_by(
|
||||
label="Dummy Root Collection Label"
|
||||
).first()
|
||||
|
||||
assert root_collection
|
||||
assert root_collection.is_root
|
||||
assert not root_collection.is_leaf
|
||||
assert root_collection.version == unexported_version
|
||||
|
||||
collection_1: m.Collection = m.Collection.query.filter_by(
|
||||
label="Dummy Collection 1 Label"
|
||||
).first()
|
||||
|
||||
assert collection_1
|
||||
assert not collection_1.is_root
|
||||
assert collection_1.is_leaf
|
||||
assert collection_1.version == unexported_version
|
||||
|
||||
collection_2: m.Collection = m.Collection.query.filter_by(
|
||||
label="Dummy Collection 2 Label"
|
||||
).first()
|
||||
|
||||
assert collection_2
|
||||
assert not collection_2.is_leaf
|
||||
assert not collection_2.is_root
|
||||
assert collection_2.version == unexported_version
|
||||
|
||||
subcollection_2_1: m.Collection = m.Collection.query.filter_by(
|
||||
label="Dummy SubCollection 2.1 Label"
|
||||
).first()
|
||||
|
||||
assert subcollection_2_1
|
||||
assert subcollection_2_1.is_leaf
|
||||
assert not subcollection_2_1.is_root
|
||||
|
||||
# root
|
||||
# - collection 1 (leaf)
|
||||
# - section 1.1
|
||||
# - collection 2
|
||||
# - subcollection 2.1 (leaf)
|
||||
# - section 2.1.1
|
||||
# - section 2.1.2
|
||||
|
||||
section_1_1: m.Section = m.Section.query.filter_by(
|
||||
label="Dummy Section 1.1 Label"
|
||||
).first()
|
||||
|
||||
assert section_1_1
|
||||
assert section_1_1.user == user
|
||||
assert section_1_1.collection == collection_1
|
||||
|
||||
section_2_1_1: m.Section = m.Section.query.filter_by(
|
||||
label="Dummy Section 2.1.1 Label"
|
||||
).first()
|
||||
|
||||
assert section_2_1_1
|
||||
assert section_2_1_1.user == user
|
||||
assert section_2_1_1.collection == subcollection_2_1
|
||||
|
||||
section_2_1_2: m.Section = m.Section.query.filter_by(
|
||||
label="Dummy Section 2.1.2 Label"
|
||||
).first()
|
||||
|
||||
assert section_2_1_2
|
||||
assert section_2_1_2.user == user
|
||||
assert section_2_1_2.collection == subcollection_2_1
|
||||
|
||||
# interpretations
|
||||
|
||||
# root
|
||||
# - collection 1 (leaf)
|
||||
# - section 1.1
|
||||
# - interpretation 1
|
||||
# - collection 2
|
||||
# - subcollection 2.1 (leaf)
|
||||
# - section 2.1.1
|
||||
# - interpretation 2 (marked)
|
||||
# - section 2.1.2
|
||||
# - interpretation 3 (marked)
|
||||
# - interpretation 4
|
||||
|
||||
interpretation_1: m.Interpretation = m.Interpretation.query.filter_by(
|
||||
label="Dummy Interpretation 1 Label"
|
||||
).first()
|
||||
|
||||
assert interpretation_1
|
||||
assert interpretation_1.user == user
|
||||
assert interpretation_1.section == section_1_1
|
||||
|
||||
interpretation_2: m.Interpretation = m.Interpretation.query.filter_by(
|
||||
label="Dummy Interpretation 2 Label"
|
||||
).first()
|
||||
|
||||
assert interpretation_2
|
||||
assert interpretation_2.marked
|
||||
assert interpretation_2.user == user
|
||||
assert interpretation_2.section == section_2_1_1
|
||||
|
||||
interpretation_3: m.Interpretation = m.Interpretation.query.filter_by(
|
||||
label="Dummy Interpretation 3 Label"
|
||||
).first()
|
||||
|
||||
assert interpretation_3
|
||||
assert interpretation_3.marked
|
||||
assert interpretation_3.user == user
|
||||
assert interpretation_3.section == section_2_1_2
|
||||
|
||||
interpretation_4: m.Interpretation = m.Interpretation.query.filter_by(
|
||||
label="Dummy Interpretation 3 Label"
|
||||
).first()
|
||||
|
||||
assert interpretation_4
|
||||
assert interpretation_4.user == user
|
||||
assert interpretation_4.section == section_2_1_2
|
||||
|
||||
# comments
|
||||
# - interpretation 2
|
||||
# - comment 1
|
||||
# - comment 1.1
|
||||
# - comment 1.2 (marked)
|
||||
# - comment 2
|
||||
# - comment 3
|
||||
# - comment 3.1 (marked)
|
||||
# - comment 3.2 (included_with_interpreation)
|
||||
# - comment 3.3
|
||||
|
||||
comment_1: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 1 Text"
|
||||
).first()
|
||||
|
||||
assert not comment_1.parrent
|
||||
|
||||
comment_1_1: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 1.1 Text"
|
||||
).first()
|
||||
|
||||
comment_1_2: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 1.2 Text"
|
||||
).first()
|
||||
|
||||
assert comment_1_1 in comment_1.children
|
||||
assert comment_1_1 in comment_1.children
|
||||
assert comment_1_2.parrent == comment_1
|
||||
assert comment_1_2.parrent == comment_1
|
||||
assert comment_1_2.marked
|
||||
|
||||
comment_2: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 2 Text"
|
||||
).first()
|
||||
|
||||
assert not comment_2.parrent
|
||||
assert not comment_2.children
|
||||
|
||||
comment_3: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 3 Text"
|
||||
).first()
|
||||
|
||||
assert not comment_3.parrent
|
||||
assert comment_3.children
|
||||
|
||||
comment_3_1: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 3.1 Text"
|
||||
).first()
|
||||
|
||||
comment_3_2: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 3.2 Text"
|
||||
).first()
|
||||
|
||||
comment_3_3: m.Comment = m.Comment.query.filter_by(
|
||||
text="Dummy Comment 3.3 Text"
|
||||
).first()
|
||||
|
||||
assert comment_3_1 in comment_3.children
|
||||
assert comment_3_2 in comment_3.children
|
||||
assert comment_3_3 in comment_3.children
|
||||
assert comment_3_1.marked
|
||||
assert comment_3_2.included_with_interpreation
|
||||
|
||||
assert comment_1 in interpretation_2.comments
|
||||
assert comment_2 in interpretation_2.comments
|
||||
assert comment_3 in interpretation_2.comments
|
||||
|
||||
# - comment 3.1 (2 possitive, 2 negative)
|
||||
# - comment 3.2 (1 negative)
|
||||
# - comment 3.3 (1 possitive)
|
||||
|
||||
assert len(comment_3_1.votes) == 4
|
||||
assert len(comment_3_2.votes) == 1
|
||||
assert len(comment_3_3.votes) == 1
|
||||
|
||||
# - interpretation 1 (2 possitive, 1 negative)
|
||||
# - interpretation 2 (1 negative)
|
||||
# - interpretation 3 (1 possitive)
|
||||
assert len(interpretation_1.votes) == 3
|
||||
assert len(interpretation_2.votes) == 1
|
||||
assert len(interpretation_3.votes) == 1
|
||||
|
||||
# interpretation tags
|
||||
# - tags: 1,
|
||||
# - interpretation 2
|
||||
# - tags: 2, 3
|
||||
# - interpretation 3
|
||||
# - tags: 1, 3
|
||||
assert len(interpretation_1.tags) == 1
|
||||
assert len(interpretation_2.tags) == 2
|
||||
assert len(interpretation_3.tags) == 2
|
||||
|
||||
# # - comment 1
|
||||
# # - tags: 1,
|
||||
# # - comment 2
|
||||
# # - tags: 2, 3
|
||||
# # - comment 3
|
||||
# # - tags: 1, 3
|
||||
# assert len(comment_1.tags) == 1
|
||||
# assert len(comment_2.tags) == 2
|
||||
# assert len(comment_3.tags) == 2
|
|
@ -36,14 +36,6 @@ def test_create_admin(runner: FlaskCliRunner):
|
|||
assert m.User.query.filter_by(username=app.config["ADMIN_USERNAME"]).first()
|
||||
|
||||
|
||||
def test_populate_db(runner: FlaskCliRunner):
|
||||
TEST_COUNT = 56
|
||||
count_before = m.User.query.count()
|
||||
res: Result = runner.invoke(args=["db-populate", "--count", f"{TEST_COUNT}"])
|
||||
assert f"populated by {TEST_COUNT}" in res.stdout
|
||||
assert (m.User.query.count() - count_before) == TEST_COUNT
|
||||
|
||||
|
||||
def test_delete_user(populate: FlaskClient):
|
||||
login(populate)
|
||||
users = m.User.query.all()
|
||||
|
|
|
@ -5,10 +5,8 @@ TEST_ADMIN_EMAIL = "bob@test.com"
|
|||
TEST_ADMIN_PASSWORD = "password"
|
||||
|
||||
|
||||
def create(
|
||||
username=TEST_ADMIN_NAME, email=TEST_ADMIN_EMAIL, password=TEST_ADMIN_PASSWORD
|
||||
):
|
||||
user = User(username=username, email=email)
|
||||
def create(username=TEST_ADMIN_NAME, password=TEST_ADMIN_PASSWORD):
|
||||
user = User(username=username)
|
||||
user.password = password
|
||||
user.save()
|
||||
return user.id
|
||||
|
|
Loading…
Reference in New Issue