drafts-orm-struct

This commit is contained in:
tonyrewin 2023-01-16 11:32:36 +03:00 committed by bniwredyc
parent 3875ac5d4e
commit 6a8596b764
6 changed files with 88 additions and 43 deletions

View File

@ -1,22 +1,31 @@
from datetime import datetime from datetime import datetime
from sqlalchemy import Column, ForeignKey, DateTime, String from sqlalchemy import Boolean, Column, ForeignKey, DateTime, String
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from base.orm import Base from base.orm import Base
from orm.user import User from orm.user import User
from orm.topic import Topic
class DraftTopic(Base):
__tablename__ = "draft_topic"
id = None # type: ignore
collab = Column(ForeignKey("draft_collab.id"), primary_key=True)
topic = Column(ForeignKey("topic.id"), primary_key=True)
class DraftAuthor(Base): class DraftAuthor(Base):
__tablename__ = "collab_author" __tablename__ = "draft_author"
id = None # type: ignore id = None # type: ignore
collab = Column(ForeignKey("collab.id"), primary_key=True) collab = Column(ForeignKey("draft_collab.id"), primary_key=True)
author = Column(ForeignKey("user.id"), primary_key=True) author = Column(ForeignKey("user.id"), primary_key=True)
# accepted = Column(Boolean, default=False) accepted = Column(Boolean, default=False)
class DraftCollab(Base): class DraftCollab(Base):
__tablename__ = "draftcollab" __tablename__ = "draft_collab"
slug = Column(String, nullable=True, comment="Slug") slug = Column(String, nullable=True, comment="Slug")
title = Column(String, nullable=True, comment="Title") title = Column(String, nullable=True, comment="Title")
@ -25,8 +34,7 @@ class DraftCollab(Base):
body = Column(String, nullable=True, comment="Body") body = Column(String, nullable=True, comment="Body")
cover = Column(String, nullable=True, comment="Cover") cover = Column(String, nullable=True, comment="Cover")
authors = relationship(lambda: User, secondary=DraftAuthor.__tablename__) authors = relationship(lambda: User, secondary=DraftAuthor.__tablename__)
topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) topics = relationship(lambda: Topic, secondary=DraftTopic.__tablename__)
invites = relationship(lambda: User, secondary=CollabInvited.__tablename__)
createdAt = Column(DateTime, default=datetime.now, comment="Created At") createdAt = Column(DateTime, default=datetime.now, comment="Created At")
updatedAt = Column(DateTime, default=datetime.now, comment="Updated At") updatedAt = Column(DateTime, default=datetime.now, comment="Updated At")
chat = Column(String, unique=True, nullable=True) chat = Column(String, unique=True, nullable=True)

View File

