Spaces:
Running
Running
File size: 7,477 Bytes
4d1849f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# FILE: modules/user_auth.py
import json
import os
import sys
import logging
logger = logging.getLogger("ZOTHEOS_UserAuth")
if not logger.handlers:
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - [%(funcName)s] - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
USERS_FILE_PATH = "stripe_users.json" # Default name, path will be determined below
try:
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
# Running in a PyInstaller bundle
# _MEIPASS is the path to the temporary directory where PyInstaller unpacks files
application_path = sys._MEIPASS
logger.debug(f"UserAuth running in PyInstaller bundle. MEIPASS: {application_path}")
# stripe_users.json should be in the root of _MEIPASS, alongside the .exe's main script
candidate_path = os.path.join(application_path, "stripe_users.json")
# Check if it exists there directly
if os.path.exists(candidate_path):
USERS_FILE_PATH = candidate_path
else:
# Fallback: if user_auth.py is in a 'modules' subdir within _MEIPASS, try one level up for stripe_users.json
# This handles if --add-data "modules;modules" was used and user_auth.py is at _MEIPASS/modules/user_auth.py
# and stripe_users.json was added to _MEIPASS/.
# This might happen if the main script is also at the root of _MEIPASS.
current_module_dir = os.path.dirname(os.path.abspath(__file__)) # This would be _MEIPASS/modules
project_root_guess = os.path.dirname(current_module_dir) # This would be _MEIPASS
alt_candidate_path = os.path.join(project_root_guess, "stripe_users.json")
if os.path.exists(alt_candidate_path):
USERS_FILE_PATH = alt_candidate_path
else:
# If still not found, log a warning. The get_user_tier will handle the FileNotFoundError.
logger.warning(f"stripe_users.json not found at primary bundle path '{candidate_path}' or alternate '{alt_candidate_path}'. It must be bundled at the root relative to the main script.")
# Keep USERS_FILE_PATH as "stripe_users.json" to allow relative loading if script is at root of _MEIPASS
# This will likely fail if not at root, and get_user_tier will default to 'free'
else:
# Running as a normal script (user_auth.py is in modules folder)
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir)
USERS_FILE_PATH = os.path.join(project_root, "stripe_users.json")
logger.info(f"User authentication file path dynamically set to: {os.path.abspath(USERS_FILE_PATH) if os.path.isabs(USERS_FILE_PATH) else USERS_FILE_PATH}")
except Exception as e_path:
logger.error(f"Critical error setting USERS_FILE_PATH in user_auth.py: {e_path}. Using default 'stripe_users.json'.")
USERS_FILE_PATH = "stripe_users.json"
def get_user_tier(user_token: str) -> str:
"""
Retrieves the user's tier based on their token from stripe_users.json.
Defaults to 'free' if token not found or an error occurs.
"""
default_tier = "free"
if not user_token or not isinstance(user_token, str) or not user_token.strip():
# This log is fine, but can be noisy if called frequently with no token (e.g. UI init)
# logger.debug("No user token provided or invalid token, defaulting to 'free' tier.")
return default_tier
try:
# Log the path being attempted for diagnosis
logger.debug(f"Attempting to load users file from: {os.path.abspath(USERS_FILE_PATH)}")
if not os.path.exists(USERS_FILE_PATH):
logger.warning(f"Users file '{USERS_FILE_PATH}' not found. Defaulting all users to '{default_tier}' tier. Please ensure this file is correctly bundled at the application root.")
return default_tier
with open(USERS_FILE_PATH, "r", encoding="utf-8") as f:
users = json.load(f)
tier = users.get(user_token, default_tier)
log_token_display = user_token[:3] + "***" if len(user_token) > 3 else user_token
logger.info(f"Token '{log_token_display}' resolved to tier: '{tier}'.")
return tier
except json.JSONDecodeError:
logger.error(f"Error decoding JSON from {USERS_FILE_PATH}. Defaulting to '{default_tier}' tier.", exc_info=True)
return default_tier
except Exception as e:
logger.error(f"An unexpected error occurred in get_user_tier: {e}. Defaulting to '{default_tier}' tier.", exc_info=True)
return default_tier
if __name__ == '__main__':
logger.setLevel(logging.DEBUG)
print(f"--- Testing user_auth.py ---")
print(f"USERS_FILE_PATH is configured as: {os.path.abspath(USERS_FILE_PATH)}")
# Create a dummy stripe_users.json in the expected location for testing if it doesn't exist
# For standalone testing, this means it looks for it relative to where this script would be if it were project root.
# If this script is in 'modules', project_root is one level up.
# Determine the correct test path based on whether script is run directly or from project root
if os.path.basename(os.getcwd()) == "modules": # If CWD is modules folder
test_stripe_users_path = "../stripe_users.json"
else: # If CWD is project root (where zotheos_interface_public.py is)
test_stripe_users_path = "stripe_users.json"
if not os.path.exists(test_stripe_users_path):
print(f"'{test_stripe_users_path}' not found relative to CWD ({os.getcwd()}). Creating a dummy file for testing purposes at this location.")
dummy_users_for_test = {
"TOKEN_FREE_USER": "free",
"TOKEN_STARTER_USER": "starter",
"TOKEN_PRO_USER": "pro"
}
try:
with open(test_stripe_users_path, "w") as f:
json.dump(dummy_users_for_test, f, indent=2)
print(f"Dummy '{test_stripe_users_path}' created successfully with test tokens.")
# Update USERS_FILE_PATH for this test run if it was different
USERS_FILE_PATH = test_stripe_users_path
print(f"For this test run, USERS_FILE_PATH is now: {os.path.abspath(USERS_FILE_PATH)}")
except Exception as e_create:
print(f"Could not create dummy users file at {test_stripe_users_path}: {e_create}")
print("Please ensure stripe_users.json exists in the project root for user_auth.py to function correctly.")
print("\nTest Results:")
test_tokens = {
"Pro User Token": "TOKEN_PRO_USER",
"Starter User Token": "TOKEN_STARTER_USER",
"Free User Token": "TOKEN_FREE_USER",
"Non-existent Token": "invalid_dummy_token_123",
"Empty String Token": "",
}
for description, token_to_test in test_tokens.items():
actual_tier = get_user_tier(token_to_test)
print(f"- Test '{description}' (Input: '{token_to_test}'): Tier = '{actual_tier}'")
print(f"\n--- End of user_auth.py test ---") |