Fixed Breaking Legacy change

This commit is contained in:
2025-11-10 17:21:18 -05:00
parent 3c2e825210
commit 5cb079dad7
3 changed files with 36 additions and 45 deletions
+26 -39
View File
@@ -20,6 +20,7 @@ from textual.widgets import (
from flows.otp import otp_activities_by_agent, otp_revoke from flows.otp import otp_activities_by_agent, otp_revoke
from flows.prepPolicy import menu_policy_enforce from flows.prepPolicy import menu_policy_enforce
from flows.quietAgent import findQuietAgents
from models.agent import Agent from models.agent import Agent
from models.policy import Policy from models.policy import Policy
from screens.moveagentworkflowscreen import MoveAgentWorkflowScreen from screens.moveagentworkflowscreen import MoveAgentWorkflowScreen
@@ -325,6 +326,8 @@ class MainMenuScreen(Screen):
self.app.push_screen(OTPWorkflowScreen(self.app.devices)) self.app.push_screen(OTPWorkflowScreen(self.app.devices))
event.stop() event.stop()
return # Don't exit the app return # Don't exit the app
case "find_quiet_button":
_PENDING_JOB = ("legacy", findQuietAgents, (self.app.api,), {})
case "otp_activities_button": case "otp_activities_button":
_PENDING_JOB = ("legacy", otp_activities_by_agent, (self.app.api,), {}) _PENDING_JOB = ("legacy", otp_activities_by_agent, (self.app.api,), {})
case "otp_revoke_button": case "otp_revoke_button":
@@ -353,7 +356,6 @@ class Loxide(App):
text-align: center; text-align: center;
} }
""" """
BINDINGS = [ BINDINGS = [
("q", "quit", "Quit"), ("q", "quit", "Quit"),
("d", "open_dir", "Open Directory"), ("d", "open_dir", "Open Directory"),
@@ -367,17 +369,20 @@ class Loxide(App):
if not os.path.isdir(wd): if not os.path.isdir(wd):
wd = os.getcwd() wd = os.getcwd()
self.working_dir = wd self.working_dir = wd
# Initial data load
self.refresh_data()
# Add error handling for API calls def refresh_data(self) -> None:
"""Public method to refresh policies and devices from the API."""
try: try:
self.policies = [ self.policies = [
Policy(**row.to_dict()) for _, row in api.policy_find_all().iterrows() Policy(**row.to_dict())
for _, row in self.api.policy_find_all().iterrows()
] ]
self.devices = [ self.devices = [
Agent(**row.to_dict()) for _, row in api.agent_find_all().iterrows() Agent(**row.to_dict())
for _, row in self.api.agent_find_all().iterrows()
] ]
# Enrich agents with policy information
if self.policies and self.devices: if self.policies and self.devices:
for agent in self.devices: for agent in self.devices:
agent.enrich_with_policies(self.policies) agent.enrich_with_policies(self.policies)
@@ -401,6 +406,8 @@ class Loxide(App):
self.exit() self.exit()
def action_open_dir(self) -> None: def action_open_dir(self) -> None:
# Refresh data before proceeding
self.refresh_data()
screen = self.screen_stack[-1] screen = self.screen_stack[-1]
if isinstance(screen, MainMenuScreen): if isinstance(screen, MainMenuScreen):
if screen.current_tab != "dir": if screen.current_tab != "dir":
@@ -417,7 +424,6 @@ def _restore_terminal_for_legacy() -> None:
sys.stdout.write("\033[?1000l\033[?1002l\033[?1003l\033[?1006l") sys.stdout.write("\033[?1000l\033[?1002l\033[?1003l\033[?1006l")
sys.stdout.write("\033[2J\033[H") sys.stdout.write("\033[2J\033[H")
sys.stdout.flush() sys.stdout.flush()
if os.name == "nt": if os.name == "nt":
try: try:
import ctypes import ctypes
@@ -434,7 +440,6 @@ def _restore_terminal_for_legacy() -> None:
def _run_legacy_job(func, args, kwargs) -> None: def _run_legacy_job(func, args, kwargs) -> None:
logger.debug("Running legacy job: %s", getattr(func, "__name__", func)) logger.debug("Running legacy job: %s", getattr(func, "__name__", func))
_restore_terminal_for_legacy() _restore_terminal_for_legacy()
try: try:
func(*args, **kwargs) func(*args, **kwargs)
finally: finally:
@@ -449,24 +454,31 @@ def _run_legacy_job(func, args, kwargs) -> None:
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def run_Loxide(api: AirlockAPIWrapper) -> None: def run_Loxide(api: AirlockAPIWrapper) -> None:
global _PENDING_JOB global _PENDING_JOB
while True:
base_dir = get_base_directory() base_dir = get_base_directory()
env_path = base_dir / ".env" env_path = base_dir / ".env"
dotenv.load_dotenv(dotenv_path=env_path, override=True) dotenv.load_dotenv(dotenv_path=env_path, override=True)
max_attempts = 5
attempts = 0
while attempts < max_attempts:
attempts += 1
logger.debug("Starting job loop iteration (attempt %d)", attempts)
_PENDING_JOB = None _PENDING_JOB = None
app = Loxide(api) app = Loxide(api)
try: try:
app.run() app.run()
except SystemExit as exc: except SystemExit as exc:
if exc.code != 0:
logger.debug("Caught SystemExit from Textual: %s", exc) logger.debug("Caught SystemExit from Textual: %s", exc)
raise
job = _PENDING_JOB job = _PENDING_JOB
logger.debug("After app.run(), _PENDING_JOB = %r", job) logger.debug("After app.run(), _PENDING_JOB = %r", job)
if not job: if not job:
logger.debug("No job pending, exiting loop")
break break
if job[0] == "legacy": if job[0] == "legacy":
@@ -475,49 +487,24 @@ def run_Loxide(api: AirlockAPIWrapper) -> None:
continue continue
if job[0] == "restart": if job[0] == "restart":
# just loop again; fresh .env was already loaded at the top logger.debug("Restarting job loop")
continue continue
if job[0] == "multi_agent_action": if job[0] == "multi_agent_action":
# Handle multi-agent selection
logger.info("Multi-agent action with selected agents: %s", job[1]) logger.info("Multi-agent action with selected agents: %s", job[1])
continue continue
# NEW: Handle OTP workflow
if job[0] == "otp_workflow": if job[0] == "otp_workflow":
_, devices, requestor, reasoning, duration = job _, devices, requestor, reasoning, duration = job
# Call your OTP generation with the parameters
def otp_generate_with_params(): def otp_generate_with_params():
# Your OTP logic here
print(f"\n{'='*60}") pass
print("OTP GENERATION")
print(f"{'='*60}")
print(f"Requestor: {requestor}")
print(f"Reasoning: {reasoning}")
print(f"Duration: {duration} minutes")
print(f"\nGenerating OTPs for {len(devices)} devices:")
print(f"{'='*60}\n")
# Call your actual OTP generation function
# You'll need to adapt otp_generate to accept these parameters
# For now, this is a placeholder showing the structure
for device in devices:
print(f"Device: {device}")
print(f" Requestor: {requestor}")
print(f" Reason: {reasoning}")
print(f" Duration: {duration} minutes")
# TODO: Actually call your API to generate OTP
# result = api.generate_otp(device, requestor, reasoning, duration)
print()
print(f"{'='*60}")
print("OTP Generation Complete!")
print(f"{'='*60}")
_run_legacy_job(otp_generate_with_params, (), {}) _run_legacy_job(otp_generate_with_params, (), {})
continue continue
logger.error("Unknown job type: %r", job)
break break
+4 -1
View File
@@ -506,6 +506,7 @@ class AgentMoveOperations(Widget):
unsuccessful = [] unsuccessful = []
status_label = self.query_one("#status_label", Static) status_label = self.query_one("#status_label", Static)
status_label.update("Exporting CSV...") status_label.update("Exporting CSV...")
self.app.refresh_data()
agents = self.agents agents = self.agents
policies = self.app.policies policies = self.app.policies
path = self.app.working_dir path = self.app.working_dir
@@ -604,6 +605,8 @@ class AgentMoveOperations(Widget):
successful.append((agent, f"Moved to {mode}: {result}")) successful.append((agent, f"Moved to {mode}: {result}"))
logger.info(f"Successfully toggled {agent.hostname} to {mode}") logger.info(f"Successfully toggled {agent.hostname} to {mode}")
self.app.refresh_data()
except Exception as e: except Exception as e:
unsuccessful.append((agent, str(e))) unsuccessful.append((agent, str(e)))
logger.error(f"Failed to toggle {agent.hostname}: {e}") logger.error(f"Failed to toggle {agent.hostname}: {e}")
@@ -728,7 +731,7 @@ class AgentMoveOperations(Widget):
status_label.update(f"Error: {str(e)}") status_label.update(f"Error: {str(e)}")
self.operation_in_progress = False self.operation_in_progress = False
return return
self.app.refresh_data()
self.operation_in_progress = False self.operation_in_progress = False
status_label.update("Operation complete!") status_label.update("Operation complete!")
+3 -2
View File
@@ -80,11 +80,11 @@ class MultiAgentSelector(Widget):
select_buttons.styles.margin = (0, 0, 0, 0) select_buttons.styles.margin = (0, 0, 0, 0)
select_none_button = Button("🚫 Select None", id="select_none") select_none_button = Button("🚫 Select None", id="select_none")
select_none_button.styles.margin = (1, 0, 0, 1) select_none_button.styles.margin = (1, 1, 0, 1)
yield select_none_button yield select_none_button
select_all_button = Button("✅ Select All", id="select_all") select_all_button = Button("✅ Select All", id="select_all")
select_all_button.styles.margin = (1, 1, 0, 1) select_all_button.styles.margin = (1, 0, 0, 1)
yield select_all_button yield select_all_button
with Horizontal() as button_row: with Horizontal() as button_row:
@@ -93,6 +93,7 @@ class MultiAgentSelector(Widget):
back_button = Button("← Back", id="back_button") back_button = Button("← Back", id="back_button")
back_button.styles.width = "1fr" back_button.styles.width = "1fr"
back_button.styles.margin = (0, 0, 0, 1)
yield back_button yield back_button
submit_button = Button( submit_button = Button(