@ -8,7 +8,8 @@ from resolvers.auth import (
get_current_user, get_current_user,
) )
from resolvers.create.collab import remove_coauthor, invite_coauthor from resolvers.create.collab import load_drafts, create_draft, update_draft, delete_draft,\
accept_coauthor, invite_coauthor
from resolvers.create.migrate import markdown_body from resolvers.create.migrate import markdown_body
from resolvers.create.editor import create_shout, delete_shout, update_shout from resolvers.create.editor import create_shout, delete_shout, update_shout
@ -93,8 +94,12 @@ __all__ = [
# create.migrate # create.migrate
"markdown_body", "markdown_body",
# create.collab # create.collab
"load_drafts",
"create_draft",
"update_draft",
"delete_draft",
"invite_coauthor", "invite_coauthor",
"remove_coauthor", "accept_coauthor",
# zine.topics # zine.topics
"topics_all", "topics_all",
"topics_by_community", "topics_by_community",

View File

@ -3,33 +3,33 @@ from auth.credentials import AuthCredentials
from base.orm import local_session from base.orm import local_session
from base.resolvers import query, mutation from base.resolvers import query, mutation
from base.exceptions import ObjectNotExist, BaseHttpException from base.exceptions import ObjectNotExist, BaseHttpException
from orm.draft import DraftCollab, CollabAuthor from orm.draft import DraftCollab, DraftAuthor, DraftTopic
from orm.shout import Shout from orm.shout import Shout
from orm.user import User from orm.user import User
# TODO: use updatedAt
@query.field("loadDrafts") @query.field("loadDrafts")
@login_required @login_required
async def get_drafts(_, info): async def load_drafts(_, info):
auth: AuthCredentials = info.context["request"].auth auth: AuthCredentials = info.context["request"].auth
drafts = [] drafts = []
with local_session() as session: with local_session() as session:
drafts = session.query(DraftCollab).filter(auth.user_id in DraftCollab.authors) drafts = session.query(DraftCollab).filter(auth.user_id in DraftCollab.authors)
return { return drafts
"drafts": drafts
}
@mutation.field("createDraft") # TODO @mutation.field("createDraft") # TODO
@login_required @login_required
async def create_draft(_, info): async def create_draft(_, info, draft_input):
auth: AuthCredentials = info.context["request"].auth auth: AuthCredentials = info.context["request"].auth
with local_session() as session: with local_session() as session:
pass collab = DraftCollab.create(**draft_input)
session.add(collab)
session.commit()
# TODO: email notify to all authors
return {}
@mutation.field("deleteDraft") # TODO @mutation.field("deleteDraft") # TODO
@ -38,15 +38,29 @@ async def delete_draft(_, info, draft: int = 0):
auth: AuthCredentials = info.context["request"].auth auth: AuthCredentials = info.context["request"].auth
with local_session() as session: with local_session() as session:
pass collab = session.query(DraftCollab).where(DraftCollab.id == draft_input.id).one()
if auth.user_id not in s.authors:
# raise BaseHttpException("only owner can remove coauthors")
return {
"error": "Only authors can update a draft"
}
elif not collab:
return {
"error": "There is no draft with this id"
}
else:
session.delete(collab)
session.commit()
return {}
@mutation.field("updateDraft") # TODO
@mutation.field("updateDraft") # TODO: draft input type
@login_required @login_required
async def update_draft(_, info, author: int = 0, draft: int = 0): async def update_draft(_, info, draft_input):
auth: AuthCredentials = info.context["request"].auth auth: AuthCredentials = info.context["request"].auth
with local_session() as session: with local_session() as session:
s = session.query(DraftCollab).where(DraftCollab.id == draft).one() # raises Error when not found collab = session.query(DraftCollab).where(DraftCollab.id == draft_input.id).one() # raises Error when not found
if auth.user_id not in s.authors: if auth.user_id not in s.authors:
# raise BaseHttpException("only owner can remove coauthors") # raise BaseHttpException("only owner can remove coauthors")
return { return {
@ -57,12 +71,8 @@ async def update_draft(_, info, author: int = 0, draft: int = 0):
"error": "There is no draft with this id" "error": "There is no draft with this id"
} }
else: else:
c = session.query(DraftCollab).where(DraftCollab.id == draft).one() draft_input["updatedAt"] = datetime.now(tz=timezone.utc)
ca = session.query(CollabAuthor).join(User).where(c.id == draft).filter(User.id == author).one() collab.update(**draft_input)
session.remve(ca)
c.invites = filter(lambda x: x.id == author, c.invites)
c.authors = filter(lambda x: x.id == author, c.authors)
session.add(c)
session.commit() session.commit()
# TODO: email notify # TODO: email notify
@ -80,11 +90,19 @@ async def invite_coauthor(_, info, author: int = 0, draft: int = 0):
return { return {
"error": "You are not in authors list" "error": "You are not in authors list"
} }
else: elif c.id:
invited_user = session.query(User).where(User.id == author).one() invited_user = session.query(User).where(User.id == author).one()
c.invites.append(invited_user) da = DraftAuthor.create({
session.add(c) "accepted": False,
"collab": c.id,
"author": invited_user.id
})
session.add(da)
session.commit() session.commit()
else:
return {
"error": "Draft is not found"
}
# TODO: email notify # TODO: email notify
return {} return {}
@ -96,13 +114,17 @@ async def accept_coauthor(_, info, draft: int):
auth: AuthCredentials = info.context["request"].auth auth: AuthCredentials = info.context["request"].auth
with local_session() as session: with local_session() as session:
c = session.query(DraftCollab).where(DraftCollab.id == draft).one() # c = session.query(DraftCollab).where(DraftCollab.id == draft).one()
accepted = filter(lambda x: x.id == auth.user_id, c.invites).pop() a = session.query(DraftAuthor).where(DraftAuthor.collab == draft).filter(DraftAuthor.author == auth.user_id).one()
if accepted: if not a.accepted:
c.authors.append(accepted) a.accepted = True
session.add(c)
session.commit() session.commit()
# TODO: email notify
return {} return {}
elif a.accepted == True:
return {
"error": "You have accepted invite before"
}
else: else:
# raise BaseHttpException("only invited can accept") # raise BaseHttpException("only invited can accept")
return { return {

View File

@ -14,7 +14,7 @@ from resolvers.zine.reactions import reactions_follow, reactions_unfollow
from services.zine.gittask import GitTask from services.zine.gittask import GitTask
from resolvers.inbox.chats import create_chat from resolvers.inbox.chats import create_chat
from services.inbox.storage import MessagesStorage from services.inbox.storage import MessagesStorage
from orm.collab import Collab from orm.draft import DraftCollab
@mutation.field("createShout") @mutation.field("createShout")

View File

@ -218,10 +218,13 @@ def author_unfollow(user_id, slug):
).first() ).first()
) )
if not flw: if not flw:
raise Exception("[resolvers.profile] follower not exist, cant unfollow") return {
"error": "Follower is not exist, cant unfollow"
}
else: else:
session.delete(flw) session.delete(flw)
session.commit() session.commit()
return {}
@query.field("authorsAll") @query.field("authorsAll")

View File

@ -69,6 +69,7 @@ type Result {
members: [ChatMember] members: [ChatMember]
shout: Shout shout: Shout
shouts: [Shout] shouts: [Shout]
drafts: [DraftCollab]
author: Author author: Author
authors: [Author] authors: [Author]
reaction: Reaction reaction: Reaction
@ -538,10 +539,16 @@ type Chat {
private: Boolean private: Boolean
} }
type Collab { type DraftCollab {
authors: [String]! slug: String
invites: [String] title: String
shout: Shout subtitle: String
body: String
cover: String
layout: String
authors: [Int]!
topics: [String]
chat: Chat chat: Chat
createdAt: Int! createdAt: Int!
updatedAt: Int
} }