diff --git a/orm/shout.py b/orm/shout.py index bc0b4a1f..69f2d91d 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -2,7 +2,7 @@ from typing import List from datetime import datetime from sqlalchemy import Table, Column, Integer, String, ForeignKey, DateTime, Boolean from sqlalchemy.orm import relationship -from orm import Permission, User, Topic +from orm import Permission, User, Topic, Comment from orm.base import Base class ShoutAuthor(Base): @@ -11,6 +11,13 @@ class ShoutAuthor(Base): id = None shout = Column(ForeignKey('shout.id'), primary_key = True) user = Column(ForeignKey('user.id'), primary_key = True) + +class ShoutViewer(Base): + __tablename__ = "shout_viewer" + + id = None + shout = Column(ForeignKey('shout.id'), primary_key = True) + user = Column(ForeignKey('user.id'), primary_key = True) class ShoutTopic(Base): __tablename__ = 'shout_topic' @@ -49,14 +56,16 @@ class Shout(Base): replyTo: int = Column(ForeignKey("shout.id"), nullable=True) versionOf: int = Column(ForeignKey("shout.id"), nullable=True) tags: str = Column(String, nullable=True) - published: bool = Column(Boolean, default=False) + publishedBy: bool = Column(ForeignKey("user.id"), nullable=True) publishedAt: str = Column(DateTime, nullable=True) cover: str = Column(String, nullable = True) title: str = Column(String, nullable = True) subtitle: str = Column(String, nullable = True) + comments = relationship(Comment) layout: str = Column(String, nullable = True) authors = relationship(lambda: User, secondary=ShoutAuthor.__tablename__) # NOTE: multiple authors topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) ratings = relationship(ShoutRating, foreign_keys=ShoutRating.shout_id) views = relationship(ShoutViewByDay) + visibleFor = relationship(lambda: User, secondary=ShoutViewer.__tablename__) old_id: str = Column(String, nullable = True) diff --git a/resolvers/__init__.py b/resolvers/__init__.py index b9a70416..c0ea8d4c 100644 --- a/resolvers/__init__.py +++ b/resolvers/__init__.py @@ -1,11 +1,11 @@ from resolvers.auth import login, sign_out, get_user, is_email_free, register, confirm from resolvers.inbox import create_message, delete_message, update_message, get_messages -from resolvers.zine import create_shout +from resolvers.zine import create_shout, get_shout_by_slug +from resolvers.profile import get_user_by_slug, get_current_user __all__ = [ "login", "register", - "get_user", "is_email_free", "confirm", # TODO: "reset_password_code", @@ -14,5 +14,8 @@ __all__ = [ "delete_message", "get_messages", "update_messages", - "create_shout" + "create_shout", + "get_current_user", + "get_user_by_slug", + "get_shout_by_slug" ] diff --git a/resolvers/auth.py b/resolvers/auth.py index c9e7be08..cf93b607 100644 --- a/resolvers/auth.py +++ b/resolvers/auth.py @@ -73,15 +73,6 @@ async def sign_out(_, info: GraphQLResolveInfo): status = await Authorize.revoke(token) return True -@query.field("getCurrentUser") -@login_required -async def get_user(_, info): - auth = info.context["request"].auth - user_id = auth.user_id - with local_session() as session: - user = session.query(User).filter(User.id == user_id).first() - return { "user": user } - @query.field("isEmailFree") async def is_email_free(_, info, email): with local_session() as session: diff --git a/resolvers/profile.py b/resolvers/profile.py new file mode 100644 index 00000000..83a4dcc7 --- /dev/null +++ b/resolvers/profile.py @@ -0,0 +1,21 @@ +from orm import User +from orm.base import local_session +from resolvers.base import mutation, query, subscription +from auth.authenticate import login_required +import asyncio + +@query.field("getUserBySlug") # get a public profile +async def get_user_by_slug(_, info, slug): + with local_session() as session: + user = session.query(User).filter(User.slug == slug).first() + return { "user": user } # TODO: remove some fields for public + + +@query.field("getCurrentUser") +@login_required +async def get_user(_, info): + auth = info.context["request"].auth + user_id = auth.user_id + with local_session() as session: + user = session.query(User).filter(User.id == user_id).first() + return { "user": user } \ No newline at end of file diff --git a/resolvers/zine.py b/resolvers/zine.py index 45abe5de..11a510a8 100644 --- a/resolvers/zine.py +++ b/resolvers/zine.py @@ -258,24 +258,20 @@ async def update_shout(_, info, id, input): "shout" : shout } -# TODO: get shout with comments query - -@query.field("getShout") #FIXME: add shout joined with comments -async def get_shout(_, info, shout_id): - month_ago = datetime.now() - timedelta(days = 30) +@query.field("getShoutBySlug") #FIXME: add shout joined with comments +async def get_shout_by_slug(_, info, slug): + # month_ago = datetime.now() - timedelta(days = 30) with local_session() as session: - stmt = select(Comment, func.sum(CommentRating.value).label("rating")).\ - join(CommentRating).\ - where(CommentRating.ts > month_ago).\ - where(Comment.shout == shout_id).\ - # join(ShoutComment) - group_by(Shout.id).\ - order_by(desc("rating")).\ + stmt = select(Shout, func.sum(ShoutRating.value).label("rating")).\ + join(ShoutRating).\ + # where(ShoutRating.ts > month_ago).\ + where(Shout.slug == slug).\ + # TODO: join(Comment) to .comments limit(limit) shouts = [] for row in session.execute(stmt): shout = row.Shout shout.rating = row.rating - shout.comments + # TODO: shout.comments = shouts.append(shout) return shout \ No newline at end of file diff --git a/schema.graphql b/schema.graphql index f8256d68..20ebd23e 100644 --- a/schema.graphql +++ b/schema.graphql @@ -83,21 +83,24 @@ type Query { isEmailFree(email: String!): Result! signIn(email: String!, password: String): AuthResult! signOut: Result! - # user profile + + # profile getCurrentUser: UserResult! - getUserById(id: Int!): UserResult! - # getUserRating(shout: Int): Int! + getUserBySlug(slug: String!): UserResult! + # rateUser(shout: Int): Int! # messages getMessages(count: Int = 100, page: Int = 1): [Message!]! # shouts + getShoutBySlug(slug: String!): Shout! # NOTE: with .comments: Comments[] # getShoutRating(shout: Int): Int! # shoutsByAuthor(author: Int): [Shout]! # shoutsByReplyTo(shout: Int): [Shout]! # shoutsByTags(tags: [String]): [Shout]! # shoutsByTime(time: DateTime): [Shout]! + # mainpage topShoutsByView(limit: Int): [Shout]! topShoutsByRating(limit: Int): [Shout]! favoritesShouts(limit: Int): [Shout]! @@ -184,6 +187,7 @@ type Comment { id: Int! author: Int! body: String! + replyTo: Int! createdAt: DateTime! updatedAt: DateTime! shout: Int! @@ -198,29 +202,30 @@ type Comment { # is publication type Shout { id: Int! - authors: [Int!]! slug: String! body: String! createdAt: DateTime! - updatedAt: DateTime! - community: Int + authors: [User!]! + comments: [Comment] + ratigns: [Rating] + visibleFor: [User] + community: Community cover: String layout: String - deletedAt: DateTime - deletedBy: Int rating: Int - ratigns: [Rating] - published: Boolean! - publishedAt: DateTime # if there is no published field - it is not published - replyTo: Int # another shout + views: Int + replyTo: Shout + versionOf: Shout tags: [String] # actual values topics: [String] # topic-slugs, order has matter title: String subtitle: String - versionOf: String - visibleForRoles: [String] # role ids are strings - visibleForUsers: [Int] - views: Int + updatedAt: DateTime + updatedBy: Int # can be user id? + deletedAt: DateTime + deletedBy: Int + publishedBy: Int # if there is no published field - it is not published + publishedAt: DateTime old_id: String }