From 30c51ecac152c6c06dc54532348694d1fbe72432 Mon Sep 17 00:00:00 2001 From: tonyrewin Date: Sun, 19 Jun 2022 14:11:14 +0300 Subject: [PATCH] proposals prototype --- orm/proposal.py | 15 ++++-- resolvers/editor.py | 124 +++++++++++++++++++++++++++++++++++++++++++- schema.graphql | 13 +++-- 3 files changed, 141 insertions(+), 11 deletions(-) diff --git a/orm/proposal.py b/orm/proposal.py index d84fee0a..2311b8e0 100644 --- a/orm/proposal.py +++ b/orm/proposal.py @@ -9,10 +9,15 @@ from orm.base import Base class Proposal(Base): __tablename__ = 'proposal' - author_id: int = Column(Integer, ForeignKey("user.id"), nullable=False, comment="Author") - shout_id: int = Column(Integer, ForeignKey("shout.id"), nullable=False, comment="Shout") - body: str = Column(String, nullable=False, comment="Body") - createdAt: str = Column(datetime, nullable=False, comment="Created at") + shout: int = Column(Integer, ForeignKey("shout.id"), nullable=False, comment="Shout") range: str = Column(String, nullable=True, comment="Range in format :") - + body: str = Column(String, nullable=False, comment="Body") + createdBy: int = Column(Integer, ForeignKey("user.id"), nullable=False, comment="Author") + createdAt: str = Column(datetime, nullable=False, comment="Created at") + updatedAt: str = Column(datetime, nullable=True, comment="Updated at") + acceptedAt: str = Column(datetime, nullable=True, comment="Accepted at") + acceptedBy: str = Column(datetime, nullable=True, comment="Accepted by") + deletedAt: str = Column(datetime, nullable=True, comment="Deleted at") + declinedAt: str = Column(datetime, nullable=True, comment="Declined at) + declinedBy: str = Column(datetime, nullable=True, comment="Declined by") # TODO: debug, logix \ No newline at end of file diff --git a/resolvers/editor.py b/resolvers/editor.py index f95ab230..9e70632d 100644 --- a/resolvers/editor.py +++ b/resolvers/editor.py @@ -1 +1,123 @@ -# TODO: implement me \ No newline at end of file +from orm import Proposal, ProposalRating +from orm.base import local_session +from resolvers.base import mutation, query, subscription +from auth.authenticate import login_required +import asyncio +from datetime import datetime + +class ProposalResult: + def __init__(self, status, proposal): + self.status = status + self.proposal = proposal + +@mutation.field("createProposal") +@login_required +async def create_proposal(_, info, body, shout, range = None): + auth = info.context["request"].auth + user_id = auth.user_id + + proposal = Proposal.create( + createdBy = user_id, + body = body, + shout = shout, + range = range + ) + + result = ProposalResult("NEW", proposal) + await ProposalSubscriptions.put(result) + + return {"proposal": proposal} + +@mutation.field("updateProposal") +@login_required +async def update_proposal(_, info, id, body): + auth = info.context["request"].auth + user_id = auth.user_id + + with local_session() as session: + proposal = session.query(Proposal).filter(Proposal.id == id).first() + shout = session.query(Shout.slug === proposal.shout) + if not proposal: + return {"error": "invalid proposal id"} + if proposal.author != user_id: + return {"error": "access denied"} + proposal.body = body + proposal.updatedAt = datetime.now() + session.commit() + + result = ProposalResult("UPDATED", proposal) + await ProposalSubscriptions.put(result) + + return {"proposal": proposal} + +@mutation.field("deleteProposal") +@login_required +async def delete_proposal(_, info, id): + auth = info.context["request"].auth + user_id = auth.user_id + + with local_session() as session: + proposal = session.query(Proposal).filter(Proposal.id == id).first() + if not proposal: + return {"error": "invalid proposal id"} + if proposal.createdBy != user_id: + return {"error": "access denied"} + + proposal.deletedAt = datetime.now() + session.commit() + + result = ProposalResult("DELETED", proposal) + await ProposalSubscriptions.put(result) + + return {} + +@mutation.field("rateProposal") +@login_required +async def rate_proposal(_, info, id, value): + auth = info.context["request"].auth + user_id = auth.user_id + + with local_session() as session: + proposal = session.query(Proposal).filter(Proposal.id == id).first() + if not proposal: + return {"error": "invalid proposal id"} + + rating = session.query(ProposalRating).\ + filter(ProposalRating.proposal_id == id and ProposalRating.createdBy == user_id).first() + if rating: + rating.value = value + session.commit() + + if not rating: + ProposalRating.create( + proposal_id = id, + createdBy = user_id, + value = value) + + result = ProposalResult("UPDATED_RATING", proposal) + await ProposalSubscriptions.put(result) + + return {} + + +@mutation.field("acceptProposal") +@login_required +async def accept_proposal(_, info, id): + auth = info.context["request"].auth + user_id = auth.user_id + + with local_session() as session: + proposal = session.query(Proposal).filter(Proposal.id == id).first() + if not proposal: + return {"error": "invalid proposal id"} + if proposal.acceptedBy == user_id: # TODO: manage ACL here to give access all editors + return {"error": "access denied"} + + proposal.acceptedAt = datetime.now() + proposal.acceptedBy = user_id + session.commit() + + result = ProposalResult("ACCEPTED", proposal) + await ProposalSubscriptions.put(result) + + return {} diff --git a/schema.graphql b/schema.graphql index a57242f7..469e20e4 100644 --- a/schema.graphql +++ b/schema.graphql @@ -353,14 +353,17 @@ type Topic { topicStat: TopicStat } -# TODO: resolvers to add/remove topics from publication - type Proposal { - body: String! - shout: Int! + createdBy: String! + shout: string! range: String # full / 0:2340 - author: Int! + body: String! createdAt: DateTime! + updatedAt: DateTime + acceptedAt: DateTime + acceptedBy: string + declinedAt: DateTime + declinedBy: string } type Token {