Merge branch 'prepare-comments' of github.com:Discours/discours-backend into prepare-comments

This commit is contained in:
Igor Lobanov 2022-11-23 12:56:15 +01:00
commit 5c803afa39
11 changed files with 59 additions and 37 deletions

View File

@ -28,6 +28,7 @@ class SessionToken:
token is of specified type token is of specified type
""" """
try: try:
print('[auth.authenticate] session token verify')
payload = JWTCodec.decode(token) payload = JWTCodec.decode(token)
except ExpiredSignatureError: except ExpiredSignatureError:
payload = JWTCodec.decode(token, verify_exp=False) payload = JWTCodec.decode(token, verify_exp=False)
@ -58,6 +59,8 @@ class JWTAuthenticate(AuthenticationBackend):
try: try:
payload = await SessionToken.verify(token) payload = await SessionToken.verify(token)
except Exception as exc: except Exception as exc:
print("[auth.authenticate] session token verify error")
print(exc)
return AuthCredentials(scopes=[], error_message=str(exc)), AuthUser( return AuthCredentials(scopes=[], error_message=str(exc)), AuthUser(
user_id=None user_id=None
) )

View File

@ -81,6 +81,7 @@ class Identity:
@staticmethod @staticmethod
async def onetime(token: str) -> User: async def onetime(token: str) -> User:
try: try:
print('[auth.identity] using one time token')
payload = JWTCodec.decode(token) payload = JWTCodec.decode(token)
if not await TokenStorage.exist(f"{payload.user_id}-{token}"): if not await TokenStorage.exist(f"{payload.user_id}-{token}"):
raise InvalidToken("Login token has expired, please login again") raise InvalidToken("Login token has expired, please login again")

View File

@ -36,11 +36,13 @@ class TokenStorage:
@staticmethod @staticmethod
async def revoke(token: str) -> bool: async def revoke(token: str) -> bool:
payload = None
try: try:
print("[auth.tokenstorage] revoke token")
payload = JWTCodec.decode(token) payload = JWTCodec.decode(token)
except: # noqa except: # noqa
pass pass
else: finally:
await redis.execute("DEL", f"{payload.user_id}-{token}") await redis.execute("DEL", f"{payload.user_id}-{token}")
return True return True

View File

@ -1,5 +1,5 @@
from aioredis import from_url from aioredis import from_url
from asyncio import sleep
from settings import REDIS_URL from settings import REDIS_URL
@ -21,7 +21,12 @@ class RedisCache:
self._instance = None self._instance = None
async def execute(self, command, *args, **kwargs): async def execute(self, command, *args, **kwargs):
return await self._instance.execute_command(command, *args, **kwargs) while not self._instance:
await sleep(1)
try:
await self._instance.execute_command(command, *args, **kwargs)
except Exception:
pass
async def lrange(self, key, start, stop): async def lrange(self, key, start, stop):
return await self._instance.lrange(key, start, stop) return await self._instance.lrange(key, start, stop)

View File

@ -42,6 +42,7 @@ async def get_current_user(_, info):
async def confirm_email(_, info, token): async def confirm_email(_, info, token):
"""confirm owning email address""" """confirm owning email address"""
try: try:
print('[resolvers.auth] confirm email by token')
payload = JWTCodec.decode(token) payload = JWTCodec.decode(token)
user_id = payload.user_id user_id = payload.user_id
await TokenStorage.get(f"{user_id}-{token}") await TokenStorage.get(f"{user_id}-{token}")
@ -175,7 +176,7 @@ async def login(_, info, email: str, password: str = "", lang: str = "ru"):
} }
except InvalidPassword: except InvalidPassword:
print(f"[auth] {email}: invalid password") print(f"[auth] {email}: invalid password")
raise InvalidPassword("invalid passoword") # contains webserver status raise InvalidPassword("invalid password") # contains webserver status
# return {"error": "invalid password"} # return {"error": "invalid password"}

View File

@ -33,18 +33,24 @@ async def load_messages(chatId: str, limit: int, offset: int):
async def load_chats(_, info, limit: int, offset: int): async def load_chats(_, info, limit: int, offset: int):
""" load :limit chats of current user with :offset """ """ load :limit chats of current user with :offset """
user = info.context["request"].user user = info.context["request"].user
chats = await redis.execute("GET", f"chats_by_user/{user.slug}") if user:
if chats: chats = await redis.execute("GET", f"chats_by_user/{user.slug}")
chats = list(json.loads(chats))[offset:offset + limit] if chats:
if not chats: chats = list(json.loads(chats))[offset:offset + limit]
chats = [] if not chats:
for c in chats: chats = []
c['messages'] = await load_messages(c['id'], limit, offset) for c in chats:
c['unread'] = await get_unread_counter(c['id'], user.slug) c['messages'] = await load_messages(c['id'], limit, offset)
return { c['unread'] = await get_unread_counter(c['id'], user.slug)
"chats": chats, return {
"error": None "chats": chats,
} "error": None
}
else:
return {
"error": "please login",
"chats": []
}
@query.field("loadMessagesBy") @query.field("loadMessagesBy")

