From ee3b186ba16bf3b7fadb70265d480a6734741cb8 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 20 Aug 2021 11:08:32 +0300 Subject: [PATCH] model upgrade --- orm/__init__.py | 5 ++++- orm/notification.py | 10 +--------- orm/rating.py | 9 +++++++++ orm/shout.py | 27 ++++++++++++++++++++------- orm/topic.py | 18 ++++++++++++++++++ orm/user.py | 42 +++++++++++++++++++++++++----------------- resolvers/zine.py | 4 ++-- schema.graphql | 8 ++++++-- 8 files changed, 85 insertions(+), 38 deletions(-) create mode 100644 orm/rating.py create mode 100644 orm/topic.py diff --git a/orm/__init__.py b/orm/__init__.py index 864b432a..5671cc8f 100644 --- a/orm/__init__.py +++ b/orm/__init__.py @@ -1,10 +1,13 @@ from orm.rbac import Organization, Operation, Resource, Permission, Role from orm.user import User from orm.message import Message +from orm.topic import Topic +from orm.rating import Rating +from orm.notification import Notification from orm.shout import Shout from orm.base import Base, engine -__all__ = ["User", "Role", "Operation", "Permission", "Message", "Shout"] +__all__ = ["User", "Role", "Operation", "Permission", "Message", "Shout", "Topic", "Rating", "Notification"] Base.metadata.create_all(engine) Operation.init_table() diff --git a/orm/notification.py b/orm/notification.py index 32652403..6780ab12 100644 --- a/orm/notification.py +++ b/orm/notification.py @@ -6,12 +6,4 @@ class Notification(Base): kind: str = Column(String, unique = True, primary_key = True) template: str = Column(String, nullable = False) - variables: JSONType = Column(JSONType, nullable = True) # [ , .. ] - -class UserNotification(Base): - __tablename__ = 'user_notification' - - id: int = Column(Integer, primary_key = True) - user_id: int = Column(Integer, ForeignKey("user.id")) - kind: str = Column(String, ForeignKey("notification.kind")) - values: JSONType = Column(JSONType, nullable = True) # [ , .. ] \ No newline at end of file + variables: JSONType = Column(JSONType, nullable = True) # [ , .. ] \ No newline at end of file diff --git a/orm/rating.py b/orm/rating.py new file mode 100644 index 00000000..f4d867ac --- /dev/null +++ b/orm/rating.py @@ -0,0 +1,9 @@ +from sqlalchemy import Column, Integer, String, ForeignKey +# from orm import Permission +from orm.base import Base + +class Rating(Base): + __tablename__ = "rating" + + createdBy: int = Column(Integer, ForeignKey("user.id"), primary_key = True) + value: int = Column(Integer, nullable=False) diff --git a/orm/shout.py b/orm/shout.py index 80e46be0..d812276c 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -1,24 +1,37 @@ from typing import List from datetime import datetime -from sqlalchemy import Column, Integer, String, ForeignKey, DateTime - -from orm import Permission +from sqlalchemy import Table, Column, Integer, String, ForeignKey, DateTime, Boolean +from sqlalchemy.orm import relationship +from orm import Permission, User, Topic from orm.base import Base +ShoutAuthors = Table('shout_authors', + Base.metadata, + Column('shout', String, ForeignKey('shout.slug')), + Column('user_id', Integer, ForeignKey('user.id')) +) + +ShoutTopics = Table('shout_topics', + Base.metadata, + Column('shout', String, ForeignKey('shout.slug')), + Column('topic', String, ForeignKey('topic.slug')) +) class Shout(Base): __tablename__ = 'shout' slug: str = Column(String, primary_key=True) org_id: int = Column(Integer, ForeignKey("organization.id"), nullable=False, comment="Organization") - author_id: int = Column(Integer, ForeignKey("user.id"), nullable = False, comment="Author") body: str = Column(String, nullable=False, comment="Body") createdAt: str = Column(DateTime, nullable=False, default = datetime.now, comment="Created at") updatedAt: str = Column(DateTime, nullable=True, comment="Updated at") replyTo: str = Column(ForeignKey("shout.slug"), nullable=True) versionOf: str = Column(ForeignKey("shout.slug"), nullable=True) tags: str = Column(String, nullable=True) - topics: str = Column(String, nullable=True) views: int = Column(Integer, default=0) - - # TODO: add all the fields + published: bool = Column(Boolean, default=False) + publishedAt: str = Column(DateTime, nullable=True) + cover: str = Column(String, nullable = True) + layout: str = Column(String, nullable = True) + authors = relationship(lambda: User, secondary=ShoutAuthors) # NOTE: multiple authors + topics = relationship(lambda: Topic, secondary=ShoutTopics) diff --git a/orm/topic.py b/orm/topic.py new file mode 100644 index 00000000..ef0e165a --- /dev/null +++ b/orm/topic.py @@ -0,0 +1,18 @@ +from typing import List +from datetime import datetime +from sqlalchemy import Column, Integer, String, ForeignKey, DateTime +from sqlalchemy.orm import relationship, backref +from orm import Permission +from orm.base import Base + +class Topic(Base): + __tablename__ = 'topic' + + slug: str = Column(String, unique = True, nullable = False, primary_key=True) + org_id: str = Column(ForeignKey("organization.id"), nullable=False) + createdAt: str = Column(DateTime, nullable=False, default = datetime.now, comment="Created at") + createdBy: str = Column(ForeignKey("user.id"), nullable=False, comment="Author") + value: str = Column(String, nullable=False, comment="Value") + alters = relationship(lambda: Topic, backref=backref("topic", remote_side=[slug])) + alter_id: str = Column(ForeignKey("topic.slug")) + # TODO: add all the fields diff --git a/orm/user.py b/orm/user.py index 552158ba..e3c8a8ca 100644 --- a/orm/user.py +++ b/orm/user.py @@ -1,27 +1,35 @@ from typing import List -from sqlalchemy import Column, Integer, String, ForeignKey, Boolean, DateTime, JSON as JSONType +from sqlalchemy import Table, Column, Integer, String, ForeignKey, Boolean, DateTime, JSON as JSONType from sqlalchemy.orm import relationship from orm import Permission from orm.base import Base, local_session -from orm.notification import UserNotification +from orm.rating import Rating +from orm.rbac import Role -class UserRating(Base): - __tablename__ = 'user_rating' +class UserNotifications(Base): + __tablename__ = 'user_notifications' - createdBy: int = Column(Integer, ForeignKey("user.id"), primary_key = True) - value: int = Column(Integer, nullable=False) - -class UserRole(Base): - __tablename__ = 'user_role' - id: int = Column(Integer, primary_key = True) user_id: int = Column(Integer, ForeignKey("user.id")) - role_id str = Column(String, ForeignKey("role.name")) + kind: str = Column(String, ForeignKey("notification.kind")) + values: JSONType = Column(JSONType, nullable = True) # [ , .. ] + +UserRatings = Table("user_ratings", + Base.metadata, + Column('user_id', Integer, ForeignKey('user.id')), + Column('rater_id', Integer, ForeignKey('rating.createdBy')) +) + +UserRoles = Table("user_roles", + Base.metadata, + Column('user_id', Integer, ForeignKey('user.id')), + Column('role', String, ForeignKey('role.name')) +) class User(Base): - __tablename__ = 'user' + __tablename__ = "user" email: str = Column(String, unique=True, nullable=False, comment="Email") username: str = Column(String, nullable=False, comment="Login") @@ -30,16 +38,16 @@ class User(Base): userpic: str = Column(String, nullable=True, comment="Userpic") viewname: str = Column(String, nullable=True, comment="Display name") rating: int = Column(Integer, nullable=True, comment="Rating") - slug: str = Column(String, unique=True, nullable=True, comment="Slug") + slug: str = Column(String, unique=True, comment="Author's slug") muted: bool = Column(Boolean, default=False) emailConfirmed: bool = Column(Boolean, default=False) createdAt: DateTime = Column(DateTime, nullable=False, comment="Created at") wasOnlineAt: DateTime = Column(DateTime, nullable=False, comment="Was online at") links: JSONType = Column(JSONType, nullable=True, comment="Links") oauth: str = Column(String, nullable=True) - notifications = relationship(lambda: UserNotification) - ratings = relationship(lambda: UserRating) - roles = relationship(lambda: UserRole) + notifications = relationship(lambda: UserNotifications) + ratings = relationship(lambda: Rating, secondary=UserRatings) + roles = relationship(lambda: Role, secondary=UserRoles) @classmethod def get_permission(cls, user_id): @@ -54,5 +62,5 @@ class User(Base): return scope -if __name__ == '__main__': +if __name__ == "__main__": print(User.get_permission(user_id=1)) diff --git a/resolvers/zine.py b/resolvers/zine.py index 581f820b..fd354c6a 100644 --- a/resolvers/zine.py +++ b/resolvers/zine.py @@ -97,7 +97,7 @@ async def create_shout(_, info, input): new_shout = Shout.create( slug = input["slug"], org_id = org_id, - author_id = user_id, + authors = [user_id, ], body = input["body"], replyTo = input.get("replyTo"), versionOf = input.get("versionOf"), @@ -135,7 +135,7 @@ async def update_shout(_, info, input): "error" : "shout not found" } - if shout.author_id != user_id: + if shout.authors[0] != user_id: scopes = auth.scopes print(scopes) if not Resource.shout_id in scopes: diff --git a/schema.graphql b/schema.graphql index de0b0af7..d9de063d 100644 --- a/schema.graphql +++ b/schema.graphql @@ -178,7 +178,9 @@ type Message { type Shout { org_id: Int! slug: String! - author: Int! + authors: [Int!]! + cover: String + layout: String body: String! createdAt: DateTime! updatedAt: DateTime! @@ -186,7 +188,8 @@ type Shout { deletedBy: Int rating: Int ratigns: [Rating] - published: DateTime # if there is no published field - it is not published + published: Boolean! + publishedAt: DateTime # if there is no published field - it is not published replyTo: String # another shout tags: [String] # actual values topics: [String] # topic-slugs, order has matter @@ -202,6 +205,7 @@ type Topic { createdBy: Int! # User createdAt: DateTime! value: String + desc: String parents: [String] # NOTE: topic can have parent topics children: [String] # and children }