Merge remote-tracking branch 'origin/main' into main

This commit is contained in:
tonyrewin 2022-11-30 09:16:58 +03:00
commit d0b875c157
4 changed files with 116 additions and 74 deletions

View File

@ -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)

View File

@ -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")

View File

@ -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,31 @@ 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,
"topics": inp.get("topics", []),
"mainTopic": inp.get("topics", []).pop(),
"visibility": "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)
# NOTE: shout made by one first author
sa = ShoutAuthor.create(shout=new_shout.slug, user=user.slug)

View File

@ -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
@ -164,8 +165,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
@ -185,8 +186,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!
@ -371,14 +373,6 @@ type User {
oid: String
}
type Collab {
authors: [String]!
invites: [String]
createdAt: DateTime!
title: String
body: String
}
enum ReactionKind {
LIKE
DISLIKE
@ -525,3 +519,11 @@ type Chat {
unread: Int
private: Boolean
}
type Collab {
authors: [String]!
invites: [String]
shout: Shout
chat: Chat
createdAt: Int!
}