From 4eb98e7d0c57da49cd216721281eeac1751480fd Mon Sep 17 00:00:00 2001 From: tonyrewin Date: Thu, 24 Nov 2022 19:26:12 +0300 Subject: [PATCH 1/2] create-shout-handling --- resolvers/create/editor.py | 27 +++++++++++++++++++++++++-- schema.graphql | 30 +++++++++++++++--------------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/resolvers/create/editor.py b/resolvers/create/editor.py index 220ff229..d044469c 100644 --- a/resolvers/create/editor.py +++ b/resolvers/create/editor.py @@ -5,10 +5,13 @@ from base.orm import local_session from base.resolvers import mutation from orm.rbac import Resource from orm.shout import Shout, ShoutAuthor, ShoutTopic +from orm.collab import Collab +from services.inbox import MessagesStorage from orm.topic import TopicFollower from orm.user import User from resolvers.zine.reactions import reactions_follow, reactions_unfollow from services.zine.gittask import GitTask +from resolvers.inbox.chats import create_chat @mutation.field("createShout") @@ -19,9 +22,29 @@ async def create_shout(_, info, inp): topic_slugs = inp.get("topic_slugs", []) if topic_slugs: del inp["topic_slugs"] - + body = inp.get("body") with local_session() as session: - new_shout = Shout.create(**inp) + if body: + # now we should create a draft shout (can be viewed only by authors) + authors = inp.get("authors", []) + new_shout = Shout.create({ + "title": inp.get("title", body[:12] + '...'), + "body": body, + "authors": authors + }) + authors.remove(user.slug) + if authors: + chat = create_chat(None, info, new_shout.title, members=authors) + # create a cooperative chatroom + MessagesStorage.register_chat(chat) + # now we should create a collab + new_collab = Collab.create({ + "shout": new_shout.id, + "authors": [user.slug, ], + "invites": authors + }) + session.add(new_collab) + session.commit() # NOTE: shout made by one first author sa = ShoutAuthor.create(shout=new_shout.slug, user=user.slug) diff --git a/schema.graphql b/schema.graphql index adce2273..8363eac7 100644 --- a/schema.graphql +++ b/schema.graphql @@ -94,12 +94,13 @@ type ReactionUpdating { ################################### Inputs ################################### input ShoutInput { - slug: String! - body: String! - community: String! - mainTopic: String - topic_slugs: [String] + slug: String title: String + body: String! + authors: [String] + topics: [String] + community: Int + mainTopic: String subtitle: String versionOf: String visibleForRoles: [String] # role ids are strings @@ -165,8 +166,8 @@ type Mutation { confirmEmail(token: String!): AuthResult! # shout - createShout(input: ShoutInput!): Result! - updateShout(input: ShoutInput!): Result! + createShout(inp: ShoutInput!): Result! + updateShout(inp: ShoutInput!): Result! deleteShout(slug: String!): Result! # user profile @@ -371,14 +372,6 @@ type User { oid: String } -type Collab { - authors: [String]! - invites: [String] - createdAt: DateTime! - title: String - body: String -} - enum ReactionKind { LIKE DISLIKE @@ -524,3 +517,10 @@ type Chat { unread: Int private: Boolean } + +type Collab { + authors: [String]! + invites: [String] + shout: Shout + chat: Chat +} From 7a818ff8f5cb0536baf369f38a8c8a2d0303560f Mon Sep 17 00:00:00 2001 From: tonyrewin Date: Thu, 24 Nov 2022 20:53:39 +0300 Subject: [PATCH 2/2] collab methods updates --- orm/collab.py | 21 +++++--- resolvers/create/collab.py | 104 ++++++++++++++++++++----------------- resolvers/create/editor.py | 6 ++- schema.graphql | 6 ++- 4 files changed, 78 insertions(+), 59 deletions(-) diff --git a/orm/collab.py b/orm/collab.py index 3e3a5839..a159f1d7 100644 --- a/orm/collab.py +++ b/orm/collab.py @@ -1,6 +1,6 @@ from datetime import datetime -from sqlalchemy import Boolean, Column, String, ForeignKey, DateTime +from sqlalchemy import Column, ForeignKey, DateTime, String from sqlalchemy.orm import relationship from base.orm import Base from orm.user import User @@ -12,16 +12,23 @@ class CollabAuthor(Base): id = None # type: ignore collab = Column(ForeignKey("collab.id"), primary_key=True) author = Column(ForeignKey("user.slug"), primary_key=True) - accepted = Column(Boolean, default=False) + invitedBy = Column(ForeignKey("user.slug")) + + +class CollabInvited(Base): + __tablename__ = "collab_invited" + + id = None # type: ignore + collab = Column(ForeignKey("collab.id"), primary_key=True) + author = Column(ForeignKey("user.slug"), primary_key=True) + invitedBy = Column(ForeignKey("user.slug")) class Collab(Base): __tablename__ = "collab" - authors = Column() - title = Column(String, nullable=True, comment="Title") - body = Column(String, nullable=True, comment="Body") - pic = Column(String, nullable=True, comment="Picture") + shout = Column(ForeignKey("shout.id"), primary_key=True) authors = relationship(lambda: User, secondary=CollabAuthor.__tablename__) + invites = relationship(lambda: User, secondary=CollabInvited.__tablename__) createdAt = Column(DateTime, default=datetime.now, comment="Created At") - createdBy = Column(ForeignKey("user.id"), comment="Created By") + chat = Column(String, unique=True, nullable=False) diff --git a/resolvers/create/collab.py b/resolvers/create/collab.py index 058a90c2..1bcbabb3 100644 --- a/resolvers/create/collab.py +++ b/resolvers/create/collab.py @@ -1,9 +1,8 @@ -from datetime import datetime, timezone - from auth.authenticate import login_required from base.orm import local_session from base.resolvers import query, mutation -from orm.collab import Collab +from base.exceptions import OperationNotAllowed, ObjectNotExist +from orm.collab import Collab, CollabAuthor from orm.shout import Shout from orm.user import User @@ -11,65 +10,74 @@ from orm.user import User @query.field("getCollabs") @login_required async def get_collabs(_, info): - auth = info.context["request"].auth - user_id = auth.user_id + user = info.context["request"].user with local_session() as session: - user = session.query(User).where(User.id == user_id).first() collabs = session.query(Collab).filter(user.slug in Collab.authors) return collabs -@mutation.field("inviteAuthor") +@mutation.field("inviteCoauthor") @login_required -async def invite_author(_, info, author, shout): - auth = info.context["request"].auth - user_id = auth.user_id - +async def invite_coauthor(_, info, author: str, shout: int): + user = info.context["request"].user with local_session() as session: - shout = session.query(Shout).filter(Shout.slug == shout).first() - if not shout: - return {"error": "invalid shout slug"} - authors = [a.id for a in shout.authors] - if user_id not in authors: - return {"error": "access denied"} - author = session.query(User).filter(User.id == author.id).first() - if author: - if author.id in authors: - return {"error": "already added"} - shout.authors.append(author) - shout.updated_at = datetime.now(tz=timezone.utc) - session.add(shout) - session.commit() + s = session.query(Shout).where(Shout.id == shout).one() + if not s: + raise ObjectNotExist("invalid shout id") + else: + c = session.query(Collab).where(Collab.shout == shout).one() + if user.slug not in c.authors: + raise OperationNotAllowed("you are not in authors list") + else: + invited_user = session.query(User).where(User.slug == author).one() + c.invites.append(invited_user) + session.add(c) + session.commit() # TODO: email notify return {} -@mutation.field("removeAuthor") +@mutation.field("removeCoauthor") @login_required -async def remove_author(_, info, author, shout): - auth = info.context["request"].auth - user_id = auth.user_id - +async def remove_coauthor(_, info, author: str, shout: int): + user = info.context["request"].user with local_session() as session: - shout = session.query(Shout).filter(Shout.slug == shout).first() - if not shout: - return {"error": "invalid shout slug"} - authors = [author.id for author in shout.authors] - if user_id not in authors: - return {"error": "access denied"} - author = session.query(User).filter(User.slug == author).first() - if author: - if author.id not in authors: - return {"error": "not in authors"} - shout.authors.remove(author) - shout.updated_at = datetime.now(tz=timezone.utc) - session.add(shout) - session.commit() - - # result = Result("INVITED") - # FIXME: await ShoutStorage.put(result) + s = session.query(Shout).where(Shout.id == shout).one() + if not s: + raise ObjectNotExist("invalid shout id") + if user.slug != s.createdBy.slug: + raise OperationNotAllowed("only onwer can remove coauthors") + else: + c = session.query(Collab).where(Collab.shout == shout).one() + ca = session.query(CollabAuthor).where(c.shout == shout, c.author == author).one() + session.remve(ca) + c.invites = filter(lambda x: x.slug == author, c.invites) + c.authors = filter(lambda x: x.slug == author, c.authors) + session.add(c) + session.commit() # TODO: email notify - return {} + + +@mutation.field("acceptCoauthor") +@login_required +async def accept_coauthor(_, info, shout: int): + user = info.context["request"].user + with local_session() as session: + s = session.query(Shout).where(Shout.id == shout).one() + if not s: + raise ObjectNotExist("invalid shout id") + else: + c = session.query(Collab).where(Collab.shout == shout).one() + accepted = filter(lambda x: x.slug == user.slug, c.invites).pop() + if accepted: + c.authors.append(accepted) + s.authors.append(accepted) + session.add(s) + session.add(c) + session.commit() + return {} + else: + raise OperationNotAllowed("only invited can accept") diff --git a/resolvers/create/editor.py b/resolvers/create/editor.py index d044469c..78f4d4d1 100644 --- a/resolvers/create/editor.py +++ b/resolvers/create/editor.py @@ -30,7 +30,10 @@ async def create_shout(_, info, inp): new_shout = Shout.create({ "title": inp.get("title", body[:12] + '...'), "body": body, - "authors": authors + "authors": authors, + "topics": inp.get("topics", []), + "mainTopic": inp.get("topics", []).pop(), + "visibility": "authors" }) authors.remove(user.slug) if authors: @@ -44,7 +47,6 @@ async def create_shout(_, info, inp): "invites": authors }) session.add(new_collab) - session.commit() # NOTE: shout made by one first author sa = ShoutAuthor.create(shout=new_shout.slug, user=user.slug) diff --git a/schema.graphql b/schema.graphql index 8363eac7..ecad49fc 100644 --- a/schema.graphql +++ b/schema.graphql @@ -187,8 +187,9 @@ type Mutation { deleteReaction(id: Int!): Result! # collab - inviteAuthor(author: String!, shout: String!): Result! - removeAuthor(author: String!, shout: String!): Result! + inviteCoauthor(author: String!, shout: int!): Result! + removeCouthor(author: String!, shout: Int!): Result! + acceptCoauthor(shout: Int!): Result! # following follow(what: FollowingEntity!, slug: String!): Result! @@ -523,4 +524,5 @@ type Collab { invites: [String] shout: Shout chat: Chat + createdAt: Int! }