Bug fix for Revoke OTP resolved, no longer crashes when select all is chosen when there are no active sessions, Swapped Revoke OTP and Quiet Hosts locations on menus
This commit is contained in:
@@ -58,9 +58,14 @@ class OTPRevokeWidget(Static):
|
|||||||
}
|
}
|
||||||
#button_container {
|
#button_container {
|
||||||
height: auto;
|
height: auto;
|
||||||
|
width: 100%;
|
||||||
padding: 1;
|
padding: 1;
|
||||||
align: center middle;
|
align: center middle;
|
||||||
}
|
}
|
||||||
|
#button_container Button {
|
||||||
|
min-width: 16;
|
||||||
|
margin: 0 1;
|
||||||
|
}
|
||||||
#result_container {
|
#result_container {
|
||||||
height: auto;
|
height: auto;
|
||||||
max-height: 10;
|
max-height: 10;
|
||||||
@@ -87,29 +92,10 @@ class OTPRevokeWidget(Static):
|
|||||||
|
|
||||||
# Action buttons
|
# Action buttons
|
||||||
with Horizontal(id="button_container"):
|
with Horizontal(id="button_container"):
|
||||||
self.refresh_button = Button("🔄 Refresh", id="refresh_btn")
|
yield Button("Refresh", id="refresh_btn")
|
||||||
self.refresh_button.styles.width = "15%"
|
yield Button("Select All", id="select_all_btn")
|
||||||
self.refresh_button.styles.margin = (1, 1, 1, 1)
|
yield Button("Clear Selection", id="select_none_btn")
|
||||||
yield self.refresh_button
|
yield Button("Revoke Selected", id="revoke_btn", variant="error")
|
||||||
|
|
||||||
self.select_all_button = Button("☑️ Select All", id="select_all_btn")
|
|
||||||
self.select_all_button.styles.width = "15%"
|
|
||||||
self.select_all_button.styles.margin = (1, 1, 1, 1)
|
|
||||||
yield self.select_all_button
|
|
||||||
|
|
||||||
self.select_none_button = Button(
|
|
||||||
"❌ Clear Selection", id="select_none_btn"
|
|
||||||
)
|
|
||||||
self.select_none_button.styles.width = "20%"
|
|
||||||
self.select_none_button.styles.margin = (1, 1, 1, 1)
|
|
||||||
yield self.select_none_button
|
|
||||||
|
|
||||||
self.revoke_button = Button(
|
|
||||||
"🛑 Revoke Selected", id="revoke_btn", variant="error"
|
|
||||||
)
|
|
||||||
self.revoke_button.styles.width = "20%"
|
|
||||||
self.revoke_button.styles.margin = (1, 1, 1, 1)
|
|
||||||
yield self.revoke_button
|
|
||||||
|
|
||||||
# Results display
|
# Results display
|
||||||
with Vertical(id="result_container"):
|
with Vertical(id="result_container"):
|
||||||
@@ -122,7 +108,7 @@ class OTPRevokeWidget(Static):
|
|||||||
# Configure sessions table
|
# Configure sessions table
|
||||||
self.sessions_table.clear()
|
self.sessions_table.clear()
|
||||||
self.sessions_table.add_columns(
|
self.sessions_table.add_columns(
|
||||||
"☐", "OTP ID", "Hostname", "Status", "Purpose", "Granted"
|
"", "OTP ID", "Hostname", "Status", "Purpose", "Granted"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable row selection with checkbox column
|
# Enable row selection with checkbox column
|
||||||
@@ -213,7 +199,11 @@ class OTPRevokeWidget(Static):
|
|||||||
|
|
||||||
elif btn.id == "select_all_btn":
|
elif btn.id == "select_all_btn":
|
||||||
# Select all visible rows
|
# Select all visible rows
|
||||||
if self._filtered_df is not None:
|
if (
|
||||||
|
self._filtered_df is not None
|
||||||
|
and not self._filtered_df.empty
|
||||||
|
and "otpid" in self._filtered_df.columns
|
||||||
|
):
|
||||||
self._selected_otpids = set(str(x) for x in self._filtered_df["otpid"])
|
self._selected_otpids = set(str(x) for x in self._filtered_df["otpid"])
|
||||||
await self._refresh_table()
|
await self._refresh_table()
|
||||||
|
|
||||||
@@ -235,7 +225,12 @@ class OTPRevokeWidget(Static):
|
|||||||
# Get the row index from the cursor row
|
# Get the row index from the cursor row
|
||||||
row_index = self.sessions_table.cursor_row
|
row_index = self.sessions_table.cursor_row
|
||||||
|
|
||||||
if self._filtered_df is not None and row_index < len(self._filtered_df):
|
if (
|
||||||
|
self._filtered_df is not None
|
||||||
|
and not self._filtered_df.empty
|
||||||
|
and "otpid" in self._filtered_df.columns
|
||||||
|
and row_index < len(self._filtered_df)
|
||||||
|
):
|
||||||
# Get the OTP ID for this row
|
# Get the OTP ID for this row
|
||||||
otpid = str(self._filtered_df.iloc[row_index]["otpid"])
|
otpid = str(self._filtered_df.iloc[row_index]["otpid"])
|
||||||
|
|
||||||
@@ -257,12 +252,12 @@ class OTPRevokeWidget(Static):
|
|||||||
async def _revoke_selected(self) -> None:
|
async def _revoke_selected(self) -> None:
|
||||||
"""Revoke the selected OTP sessions."""
|
"""Revoke the selected OTP sessions."""
|
||||||
if not self._selected_otpids:
|
if not self._selected_otpids:
|
||||||
self.results_display.update("❌ No sessions selected for revocation")
|
self.results_display.update("No sessions selected for revocation")
|
||||||
return
|
return
|
||||||
|
|
||||||
api = getattr(self.app, "api", None)
|
api = getattr(self.app, "api", None)
|
||||||
if not api:
|
if not api:
|
||||||
self.results_display.update("❌ API not available")
|
self.results_display.update("API not available")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Collect results
|
# Collect results
|
||||||
@@ -303,13 +298,13 @@ class OTPRevokeWidget(Static):
|
|||||||
else "No response"
|
else "No response"
|
||||||
)
|
)
|
||||||
results.append(
|
results.append(
|
||||||
f"❌ Failed to revoke OTP {otpid} for {hostname}: {error_msg}"
|
f"Failed to revoke OTP {otpid} for {hostname}: {error_msg}"
|
||||||
)
|
)
|
||||||
logger.error(f"Failed to revoke OTP {otpid}: {error_msg}")
|
logger.error(f"Failed to revoke OTP {otpid}: {error_msg}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
failure_count += 1
|
failure_count += 1
|
||||||
results.append(f"❌ Error revoking OTP {otpid}: {str(e)}")
|
results.append(f"Error revoking OTP {otpid}: {str(e)}")
|
||||||
logger.exception(f"Exception revoking OTP {otpid}: {e}")
|
logger.exception(f"Exception revoking OTP {otpid}: {e}")
|
||||||
|
|
||||||
# Update results display
|
# Update results display
|
||||||
@@ -368,7 +363,11 @@ class OTPRevokeScreen(Screen):
|
|||||||
|
|
||||||
async def action_select_all(self) -> None:
|
async def action_select_all(self) -> None:
|
||||||
"""Select all visible sessions."""
|
"""Select all visible sessions."""
|
||||||
if self.widget._filtered_df is not None:
|
if (
|
||||||
|
self.widget._filtered_df is not None
|
||||||
|
and not self.widget._filtered_df.empty
|
||||||
|
and "otpid" in self.widget._filtered_df.columns
|
||||||
|
):
|
||||||
self.widget._selected_otpids = set(
|
self.widget._selected_otpids = set(
|
||||||
str(x) for x in self.widget._filtered_df["otpid"]
|
str(x) for x in self.widget._filtered_df["otpid"]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ class QuietAgentWorkflowScreen(Screen):
|
|||||||
|
|
||||||
# Delay the analysis start to ensure UI refresh completes first
|
# Delay the analysis start to ensure UI refresh completes first
|
||||||
# This prevents Rust output from starting before the screen is cleared
|
# This prevents Rust output from starting before the screen is cleared
|
||||||
self.set_timer(0.2, self._perform_analysis_worker)
|
self.set_timer(0.5, self._perform_analysis_worker)
|
||||||
|
|
||||||
def _perform_analysis_worker(self) -> None:
|
def _perform_analysis_worker(self) -> None:
|
||||||
"""Perform the actual agent activity analysis."""
|
"""Perform the actual agent activity analysis."""
|
||||||
|
|||||||
+4
-4
@@ -92,15 +92,15 @@ class MainMenuScreen(Screen):
|
|||||||
BUTTON_DEFS = {
|
BUTTON_DEFS = {
|
||||||
"agent_actions": [
|
"agent_actions": [
|
||||||
(
|
(
|
||||||
"🖥️ - Find, Move, or Generate OTP for Agents",
|
"🖥️ - Find agent, Move agent, or Generate One Time Pass",
|
||||||
"move_agent_workflow_button",
|
"move_agent_workflow_button",
|
||||||
),
|
),
|
||||||
("🎫 - Review and appove OTP Activities", "otp_activities_button"),
|
("🎫 - Review and approve OTP Activities", "otp_activities_button"),
|
||||||
("🔕 - Find and Move Quiet Hosts to Enforcement", "find_quiet_button"),
|
("🛑 - Revoke Active OTP Session", "otp_revoke_button"),
|
||||||
],
|
],
|
||||||
"policy": [
|
"policy": [
|
||||||
("⚖️ - Prepare Policy For Enforcement", "policy_prep_button"),
|
("⚖️ - Prepare Policy For Enforcement", "policy_prep_button"),
|
||||||
("🛑 - Revoke OTPs", "otp_revoke_button"),
|
("🔕 - Find and Move Quiet Hosts to Enforcement", "find_quiet_button"),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user