fmt
All checks were successful
Deploy to core / deploy (push) Successful in 1m42s

This commit is contained in:
Untone 2024-02-05 12:47:26 +03:00
parent 77dddedae6
commit 7746d1992f
3 changed files with 49 additions and 38 deletions

View File

@ -32,6 +32,7 @@ async def get_shouts_drafts(_, info):
joinedload(Shout.topics), joinedload(Shout.topics),
) )
.filter(and_(Shout.deleted_at.is_(None), Shout.created_by == author.id)) .filter(and_(Shout.deleted_at.is_(None), Shout.created_by == author.id))
.filter(Shout.published_at.is_(None))
.group_by(Shout.id) .group_by(Shout.id)
) )
shouts = [shout for [shout] in session.execute(q).unique()] shouts = [shout for [shout] in session.execute(q).unique()]
@ -161,6 +162,7 @@ def patch_topics(session, shout, topics_input):
@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):
user_id = info.context['user_id'] user_id = info.context['user_id']
roles = info.context['roles']
if not shout_input: if not shout_input:
shout_input = {} shout_input = {}
with local_session() as session: with local_session() as session:
@ -178,7 +180,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 is not author.id and author.id not in shout.authors: if shout.created_by is not author.id and author.id not in shout.authors and 'editor' not in roles:
return {'error': 'access denied'} return {'error': 'access denied'}
# topics patch # topics patch
@ -215,13 +217,14 @@ async def update_shout(_, info, shout_id, shout_input=None, publish=False):
@login_required @login_required
async def delete_shout(_, info, shout_id): async def delete_shout(_, info, shout_id):
user_id = info.context['user_id'] user_id = info.context['user_id']
roles = info.context['roles']
with local_session() as session: with local_session() as session:
author = session.query(Author).filter(Author.user == user_id).first() author = session.query(Author).filter(Author.user == 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 and shout: if author and shout:
if shout.created_by is not author.id and author.id not in shout.authors: if shout.created_by is not author.id and author.id not in shout.authors and 'editor' not in roles:
return {'error': 'access denied'} return {'error': 'access denied'}
for author_id in shout.authors: for author_id in shout.authors:

View File

@ -212,40 +212,42 @@ async def create_reaction(_, info, reaction):
@login_required @login_required
async def update_reaction(_, info, rid, reaction): async def update_reaction(_, info, rid, reaction):
user_id = info.context['user_id'] user_id = info.context['user_id']
with local_session() as session: roles = info.context['roles']
q = select(Reaction).filter(Reaction.id == rid) if user_id and roles:
aliased_reaction = aliased(Reaction) with local_session() as session:
q = add_stat_columns(q, aliased_reaction) q = select(Reaction).filter(Reaction.id == rid)
q = q.group_by(Reaction.id) aliased_reaction = aliased(Reaction)
q = add_stat_columns(q, aliased_reaction)
q = q.group_by(Reaction.id)
[r, reacted_stat, commented_stat, likes_stat, dislikes_stat, _l] = session.execute(q).unique().first() [r, reacted_stat, commented_stat, likes_stat, dislikes_stat, _l] = session.execute(q).unique().first()
if not r: if not r:
return {'error': 'invalid reaction id'} return {'error': 'invalid reaction id'}
author = session.query(Author).filter(Author.user == user_id).first() author = session.query(Author).filter(Author.user == user_id).first()
if author: if author:
if r.created_by != author.id: if r.created_by != author.id and 'editor' not in roles:
return {'error': 'access denied'} return {'error': 'access denied'}
body = reaction.get('body') body = reaction.get('body')
if body: if body:
r.body = body r.body = body
r.updated_at = int(time.time()) r.updated_at = int(time.time())
if r.kind != reaction['kind']: if r.kind != reaction['kind']:
# TODO: change mind detection can be here # TODO: change mind detection can be here
pass pass
session.commit() session.commit()
r.stat = { r.stat = {
'reacted': reacted_stat, 'reacted': reacted_stat,
'commented': commented_stat, 'commented': commented_stat,
'rating': int(likes_stat or 0) - int(dislikes_stat or 0), 'rating': int(likes_stat or 0) - int(dislikes_stat or 0),
} }
await notify_reaction(r.dict(), 'update') await notify_reaction(r.dict(), 'update')
return {'reaction': r} return {'reaction': r}
else: else:
return {'error': 'not authorized'} return {'error': 'not authorized'}
return {'error': 'cannot create reaction'} return {'error': 'cannot create reaction'}
@ -253,13 +255,14 @@ async def update_reaction(_, info, rid, reaction):
@login_required @login_required
async def delete_reaction(_, info, reaction_id): async def delete_reaction(_, info, reaction_id):
user_id = info.context['user_id'] user_id = info.context['user_id']
roles = info.context['roles']
with local_session() as session: with local_session() as session:
r = session.query(Reaction).filter(Reaction.id == reaction_id).first() r = session.query(Reaction).filter(Reaction.id == reaction_id).first()
if not r: if not r:
return {'error': 'invalid reaction id'} return {'error': 'invalid reaction id'}
author = session.query(Author).filter(Author.user == user_id).first() author = session.query(Author).filter(Author.user == user_id).first()
if author: if author:
if r.created_by is author.id: if r.created_by is author.id and 'editor' not in roles:
return {'error': 'access denied'} return {'error': 'access denied'}
if r.kind in [ReactionKind.LIKE.value, ReactionKind.DISLIKE.value]: if r.kind in [ReactionKind.LIKE.value, ReactionKind.DISLIKE.value]:

View File

@ -31,7 +31,7 @@ async def request_data(gql, headers=None):
return None return None
async def check_auth(req) -> str | None: async def check_auth(req):
token = req.headers.get('Authorization') token = req.headers.get('Authorization')
user_id = '' user_id = ''
if token: if token:
@ -55,8 +55,10 @@ async def check_auth(req) -> str | None:
} }
data = await request_data(gql) data = await request_data(gql)
if data: if data:
user_id = data.get('data', {}).get(query_name, {}).get('claims', {}).get('sub') user_data = data.get('data', {}).get(query_name, {}).get('claims', {})
return user_id user_id = user_data.get('sub')
user_roles = user_data.get('allowed_roles')
return [user_id, user_roles]
if not user_id: if not user_id:
raise HTTPException(status_code=401, detail='Unauthorized') raise HTTPException(status_code=401, detail='Unauthorized')
@ -88,9 +90,11 @@ def login_required(f):
info = args[1] info = args[1]
context = info.context context = info.context
req = context.get('request') req = context.get('request')
user_id = await check_auth(req) [user_id, user_roles] = (await check_auth(req)) or []
if user_id: if user_id and user_roles:
logger.info(f' got {user_id} roles: {user_roles}')
context['user_id'] = user_id.strip() context['user_id'] = user_id.strip()
context['roles'] = user_roles
return await f(*args, **kwargs) return await f(*args, **kwargs)
return decorated_function return decorated_function
@ -100,9 +104,10 @@ def auth_request(f):
@wraps(f) @wraps(f)
async def decorated_function(*args, **kwargs): async def decorated_function(*args, **kwargs):
req = args[0] req = args[0]
user_id = await check_auth(req) [user_id, user_roles] = (await check_auth(req)) or []
if user_id: if user_id:
req['user_id'] = user_id.strip() req['user_id'] = user_id.strip()
req['roles'] = user_roles
return await f(*args, **kwargs) return await f(*args, **kwargs)
return decorated_function return decorated_function