11"""Request handlers."""
22from datetime import datetime , timedelta
3+ from urllib .parse import urljoin
34import uuid
45
56from sanic .blueprints import Blueprint
1112from .constants import *
1213from .exceptions import FdkSessionNotFoundError , FdkInvalidOAuthError
1314from .extension import extension
14- from .middleware .session_middleware import session_middleware
15+ from .middleware .session_middleware import session_middleware , partner_session_middleware
1516from .session .session import Session
1617from .session .session_storage import SessionStorage
1718from .utilities import logger
@@ -99,7 +100,7 @@ async def auth_handler(request: Request):
99100 if not extension .is_online_access_mode ():
100101 session_id = Session .generate_session_id (False , ** {
101102 "cluster" : extension .cluster ,
102- "company_id " : company_id
103+ "id " : company_id
103104 })
104105 session = await SessionStorage .get_session (session_id )
105106 if not session :
@@ -156,7 +157,7 @@ async def auto_install_handler(request: Request):
156157 platform_config = extension .get_platform_config (company_id = company_id )
157158 session_id = Session .generate_session_id (False , ** {
158159 "cluster" : extension .cluster ,
159- "company_id " : company_id
160+ "id " : company_id
160161 })
161162
162163 session = await SessionStorage .get_session (session_id = session_id )
@@ -203,7 +204,7 @@ async def uninstall_handler(request: Request):
203204 if not extension .is_online_access_mode ():
204205 session_id = Session .generate_session_id (False , ** {
205206 "cluster" : extension .cluster ,
206- "company_id " : company_id
207+ "id " : company_id
207208 })
208209 await SessionStorage .delete_session (session_id = session_id )
209210
@@ -214,17 +215,137 @@ async def uninstall_handler(request: Request):
214215 logger .exception (e )
215216 return json_response ({"error_message" : str (e )}, 500 )
216217
218+ async def adm_install_handler (request : Request ):
219+ try :
220+ organization_id = request .args .get ("organization_id" )
221+ partner_config = extension .get_partner_config (organization_id )
222+
223+ session = Session (Session .generate_session_id (True ))
224+ session_expires = datetime .now () + timedelta (seconds = SESSION_EXPIRY_IN_SECONDS ) # 15 mins
225+
226+ if session .is_new :
227+ session .organization_id = organization_id
228+ session .scope = extension .scopes
229+ session .expires = session_expires
230+ session .access_mode = ONLINE_ACCESS_MODE # Always generate online mode token for extension launch
231+ session .extension_id = extension .api_key
232+
233+ request .conn_info .ctx .fdk_session = session
234+ request .conn_info .ctx .extension = extension
235+
236+ session .state = str (uuid .uuid4 ())
237+
238+ auth_callback = extension .get_adm_auth_callback ()
239+
240+ # start authorization flow
241+ redirect_url = partner_config .oauthClient .startAuthorization ({
242+ "scope" : session .scope ,
243+ "redirectUri" : auth_callback ,
244+ "state" : session .state ,
245+ "access_mode" : ONLINE_ACCESS_MODE # Always generate online mode token for extension launch
246+ })
247+
248+ logger .debug (f"Redirecting after partner install callback to url: { redirect_url } " )
249+
250+ cookie_name = ADMIN_SESSION_COOKIE_NAME
251+
252+ next_response = redirect (redirect_url )
253+ next_response .cookies [cookie_name ] = session .session_id
254+ next_response .cookies [cookie_name ]["secure" ] = True
255+ next_response .cookies [cookie_name ]["samesite" ] = "None"
256+ next_response .cookies [cookie_name ]["httponly" ] = True
257+ next_response .cookies [cookie_name ]["expires" ] = session .expires
258+
259+ await SessionStorage .save_session (session )
260+
261+ return next_response
262+ except Exception as e :
263+ logger .exception (e )
264+ return json_response ({"error_message" : str (e )}, 500 )
265+
266+ async def adm_auth_handler (request : Request ):
267+ try :
268+ if not request .conn_info .ctx .fdk_session :
269+ raise FdkSessionNotFoundError ("Can not complete oauth process as session not found" )
270+
271+ if request .conn_info .ctx .fdk_session .state != request .args .get ("state" ):
272+ raise FdkInvalidOAuthError ("Invalid oauth call" )
273+
274+ organization_id = request .conn_info .ctx .fdk_session .organization_id
275+
276+ partner_config = extension .get_partner_config (organization_id )
277+ await partner_config .oauthClient .verifyCallback (request .args )
278+
279+ token : dict = partner_config .oauthClient .raw_token
280+ session_expires = datetime .now () + timedelta (seconds = token ["expires_in" ])
281+
282+ request .conn_info .ctx .fdk_session .expires = session_expires
283+ token ["access_token_validity" ] = int (session_expires .timestamp ()* 1000 )
284+ request .conn_info .ctx .fdk_session .update_token (token )
285+
286+ await SessionStorage .save_session (request .conn_info .ctx .fdk_session )
287+
288+
289+ if not extension .is_online_access_mode ():
290+ session_id = Session .generate_session_id (False , ** {
291+ "cluster" : extension .cluster ,
292+ "id" : organization_id
293+ })
294+ session = await SessionStorage .get_session (session_id )
295+ if not session :
296+ session = Session (session_id = session_id )
297+ elif session .extension_id != extension .api_key :
298+ session = Session (session_id = session_id )
299+
300+ #TODO: Do we need this here again
301+ partner_config = extension .get_partner_config (organization_id )
302+ offline_token_response = await partner_config .oauthClient .getOfflineAccessToken (
303+ extension .scopes , request .args .get ("code" )
304+ )
305+
306+ session .organization_id = organization_id
307+ session .scope = extension .scopes
308+ session .state = request .conn_info .ctx .fdk_session .state
309+ session .extension_id = extension .api_key
310+ offline_token_response ["access_token_validity" ] = partner_config .oauthClient .token_expires_at
311+ offline_token_response ["access_mode" ] = OFFLINE_ACCESS_MODE
312+ session .update_token (offline_token_response )
313+
314+ await SessionStorage .save_session (session = session )
315+
316+
317+ redirect_url = urljoin (extension .base_url , '/admin' )
318+ next_response = redirect (redirect_url )
319+
320+ cookie_name = ADMIN_SESSION_COOKIE_NAME
321+ next_response .cookies [cookie_name ] = request .conn_info .ctx .fdk_session .session_id
322+ next_response .cookies [cookie_name ]["secure" ] = True
323+ next_response .cookies [cookie_name ]["samesite" ] = "None"
324+ next_response .cookies [cookie_name ]["httponly" ] = True
325+ next_response .cookies [cookie_name ]["expires" ] = session_expires
326+
327+ logger .debug (f"Redirecting after auth callback to url: { redirect_url } " )
328+
329+ return next_response
330+ except Exception as e :
331+ logger .exception (e )
332+ return json_response ({"error_message" : str (e )}, 500 )
217333
218334def setup_routes () -> BlueprintGroup :
219335 fdk_routes_bp1 = Blueprint ("fdk_routes_bp1" )
220336 fdk_routes_bp2 = Blueprint ("fdk_routes_bp2" )
337+ fdk_routes_bp3 = Blueprint ("fdk_routes_bp3" )
221338
222339 fdk_routes_bp1 .middleware (session_middleware , "request" )
223340 fdk_routes_bp1 .add_route (auth_handler , "/fp/auth" , methods = ["GET" ])
224341 fdk_routes_bp1 .add_route (auto_install_handler , "/fp/auto_install" , methods = ["POST" ])
225342
226343 fdk_routes_bp2 .add_route (install_handler , "/fp/install" , methods = ["GET" ])
344+ fdk_routes_bp2 .add_route (adm_install_handler , "/adm/install" , methods = ["GET" ])
227345 fdk_routes_bp2 .add_route (uninstall_handler , "/fp/uninstall" , methods = ["POST" ])
228346
229- fdk_route = Blueprint .group (fdk_routes_bp1 , fdk_routes_bp2 )
347+ fdk_routes_bp3 .middleware (partner_session_middleware , "request" )
348+ fdk_routes_bp3 .add_route (adm_auth_handler , "/adm/auth" , methods = ["GET" ])
349+
350+ fdk_route = Blueprint .group (fdk_routes_bp1 , fdk_routes_bp2 , fdk_routes_bp3 )
230351 return fdk_route
0 commit comments