0.2.15
Some checks failed
deploy / deploy (push) Failing after 1m58s

This commit is contained in:
Untone 2023-11-24 02:00:28 +03:00
parent c150d28447
commit a63cf24812
12 changed files with 187 additions and 139 deletions

View File

@ -1,3 +1,11 @@
[0.2.15]
- schema: Shout.created_by removed
- schema: Shout.mainTopic removed
- services: cached elasticsearch connector
- services: auth is using user_id from authorizer
- resolvers: notify_* usage fixes
- resolvers: login_required usage fixes
[0.2.14] [0.2.14]
- schema: some fixes from migrator - schema: some fixes from migrator
- schema: .days -> .time_ago - schema: .days -> .time_ago
@ -5,7 +13,6 @@
- services: db access simpler, no contextmanager - services: db access simpler, no contextmanager
- services: removed Base.create() method - services: removed Base.create() method
- services: rediscache updated - services: rediscache updated
- resolvers: many minor fixes
- resolvers: get_reacted_shouts_updates as followedReactions query - resolvers: get_reacted_shouts_updates as followedReactions query
[0.2.13] [0.2.13]

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "discoursio-core" name = "discoursio-core"
version = "0.2.14" version = "0.2.15"
description = "core module for discours.io" description = "core module for discours.io"
authors = ["discoursio devteam"] authors = ["discoursio devteam"]
license = "MIT" license = "MIT"

View File

