diff --git a/frontend/templates/setup.html b/frontend/templates/setup.html
index 3e740564..c091f8d0 100644
--- a/frontend/templates/setup.html
+++ b/frontend/templates/setup.html
@@ -304,20 +304,10 @@
// Password validation function
function validatePassword(password) {
- // At least 10 characters, 1 number, 1 uppercase letter, 1 non-alphanumeric character
+ // Only check for minimum length of 10 characters
if (password.length < 10) {
return 'Password must be at least 10 characters long.';
}
- if (!/\d/.test(password)) {
- return 'Password must include at least one number.';
- }
- if (!/[A-Z]/.test(password)) {
- return 'Password must include at least one uppercase letter.';
- }
- // Check for any character that is NOT a letter or digit
- if (!/[^A-Za-z0-9]/.test(password)) {
- return 'Password must include at least one special character (any non-letter, non-digit).';
- }
return null; // Password is valid
}
diff --git a/frontend/templates/user.html b/frontend/templates/user.html
index 1f56bfdb..e3030e40 100644
--- a/frontend/templates/user.html
+++ b/frontend/templates/user.html
@@ -339,22 +339,12 @@
});
}
- // Password validation function (same as in setup.html)
+ // Password validation function
function validatePassword(password) {
- // At least 10 characters, 1 number, 1 uppercase letter, 1 non-alphanumeric character
+ // Only check for minimum length of 10 characters
if (password.length < 10) {
return 'Password must be at least 10 characters long.';
}
- if (!/\d/.test(password)) {
- return 'Password must include at least one number.';
- }
- if (!/[A-Z]/.test(password)) {
- return 'Password must include at least one uppercase letter.';
- }
- // Check for any character that is NOT a letter or digit
- if (!/[^A-Za-z0-9]/.test(password)) {
- return 'Password must include at least one special character (any non-letter, non-digit).';
- }
return null; // Password is valid
}
diff --git a/src/primary/apps/readarr/api.py b/src/primary/apps/readarr/api.py
index 9e4ed11d..7aff29a0 100644
--- a/src/primary/apps/readarr/api.py
+++ b/src/primary/apps/readarr/api.py
@@ -18,7 +18,7 @@ logger = get_logger("readarr")
# Use a session for better performance
session = requests.Session()
-# Default API timeout in seconds
+# Default API timeout in seconds - used as fallback only
API_TIMEOUT = 30
def check_connection(api_url: str, api_key: str, timeout: int = 30) -> bool:
@@ -130,6 +130,8 @@ def arr_request(endpoint: str, method: str = "GET", data: Dict = None, app_type:
# api_url, api_key = keys_manager.get_api_keys(app_type) # Old way
api_url = settings_manager.get_setting(app_type, "api_url")
api_key = settings_manager.get_setting(app_type, "api_key")
+ # Get user-configured timeout, fall back to default if not set
+ api_timeout = settings_manager.get_setting(app_type, "api_timeout", API_TIMEOUT)
if not api_url or not api_key:
logger.error("API URL or API key is missing. Check your settings.")
@@ -149,13 +151,13 @@ def arr_request(endpoint: str, method: str = "GET", data: Dict = None, app_type:
try:
if method == "GET":
- response = session.get(url, headers=headers, timeout=API_TIMEOUT)
+ response = session.get(url, headers=headers, timeout=api_timeout)
elif method == "POST":
- response = session.post(url, headers=headers, json=data, timeout=API_TIMEOUT)
+ response = session.post(url, headers=headers, json=data, timeout=api_timeout)
elif method == "PUT":
- response = session.put(url, headers=headers, json=data, timeout=API_TIMEOUT)
+ response = session.put(url, headers=headers, json=data, timeout=api_timeout)
elif method == "DELETE":
- response = session.delete(url, headers=headers, timeout=API_TIMEOUT)
+ response = session.delete(url, headers=headers, timeout=api_timeout)
else:
logger.error(f"Unsupported HTTP method: {method}")
return None
diff --git a/src/primary/apps/readarr_routes.py b/src/primary/apps/readarr_routes.py
index 7f796615..f151ef76 100644
--- a/src/primary/apps/readarr_routes.py
+++ b/src/primary/apps/readarr_routes.py
@@ -19,6 +19,7 @@ def test_connection():
data = request.json
api_url = data.get('api_url')
api_key = data.get('api_key')
+ api_timeout = data.get('api_timeout', 60) # Get timeout from request or use default of 60
if not api_url or not api_key:
return jsonify({"success": False, "message": "API URL and API Key are required"}), 400
@@ -28,8 +29,8 @@ def test_connection():
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
try:
- # This is similar to: curl -H "X-Api-Key: api-key" http://ip-address/api/v1/system/status
- response = requests.get(test_url, headers=headers, timeout=10)
+ # Use the specified timeout value
+ response = requests.get(test_url, headers=headers, timeout=api_timeout)
# Check status code explicitly
if response.status_code == 401:
@@ -46,6 +47,9 @@ def test_connection():
# Save the API keys only if connection test is successful
settings_manager.save_setting("readarr", "api_url", api_url)
settings_manager.save_setting("readarr", "api_key", api_key)
+ # Also save the timeout if provided
+ if 'api_timeout' in data:
+ settings_manager.save_setting("readarr", "api_timeout", api_timeout)
with open(LOG_FILE, 'a') as f:
f.write(f"{timestamp} - readarr - INFO - Connection test successful: {api_url}\n")
diff --git a/src/primary/auth.py b/src/primary/auth.py
index 04ff5225..c6efbd47 100644
--- a/src/primary/auth.py
+++ b/src/primary/auth.py
@@ -105,15 +105,8 @@ def validate_password_strength(password: str) -> Optional[str]:
"""
if len(password) < 10:
return "Password must be at least 10 characters long."
- if not re.search(r"\d", password):
- return "Password must include at least one number."
- if not re.search(r"[A-Z]", password):
- return "Password must include at least one uppercase letter."
- # Check for any non-alphanumeric character (including space)
- if not re.search(r"[^A-Za-z0-9]", password):
- return "Password must include at least one special character (any non-letter, non-digit)."
- # If all checks pass
+ # If check passes
return None
def user_exists() -> bool: