-
Notifications
You must be signed in to change notification settings - Fork 228
Dev/sso login ux #608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Dev/sso login ux #608
Changes from 25 commits
89f3d5b
cdeaf63
dbad147
799e93b
e1737d8
caa7809
71c5eb1
c187ead
412e944
9283e8a
be26dee
5ea4841
8a482b5
ab2794c
5b35284
8355b0f
1a2ab33
a536648
dd29430
36fcfea
4820620
2d6ad0b
05d0dff
fd46826
4816fd6
bff2459
4b0b129
c048ee2
6a46ca2
274126d
6ac7cb6
a5779b4
4df33e2
e3b1e8c
b53051a
5a14983
372b627
baf92c7
2b4f7cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,7 @@ | |
| from . import util | ||
| from . import bolt_util | ||
| from .plotter import Plotter | ||
| from .util import in_databricks, setup_logger, in_ipython, make_iframe | ||
| from .util import in_databricks, setup_logger, in_ipython, make_iframe, display_message_html | ||
| from .exceptions import SsoRetrieveTokenTimeoutException, TokenExpireException | ||
|
|
||
| from .messages import ( | ||
|
|
@@ -135,6 +135,12 @@ def __reset_token_creds_in_memory(): | |
| PyGraphistry._config["api_key"] = None | ||
| PyGraphistry._is_authenticated = False | ||
|
|
||
| @staticmethod | ||
| def __reset_sso_variables_in_memory(): | ||
| """Reset the sso related variable in memory, used when switching hosts, switching register method""" | ||
|
|
||
| PyGraphistry._config["sso_state"] = None | ||
| PyGraphistry._config["sso_opt_into_type"] = None | ||
|
|
||
|
|
||
| @staticmethod | ||
|
|
@@ -271,7 +277,7 @@ def _handle_auth_url(auth_url, sso_timeout, sso_opt_into_type): | |
| if in_ipython() or in_databricks() or sso_opt_into_type == 'display': # If run in notebook, just display the HTML | ||
| # from IPython.core.display import HTML | ||
| from IPython.display import display, HTML | ||
| display(HTML(f'<a href="{auth_url}" target="_blank">Login SSO</a>')) | ||
| display(HTML(f'<a href="{auth_url}" target="_blank">Login SSO</a><br /><span>Please click the above URL to open browser to login</span>')) | ||
| print("Please click the above URL to open browser to login") | ||
| print(f"If you cannot see the URL, please open browser, browse to this URL: {auth_url}") | ||
| print("Please close browser tab after SSO login to back to notebook") | ||
|
|
@@ -406,6 +412,8 @@ def refresh(token=None, fail_silent=False): | |
| logger.debug("2. @PyGraphistry refresh :relogin") | ||
| if isinstance(e, TokenExpireException): | ||
| print("Token is expired, you need to relogin") | ||
| PyGraphistry._config['api_token'] = None | ||
| PyGraphistry._is_authenticated = False | ||
| return PyGraphistry.relogin() | ||
|
|
||
| if not fail_silent: | ||
|
|
@@ -414,7 +422,7 @@ def refresh(token=None, fail_silent=False): | |
|
|
||
| @staticmethod | ||
| def verify_token(token=None, fail_silent=False) -> bool: | ||
| """Return True iff current or provided token is still valid""" | ||
| """Return True if current or provided token is still valid""" | ||
| using_self_token = token is None | ||
| try: | ||
| logger.debug("JWT refresh") | ||
|
|
@@ -570,6 +578,11 @@ def certificate_validation(value=None): | |
| def set_bolt_driver(driver=None): | ||
| PyGraphistry._config["bolt_driver"] = bolt_util.to_bolt_driver(driver) | ||
|
|
||
| @staticmethod | ||
| def set_sso_opt_into_type(value: Optional[str]): | ||
| PyGraphistry._config["sso_opt_into_type"] = value | ||
|
|
||
|
|
||
| @staticmethod | ||
| def register( | ||
| key: Optional[str] = None, | ||
|
|
@@ -707,6 +720,8 @@ def register( | |
| PyGraphistry.set_bolt_driver(bolt) | ||
| # Reset token creds | ||
| PyGraphistry.__reset_token_creds_in_memory() | ||
| # Reset sso related variables in memory | ||
| PyGraphistry.__reset_sso_variables_in_memory() | ||
|
|
||
| if not (username is None) and not (password is None): | ||
| PyGraphistry.login(username, password, org_name) | ||
|
|
@@ -2446,7 +2461,140 @@ def _handle_api_response(response): | |
| logger.error('Error: %s', response, exc_info=True) | ||
| raise Exception("Unknown Error") | ||
|
|
||
| @staticmethod | ||
| def sso_repeat_get_token(repeat: int = 20, wait: int = 5): | ||
| """ Function to repeatly call to obtain the jwt token after sso login | ||
| Function to obtain the JWT token after SSO login | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @sabizmil can you check all public method docstr as these show up in the readthedocs? Spelling, grammar, docstr types, and examples, following format of the rest
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated in the latest commit |
||
| """ | ||
|
|
||
| for _ in range(repeat): | ||
| token = PyGraphistry.sso_get_token() | ||
| if token: | ||
| return token | ||
| time.sleep(wait) | ||
|
|
||
| return | ||
|
|
||
| @staticmethod | ||
| def sso_wait_for_token_display(repeat: int = 20, wait: int = 5, fail_silent: bool = False, display_mode: str = 'text'): | ||
| if display_mode == 'html': | ||
| PyGraphistry.sso_wait_for_token_html_display(repeat, wait, fail_silent) | ||
| else: | ||
| PyGraphistry.sso_wait_for_token_text_display(repeat, wait, fail_silent) | ||
|
|
||
| @staticmethod | ||
| def sso_wait_for_token_text_display(repeat: int = 20, wait: int = 5, fail_silent: bool = False): | ||
| """Get the JWT token for SSO login and display corresponding message in text | ||
| Get the JWT token for SSO login and display corresponding message in text | ||
| """ | ||
| if not PyGraphistry.api_token(): | ||
| msg_text = '....' | ||
| if not PyGraphistry.sso_repeat_get_token(repeat, wait): | ||
| msg_text = f'{msg_text}\nFailed to get token after {repeat*wait} seconds ....' | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
| if not fail_silent: | ||
| msg = f"Failed to get token after {repeat*wait} seconds. Please re-run the login process" | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
| if in_ipython() or in_databricks() or PyGraphistry.set_sso_opt_into_type == "display": | ||
| display_message_html(f"<strong>{msg}</strong>") | ||
| raise Exception(msg) | ||
| else: | ||
| msg_text = f'{msg_text}\nGot token' | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
| print(msg_text) | ||
| return | ||
|
|
||
| msg_text = f'{msg_text}\nGot token' | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
| print(msg_text) | ||
| else: | ||
| print('Token is valid, no waiting required.') | ||
|
|
||
|
|
||
| @staticmethod | ||
| def sso_wait_for_token_html_display(repeat: int = 20, wait: int = 5, fail_silent: bool = False): | ||
| """Get the JWT token for SSO login and display corresponding message in HTML | ||
| Get the JWT token for SSO login and display corresponding message in HTML | ||
| """ | ||
| from IPython.display import display, HTML | ||
| if not PyGraphistry.api_token(): | ||
| msg_html = '<br /><strong> .... </strong>' | ||
| if not PyGraphistry.sso_repeat_get_token(repeat, wait): | ||
| msg_html = f'{msg_html}<br /><strong>Failed to get token after {repeat*wait} seconds .... </strong>' | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if not fail_silent: | ||
| raise Exception(f"Failed to get token after {repeat*wait} seconds. Please re-run the login process") | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
| else: | ||
| msg_html = f'{msg_html}<br /><strong>Got token</strong>' | ||
| display(HTML(msg_html)) | ||
| return | ||
|
|
||
| msg_html = f'{msg_html}<br /><strong>Got token</strong>' | ||
| display(HTML(msg_html)) | ||
| else: | ||
| display(HTML('<br /><strong>Token is valid, no waiting required.</strong>')) | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| @staticmethod | ||
| def sso_verify_token_display( | ||
| repeat: int = 20, | ||
| wait: int = 5, | ||
| display_mode: str = 'text' | ||
| ) -> bool: | ||
| if display_mode == 'html': | ||
| from IPython.display import display, HTML, clear_output | ||
| clear_output() | ||
|
|
||
| required_login = False | ||
| token = PyGraphistry.api_token() | ||
| if token: | ||
| is_valid = PyGraphistry.verify_token() | ||
| print(f"is_valid : {is_valid}") | ||
| if not is_valid: | ||
| print("***********token not valid, refresh token*****************") | ||
| if display_mode == 'html': | ||
| display(HTML('<br /><strong>Refresh token ....</strong>')) | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
| try: | ||
| PyGraphistry.refresh() | ||
| except Exception: | ||
| required_login = True | ||
|
|
||
| else: | ||
| print("Token is still valid") | ||
| if display_mode == 'html': | ||
| display(HTML('<br /><strong>Token is still valid ....</strong>')) | ||
|
vaimdev marked this conversation as resolved.
|
||
|
|
||
| else: | ||
| required_login = True | ||
|
|
||
| if required_login: | ||
| print("***********Prepare to sign in*****************") | ||
| msg_html = f'<br /><strong>Prepare to sign in ....</strong><br><strong>Please Login with the link appear later. Waiting for success login for {repeat*wait} seconds, please login within {wait} seconds....</strong><br /><strong>Please close the browser tab and come back to dashboard....</strong>' | ||
|
vaimdev marked this conversation as resolved.
Outdated
|
||
| display(HTML(msg_html)) | ||
|
|
||
|
|
||
| return not required_login | ||
|
|
||
|
|
||
| # Databricks Dashboard SSO helper functions | ||
| class DatabricksHelper(): | ||
| """Helper class for databricks. | ||
|
|
||
| **Helper class to improve the sso login flow** | ||
|
|
||
| """ | ||
| @staticmethod | ||
| def register_databricks_sso( | ||
| server: Optional[str] = None, | ||
| org_name: Optional[str] = None, | ||
| idp_name: Optional[str] = None, | ||
| **kwargs | ||
| ): | ||
| if not PyGraphistry.api_token(): | ||
| PyGraphistry.register(api=3, protocol="https", server=server, is_sso_login=True, org_name=org_name, idp_name=idp_name, sso_timeout=None, sso_opt_into_type="display") | ||
|
|
||
|
|
||
| # @staticmethod | ||
| # def databricks_sso_login(server="hub.graphistry.com", org_name=None, idp_name=None, retry=5, wait=20): | ||
| # from IPython.display import clear_output | ||
| # clear_output() | ||
| # if not PyGraphistry.api_token(): | ||
| # PyGraphistry.register(api=3, protocol="https", server=server, is_sso_login=True, org_name=org_name, idp_name=idp_name, sso_timeout=None, sso_opt_into_type="display") | ||
|
|
||
|
|
||
| client_protocol_hostname = PyGraphistry.client_protocol_hostname | ||
|
|
@@ -2501,6 +2649,11 @@ def _handle_api_response(response): | |
| personal_key_secret = PyGraphistry.personal_key_secret | ||
| switch_org = PyGraphistry.switch_org | ||
|
|
||
| # databricks dashboard helper functions | ||
| sso_wait_for_token_display = PyGraphistry.sso_wait_for_token_display | ||
| sso_verify_token_display = PyGraphistry.sso_verify_token_display | ||
| sso_repeat_get_token = PyGraphistry.sso_repeat_get_token | ||
| register_databricks_sso = PyGraphistry.DatabricksHelper.register_databricks_sso | ||
|
|
||
|
|
||
| class NumpyJSONEncoder(json.JSONEncoder): | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.