class UserRoles(db.Model): __tablename__ = 'user_roles' id = db.Column(db.Integer(), primary_key=True) user_id = db.Column(db.Integer(), db.ForeignKey('user.user_id', ondelete='CASCADE')) role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE'))
class Result(db.Model): id = db.Column(db.Integer, primary_key=True) city = db.Column(db.String(30), unique=False, nullable=False) name = db.Column(db.String(100), unique=False, nullable=False) address = db.Column(db.String(300), unique=False, nullable=False) rating = db.Column(db.String(5), unique=False, nullable=False) distance = db.Column(db.String(10), unique=False, nullable=False) duration = db.Column(db.Integer(), unique=False, nullable=False) photo_url = db.Column(db.String()) def __repr__(self): return f"Result('{self.origin}, {self.name}', '{self.address}', '{self.rating}', '{self.distance}', '{self.duration}')"
class User(db.Model, UserMixin): id = db.Column(db.Integer(), primary_key=True) email = db.Column(db.String(length=50), nullable=False, unique=True) password = db.Column(db.String(length=30), nullable=False) ikon = db.Column(db.Integer(), default=0) epic = db.Column(db.Integer(), default=0) mc = db.Column(db.Integer(), default=0) powder = db.Column(db.Integer(), default=0) indy = db.Column(db.Integer(), default=0) fav1 = db.Column(db.String(length=100)) fav2 = db.Column(db.String(length=100)) fav3 = db.Column(db.String(length=100)) fav4 = db.Column(db.String(length=100))
class Location(db.Model): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(length=100), nullable=False, unique=True) state = db.Column(db.String(length=2), nullable=False) reigon = db.Column(db.String(length=20), nullable=False) lat = db.Column(db.String(length=100), nullable=False) lon = db.Column(db.String(length=100), nullable=False) ikon = db.Column(db.Integer(), default=0) epic = db.Column(db.Integer(), default=0) mc = db.Column(db.Integer(), default=0) powder = db.Column(db.Integer(), default=0) indy = db.Column(db.Integer(), default=0) forecast0 = db.Column(db.Float()) forecast1 = db.Column(db.Float()) forecast2 = db.Column(db.Float()) forecast3 = db.Column(db.Float()) forecast4 = db.Column(db.Float()) forecast5 = db.Column(db.Float()) forecast6 = db.Column(db.Float()) forecast7 = db.Column(db.Float()) forecast8 = db.Column(db.Float()) forecast9 = db.Column(db.Float())
class Comment(db.Model): # type: ignore __tablename__ = "comments" id = db.Column(db.Integer(), primary_key=True) body = db.Column(db.String(200), nullable=False) path = db.Column(db.Text(), index=True) created_at = db.Column( db.DateTime(timezone=True), server_default=sql.func.current_timestamp(), nullable=False, ) updated_at = db.Column( db.DateTime(timezone=True), onupdate=sql.func.current_timestamp(), ) thread_at = db.Column( db.DateTime(timezone=True), server_default=sql.func.current_timestamp(), nullable=False, ) replies = db.relationship( "Comment", cascade="all, delete", backref=db.backref("parent", remote_side=[id]), lazy="dynamic", ) author_id = db.Column(db.Integer(), db.ForeignKey("accounts.id")) blog_id = db.Column(db.Integer(), db.ForeignKey("blogs.id"), nullable=False) parent_id = db.Column(db.Integer(), db.ForeignKey("comments.id")) def __repr__(self): return f"<Comment {self.id} - {self.body}>" # Factories @classmethod def new( cls, *, body: str, author: Any, blog: Any, parent: Optional[Any] = None, thread_at: Optional[datetime.datetime] = None, ): # TODO: Make this a transaction comment = cls( body=body, author=author, blog=blog, parent=parent, thread_at=thread_at, ) db.session.add(comment) db.session.commit() comment.updated_at = None prefix = f"{comment.parent.path}." if comment.parent else "" comment.path = prefix + "{:0{}d}".format(comment.id, NUMBER_OF_DIGITS) db.session.commit() return comment # Mutators def update(self, **kwargs): """ Update Comment. """ allowed_attributes = [ "body", "author", ] for key, value in kwargs.items(): assert key in allowed_attributes setattr(self, key, value) db.session.commit() def delete(self): """ Delete Comment. """ db.session.delete(self) db.session.commit() # Properties @property def level(self): return len(self.path) // NUMBER_OF_DIGITS - 1
class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(50), unique=True)
class Category(db.Model): # type: ignore __tablename__ = "categories" id = db.Column(db.Integer(), primary_key=True) title = db.Column(db.String(100), index=True, unique=True, nullable=False) slug = db.Column(db.String(200), unique=True, nullable=False) description = db.Column(db.String(150), nullable=False) created_at = db.Column( db.DateTime(timezone=True), server_default=sql.func.current_timestamp(), nullable=False, ) updated_at = db.Column(db.DateTime(timezone=True), onupdate=sql.func.current_timestamp()) blogs = db.relationship("Blog", secondary=association_table, backref="categories") def __repr__(self): return f"<Category {self.title}>" @classmethod def new( cls, title: str, slug: str, description: str, ): """ Create a new Category in the database. Returns a Category. """ category = cls( title=title, slug=slug, description=description, ) db.session.add(category) db.session.commit() return category # Mutators def update(self, **kwargs): """ Update Category. """ allowed_attributes = ["title", "description"] for key, value in kwargs.items(): assert key in allowed_attributes setattr(self, key, value) db.session.commit() def delete(self): """ Delete Category. """ db.session.delete(self) db.session.commit()
# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from sqlalchemy import sql from website import db association_table = db.Table( "category_blog_association", db.Column("blogs_id", db.Integer(), db.ForeignKey("blogs.id")), db.Column("categories_id", db.Integer(), db.ForeignKey("categories.id")), ) class Category(db.Model): # type: ignore __tablename__ = "categories" id = db.Column(db.Integer(), primary_key=True) title = db.Column(db.String(100), index=True, unique=True, nullable=False) slug = db.Column(db.String(200), unique=True, nullable=False) description = db.Column(db.String(150), nullable=False) created_at = db.Column( db.DateTime(timezone=True), server_default=sql.func.current_timestamp(),
class Blog(db.Model): # type: ignore __tablename__ = "blogs" id = db.Column(db.Integer(), primary_key=True) title = db.Column(db.String(100), index=True, nullable=False) slug = db.Column(db.String(200), unique=True, nullable=False) description = db.Column(db.String(150)) body = db.Column(db.Text(), nullable=False) published = db.Column(db.Boolean(), nullable=False, default=False) comment = db.Column(db.Boolean(), nullable=False, default=False) created_at = db.Column( db.DateTime(timezone=True), server_default=sql.func.current_timestamp(), nullable=False, ) updated_at = db.Column(db.DateTime(timezone=True), onupdate=sql.func.current_timestamp()) author_id = db.Column(db.Integer(), db.ForeignKey("accounts.id"), nullable=True) comments = db.relationship("Comment", cascade="all, delete", backref="blog", lazy=True) def __repr__(self): return f"<Blog {self.title}>" # TODO: We need to prevent blank values. # @orm.validates("title") # def validate(self, key, value): # assert value # return value # Factories @classmethod def new( cls, title: str, slug: str, body: str, author: Any, description: Optional[str] = None, categories: Optional[List[Any]] = None, published: bool = False, comment: bool = False, ): """ Create a new Blog in the database. Returns a Blog. """ blog = cls( title=title, slug=slug, description=description, body=body, author=author, published=published, comment=comment, ) if categories: blog.categories = categories db.session.add(blog) db.session.commit() return blog # Mutators def update(self, **kwargs): """ Update Blog. """ allowed_attributes = [ "title", "description", "body", "author", "categories", "published", "comment", ] for key, value in kwargs.items(): assert key in allowed_attributes setattr(self, key, value) db.session.commit() def delete(self): """ Delete Blog. """ db.session.delete(self) db.session.commit() # Properties @property def is_published(self) -> bool: return self.published
class Account(db.Model, flask_login.UserMixin): # type: ignore __tablename__ = "accounts" id = db.Column(db.Integer(), primary_key=True) username = db.Column(db.String(64), index=True, unique=True, nullable=False) display = db.Column(db.String(100), nullable=False) email = db.Column(db.String(120), index=True, unique=True, nullable=False) password = db.Column(db.String(255), nullable=False) about = db.Column(db.String(300)) # Authorisation statuses. admin = db.Column(db.Boolean(), nullable=False, default=False, server_default="0") confirmed = db.Column(db.Boolean(), nullable=False, default=False) created_at = db.Column( db.DateTime(timezone=True), server_default=sql.func.current_timestamp(), nullable=False, ) updated_at = db.Column(db.DateTime(timezone=True), onupdate=sql.func.current_timestamp()) seen_at = db.Column(db.DateTime(timezone=True), onupdate=sql.func.current_timestamp()) blogs = db.relationship("Blog", backref="author", lazy=True) comments = db.relationship("Comment", backref="author", lazy=True) def __repr__(self): return f"<Account {self.username}>" @login.user_loader def load_account(account_id): return Account.query.get(ident=int(account_id)) @classmethod def new( cls, username: str, display: str, email: str, password: str, admin: bool = False, confirmed: bool = False, ): """ Create a new Account in the database. Password is hashed before being saved to the database. Returns an Account. """ hashed_password = cls._hash_password(password=password) account = cls( username=username, display=display if display else username, email=email, password=hashed_password, admin=admin, confirmed=confirmed, ) db.session.add(account) db.session.commit() return account # Mutators def update(self, **kwargs): """ Update Account. """ allowed_attributes = [ "username", "display", "email", "password", "about", "admin", "confirmed", "seen_at", ] for key, value in kwargs.items(): assert key in allowed_attributes if key == "display": if not value: value = self.username if key == "password": value = Account._hash_password(password=value) setattr(self, key, value) db.session.commit() def delete(self, delete_blogs: bool = False): """ Delete Account. Params: - `delete_blogs` whether the blogs associated to the Account should be deleted. If set to `False`, the blogs will instead be transferred to the default Account. """ # TODO: Make this an atomic transaction - i.e. all-or-nothing. for blog in self.blogs: if delete_blogs: blog.delete() else: blog.update(author=None) db.session.delete(self) db.session.commit() def check_password(self, password: str) -> bool: """ Check the password against saved hashed password. """ return security.check_password_hash(pwhash=self.password, password=password) # Properties @property def is_admin(self) -> bool: return self.admin @property def is_confirmed(self) -> bool: if flask.current_app.config["ACCOUNT_ALWAYS_CONFIRMED"]: return True return self.confirmed # Queries # Private @classmethod def _hash_password(cls, password: str) -> str: """ Return hashed password. """ return security.generate_password_hash(password=password)
class UserRoles(db.Model): id = db.Column(db.Integer(), primary_key=True) user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE')) role_id = db.Column(db.Integer(), db.ForeignKey('role.id', ondelete='CASCADE'))
class Role(db.Model): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(50), unique=True) def __repr__(self): return f"{self.name}"