2024-01-25 19:41:27 +00:00
from functools import wraps
2024-04-08 07:38:58 +00:00
2024-02-19 09:49:33 +00:00
import httpx
2024-01-23 18:59:46 +00:00
2024-08-07 05:57:56 +00:00
from cache . cache import get_cached_author_by_user_id
2024-08-09 06:37:06 +00:00
from resolvers . stat import get_with_stat
2024-02-19 08:10:12 +00:00
from settings import ADMIN_SECRET , AUTH_URL
2024-08-09 06:37:06 +00:00
from utils . logger import root_logger as logger
2024-01-13 08:49:12 +00:00
2024-02-21 07:27:16 +00:00
2024-01-25 19:41:27 +00:00
async def request_data ( gql , headers = None ) :
if headers is None :
2024-04-17 15:32:23 +00:00
headers = { " Content-Type " : " application/json " }
2024-01-10 13:29:49 +00:00
try :
2024-06-12 09:48:09 +00:00
# logger.debug(f"{AUTH_URL} {gql} {headers}")
2024-02-19 08:10:12 +00:00
async with httpx . AsyncClient ( ) as client :
response = await client . post ( AUTH_URL , json = gql , headers = headers )
if response . status_code == 200 :
data = response . json ( )
2024-04-17 15:32:23 +00:00
errors = data . get ( " errors " )
2024-02-19 08:10:12 +00:00
if errors :
2024-06-06 08:24:26 +00:00
logger . error ( f " { AUTH_URL } response: { data } " )
2024-02-19 08:10:12 +00:00
else :
return data
2024-06-06 08:13:54 +00:00
except Exception as _e :
2024-01-23 19:12:22 +00:00
# Handling and logging exceptions during authentication check
2024-04-22 09:48:57 +00:00
import traceback
2024-04-23 11:31:34 +00:00
2024-06-06 08:13:54 +00:00
logger . error ( f " request_data error: { traceback . format_exc ( ) } " )
2024-02-27 11:16:54 +00:00
return None
2024-01-10 13:29:49 +00:00
2024-02-19 12:51:09 +00:00
async def check_auth ( req ) :
2024-04-17 15:32:23 +00:00
token = req . headers . get ( " Authorization " )
user_id = " "
2024-02-23 21:00:46 +00:00
user_roles = [ ]
2024-02-20 15:20:57 +00:00
if token :
2024-02-23 11:53:14 +00:00
# Logging the authentication token
2024-04-17 15:32:23 +00:00
logger . debug ( f " { token } " )
query_name = " validate_jwt_token "
operation = " ValidateToken "
variables = { " params " : { " token_type " : " access_token " , " token " : token } }
2024-02-23 11:53:14 +00:00
gql = {
2024-04-17 15:32:23 +00:00
" query " : f " query { operation } ($params: ValidateJWTTokenInput!) {{ "
+ f " { query_name } (params: $params) {{ is_valid claims }} "
+ " } " ,
" variables " : variables ,
" operationName " : operation ,
2024-02-23 11:53:14 +00:00
}
data = await request_data ( gql )
if data :
2024-02-26 09:52:22 +00:00
logger . debug ( data )
2024-04-17 15:32:23 +00:00
user_data = data . get ( " data " , { } ) . get ( query_name , { } ) . get ( " claims " , { } )
user_id = user_data . get ( " sub " , " " )
user_roles = user_data . get ( " allowed_roles " , [ ] )
2024-02-27 10:40:56 +00:00
return user_id , user_roles
2024-01-23 19:12:22 +00:00
2023-12-24 22:42:39 +00:00
2024-01-10 13:29:49 +00:00
async def add_user_role ( user_id ) :
2024-04-17 15:32:23 +00:00
logger . info ( f " add author role for user_id: { user_id } " )
query_name = " _update_user "
operation = " UpdateUserRoles "
2024-01-25 19:41:27 +00:00
headers = {
2024-04-17 15:32:23 +00:00
" Content-Type " : " application/json " ,
" x-authorizer-admin-secret " : ADMIN_SECRET ,
2024-01-25 19:41:27 +00:00
}
2024-04-17 15:32:23 +00:00
variables = { " params " : { " roles " : " author, reader " , " id " : user_id } }
2023-12-24 22:42:39 +00:00
gql = {
2024-04-17 15:32:23 +00:00
" query " : f " mutation { operation } ($params: UpdateUserInput!) {{ { query_name } (params: $params) {{ id roles }} }} " ,
" variables " : variables ,
" operationName " : operation ,
2023-12-24 22:42:39 +00:00
}
2024-01-10 13:29:49 +00:00
data = await request_data ( gql , headers )
if data :
2024-04-17 15:32:23 +00:00
user_id = data . get ( " data " , { } ) . get ( query_name , { } ) . get ( " id " )
2024-01-10 13:29:49 +00:00
return user_id
2023-10-23 14:47:11 +00:00
2024-01-25 19:41:27 +00:00
2023-10-23 14:47:11 +00:00
def login_required ( f ) :
2024-01-23 18:59:46 +00:00
@wraps ( f )
2023-10-23 14:47:11 +00:00
async def decorated_function ( * args , * * kwargs ) :
info = args [ 1 ]
2024-04-17 15:32:23 +00:00
req = info . context . get ( " request " )
2024-04-19 15:22:07 +00:00
user_id , user_roles = await check_auth ( req )
if user_id and user_roles :
logger . info ( f " got { user_id } roles: { user_roles } " )
info . context [ " user_id " ] = user_id . strip ( )
info . context [ " roles " ] = user_roles
2024-05-20 23:01:18 +00:00
author = await get_cached_author_by_user_id ( user_id , get_with_stat )
2024-04-30 13:18:50 +00:00
if not author :
2024-05-01 01:01:21 +00:00
logger . error ( f " author profile not found for user { user_id } " )
2024-04-19 15:22:07 +00:00
info . context [ " author " ] = author
2024-02-27 11:16:54 +00:00
return await f ( * args , * * kwargs )
2023-10-23 14:47:11 +00:00
return decorated_function
2024-11-12 14:56:20 +00:00
def login_accepted ( f ) :
"""
Декоратор , который добавляет данные авторизации в контекст , если они доступны ,
но не блокирует доступ для неавторизованных пользователей .
"""
@wraps ( f )
async def decorated_function ( * args , * * kwargs ) :
info = args [ 1 ]
req = info . context . get ( " request " )
2024-11-14 11:00:33 +00:00
logger . debug ( " login_accepted: Проверка авторизации пользователя. " )
2024-11-12 14:56:20 +00:00
user_id , user_roles = await check_auth ( req )
2024-11-14 11:00:33 +00:00
logger . debug ( f " login_accepted: user_id= { user_id } , user_roles= { user_roles } " )
2024-11-12 14:56:20 +00:00
if user_id and user_roles :
2024-11-14 11:00:33 +00:00
logger . info ( f " login_accepted: Пользователь авторизован: { user_id } с ролями { user_roles } " )
2024-11-12 14:56:20 +00:00
info . context [ " user_id " ] = user_id . strip ( )
info . context [ " roles " ] = user_roles
# Пробуем получить профиль автора
author = await get_cached_author_by_user_id ( user_id , get_with_stat )
2024-11-14 11:00:33 +00:00
if author :
logger . debug ( f " login_accepted: Найден профиль автора: { author } " )
# Предполагается, что `author` является объектом с атрибутом `id`
info . context [ " author " ] = author . dict ( )
else :
logger . error ( f " login_accepted: Профиль автора не найден для пользователя { user_id } . Используем базовые данные. " ) # Используем базовую информацию о б автор
2024-11-12 14:56:20 +00:00
else :
2024-11-14 11:00:33 +00:00
logger . debug ( " login_accepted: Пользователь не авторизован. Очищаем контекст. " )
2024-11-12 14:56:20 +00:00
info . context [ " user_id " ] = None
info . context [ " roles " ] = None
info . context [ " author " ] = None
return await f ( * args , * * kwargs )
return decorated_function