Explorar el Código

Fix pylint and pydocstyle issues

Sean hace 3 años
padre
commit
c12ab0523a
Se han modificado 6 ficheros con 113 adiciones y 20 borrados
  1. 5 5
      .pre-commit-config.yaml
  2. 10 0
      .pylintrc
  3. 1 0
      ocma/__init__.py
  4. 3 0
      ocma/cli.py
  5. 90 14
      ocma/connect.py
  6. 4 1
      tests/sample_test.py

+ 5 - 5
.pre-commit-config.yaml

@@ -1,6 +1,6 @@
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.0.1
+    rev: v4.3.0
     hooks:
       - id: check-yaml
       - id: end-of-file-fixer
@@ -11,17 +11,17 @@ repos:
         args: ["--maxkb=1000"]
 
   - repo: https://github.com/psf/black
-    rev: 21.9b0
+    rev: 22.8.0
     hooks:
       - id: black
 
   - repo: https://github.com/pre-commit/mirrors-prettier
-    rev: v2.3.2
+    rev: v2.7.1
     hooks:
       - id: prettier
 
   - repo: https://github.com/pycqa/isort
-    rev: 5.8.0
+    rev: 5.10.1
     hooks:
       - id: isort
         name: isort (python)
@@ -33,7 +33,7 @@ repos:
         name: pydocstyle
 
   - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v0.920
+    rev: v0.971
     hooks:
       - id: mypy
         name: mypy

+ 10 - 0
.pylintrc

@@ -0,0 +1,10 @@
+[MASTER]
+
+[MESSAGES CONTROL]
+disable=import-error,too-many-arguments
+
+[FORMAT]
+max-line-length=150
+
+[BASIC]
+good-names=w, by, i, e

+ 1 - 0
ocma/__init__.py

@@ -0,0 +1 @@
+"""Openconnect Microsoft login helper."""

+ 3 - 0
ocma/cli.py

@@ -1,3 +1,5 @@
+"""CLI interface."""
+
 import argparse
 from typing import Optional
 
@@ -5,6 +7,7 @@ from ocma import connect
 
 
 def run() -> None:
+    """Run the CLI interface."""
     parser = argparse.ArgumentParser(description="openconnect-microsoft-authenticator")
 
     # add argument

+ 90 - 14
ocma/connect.py

@@ -1,3 +1,5 @@
+"""Openconnect-Microsoft-login connection helpers."""
+
 import logging
 import time
 from dataclasses import dataclass
@@ -34,6 +36,8 @@ LOGGER.setLevel(logging.INFO)
 
 @dataclass
 class VPNCookie:
+    """VPN cookie data container."""
+
     domain: str
     cookie: str
 
@@ -46,6 +50,34 @@ def login(
     headless: bool = True,
     log_messages: bool = False,
 ) -> VPNCookie:
+    """
+    Log in to the vpn.
+
+    Parameters
+    ----------
+    username : str
+        Microsoft account username.
+    password : str
+        Microsoft account password.
+    mfa_secret : Optional[str], optional
+        Multifactor secret, by default None
+    vpn_site : _type_, optional
+        VPN site to log into, by default "https://vpn.fhnw.ch"
+    headless : bool, optional
+        If the browser should be run in headless mode, by default True
+    log_messages : bool, optional
+        If messages should be logged to the console, by default False
+
+    Returns
+    -------
+    VPNCookie
+        Cookie to log into the openconnect VPN.
+
+    Raises
+    ------
+    ValueError
+        If anything went sideways during the login.
+    """
     if log_messages:
         formatter = logging.Formatter(
             "%(asctime)s: %(levelname)s - %(name)s - %(message)s"
@@ -100,16 +132,16 @@ def _fill_login(driver: webdriver.Firefox, username: str, password: str) -> None
     driver.find_element(By.NAME, PASSWORD_INPUT_NAME).send_keys(password)
     click_continue(driver)
 
-    on_login_form = lambda: "saml2" in driver.current_url
-
     retries = MAX_RETRY_DOMAIN_CHECK
-    while on_login_form() and retries > 0:
+    while on_login_form(driver) and retries > 0:
         LOGGER.info(
-            f"Login information may not have yet been confirmed. Checking again (Try {MAX_RETRY_DOMAIN_CHECK - retries + 1} of {MAX_RETRY_DOMAIN_CHECK})"
+            "Login information may not have yet been confirmed. Checking again (Try %s of %s)",
+            MAX_RETRY_DOMAIN_CHECK - retries + 1,
+            MAX_RETRY_DOMAIN_CHECK,
         )
         time.sleep(ELEMENT_CHECK_DELAY)
 
-        if on_login_form():
+        if on_login_form(driver):
             LOGGER.info("Login information has not yet been confirmed. Trying again")
             click_continue(driver)  # Confirm password
         retries -= 1
@@ -120,6 +152,23 @@ def _fill_login(driver: webdriver.Firefox, username: str, password: str) -> None
     LOGGER.info("Login information filled out")
 
 
+def on_login_form(driver: webdriver.Firefox) -> bool:
+    """
+    Check if we are on the login form.
+
+    Parameters
+    ----------
+    driver : webdriver.Firefox
+        The web driver to check on.
+
+    Returns
+    -------
+    bool
+        True if we are on the login form, else false.
+    """
+    return "saml2" in driver.current_url
+
+
 def _fill_mfa(driver: webdriver.Firefox, mfa_secret: Optional[str]) -> None:
     LOGGER.info("Checking if we can fill in MFA information")
 
@@ -136,7 +185,7 @@ def _fill_mfa(driver: webdriver.Firefox, mfa_secret: Optional[str]) -> None:
 
     for i in range(MFA_MAX_RETRY_COUNT):
         LOGGER.info(
-            f"Filling in MFA information (Try {i + 1} of {MFA_MAX_RETRY_COUNT})"
+            "Filling in MFA information (Try %s of %s)", i + 1, MFA_MAX_RETRY_COUNT
         )
         if not _find_element(driver, By.NAME, MFA_INPUT_NAME):
             time.sleep(ELEMENT_CHECK_DELAY)
@@ -146,35 +195,35 @@ def _fill_mfa(driver: webdriver.Firefox, mfa_secret: Optional[str]) -> None:
         driver.find_element(By.NAME, MFA_INPUT_NAME).send_keys(mfa_code)
         click_continue(driver, MFA_CONTINUE_BUTTON_ID)  # Confirm otp
 
-        LOGGER.info(f"Confirmed MFA code")
+        LOGGER.info("Confirmed MFA code")
 
         if not driver.current_url.endswith("/login"):
             # We have moved on
-            LOGGER.info(f"We have moved away from the MFA page")
+            LOGGER.info("We have moved away from the MFA page")
             break
 
         # Check for any errors
         if not _find_element(driver, By.ID, MFA_ERROR_TEXT_ID, 2):
             # Did not find an error
-            LOGGER.info(f"MFA seems to have been accepted, no errors")
+            LOGGER.info("MFA seems to have been accepted, no errors")
             break
 
 
 def _confirm_stay_signed_in(driver: webdriver.Firefox) -> bool:
-    LOGGER.info(f"Cheking if we should confirm if we should stay signed in")
+    LOGGER.info("Cheking if we should confirm if we should stay signed in")
 
     if not _is_on_ms_login_page(driver):
-        LOGGER.info(f"Already logged in, can't confirm 'stay signed in'")
+        LOGGER.info("Already logged in, can't confirm 'stay signed in'")
         return False
 
     if not driver.current_url.endswith("/common/SAS/ProcessAuth"):
         LOGGER.info(
-            f"We have reached a dead end. We have completed the login, but not on the 'stay signed in' page"
+            "We have reached a dead end. We have completed the login, but not on the 'stay signed in' page"
         )
         return False
 
     click_continue(driver)  # Confirm stay signed in
-    LOGGER.info(f"Confirmed to 'stay signed in'")
+    LOGGER.info("Confirmed to 'stay signed in'")
     return True
 
 
@@ -229,7 +278,21 @@ def _is_on_ms_login_page(driver: webdriver.Firefox) -> bool:
 
 
 def click_continue(driver: webdriver.Firefox, btn_id: str = CONTINUE_BUTTON_ID) -> bool:
-    """Returns true if still on login page, false if not"""
+    """
+    Click the continue button.
+
+    Parameters
+    ----------
+    driver : webdriver.Firefox
+        The driver for which to click the continue button.
+    btn_id : str, optional
+        The buttons ID to be clicked, by default CONTINUE_BUTTON_ID
+
+    Returns
+    -------
+    bool
+        True if still on login page, false if not.
+    """
     for _ in range(16):
         try:
             driver.find_element(By.ID, btn_id).click()
@@ -245,6 +308,19 @@ def click_continue(driver: webdriver.Firefox, btn_id: str = CONTINUE_BUTTON_ID)
 
 
 def get_mfa_code(secret: str) -> str:
+    """
+    Get the multifactor authentication code for the given secret.
+
+    Parameters
+    ----------
+    secret : str
+        MFA secret
+
+    Returns
+    -------
+    str
+        MFA code
+    """
     otp = OTP.fromb32(secret)
     code: str = otp.TOTP()[0]
     return code

+ 4 - 1
tests/sample_test.py

@@ -1,2 +1,5 @@
+"""Openconnect MS auth tests."""
+
+
 def test_sample() -> None:
-    pass
+    """Just a sample test."""