diff options
| -rw-r--r-- | docs/src/api/python/example.md | 2 | ||||
| -rw-r--r-- | wrappers/python/example/main.py | 138 | ||||
| -rw-r--r-- | wrappers/python/main.py | 102 |
3 files changed, 139 insertions, 103 deletions
diff --git a/docs/src/api/python/example.md b/docs/src/api/python/example.md index 906a3ca..d4f6c08 100644 --- a/docs/src/api/python/example.md +++ b/docs/src/api/python/example.md @@ -3,5 +3,5 @@ This is an example that can also be found [in the repository](https://github.com/eduvpn/eduvpn-common/blob/main/wrappers/python/main.py). It gets a config from an Institute Access server with support for multiple profiles. ```python -{{#include ../../../../wrappers/python/main.py}} +{{#include ../../../../wrappers/python/example/main.py}} ``` diff --git a/wrappers/python/example/main.py b/wrappers/python/example/main.py new file mode 100644 index 0000000..068bc20 --- /dev/null +++ b/wrappers/python/example/main.py @@ -0,0 +1,138 @@ +import eduvpn_common.main as eduvpn +from eduvpn_common.state import State, StateType +from eduvpn_common.server import Config, Profiles +from typing import Optional, List, Tuple +import webbrowser +import sys + + +# Asks the user for a profile index +# It loops up until a valid input is given +def ask_ranged_input(total: int, label: str) -> int: + range_index = None + + while range_index is None: + try: + range_index = int( + input(f"Please select a {label} by inputting a number (e.g. 1): ") + ) + if (range_index > total) or (range_index < 1): + print(f"Invalid input, input must be between 1 and {total} (inclusive)") + range_index = None + except ValueError: + print("Please enter a valid input") + + # The profile is one based, move to zero based input + return range_index - 1 + + +def setup_callbacks(edu: eduvpn.EduVPN): + @edu.event.on(State.OAUTH_STARTED, StateType.ENTER) + def enter_oauth(old_state: State, url: str): + print("OAuth started", url) + webbrowser.open(url) + + @edu.event.on(State.ASK_PROFILE, StateType.ENTER) + def enter_ask_profile(old_state: State, profiles: Profiles): + print("This server has multiple available profiles") + for index, profile in enumerate(profiles.profiles): + print(f"[{index+1}]: {profile}") + index = ask_ranged_input(len(profiles.profiles), "profile") + _eduvpn.set_profile(profiles.profiles[index].identifier) + + @edu.event.on(State.ASK_LOCATION, StateType.ENTER) + def enter_ask_location(old_state: State, locations: List[str]): + print("This server has multiple available locations") + for index, location in enumerate(locations): + print(f"[{index+1}]: {location}") + index = ask_ranged_input(len(locations), "location") + _eduvpn.set_secure_location(locations[index]) + + +def do_custom_server(edu: eduvpn.EduVPN) -> Optional[Config]: + server_url = input( + "Enter a server URL to get a configuration for (e.g. vpn.example.com): " + ) + edu.add_custom_server(server_url) + return edu.get_config_custom_server(server_url) + + +def do_institute_access(edu: eduvpn.EduVPN) -> Optional[Config]: + print("Please choose an institute access server:") + disco_servers = edu.get_disco_servers() + if not disco_servers: + raise Exception("No discovery servers found") + index = 0 + institute_servers = [] + for disco_server in sorted(disco_servers.servers, key=lambda x: str(x)): + if disco_server.server_type == "institute_access": + print(f"[{index+1}]: {disco_server}") + institute_servers.append(disco_server) + index += 1 + + ranged_index = ask_ranged_input(len(institute_servers), "institute access server") + base_url = institute_servers[ranged_index].base_url + edu.add_institute_access(base_url) + return edu.get_config_institute_access(base_url) + + +def do_secure_internet(edu: eduvpn.EduVPN) -> Optional[Config]: + print("Please choose a secure internet server:") + disco_orgs = edu.get_disco_organizations() + if not disco_orgs: + raise Exception("No discovery organizations found") + index = 0 + secure_internet_servers = [] + for disco_org in sorted(disco_orgs.organizations, key=lambda x: str(x)): + print(f"[{index+1}]: {disco_org}") + secure_internet_servers.append(disco_org) + index += 1 + + ranged_index = ask_ranged_input( + len(secure_internet_servers), "secure internet server" + ) + org_id = secure_internet_servers[ranged_index].org_id + edu.add_secure_internet_home(org_id) + return edu.get_config_secure_internet(org_id) + + +# The main entry point +if __name__ == "__main__": + _eduvpn = eduvpn.EduVPN("org.eduvpn.app.linux", "configs", "en") + setup_callbacks(_eduvpn) + + # Register with the eduVPN-common library + try: + _eduvpn.register() + except Exception as e: + print("Failed registering:", e, file=sys.stderr) + sys.exit(1) + + input_dict = { + "c": do_custom_server, + "i": do_institute_access, + "s": do_secure_internet, + } + + type_input = input( + "Which type of server do you want to connect to, choose one of (c)ustom/(i)nstitute access/(s)ecure internet): " + ) + to_call = input_dict.get(type_input) + if to_call is None: + print("Invalid type chosen", file=sys.stderr) + sys.exit(1) + + try: + config = to_call(_eduvpn) + except Exception as e: + print("Failed getting a config:", e, file=sys.stderr) + sys.exit(1) + + if config is None: + print("Failed getting a config: no configuration returned") + sys.exit(1) + print("Got a config:\n", config.config) + print("The config is of type:", config.config_type) + + # Save and exit + _eduvpn.deregister() diff --git a/wrappers/python/main.py b/wrappers/python/main.py deleted file mode 100644 index 4881828..0000000 --- a/wrappers/python/main.py +++ /dev/null @@ -1,102 +0,0 @@ -import eduvpn_common.main as eduvpn -from eduvpn_common.state import State, StateType -import webbrowser -import sys -from typing import List - -# Asks the user for a profile index -# It loops up until a valid input is given -def ask_profile_input(total: int) -> int: - profile_index = None - - while profile_index is None: - try: - profile_index = int( - input("Please select a profile by inputting a number (e.g. 1): ") - ) - if (profile_index > total) or (profile_index < 1): - print("Invalid profile range") - profile_index = None - except ValueError: - print("Please enter a valid input") - - # The profile is one based, move to zero based input - return profile_index - 1 - - -# Sets up the callbacks using the provided class -def setup_callbacks(_eduvpn: eduvpn.EduVPN) -> None: - # The callback that starst OAuth - @_eduvpn.event.on(State.NO_SERVER, StateType.ENTER) - def no_server(old_state: str, servers) -> None: - for server in servers: - print(type(server)) - print(server) - # It needs to open the URL in the web browser - @_eduvpn.event.on(State.OAUTH_STARTED, StateType.ENTER) - def oauth_initialized(old_state: str, url: str) -> None: - print(f"Got OAuth URL {url}, old state: {old_state}") - webbrowser.open(url) - - @_eduvpn.event.on(State.ASK_LOCATION, StateType.ENTER) - def ask_location(old_state: str, locations: List[str]): - _eduvpn.set_secure_location(locations[1]) - - ## The callback which asks the user for a profile - #@_eduvpn.event.on(State.ASK_PROFILE, StateType.ENTER) - #def ask_profile(old_state: str, profiles: str): - # print("Multiple profiles found, you need to select a profile:") - - # # Parse the profiles as JSON - # data = json.loads(profiles) - - # # Get a lits of profiles - # profile_strings = [x["profile_id"] for x in data["info"]["profile_list"]] - # total_profiles = len(profile_strings) - - # # Create a list of the strings to standard output - # for idx, profile in enumerate(profile_strings): - # print(f"{idx+1}. {profile}") - - # # Get the profile index from the user - # profile_index = ask_profile_input(total_profiles) - - # # Set the profile with the index - # _eduvpn.set_profile(profile_strings[profile_index]) - - -# The main entry point -if __name__ == "__main__": - _eduvpn = eduvpn.EduVPN("org.eduvpn.app.linux", "configs", "en") - setup_callbacks(_eduvpn) - - # Register with the eduVPN-common library - try: - _eduvpn.register(debug=True) - except Exception as e: - print("Failed registering:", e) - - server = input( - "Which server (Custom/Institute Access) do you want to connect to? (e.g. https://eduvpn.example.com): " - ) - - # Get a Wireguard/OpenVPN config - try: - _eduvpn.add_secure_internet("https://idp.geant.org") - config, config_type = _eduvpn.get_config_secure_internet("https://idp.geant.org") - print(f"Got a config with type: {config_type} and contents:\n{config}") - except Exception as e: - print("Failed to connect:", e) - # Save and exit - _eduvpn.deregister() - sys.exit(1) - - # Set the internal FSM state to connected - try: - _eduvpn.set_connecting() - _eduvpn.set_connected() - except Exception as e: - print("Failed to set connected:", e) - - # Save and exit - _eduvpn.deregister() |
