feat: RDP flap auto-disconnect and hide break button after reconnect (0.4.10)
Add optional auto logoff of stuck sessions on RDG flap and direct RDP failure. Hide the RDS break button on old flap 302 when the user later reconnects or the workstation session is closed. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -210,6 +210,57 @@ def find_normal_rdg_end_after_success(db: Session, success_event: Event) -> Even
|
||||
return None
|
||||
|
||||
|
||||
def _users_and_ip_match(left: Event, right: Event) -> bool:
|
||||
return _users_match(left, right) and _internal_ips_match_strict(left, right)
|
||||
|
||||
|
||||
def find_later_rdg_success_after(
|
||||
db: Session,
|
||||
*,
|
||||
anchor: Event,
|
||||
after: datetime,
|
||||
) -> Event | None:
|
||||
"""Поздний 302 на том же шлюзе, user и client PC — пользователь снова зашёл через RDG."""
|
||||
if anchor.type != RDG_SUCCESS_TYPE:
|
||||
return None
|
||||
after_at = _as_utc(after)
|
||||
|
||||
candidates = db.scalars(
|
||||
select(Event)
|
||||
.where(
|
||||
Event.host_id == anchor.host_id,
|
||||
Event.type == RDG_SUCCESS_TYPE,
|
||||
Event.occurred_at > after_at,
|
||||
Event.id != anchor.id,
|
||||
)
|
||||
.order_by(Event.occurred_at.asc())
|
||||
).all()
|
||||
|
||||
for later in candidates:
|
||||
if not _users_and_ip_match(later, anchor):
|
||||
continue
|
||||
return later
|
||||
return None
|
||||
|
||||
|
||||
def _flap_auto_disconnect_succeeded(flap_end: Event) -> bool:
|
||||
details = flap_end.details if isinstance(flap_end.details, dict) else {}
|
||||
block = details.get("rdp_flap_auto_disconnect")
|
||||
if not isinstance(block, dict):
|
||||
return False
|
||||
return block.get("ok") is True
|
||||
|
||||
|
||||
def _flap_workstation_session_closed(db: Session, flap_end: Event) -> bool:
|
||||
from app.services.host_sessions import event_session_terminated
|
||||
from app.services.rdg_workstation_session import find_workstation_login_for_rdg_end
|
||||
|
||||
login = find_workstation_login_for_rdg_end(db, flap_end)
|
||||
if login is None:
|
||||
return False
|
||||
return event_session_terminated(login, db=db)
|
||||
|
||||
|
||||
def resolve_rdg_qwinsta_enabled(db: Session | None, event: Event) -> bool:
|
||||
"""Кнопка qwinsta/logoff только на 302, пока сессия может быть активна (или RDG flap)."""
|
||||
if event.type in RDG_END_TYPES:
|
||||
@@ -220,7 +271,14 @@ def resolve_rdg_qwinsta_enabled(db: Session | None, event: Event) -> bool:
|
||||
return False
|
||||
if db is None:
|
||||
return True
|
||||
if find_rdg_end_after_success(db, event) is not None:
|
||||
flap_end = find_rdg_end_after_success(db, event)
|
||||
if flap_end is not None:
|
||||
if _flap_auto_disconnect_succeeded(flap_end):
|
||||
return False
|
||||
if _flap_workstation_session_closed(db, flap_end):
|
||||
return False
|
||||
if find_later_rdg_success_after(db, anchor=event, after=flap_end.occurred_at) is not None:
|
||||
return False
|
||||
return True
|
||||
if find_normal_rdg_end_after_success(db, event) is not None:
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user