From c24719be11e60de68a8c14e44546e2943ed2c3c7 Mon Sep 17 00:00:00 2001 From: adeshmukh-ks Date: Fri, 27 Feb 2026 22:24:19 +0530 Subject: [PATCH] Added persistent flow to example --- examples/sdk_examples/auth/login.py | 32 +++++++++++++++++-- examples/sdk_examples/records/list_records.py | 19 ++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/examples/sdk_examples/auth/login.py b/examples/sdk_examples/auth/login.py index 35ad11c..f20e893 100644 --- a/examples/sdk_examples/auth/login.py +++ b/examples/sdk_examples/auth/login.py @@ -290,6 +290,8 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: ] if pyperclip: menu.append(("c", "Copy SSO Login URL to clipboard.")) + else: + menu.append(("u", "Show SSO Login URL.")) try: wb = webbrowser.get() menu.append(("o", "Navigate to SSO Login URL with the default web browser.")) @@ -297,6 +299,7 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: wb = None if pyperclip: menu.append(("p", "Paste SSO Token from clipboard.")) + menu.append(("t", "Enter SSO Token manually.")) menu.append(("q", "Quit SSO authentication attempt and return to Commander prompt.")) lines = [ @@ -305,7 +308,7 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: step.sso_login_url, "Navigate to SSO Login URL with your browser and complete authentication.", "Copy a returned SSO Token into clipboard." - + (" Paste that token into Commander." if pyperclip else " Then paste the token below (or install pyperclip for clipboard support)."), + + (" Paste that token into Commander." if pyperclip else " Then use option 't' to enter the token manually."), 'NOTE: To copy SSO Token please click "Copy authentication token" ' 'button on "SSO Connect" page.', "", @@ -330,6 +333,12 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: print("Failed to copy SSO Login URL to clipboard.") else: print("Clipboard not available (install pyperclip).") + elif token == "u": + token = None + if not pyperclip: + print("\nSSO Login URL:", step.sso_login_url, "\n") + else: + print("Unsupported menu option (use 'c' to copy URL).") elif token == "o": token = None if wb: @@ -345,8 +354,10 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: token = "" print("Failed to paste from clipboard") else: - token = "" - print("Clipboard not available (install pyperclip).") + token = None + print("Clipboard not available (use 't' to enter token manually).") + elif token == "t": + token = getpass.getpass("Enter SSO Token: ").strip() else: if len(token) < 10: print(f"Unsupported menu option: {token}") @@ -395,6 +406,19 @@ def _two_factor_code_to_duration( return login_auth.TwoFactorDuration.EveryLogin +def enable_persistent_login(keeper_auth_context: keeper_auth.KeeperAuth) -> None: + """ + Enable persistent login and register data key for device. + Sets persistent_login to on and logout_timer to 30 days. + """ + keeper_auth.set_user_setting(keeper_auth_context, 'persistent_login', '1') + keeper_auth.register_data_key_for_device(keeper_auth_context) + mins_per_day = 60 * 24 + timeout_in_minutes = mins_per_day * 30 # 30 days + keeper_auth.set_user_setting(keeper_auth_context, 'logout_timer', str(timeout_in_minutes)) + print("Persistent login turned on successfully and device registered") + + def login(): """ Handle the login process including server selection, authentication, @@ -406,6 +430,8 @@ def login(): """ flow = LoginFlow() keeper_auth_context = flow.run() + if keeper_auth_context: + enable_persistent_login(keeper_auth_context) keeper_endpoint = flow.endpoint if keeper_auth_context else None return keeper_auth_context, keeper_endpoint diff --git a/examples/sdk_examples/records/list_records.py b/examples/sdk_examples/records/list_records.py index 28842b8..9e3ccad 100644 --- a/examples/sdk_examples/records/list_records.py +++ b/examples/sdk_examples/records/list_records.py @@ -287,6 +287,8 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: ] if pyperclip: menu.append(("c", "Copy SSO Login URL to clipboard.")) + else: + menu.append(("u", "Show SSO Login URL.")) try: wb = webbrowser.get() menu.append(("o", "Navigate to SSO Login URL with the default web browser.")) @@ -294,6 +296,7 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: wb = None if pyperclip: menu.append(("p", "Paste SSO Token from clipboard.")) + menu.append(("t", "Enter SSO Token manually.")) menu.append(("q", "Quit SSO authentication attempt and return to Commander prompt.")) lines = [ @@ -301,8 +304,8 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: "SSO Login URL:", step.sso_login_url, "Navigate to SSO Login URL with your browser and complete authentication.", - "Copy a returned SSO Token into clipboard.", - "Paste that token into Commander", + "Copy a returned SSO Token into clipboard." + + (" Paste that token into Commander." if pyperclip else " Then use option 't' to enter the token manually."), 'NOTE: To copy SSO Token please click "Copy authentication token" ' 'button on "SSO Connect" page.', "", @@ -327,6 +330,12 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: print("Failed to copy SSO Login URL to clipboard.") else: print("Clipboard not available (install pyperclip).") + elif token == "u": + token = None + if not pyperclip: + print("\nSSO Login URL:", step.sso_login_url, "\n") + else: + print("Unsupported menu option (use 'c' to copy URL).") elif token == "o": token = None if wb: @@ -342,8 +351,10 @@ def _handle_sso_token(self, step: login_auth.LoginStepSsoToken) -> None: token = "" print("Failed to paste from clipboard") else: - token = "" - print("Clipboard not available (install pyperclip).") + token = None + print("Clipboard not available (use 't' to enter token manually).") + elif token == "t": + token = getpass.getpass("Enter SSO Token: ").strip() else: if len(token) < 10: print(f"Unsupported menu option: {token}")