Files
termscp/src/ui/activities/auth/view/visible.rs
T
Christian Visintin 751f68f6d4
Deploy docs to GitHub Pages / deploy (push) Has been cancelled
Install.sh / build (ubuntu-latest) (push) Has been cancelled
CI / toolchain (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / install-scripts (push) Has been cancelled
Install.sh / build (macos-latest) (push) Has been cancelled
Site / build-site (push) Has been cancelled
CI / crates-macos-latest (push) Has been cancelled
CI / crates-ubuntu-latest (push) Has been cancelled
CI / crates-windows-latest (push) Has been cancelled
CI / doc (push) Has been cancelled
CI / deny (push) Has been cancelled
feat(smb): add SMB dialect selection and persistence (#445)
Support Auto, SMB1, SMB2, and SMB3 selection on Unix, bound negotiation to the selected dialect family, preserve legacy bookmarks as Auto, and document the new option. Windows keeps operating-system-managed negotiation.

Closes #439
2026-09-02 14:14:23 +02:00

559 lines
23 KiB
Rust

use tuirealm::subscription::{EventClause, Sub, SubClause};
use super::*;
impl AuthActivity {
pub(in crate::ui::activities::auth) fn get_host_bridge_generic_params_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::HostBridge(AuthFormId::RemoteDirectory)) => [
Id::HostBridge(AuthFormId::Port),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::RemoteDirectory),
],
Some(&Id::HostBridge(AuthFormId::LocalDirectory)) => [
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::RemoteDirectory),
Id::HostBridge(AuthFormId::LocalDirectory),
],
_ => [
Id::HostBridge(AuthFormId::Address),
Id::HostBridge(AuthFormId::Port),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
],
}
}
pub(in crate::ui::activities::auth) fn get_remote_generic_params_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::Remote(AuthFormId::RemoteDirectory)) => [
Id::Remote(AuthFormId::Port),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::RemoteDirectory),
],
Some(&Id::Remote(AuthFormId::LocalDirectory)) => [
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::RemoteDirectory),
Id::Remote(AuthFormId::LocalDirectory),
],
_ => [
Id::Remote(AuthFormId::Address),
Id::Remote(AuthFormId::Port),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
],
}
}
pub(in crate::ui::activities::auth) fn get_host_bridge_localhost_view(&self) -> [Id; 1] {
[Id::HostBridge(AuthFormId::LocalDirectory)]
}
pub(in crate::ui::activities::auth) fn get_host_bridge_s3_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::HostBridge(AuthFormId::S3AccessKey)) => [
Id::HostBridge(AuthFormId::S3Region),
Id::HostBridge(AuthFormId::S3Endpoint),
Id::HostBridge(AuthFormId::S3Profile),
Id::HostBridge(AuthFormId::S3AccessKey),
],
Some(&Id::HostBridge(AuthFormId::S3SecretAccessKey)) => [
Id::HostBridge(AuthFormId::S3Endpoint),
Id::HostBridge(AuthFormId::S3Profile),
Id::HostBridge(AuthFormId::S3AccessKey),
Id::HostBridge(AuthFormId::S3SecretAccessKey),
],
Some(&Id::HostBridge(AuthFormId::S3SecurityToken)) => [
Id::HostBridge(AuthFormId::S3Profile),
Id::HostBridge(AuthFormId::S3AccessKey),
Id::HostBridge(AuthFormId::S3SecretAccessKey),
Id::HostBridge(AuthFormId::S3SecurityToken),
],
Some(&Id::HostBridge(AuthFormId::S3SessionToken)) => [
Id::HostBridge(AuthFormId::S3AccessKey),
Id::HostBridge(AuthFormId::S3SecretAccessKey),
Id::HostBridge(AuthFormId::S3SecurityToken),
Id::HostBridge(AuthFormId::S3SessionToken),
],
Some(&Id::HostBridge(AuthFormId::S3NewPathStyle)) => [
Id::HostBridge(AuthFormId::S3SecretAccessKey),
Id::HostBridge(AuthFormId::S3SecurityToken),
Id::HostBridge(AuthFormId::S3SessionToken),
Id::HostBridge(AuthFormId::S3NewPathStyle),
],
Some(&Id::HostBridge(AuthFormId::RemoteDirectory)) => [
Id::HostBridge(AuthFormId::S3SecurityToken),
Id::HostBridge(AuthFormId::S3SessionToken),
Id::HostBridge(AuthFormId::S3NewPathStyle),
Id::HostBridge(AuthFormId::RemoteDirectory),
],
Some(&Id::HostBridge(AuthFormId::LocalDirectory)) => [
Id::HostBridge(AuthFormId::S3SessionToken),
Id::HostBridge(AuthFormId::S3NewPathStyle),
Id::HostBridge(AuthFormId::RemoteDirectory),
Id::HostBridge(AuthFormId::LocalDirectory),
],
_ => [
Id::HostBridge(AuthFormId::S3Bucket),
Id::HostBridge(AuthFormId::S3Region),
Id::HostBridge(AuthFormId::S3Endpoint),
Id::HostBridge(AuthFormId::S3Profile),
],
}
}
pub(in crate::ui::activities::auth) fn get_remote_s3_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::Remote(AuthFormId::S3AccessKey)) => [
Id::Remote(AuthFormId::S3Region),
Id::Remote(AuthFormId::S3Endpoint),
Id::Remote(AuthFormId::S3Profile),
Id::Remote(AuthFormId::S3AccessKey),
],
Some(&Id::Remote(AuthFormId::S3SecretAccessKey)) => [
Id::Remote(AuthFormId::S3Endpoint),
Id::Remote(AuthFormId::S3Profile),
Id::Remote(AuthFormId::S3AccessKey),
Id::Remote(AuthFormId::S3SecretAccessKey),
],
Some(&Id::Remote(AuthFormId::S3SecurityToken)) => [
Id::Remote(AuthFormId::S3Profile),
Id::Remote(AuthFormId::S3AccessKey),
Id::Remote(AuthFormId::S3SecretAccessKey),
Id::Remote(AuthFormId::S3SecurityToken),
],
Some(&Id::Remote(AuthFormId::S3SessionToken)) => [
Id::Remote(AuthFormId::S3AccessKey),
Id::Remote(AuthFormId::S3SecretAccessKey),
Id::Remote(AuthFormId::S3SecurityToken),
Id::Remote(AuthFormId::S3SessionToken),
],
Some(&Id::Remote(AuthFormId::S3NewPathStyle)) => [
Id::Remote(AuthFormId::S3SecretAccessKey),
Id::Remote(AuthFormId::S3SecurityToken),
Id::Remote(AuthFormId::S3SessionToken),
Id::Remote(AuthFormId::S3NewPathStyle),
],
Some(&Id::Remote(AuthFormId::RemoteDirectory)) => [
Id::Remote(AuthFormId::S3SecurityToken),
Id::Remote(AuthFormId::S3SessionToken),
Id::Remote(AuthFormId::S3NewPathStyle),
Id::Remote(AuthFormId::RemoteDirectory),
],
Some(&Id::Remote(AuthFormId::LocalDirectory)) => [
Id::Remote(AuthFormId::S3SessionToken),
Id::Remote(AuthFormId::S3NewPathStyle),
Id::Remote(AuthFormId::RemoteDirectory),
Id::Remote(AuthFormId::LocalDirectory),
],
_ => [
Id::Remote(AuthFormId::S3Bucket),
Id::Remote(AuthFormId::S3Region),
Id::Remote(AuthFormId::S3Endpoint),
Id::Remote(AuthFormId::S3Profile),
],
}
}
pub(in crate::ui::activities::auth) fn get_host_bridge_gcs_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::HostBridge(AuthFormId::LocalDirectory)) => [
Id::HostBridge(AuthFormId::GcsEndpoint),
Id::HostBridge(AuthFormId::GcsServiceAccountKey),
Id::HostBridge(AuthFormId::RemoteDirectory),
Id::HostBridge(AuthFormId::LocalDirectory),
],
_ => [
Id::HostBridge(AuthFormId::GcsBucket),
Id::HostBridge(AuthFormId::GcsEndpoint),
Id::HostBridge(AuthFormId::GcsServiceAccountKey),
Id::HostBridge(AuthFormId::RemoteDirectory),
],
}
}
pub(in crate::ui::activities::auth) fn get_remote_gcs_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::Remote(AuthFormId::LocalDirectory)) => [
Id::Remote(AuthFormId::GcsEndpoint),
Id::Remote(AuthFormId::GcsServiceAccountKey),
Id::Remote(AuthFormId::RemoteDirectory),
Id::Remote(AuthFormId::LocalDirectory),
],
_ => [
Id::Remote(AuthFormId::GcsBucket),
Id::Remote(AuthFormId::GcsEndpoint),
Id::Remote(AuthFormId::GcsServiceAccountKey),
Id::Remote(AuthFormId::RemoteDirectory),
],
}
}
pub(in crate::ui::activities::auth) fn get_host_bridge_kube_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::HostBridge(AuthFormId::KubeClientCert)) => [
Id::HostBridge(AuthFormId::KubeNamespace),
Id::HostBridge(AuthFormId::KubeClusterUrl),
Id::HostBridge(AuthFormId::KubeUsername),
Id::HostBridge(AuthFormId::KubeClientCert),
],
Some(&Id::HostBridge(AuthFormId::KubeClientKey)) => [
Id::HostBridge(AuthFormId::KubeClusterUrl),
Id::HostBridge(AuthFormId::KubeUsername),
Id::HostBridge(AuthFormId::KubeClientCert),
Id::HostBridge(AuthFormId::KubeClientKey),
],
Some(&Id::HostBridge(AuthFormId::RemoteDirectory)) => [
Id::HostBridge(AuthFormId::KubeUsername),
Id::HostBridge(AuthFormId::KubeClientCert),
Id::HostBridge(AuthFormId::KubeClientKey),
Id::HostBridge(AuthFormId::RemoteDirectory),
],
Some(&Id::HostBridge(AuthFormId::LocalDirectory)) => [
Id::HostBridge(AuthFormId::KubeClientCert),
Id::HostBridge(AuthFormId::KubeClientKey),
Id::HostBridge(AuthFormId::RemoteDirectory),
Id::HostBridge(AuthFormId::LocalDirectory),
],
_ => [
Id::HostBridge(AuthFormId::KubeNamespace),
Id::HostBridge(AuthFormId::KubeClusterUrl),
Id::HostBridge(AuthFormId::KubeUsername),
Id::HostBridge(AuthFormId::KubeClientCert),
],
}
}
pub(in crate::ui::activities::auth) fn get_remote_kube_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::Remote(AuthFormId::KubeClientCert)) => [
Id::Remote(AuthFormId::KubeNamespace),
Id::Remote(AuthFormId::KubeClusterUrl),
Id::Remote(AuthFormId::KubeUsername),
Id::Remote(AuthFormId::KubeClientCert),
],
Some(&Id::Remote(AuthFormId::KubeClientKey)) => [
Id::Remote(AuthFormId::KubeClusterUrl),
Id::Remote(AuthFormId::KubeUsername),
Id::Remote(AuthFormId::KubeClientCert),
Id::Remote(AuthFormId::KubeClientKey),
],
Some(&Id::Remote(AuthFormId::RemoteDirectory)) => [
Id::Remote(AuthFormId::KubeUsername),
Id::Remote(AuthFormId::KubeClientCert),
Id::Remote(AuthFormId::KubeClientKey),
Id::Remote(AuthFormId::RemoteDirectory),
],
Some(&Id::Remote(AuthFormId::LocalDirectory)) => [
Id::Remote(AuthFormId::KubeClientCert),
Id::Remote(AuthFormId::KubeClientKey),
Id::Remote(AuthFormId::RemoteDirectory),
Id::Remote(AuthFormId::LocalDirectory),
],
_ => [
Id::Remote(AuthFormId::KubeNamespace),
Id::Remote(AuthFormId::KubeClusterUrl),
Id::Remote(AuthFormId::KubeUsername),
Id::Remote(AuthFormId::KubeClientCert),
],
}
}
#[cfg(posix)]
pub(in crate::ui::activities::auth) fn get_host_bridge_smb_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(
&Id::HostBridge(AuthFormId::Address)
| &Id::HostBridge(AuthFormId::Port)
| &Id::HostBridge(AuthFormId::SmbShare)
| &Id::HostBridge(AuthFormId::Username),
) => [
Id::HostBridge(AuthFormId::Address),
Id::HostBridge(AuthFormId::Port),
Id::HostBridge(AuthFormId::SmbShare),
Id::HostBridge(AuthFormId::Username),
],
Some(&Id::HostBridge(AuthFormId::Password)) => [
Id::HostBridge(AuthFormId::Port),
Id::HostBridge(AuthFormId::SmbShare),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
],
Some(&Id::HostBridge(AuthFormId::SmbWorkgroup)) => [
Id::HostBridge(AuthFormId::SmbShare),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::SmbWorkgroup),
],
Some(&Id::HostBridge(AuthFormId::SmbDialect)) => [
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::SmbWorkgroup),
Id::HostBridge(AuthFormId::SmbDialect),
],
Some(&Id::HostBridge(AuthFormId::RemoteDirectory)) => [
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::SmbWorkgroup),
Id::HostBridge(AuthFormId::SmbDialect),
Id::HostBridge(AuthFormId::RemoteDirectory),
],
Some(&Id::HostBridge(AuthFormId::LocalDirectory)) => [
Id::HostBridge(AuthFormId::SmbWorkgroup),
Id::HostBridge(AuthFormId::SmbDialect),
Id::HostBridge(AuthFormId::RemoteDirectory),
Id::HostBridge(AuthFormId::LocalDirectory),
],
_ => [
Id::HostBridge(AuthFormId::Address),
Id::HostBridge(AuthFormId::Port),
Id::HostBridge(AuthFormId::SmbShare),
Id::HostBridge(AuthFormId::Username),
],
}
}
#[cfg(posix)]
pub(in crate::ui::activities::auth) fn get_remote_smb_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(
&Id::Remote(AuthFormId::Address)
| &Id::Remote(AuthFormId::Port)
| &Id::Remote(AuthFormId::SmbShare)
| &Id::Remote(AuthFormId::Username),
) => [
Id::Remote(AuthFormId::Address),
Id::Remote(AuthFormId::Port),
Id::Remote(AuthFormId::SmbShare),
Id::Remote(AuthFormId::Username),
],
Some(&Id::Remote(AuthFormId::Password)) => [
Id::Remote(AuthFormId::Port),
Id::Remote(AuthFormId::SmbShare),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
],
Some(&Id::Remote(AuthFormId::SmbWorkgroup)) => [
Id::Remote(AuthFormId::SmbShare),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::SmbWorkgroup),
],
Some(&Id::Remote(AuthFormId::SmbDialect)) => [
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::SmbWorkgroup),
Id::Remote(AuthFormId::SmbDialect),
],
Some(&Id::Remote(AuthFormId::RemoteDirectory)) => [
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::SmbWorkgroup),
Id::Remote(AuthFormId::SmbDialect),
Id::Remote(AuthFormId::RemoteDirectory),
],
Some(&Id::Remote(AuthFormId::LocalDirectory)) => [
Id::Remote(AuthFormId::SmbWorkgroup),
Id::Remote(AuthFormId::SmbDialect),
Id::Remote(AuthFormId::RemoteDirectory),
Id::Remote(AuthFormId::LocalDirectory),
],
_ => [
Id::Remote(AuthFormId::Address),
Id::Remote(AuthFormId::Port),
Id::Remote(AuthFormId::SmbShare),
Id::Remote(AuthFormId::Username),
],
}
}
#[cfg(win)]
pub(in crate::ui::activities::auth) fn get_host_bridge_smb_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(
&Id::HostBridge(AuthFormId::Address)
| &Id::HostBridge(AuthFormId::Password)
| &Id::HostBridge(AuthFormId::SmbShare)
| &Id::HostBridge(AuthFormId::Username),
) => [
Id::HostBridge(AuthFormId::Address),
Id::HostBridge(AuthFormId::SmbShare),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
],
Some(&Id::HostBridge(AuthFormId::RemoteDirectory)) => [
Id::HostBridge(AuthFormId::SmbShare),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::RemoteDirectory),
],
Some(&Id::HostBridge(AuthFormId::LocalDirectory)) => [
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::RemoteDirectory),
Id::HostBridge(AuthFormId::LocalDirectory),
],
_ => [
Id::HostBridge(AuthFormId::Address),
Id::HostBridge(AuthFormId::SmbShare),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
],
}
}
#[cfg(win)]
pub(in crate::ui::activities::auth) fn get_remote_smb_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(
&Id::Remote(AuthFormId::Address)
| &Id::Remote(AuthFormId::Password)
| &Id::Remote(AuthFormId::SmbShare)
| &Id::Remote(AuthFormId::Username),
) => [
Id::Remote(AuthFormId::Address),
Id::Remote(AuthFormId::SmbShare),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
],
Some(&Id::Remote(AuthFormId::RemoteDirectory)) => [
Id::Remote(AuthFormId::SmbShare),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::RemoteDirectory),
],
Some(&Id::Remote(AuthFormId::LocalDirectory)) => [
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::RemoteDirectory),
Id::Remote(AuthFormId::LocalDirectory),
],
_ => [
Id::Remote(AuthFormId::Address),
Id::Remote(AuthFormId::SmbShare),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
],
}
}
pub(in crate::ui::activities::auth) fn get_host_bridge_webdav_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::HostBridge(AuthFormId::LocalDirectory)) => [
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::RemoteDirectory),
Id::HostBridge(AuthFormId::LocalDirectory),
],
_ => [
Id::HostBridge(AuthFormId::WebDAVUri),
Id::HostBridge(AuthFormId::Username),
Id::HostBridge(AuthFormId::Password),
Id::HostBridge(AuthFormId::RemoteDirectory),
],
}
}
pub(in crate::ui::activities::auth) fn get_remote_webdav_view(&self) -> [Id; 4] {
match self.app.focus() {
Some(&Id::Remote(AuthFormId::LocalDirectory)) => [
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::RemoteDirectory),
Id::Remote(AuthFormId::LocalDirectory),
],
_ => [
Id::Remote(AuthFormId::WebDAVUri),
Id::Remote(AuthFormId::Username),
Id::Remote(AuthFormId::Password),
Id::Remote(AuthFormId::RemoteDirectory),
],
}
}
pub(in crate::ui::activities::auth) fn init_global_listener(&mut self) {
use tuirealm::event::{Key, KeyEvent, KeyModifiers};
if let Err(err) = self.app.mount(
Id::GlobalListener,
Box::<components::GlobalListener>::default(),
vec![
Sub::new(
EventClause::Keyboard(KeyEvent {
code: Key::Esc,
modifiers: KeyModifiers::NONE,
}),
Self::no_popup_mounted_clause(),
),
Sub::new(
EventClause::Keyboard(KeyEvent {
code: Key::Function(10),
modifiers: KeyModifiers::NONE,
}),
Self::no_popup_mounted_clause(),
),
Sub::new(
EventClause::Keyboard(KeyEvent {
code: Key::Char('c'),
modifiers: KeyModifiers::CONTROL,
}),
Self::no_popup_mounted_clause(),
),
Sub::new(
EventClause::Keyboard(KeyEvent {
code: Key::Char('h'),
modifiers: KeyModifiers::CONTROL,
}),
Self::no_popup_mounted_clause(),
),
Sub::new(
EventClause::Keyboard(KeyEvent {
code: Key::Function(1),
modifiers: KeyModifiers::NONE,
}),
Self::no_popup_mounted_clause(),
),
Sub::new(
EventClause::Keyboard(KeyEvent {
code: Key::Char('r'),
modifiers: KeyModifiers::CONTROL,
}),
Self::no_popup_mounted_clause(),
),
Sub::new(
EventClause::Keyboard(KeyEvent {
code: Key::Char('s'),
modifiers: KeyModifiers::CONTROL,
}),
Self::no_popup_mounted_clause(),
),
Sub::new(EventClause::WindowResize, SubClause::Always),
],
) {
error!("Failed to mount component: {err}");
}
}
pub(in crate::ui::activities::auth) fn get_current_form_tab(&self) -> FormTab {
match self.app.focus() {
Some(&Id::HostBridge(_)) => FormTab::HostBridge,
_ => FormTab::Remote,
}
}
fn no_popup_mounted_clause() -> SubClause<Id> {
tuirealm::subclause_and_not!(
Id::ErrorPopup,
Id::InfoPopup,
Id::Keybindings,
Id::DeleteBookmarkPopup,
Id::DeleteRecentPopup,
Id::InstallUpdatePopup,
Id::BookmarkSavePassword,
Id::WaitPopup
)
}
}