4646logger = logging .getLogger (__name__ )
4747
4848
49+ def _normalize_navigation_target (candidate : str | None ) -> str | None :
50+ if candidate is None :
51+ return None
52+ value = str (candidate ).strip ()
53+ if not value :
54+ return None
55+ parsed = urllib .parse .urlparse (value )
56+ if parsed .scheme or parsed .netloc :
57+ return None
58+ if not value .startswith ("/" ) or value .startswith ("//" ):
59+ return None
60+ return value
61+
62+
4963class LoginRequestHandler (SimpleHTTPRequestHandler ):
5064 """
5165 Handle HTTP requests for authentication flow.
@@ -83,22 +97,46 @@ def _save_token(self, query: str) -> None:
8397
8498 user_raw = arguments .get ("user" , ["" ])[0 ]
8599 token = arguments .get ("token" , ["" ])[0 ]
100+ navigation_candidate = (
101+ arguments .get ("navigate_to" , ["" ])[0 ]
102+ or arguments .get ("navigation" , ["" ])[0 ]
103+ or arguments .get ("post_auth_redirect" , ["" ])[0 ]
104+ or arguments .get ("redirect_url" , ["" ])[0 ]
105+ )
106+ navigation_target = _normalize_navigation_target (navigation_candidate )
86107
87108 if not user_raw or not token :
88109 self .send_error (HTTPStatus .BAD_REQUEST , "User and token must be provided." )
89110
90111 user = json .loads (urllib .parse .unquote (user_raw ))
91- content = AUTH_SUCCESS_PAGE .format (
92- user_key = DATALAYER_IAM_USER_KEY ,
93- uid = user .get ("uid" ),
94- handle = user ["handle_s" ],
95- first_name = user ["first_name_t" ],
96- last_name = user ["last_name_t" ],
97- email = user ["email_s" ],
98- display_name = " " .join ((user ["first_name_t" ], user ["last_name_t" ])).strip (),
99- token_key = DATALAYER_IAM_TOKEN_KEY ,
100- token = token ,
101- base_url = "/" ,
112+ content = (
113+ AUTH_SUCCESS_PAGE
114+ .replace ("__USER_KEY__" , DATALAYER_IAM_USER_KEY )
115+ .replace ("__TOKEN_KEY__" , DATALAYER_IAM_TOKEN_KEY )
116+ .replace ("__UID_JSON__" , json .dumps (user .get ("uid" , "" )))
117+ .replace ("__HANDLE_JSON__" , json .dumps (user .get ("handle_s" , "" )))
118+ .replace (
119+ "__FIRST_NAME_JSON__" , json .dumps (user .get ("first_name_t" , "" ))
120+ )
121+ .replace (
122+ "__LAST_NAME_JSON__" , json .dumps (user .get ("last_name_t" , "" ))
123+ )
124+ .replace ("__EMAIL_JSON__" , json .dumps (user .get ("email_s" , "" )))
125+ .replace (
126+ "__DISPLAY_NAME_JSON__" ,
127+ json .dumps (
128+ " " .join (
129+ (
130+ user .get ("first_name_t" , "" ),
131+ user .get ("last_name_t" , "" ),
132+ )
133+ ).strip ()
134+ ),
135+ )
136+ .replace ("__TOKEN_JSON__" , json .dumps (token ))
137+ .replace (
138+ "__NAVIGATION_TARGET_JSON__" , json .dumps (navigation_target or "" )
139+ )
102140 ).encode ("UTF-8" , "replace" )
103141 self .send_response (HTTPStatus .OK )
104142 self .send_header ("Content-type" , "text/html" )
@@ -112,14 +150,15 @@ def do_GET(self) -> None:
112150 if path .strip ("/" ).endswith ("callback" ):
113151 self ._save_token (query )
114152 elif path in {"/" , "/datalayer/login/cli" }:
115- content = LANDING_PAGE .format (
116- config = json .dumps (
117- {
118- "runUrl" : self .server .run_url , # type: ignore
119- "iamRunUrl" : self .server .iam_url , # type: ignore
120- "whiteLabel" : False ,
121- }
122- )
153+ config_json = json .dumps (
154+ {
155+ "runUrl" : self .server .run_url , # type: ignore
156+ "iamRunUrl" : self .server .iam_url , # type: ignore
157+ "whiteLabel" : False ,
158+ }
159+ )
160+ content = LANDING_PAGE .replace (
161+ "__DATALAYER_CONFIG_JSON__" , config_json
123162 ).encode ("UTF-8" , "replace" )
124163 self .send_response (HTTPStatus .OK )
125164 self .send_header ("Content-type" , "text/html" )
@@ -203,16 +242,6 @@ def __init__(
203242 bind_and_activate : bool, default True
204243 Whether to bind and activate the server.
205244 """
206- try :
207- import datalayer_ui # noqa: F401
208- except Exception :
209- print ("Sorry, I can not show the login page..." )
210- print (
211- "Check the datalayer_ui python package is available in your environment"
212- )
213- import sys
214-
215- sys .exit (- 1 )
216245 # Use DatalayerURLs for proper URL configuration
217246 self ._urls = DatalayerURLs .from_environment (run_url = run_url )
218247 self .run_url = self ._urls .run_url
@@ -246,14 +275,12 @@ def finish_request(self, request: t.Any, client_address: str) -> None:
246275 client_address : str
247276 The client address.
248277 """
249- import datalayer_ui
250-
251- DATALAYER_UI_PATH = Path (datalayer_ui .__file__ ).parent
278+ datalayer_core_static_path = HERE .parent .parent / "static"
252279 self .RequestHandlerClass (
253280 request ,
254281 client_address ,
255282 self , # type: ignore[arg-type]
256- directory = str (DATALAYER_UI_PATH / "static" ), # type: ignore[call-arg]
283+ directory = str (datalayer_core_static_path ), # type: ignore[call-arg]
257284 )
258285
259286
0 commit comments