1515 URL ,
1616)
1717
18+ from minos .api_gateway .rest .exceptions import (
19+ InvalidAuthenticationException ,
20+ NoTokenException ,
21+ )
22+
23+ ANONYMOUS = "Anonymous"
24+
1825logger = logging .getLogger (__name__ )
1926
2027
@@ -28,10 +35,27 @@ async def orchestrate(request: web.Request) -> web.Response:
2835
2936 discovery_data = await discover (discovery_host , int (discovery_port ), "/microservices" , verb , url )
3037
31- microservice_response = await call (** discovery_data , original_req = request )
38+ user = await get_user (request )
39+
40+ microservice_response = await call (** discovery_data , original_req = request , user = user )
3241 return microservice_response
3342
3443
44+ async def get_user (request ) -> str :
45+ try :
46+ await get_token (request )
47+ except NoTokenException :
48+ return ANONYMOUS
49+ else :
50+ try :
51+ original_headers = dict (request .headers .copy ())
52+ user_uuid = await authenticate ("localhost" , "8082" , "POST" , "token" , original_headers )
53+ except InvalidAuthenticationException :
54+ return ANONYMOUS
55+ else :
56+ return user_uuid
57+
58+
3559async def discover (host : str , port : int , path : str , verb : str , endpoint : str ) -> dict [str , Any ]:
3660 """Call discovery service and get microservice connection data.
3761
@@ -59,25 +83,19 @@ async def discover(host: str, port: int, path: str, verb: str, endpoint: str) ->
5983
6084
6185# noinspection PyUnusedLocal
62- async def call (address : str , port : int , original_req : web .Request , ** kwargs ) -> web .Response :
86+ async def call (address : str , port : int , original_req : web .Request , user : str , ** kwargs ) -> web .Response :
6387 """Call microservice (redirect the original call)
6488
6589 :param address: The ip of the microservices.
6690 :param port: The port of the microservice.
6791 :param original_req: The original request.
6892 :param kwargs: Additional named arguments.
93+ :param user: User that makes the request
6994 :return: The web response to be retrieved to the client.
7095 """
7196
7297 headers = original_req .headers .copy ()
73- if "Authorization" in headers and "Bearer" in headers ["Authorization" ]:
74- parts = headers ["Authorization" ].split ()
75- if len (parts ) == 2 :
76- headers ["User" ] = parts [1 ]
77- else :
78- headers ["User" ] = "None"
79- else :
80- headers ["User" ] = "None"
98+ headers ["User" ] = user
8199
82100 url = original_req .url .with_scheme ("http" ).with_host (address ).with_port (port )
83101 method = original_req .method
@@ -86,8 +104,8 @@ async def call(address: str, port: int, original_req: web.Request, **kwargs) ->
86104 logger .info (f"Redirecting { method !r} request to { url !r} ..." )
87105
88106 try :
89- async with ClientSession (headers = headers ) as session :
90- async with session .request (method = method , url = url , data = content ) as response :
107+ async with ClientSession () as session :
108+ async with session .request (headers = headers , method = method , url = url , data = content ) as response :
91109 return await _clone_response (response )
92110 except ClientConnectorError :
93111 raise web .HTTPServiceUnavailable (text = "The requested endpoint is not available." )
@@ -98,3 +116,30 @@ async def _clone_response(response: ClientResponse) -> web.Response:
98116 return web .Response (
99117 body = await response .read (), status = response .status , reason = response .reason , headers = response .headers ,
100118 )
119+
120+
121+ async def authenticate (address : str , port : str , method : str , path : str , authorization_headers : dict [str , str ]) -> str :
122+ authentication_url = URL (f"http://{ address } :{ port } /{ path } " )
123+ authentication_method = method
124+ logger .info ("Authenticating request..." )
125+
126+ try :
127+ async with ClientSession (headers = authorization_headers ) as session :
128+ async with session .request (method = authentication_method , url = authentication_url ) as response :
129+ if response .ok :
130+ jwt_payload = await response .json ()
131+ return jwt_payload ["sub" ]
132+ else :
133+ raise InvalidAuthenticationException
134+ except (ClientConnectorError , web .HTTPError ):
135+ raise InvalidAuthenticationException
136+
137+
138+ async def get_token (request : web .Request ) -> str :
139+ headers = request .headers
140+ if "Authorization" in headers and "Bearer" in headers ["Authorization" ]:
141+ parts = headers ["Authorization" ].split ()
142+ if len (parts ) == 2 :
143+ return parts [1 ]
144+
145+ raise NoTokenException
0 commit comments