@ -1,11 +1,6 @@
from resolvers.editor import create_shout, delete_shout, update_shout from resolvers.editor import create_shout, delete_shout, update_shout
from resolvers.author import ( from resolvers.author import load_authors_by, update_profile, get_authors_all, rate_author
load_authors_by,
update_profile,
get_authors_all,
rate_author
)
from resolvers.reaction import ( from resolvers.reaction import (
create_reaction, create_reaction,
@ -25,7 +20,7 @@ from resolvers.topic import (
) )
from resolvers.follower import follow, unfollow from resolvers.follower import follow, unfollow
from resolvers.reader import load_shout, load_shouts_by from resolvers.reader import load_shout, load_shouts_by, search
from resolvers.community import get_community, get_communities_all from resolvers.community import get_community, get_communities_all
__all__ = [ __all__ = [
@ -62,4 +57,6 @@ __all__ = [
# community # community
"get_community", "get_community",
"get_communities_all", "get_communities_all",
# search
"search",
] ]

View File

@ -90,9 +90,9 @@ async def author_followings(author_id: int):
@mutation.field("updateProfile") @mutation.field("updateProfile")
@login_required @login_required
async def update_profile(_, info, profile): async def update_profile(_, info, profile):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
author = session.query(Author).where(Author.id == author_id).first() author = session.query(Author).where(Author.user == user_id).first()
Author.update(author, profile) Author.update(author, profile)
session.add(author) session.add(author)
session.commit() session.commit()
@ -206,12 +206,13 @@ async def followed_authors(follower_id):
@mutation.field("rateAuthor") @mutation.field("rateAuthor")
@login_required @login_required
async def rate_author(_, info, rated_user_id, value): async def rate_author(_, info, rated_user_id, value):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
rater = session.query(Author).filter(Author.user == user_id).first()
rating = ( rating = (
session.query(AuthorRating) session.query(AuthorRating)
.filter(and_(AuthorRating.rater == author_id, AuthorRating.user == rated_user_id)) .filter(and_(AuthorRating.rater == rater.id, AuthorRating.user == rated_user_id))
.first() .first()
) )
if rating: if rating:
@ -221,7 +222,7 @@ async def rate_author(_, info, rated_user_id, value):
return {} return {}
else: else:
try: try:
rating = AuthorRating(rater=author_id, user=rated_user_id, value=value) rating = AuthorRating(rater=rater.id, user=rated_user_id, value=value)
session.add(rating) session.add(rating)
session.commit() session.commit()
except Exception as err: except Exception as err:

View File

@ -1,6 +1,8 @@
import time # For Unix timestamps import time # For Unix timestamps
from sqlalchemy import and_, select from sqlalchemy import and_, select
from sqlalchemy.orm import joinedload from sqlalchemy.orm import joinedload
from orm.author import Author
from services.auth import login_required from services.auth import login_required
from services.db import local_session from services.db import local_session
from services.schema import mutation, query from services.schema import mutation, query
@ -11,19 +13,21 @@ from services.notify import notify_shout
@query.field("loadDrafts") @query.field("loadDrafts")
@login_required
async def get_drafts(_, info): async def get_drafts(_, info):
author = info.context["request"].author user_id = info.context["user_id"]
q = (
select(Shout)
.options(
joinedload(Shout.authors),
joinedload(Shout.topics),
)
.where(and_(Shout.deleted_at.is_(None), Shout.created_by == author.id))
)
q = q.group_by(Shout.id)
shouts = []
with local_session() as session: with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first()
q = (
select(Shout)
.options(
joinedload(Shout.authors),
joinedload(Shout.topics),
)
.where(and_(Shout.deleted_at.is_(None), Shout.created_by == author.id))
)
q = q.group_by(Shout.id)
shouts = []
for [shout] in session.execute(q).unique(): for [shout] in session.execute(q).unique():
shouts.append(shout) shouts.append(shout)
return shouts return shouts
@ -32,10 +36,13 @@ async def get_drafts(_, info):
@mutation.field("createShout") @mutation.field("createShout")
@login_required @login_required
async def create_shout(_, info, inp): async def create_shout(_, info, inp):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first()
topics = session.query(Topic).filter(Topic.slug.in_(inp.get("topics", []))).all() topics = session.query(Topic).filter(Topic.slug.in_(inp.get("topics", []))).all()
# Replace datetime with Unix timestamp authors = inp.get("authors", [])
if author.id not in authors:
authors.insert(0, author.id)
current_time = int(time.time()) current_time = int(time.time())
new_shout = Shout( new_shout = Shout(
**{ **{
@ -45,11 +52,10 @@ async def create_shout(_, info, inp):
"description": inp.get("description"), "description": inp.get("description"),
"body": inp.get("body", ""), "body": inp.get("body", ""),
"layout": inp.get("layout"), "layout": inp.get("layout"),
"authors": inp.get("authors", []), "authors": authors,
"slug": inp.get("slug"), "slug": inp.get("slug"),
"topics": inp.get("topics"), "topics": inp.get("topics"),
"visibility": ShoutVisibility.AUTHORS, "visibility": ShoutVisibility.AUTHORS,
"created_id": author_id,
"created_at": current_time, # Set created_at as Unix timestamp "created_at": current_time, # Set created_at as Unix timestamp
} }
) )
@ -57,10 +63,10 @@ async def create_shout(_, info, inp):
t = ShoutTopic(topic=topic.id, shout=new_shout.id) t = ShoutTopic(topic=topic.id, shout=new_shout.id)
session.add(t) session.add(t)
# NOTE: shout made by one first author # NOTE: shout made by one first author
sa = ShoutAuthor(shout=new_shout.id, author=author_id) sa = ShoutAuthor(shout=new_shout.id, author=author.id)
session.add(sa) session.add(sa)
session.add(new_shout) session.add(new_shout)
reactions_follow(author_id, new_shout.id, True) reactions_follow(author.id, new_shout.id, True)
session.commit() session.commit()
if new_shout.slug is None: if new_shout.slug is None:
@ -74,8 +80,9 @@ async def create_shout(_, info, inp):
@mutation.field("updateShout") @mutation.field("updateShout")
@login_required @login_required
async def update_shout(_, info, shout_id, shout_input=None, publish=False): async def update_shout(_, info, shout_id, shout_input=None, publish=False):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first()
shout = ( shout = (
session.query(Shout) session.query(Shout)
.options( .options(
@ -87,7 +94,7 @@ async def update_shout(_, info, shout_id, shout_input=None, publish=False):
) )
if not shout: if not shout:
return {"error": "shout not found"} return {"error": "shout not found"}
if shout.created_by != author_id: if shout.created_by != author.id:
return {"error": "access denied"} return {"error": "access denied"}
updated = False updated = False
if shout_input is not None: if shout_input is not None:
@ -154,12 +161,13 @@ async def update_shout(_, info, shout_id, shout_input=None, publish=False):
@mutation.field("deleteShout") @mutation.field("deleteShout")
@login_required @login_required
async def delete_shout(_, info, shout_id): async def delete_shout(_, info, shout_id):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
author = session.query(Author).filter(Author.id == user_id).first()
shout = session.query(Shout).filter(Shout.id == shout_id).first() shout = session.query(Shout).filter(Shout.id == shout_id).first()
if not shout: if not shout:
return {"error": "invalid shout id"} return {"error": "invalid shout id"}
if author_id != shout.created_by: if author.id not in shout.authors:
return {"error": "access denied"} return {"error": "access denied"}
for author_id in shout.authors: for author_id in shout.authors:
reactions_unfollow(author_id, shout_id) reactions_unfollow(author_id, shout_id)

View File

@ -7,32 +7,37 @@ from services.following import FollowingManager, FollowingResult
from services.db import local_session from services.db import local_session
from orm.author import Author from orm.author import Author
from services.notify import notify_follower from services.notify import notify_follower
from services.schema import mutation
@login_required @login_required
@mutation.field("follow")
async def follow(_, info, what, slug): async def follow(_, info, what, slug):
follower_id = info.context["author_id"] user_id = info.context["user_id"]
try: try:
if what == "AUTHOR": with local_session() as session:
if author_follow(follower_id, slug): actor = session.query(Author).filter(Author.user == user_id).first()
result = FollowingResult("NEW", 'author', slug) if actor:
await FollowingManager.push('author', result) follower_id = actor.id
with local_session() as session: if what == "AUTHOR":
author = session.query(Author.id).where(Author.slug == slug).one() if author_follow(follower_id, slug):
follower = session.query(Author).where(Author.id == follower_id).one() result = FollowingResult("NEW", "author", slug)
notify_follower(follower.dict(), author.id) await FollowingManager.push("author", result)
elif what == "TOPIC": author = session.query(Author.id).where(Author.slug == slug).one()
if topic_follow(follower_id, slug): follower = session.query(Author).where(Author.id == follower_id).one()
result = FollowingResult("NEW", 'topic', slug) await notify_follower(follower.dict(), author.id)
await FollowingManager.push('topic', result) elif what == "TOPIC":
elif what == "COMMUNITY": if topic_follow(follower_id, slug):
if community_follow(follower_id, slug): result = FollowingResult("NEW", "topic", slug)
result = FollowingResult("NEW", 'community', slug) await FollowingManager.push("topic", result)
await FollowingManager.push('community', result) elif what == "COMMUNITY":
elif what == "REACTIONS": if community_follow(follower_id, slug):
if reactions_follow(follower_id, slug): result = FollowingResult("NEW", "community", slug)
result = FollowingResult("NEW", 'shout', slug) await FollowingManager.push("community", result)
await FollowingManager.push('shout', result) elif what == "REACTIONS":
if reactions_follow(follower_id, slug):
result = FollowingResult("NEW", "shout", slug)
await FollowingManager.push("shout", result)
except Exception as e: except Exception as e:
print(Exception(e)) print(Exception(e))
return {"error": str(e)} return {"error": str(e)}
@ -41,30 +46,33 @@ async def follow(_, info, what, slug):
@login_required @login_required
@mutation.field("unfollow")
async def unfollow(_, info, what, slug): async def unfollow(_, info, what, slug):
follower_id = info.context["author_id"] user_id = info.context["user_id"]
try: try:
if what == "AUTHOR": with local_session() as session:
if author_unfollow(follower_id, slug): actor = session.query(Author).filter(Author.user == user_id).first()
result = FollowingResult("DELETED", 'author', slug) if actor:
await FollowingManager.push('author', result) follower_id = actor.id
if what == "AUTHOR":
with local_session() as session: if author_unfollow(follower_id, slug):
author = session.query(Author.id).where(Author.slug == slug).one() result = FollowingResult("DELETED", "author", slug)
follower = session.query(Author).where(Author.id == follower_id).one() await FollowingManager.push("author", result)
notify_follower(follower.dict(), author.id, "unfollow") author = session.query(Author.id).where(Author.slug == slug).one()
elif what == "TOPIC": follower = session.query(Author).where(Author.id == follower_id).one()
if topic_unfollow(follower_id, slug): await notify_follower(follower.dict(), author.id, "unfollow")
result = FollowingResult("DELETED", 'topic', slug) elif what == "TOPIC":
await FollowingManager.push('topic', result) if topic_unfollow(follower_id, slug):
elif what == "COMMUNITY": result = FollowingResult("DELETED", "topic", slug)
if community_unfollow(follower_id, slug): await FollowingManager.push("topic", result)
result = FollowingResult("DELETED", 'community', slug) elif what == "COMMUNITY":
await FollowingManager.push('community', result) if community_unfollow(follower_id, slug):
elif what == "REACTIONS": result = FollowingResult("DELETED", "community", slug)
if reactions_unfollow(follower_id, slug): await FollowingManager.push("community", result)
result = FollowingResult("DELETED", 'shout', slug) elif what == "REACTIONS":
await FollowingManager.push('shout', result) if reactions_unfollow(follower_id, slug):
result = FollowingResult("DELETED", "shout", slug)
await FollowingManager.push("shout", result)
except Exception as e: except Exception as e:
return {"error": str(e)} return {"error": str(e)}

View File

@ -159,18 +159,18 @@ def set_hidden(session, shout_id):
@mutation.field("createReaction") @mutation.field("createReaction")
@login_required @login_required
async def create_reaction(_, info, reaction): async def create_reaction(_, info, reaction):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
reaction["created_by"] = author_id
shout = session.query(Shout).where(Shout.id == reaction["shout"]).one() shout = session.query(Shout).where(Shout.id == reaction["shout"]).one()
author = session.query(Author).where(Author.user == user_id).first()
reaction["created_by"] = author.id
if reaction["kind"] in [ReactionKind.DISLIKE.name, ReactionKind.LIKE.name]: if reaction["kind"] in [ReactionKind.DISLIKE.name, ReactionKind.LIKE.name]:
existing_reaction = ( existing_reaction = (
session.query(Reaction) session.query(Reaction)
.where( .where(
and_( and_(
Reaction.shout == reaction["shout"], Reaction.shout == reaction["shout"],
Reaction.created_by == author_id, Reaction.created_by == author.id,
Reaction.kind == reaction["kind"], Reaction.kind == reaction["kind"],
Reaction.reply_to == reaction.get("reply_to"), Reaction.reply_to == reaction.get("reply_to"),
) )
@ -189,7 +189,7 @@ async def create_reaction(_, info, reaction):
.where( .where(
and_( and_(
Reaction.shout == reaction["shout"], Reaction.shout == reaction["shout"],
Reaction.created_by == author_id, Reaction.created_by == author.id,
Reaction.kind == opposite_reaction_kind, Reaction.kind == opposite_reaction_kind,
Reaction.reply_to == reaction.get("reply_to"), Reaction.reply_to == reaction.get("reply_to"),
) )
@ -203,7 +203,7 @@ async def create_reaction(_, info, reaction):
r = Reaction(**reaction) r = Reaction(**reaction)
# Proposal accepting logix # Proposal accepting logix
if r.reply_to is not None and r.kind == ReactionKind.ACCEPT and author_id in shout.dict()["authors"]: if r.reply_to is not None and r.kind == ReactionKind.ACCEPT and author.id in shout.dict()["authors"]:
replied_reaction = session.query(Reaction).where(Reaction.id == r.reply_to).first() replied_reaction = session.query(Reaction).where(Reaction.id == r.reply_to).first()
if replied_reaction and replied_reaction.kind == ReactionKind.PROPOSE: if replied_reaction and replied_reaction.kind == ReactionKind.PROPOSE:
if replied_reaction.range: if replied_reaction.range:
@ -218,18 +218,17 @@ async def create_reaction(_, info, reaction):
session.commit() session.commit()
rdict = r.dict() rdict = r.dict()
rdict["shout"] = shout.dict() rdict["shout"] = shout.dict()
author = session.query(Author).where(Author.id == author_id).first()
rdict["created_by"] = author.dict() rdict["created_by"] = author.dict()
# self-regulation mechanics # self-regulation mechanics
if check_to_hide(session, r): if check_to_hide(session, r):
set_hidden(session, r.shout) set_hidden(session, r.shout)
elif check_to_publish(session, author_id, r): elif check_to_publish(session, author.id, r):
set_published(session, r.shout) set_published(session, r.shout)
try: try:
reactions_follow(author_id, reaction["shout"], True) reactions_follow(author.id, reaction["shout"], True)
except Exception as e: except Exception as e:
print(f"[resolvers.reactions] error on reactions auto following: {e}") print(f"[resolvers.reactions] error on reactions auto following: {e}")
@ -244,7 +243,7 @@ async def create_reaction(_, info, reaction):
@mutation.field("updateReaction") @mutation.field("updateReaction")
@login_required @login_required
async def update_reaction(_, info, rid, reaction): async def update_reaction(_, info, rid, reaction):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
q = select(Reaction).filter(Reaction.id == rid) q = select(Reaction).filter(Reaction.id == rid)
q = add_reaction_stat_columns(q) q = add_reaction_stat_columns(q)
@ -254,41 +253,46 @@ async def update_reaction(_, info, rid, reaction):
if not r: if not r:
return {"error": "invalid reaction id"} return {"error": "invalid reaction id"}
if r.created_by != author_id: author = session.query(Author).filter(Author.user == user_id).first()
return {"error": "access denied"} if author:
body = reaction.get("body") if r.created_by != author.id:
if body: return {"error": "access denied"}
r.body = body body = reaction.get("body")
r.updated_at = int(time.time()) if body:
if r.kind != reaction["kind"]: r.body = body
# NOTE: change mind detection can be here r.updated_at = int(time.time())
pass if r.kind != reaction["kind"]:
# NOTE: change mind detection can be here
pass
# FIXME: range is not stable after body editing # FIXME: range is not stable after body editing
if reaction.get("range"): if reaction.get("range"):
r.range = reaction.get("range") r.range = reaction.get("range")
session.commit() session.commit()
r.stat = { r.stat = {
"commented": commented_stat, "commented": commented_stat,
"reacted": reacted_stat, "reacted": reacted_stat,
"rating": rating_stat, "rating": rating_stat,
} }
await notify_reaction(r.dict(), "update") await notify_reaction(r.dict(), "update")
return {"reaction": r} return {"reaction": r}
else:
return {"error": "user"}
@mutation.field("deleteReaction") @mutation.field("deleteReaction")
@login_required @login_required
async def delete_reaction(_, info, rid): async def delete_reaction(_, info, rid):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
r = session.query(Reaction).filter(Reaction.id == rid).first() r = session.query(Reaction).filter(Reaction.id == rid).first()
if not r: if not r:
return {"error": "invalid reaction id"} return {"error": "invalid reaction id"}
if r.created_by != author_id: author = session.query(Author).filter(Author.user == user_id).first()
if not author or r.created_by != author.id:
return {"error": "access denied"} return {"error": "access denied"}
if r.kind in [ReactionKind.LIKE, ReactionKind.DISLIKE]: if r.kind in [ReactionKind.LIKE, ReactionKind.DISLIKE]:
@ -400,6 +404,11 @@ def reacted_shouts_updates(follower_id):
@login_required @login_required
@query.field("followedReactions") @query.field("followedReactions")
async def get_reacted_shouts(_, info) -> List[Shout]: async def get_reacted_shouts(_, info) -> List[Shout]:
author_id = info.context["author_id"] user_id = info.context["user_id"]
shouts = reacted_shouts_updates(author_id) with local_session() as session:
return shouts author = session.query(Author).filter(Author.user == user_id).first()
if author:
shouts = reacted_shouts_updates(author.id)
return shouts
else:
return []

View File

@ -4,10 +4,12 @@ from sqlalchemy.sql.expression import desc, asc, select, func, case, and_, nulls
from services.auth import login_required from services.auth import login_required
from services.db import local_session from services.db import local_session
from services.schema import query
from orm.topic import TopicFollower from orm.topic import TopicFollower
from orm.reaction import Reaction, ReactionKind from orm.reaction import Reaction, ReactionKind
from orm.shout import Shout, ShoutAuthor, ShoutTopic from orm.shout import Shout, ShoutAuthor, ShoutTopic
from orm.author import AuthorFollower from orm.author import AuthorFollower, Author
from services.search import SearchService
from services.viewed import ViewedStorage from services.viewed import ViewedStorage
@ -69,6 +71,7 @@ def apply_filters(q, filters, author_id=None):
return q return q
@query.field("loadShout")
async def load_shout(_, _info, slug=None, shout_id=None): async def load_shout(_, _info, slug=None, shout_id=None):
with local_session() as session: with local_session() as session:
q = select(Shout).options( q = select(Shout).options(
@ -111,6 +114,7 @@ async def load_shout(_, _info, slug=None, shout_id=None):
return None return None
@query.field("loadShoutsBy")
async def load_shouts_by(_, info, options): async def load_shouts_by(_, info, options):
""" """
:param _: :param _:
@ -145,8 +149,13 @@ async def load_shouts_by(_, info, options):
q = add_stat_columns(q) q = add_stat_columns(q)
author_id = info.context["author_id"] user_id = info.context["user_id"]
q = apply_filters(q, options.get("filters", {}), author_id) filters = options.get("filters")
if filters:
with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first()
if author:
q = apply_filters(q, filters, author.id)
order_by = options.get("order_by", Shout.published_at) order_by = options.get("order_by", Shout.published_at)
@ -180,11 +189,13 @@ async def load_shouts_by(_, info, options):
@login_required @login_required
@query.field("loadFeed")
async def get_my_feed(_, info, options): async def get_my_feed(_, info, options):
author_id = info.context["author_id"] user_id = info.context["user_id"]
with local_session() as session: with local_session() as session:
author_followed_authors = select(AuthorFollower.author).where(AuthorFollower.follower == author_id) author = session.query(Author).filter(Author.user == user_id).first()
author_followed_topics = select(TopicFollower.topic).where(TopicFollower.follower == author_id) author_followed_authors = select(AuthorFollower.author).where(AuthorFollower.follower == author.id)
author_followed_topics = select(TopicFollower.topic).where(TopicFollower.follower == author.id)
subquery = ( subquery = (
select(Shout.id) select(Shout.id)
@ -209,7 +220,7 @@ async def get_my_feed(_, info, options):
) )
q = add_stat_columns(q) q = add_stat_columns(q)
q = apply_filters(q, options.get("filters", {}), author_id) q = apply_filters(q, options.get("filters", {}), author.id)
order_by = options.get("order_by", Shout.published_at) order_by = options.get("order_by", Shout.published_at)
@ -235,3 +246,11 @@ async def get_my_feed(_, info, options):
} }
shouts.append(shout) shouts.append(shout)
return shouts return shouts
@query.field("search")
async def search(_, info, text, limit=50, offset=0):
if text and len(text) > 2:
return SearchService.search(text, limit, offset)
else:
return []

View File

@ -135,13 +135,13 @@ def topic_follow(follower_id, slug):
return False return False
def topic_unfollow(user_id, slug): def topic_unfollow(follower_id, slug):
try: try:
with local_session() as session: with local_session() as session:
sub = ( sub = (
session.query(TopicFollower) session.query(TopicFollower)
.join(Topic) .join(Topic)
.filter(and_(TopicFollower.follower == user_id, Topic.slug == slug)) .filter(and_(TopicFollower.follower == follower_id, Topic.slug == slug))
.first() .first()
) )
if sub: if sub:
@ -153,6 +153,7 @@ def topic_unfollow(user_id, slug):
return False return False
@query.field("topicsRandom")
async def topics_random(_, info, amount=12): async def topics_random(_, info, amount=12):
q = select(Topic) q = select(Topic)
q = q.join(ShoutTopic) q = q.join(ShoutTopic)

View File

@ -334,4 +334,6 @@ type Query {
communitiesAll: [Community] communitiesAll: [Community]
getCommunity: Community getCommunity: Community
search(text: String!, limit: Int, offset: Int): [Shout]
} }

View File

@ -11,7 +11,7 @@ async def check_auth(req):
query_type = "query" query_type = "query"
operation = "GetUserId" operation = "GetUserId"
headers = {"Authorization": "Bearer " + token, "Content-Type": "application/json"} headers = {"Authorization": token, "Content-Type": "application/json"}
gql = { gql = {
"query": query_type + " " + operation + " { " + query_name + " { user { id } } " + " }", "query": query_type + " " + operation + " { " + query_name + " { user { id } } " + " }",
@ -26,9 +26,7 @@ async def check_auth(req):
return False, None return False, None
r = response.json() r = response.json()
try: try:
user_id = ( user_id = r.get("data", {}).get(query_name, {}).get("user", {}).get("id", None)
r.get("data", {}).get(query_name, {}).get("user", {}).get("id", None)
)
is_authenticated = user_id is not None is_authenticated = user_id is not None
return is_authenticated, user_id return is_authenticated, user_id
except Exception as e: except Exception as e:
@ -47,7 +45,7 @@ def login_required(f):
raise Exception("You are not logged in") raise Exception("You are not logged in")
else: else:
# Добавляем author_id в контекст # Добавляем author_id в контекст
context["author_id"] = user_id context["user_id"] = user_id
# Если пользователь аутентифицирован, выполняем резолвер # Если пользователь аутентифицирован, выполняем резолвер
return await f(*args, **kwargs) return await f(*args, **kwargs)
@ -63,7 +61,7 @@ def auth_request(f):
if not is_authenticated: if not is_authenticated:
raise HTTPError("please, login first") raise HTTPError("please, login first")
else: else:
req["author_id"] = user_id req["user_id"] = user_id
return await f(*args, **kwargs) return await f(*args, **kwargs)
return decorated_function return decorated_function

View File

@ -1,8 +1,8 @@
import asyncio import asyncio
import json import json
import httpx
from services.rediscache import redis from services.rediscache import redis
from orm.shout import Shout from orm.shout import Shout
from resolvers.reader import load_shouts_by
class SearchService: class SearchService:
@ -20,15 +20,13 @@ class SearchService:
cached = await redis.execute("GET", text) cached = await redis.execute("GET", text)
if not cached: if not cached:
async with SearchService.lock: async with SearchService.lock:
options = { # Use httpx to send a request to ElasticSearch
"title": text, async with httpx.AsyncClient() as client:
"body": text, search_url = f"https://search.discours.io/search?q={text}"
"limit": limit, response = await client.get(search_url)
"offset": offset, if response.status_code == 200:
} payload = response.json()
# FIXME: use elastic request here await redis.execute("SET", text, payload)
payload = await load_shouts_by(None, None, options) return json.loads(payload)
await redis.execute("SET", text, json.dumps(payload))
return payload
else: else:
return json.loads(cached) return json.loads(cached)