View File

@ -31,6 +31,7 @@ def apply_filters(q, filters, user=None):
q = q.filter(Shout.createdAt > before) q = q.filter(Shout.createdAt > before)
return q return q
@query.field("loadShout") @query.field("loadShout")
async def load_shout(_, info, slug): async def load_shout(_, info, slug):
with local_session() as session: with local_session() as session:

View File

@ -1,5 +1,5 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from sqlalchemy import and_, asc, desc, select, text, func, column from sqlalchemy import and_, asc, desc, select, text, func
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from auth.authenticate import login_required from auth.authenticate import login_required
@ -23,12 +23,10 @@ async def get_reaction_stat(reaction_id):
def reactions_follow(user: User, slug: str, auto=False): def reactions_follow(user: User, slug: str, auto=False):
with local_session() as session: with local_session() as session:
following = ( following = (
session.query(ShoutReactionsFollower) session.query(ShoutReactionsFollower).where(and_(
.where(and_(
ShoutReactionsFollower.follower == user.slug, ShoutReactionsFollower.follower == user.slug,
ShoutReactionsFollower.shout == slug ShoutReactionsFollower.shout == slug
)) )).first()
.first()
) )
if not following: if not following:
following = ShoutReactionsFollower.create( following = ShoutReactionsFollower.create(
@ -43,12 +41,10 @@ def reactions_follow(user: User, slug: str, auto=False):
def reactions_unfollow(user, slug): def reactions_unfollow(user, slug):
with local_session() as session: with local_session() as session:
following = ( following = (
session.query(ShoutReactionsFollower) session.query(ShoutReactionsFollower).where(and_(
.where(and_(
ShoutReactionsFollower.follower == user.slug, ShoutReactionsFollower.follower == user.slug,
ShoutReactionsFollower.shout == slug ShoutReactionsFollower.shout == slug
)) )).first()
.first()
) )
if following: if following:
session.delete(following) session.delete(following)
@ -199,6 +195,7 @@ async def delete_reaction(_, info, rid):
session.commit() session.commit()
return {} return {}
def map_result_item(result_item): def map_result_item(result_item):
reaction = result_item[0] reaction = result_item[0]
user = result_item[1] user = result_item[1]

View File

@ -23,10 +23,12 @@ class UserStorage:
async def get_user(id): async def get_user(id):
with local_session() as session: with local_session() as session:
user = ( user = (
session.query(User) session.query(User).options(
.options(selectinload(User.roles), selectinload(User.ratings)) selectinload(User.roles),
.filter(User.id == id) selectinload(User.ratings)
.one() ).filter(
User.id == id
).one()
) )
return user return user

View File

@ -35,8 +35,10 @@ class ReactedStorage:
@staticmethod @staticmethod
async def get_shout_stat(slug): async def get_shout_stat(slug):
viewed = int(await ViewedStorage.get_shout(slug))
print(viewed)
return { return {
"viewed": await ViewedStorage.get_shout(slug), "viewed": viewed,
"reacted": len(await ReactedStorage.get_shout(slug)), "reacted": len(await ReactedStorage.get_shout(slug)),
"commented": len(await ReactedStorage.get_comments(slug)), "commented": len(await ReactedStorage.get_comments(slug)),
"rating": await ReactedStorage.get_rating(slug), "rating": await ReactedStorage.get_rating(slug),

View File

@ -3,7 +3,7 @@ from datetime import timedelta, timezone, datetime
from gql import Client, gql from gql import Client, gql
from gql.transport.aiohttp import AIOHTTPTransport from gql.transport.aiohttp import AIOHTTPTransport
from base.orm import local_session from base.orm import local_session
from sqlalchemy import func, select from sqlalchemy import func
from orm.shout import ShoutTopic from orm.shout import ShoutTopic
from orm.viewed import ViewedEntry from orm.viewed import ViewedEntry
from ssl import create_default_context from ssl import create_default_context
@ -119,12 +119,14 @@ class ViewedStorage:
if not shout_views: if not shout_views:
shout_views = 0 shout_views = 0
with local_session() as session: with local_session() as session:
shout_views_q = select(func.sum(ViewedEntry.amount)).where( try:
ViewedEntry.shout == shout_slug shout_views = session.query(func.sum(ViewedEntry.amount)).where(
) ViewedEntry.shout == shout_slug
shout_views = session.execute(shout_views_q) ).all()[0][0]
self.by_shouts[shout_slug] = shout_views self.by_shouts[shout_slug] = shout_views
self.update_topics(session, shout_slug) self.update_topics(session, shout_slug)
except Exception as e:
raise e
return shout_views return shout_views