91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
import os
|
|
from dotenv import load_dotenv
|
|
|
|
class ConfigManager:
|
|
"""Safely manages multi-line .env files without corrupting other content."""
|
|
|
|
@staticmethod
|
|
def get_root_env_path():
|
|
# backend/config_manager.py -> backend/ -> /
|
|
base_dir = os.path.dirname(os.path.abspath(__file__))
|
|
project_root = os.path.dirname(base_dir)
|
|
return os.path.join(project_root, "inventory.env")
|
|
|
|
@staticmethod
|
|
def update_keys(updates: dict):
|
|
"""
|
|
Updates specific keys in inventory.env.
|
|
Preserves comments and order where possible.
|
|
Appends new keys at the end if not found.
|
|
"""
|
|
env_path = ConfigManager.get_root_env_path()
|
|
|
|
if not os.path.exists(env_path):
|
|
# Create a basic file if it doesn't exist (unlikely in this project)
|
|
with open(env_path, 'w', encoding='utf-8') as f:
|
|
f.write("# TFM aInventory — Generated Configuration\n")
|
|
|
|
with open(env_path, 'r', encoding='utf-8') as f:
|
|
lines = f.readlines()
|
|
|
|
new_lines = []
|
|
keys_to_process = set(updates.keys())
|
|
processed_keys = set()
|
|
|
|
for line in lines:
|
|
trimmed = line.strip()
|
|
# Skip empty lines or comments when matching
|
|
if not trimmed or trimmed.startswith('#'):
|
|
new_lines.append(line)
|
|
continue
|
|
|
|
# Check if this line is a key assignment we want to update
|
|
found_match = False
|
|
for key in keys_to_process:
|
|
if trimmed.startswith(f"{key}="):
|
|
new_lines.append(f"{key}={updates[key]}\n")
|
|
processed_keys.add(key)
|
|
found_match = True
|
|
break
|
|
|
|
if not found_match:
|
|
new_lines.append(line)
|
|
|
|
# Append keys that weren't found in the file
|
|
missing_keys = keys_to_process - processed_keys
|
|
if missing_keys:
|
|
if new_lines and not new_lines[-1].endswith('\n'):
|
|
new_lines.append('\n')
|
|
if new_lines and not new_lines[-1].strip() == '':
|
|
new_lines.append('\n')
|
|
|
|
new_lines.append("# --- Automatically Added Keys ---\n")
|
|
for key in missing_keys:
|
|
new_lines.append(f"{key}={updates[key]}\n")
|
|
|
|
with open(env_path, 'w', encoding='utf-8') as f:
|
|
f.writelines(new_lines)
|
|
|
|
# Force reload environment variables for the current process
|
|
load_dotenv(env_path, override=True)
|
|
return True
|
|
|
|
@staticmethod
|
|
def get_masked_key(key_name: str):
|
|
"""Returns a masked version of the environment variable."""
|
|
val = os.environ.get(key_name)
|
|
if not val:
|
|
return None
|
|
|
|
# Determine prefix based on key type
|
|
prefix = ""
|
|
if key_name == "GEMINI_API_KEY":
|
|
prefix = "G-"
|
|
elif key_name == "CLAUDE_API_KEY":
|
|
prefix = "sk-"
|
|
|
|
if len(val) <= 8:
|
|
return f"{prefix}****"
|
|
|
|
return f"{prefix}****{val[-4:]}"
|