Present desktop OTP and sensitive outputs
This commit is contained in:
@@ -32,6 +32,13 @@ pub enum UiAction {
|
||||
CopyEntry,
|
||||
DeleteEntry,
|
||||
ToggleReveal,
|
||||
GenerateOtp,
|
||||
CopyOtp,
|
||||
ImportOtp,
|
||||
ShowOtpUri,
|
||||
CopyOtpUri,
|
||||
ShowOtpQr,
|
||||
RemoveOtp,
|
||||
GitStatus,
|
||||
GitPull,
|
||||
GitPush,
|
||||
@@ -72,6 +79,13 @@ impl UiAction {
|
||||
Self::CopyEntry => "copy-entry",
|
||||
Self::DeleteEntry => "delete-entry",
|
||||
Self::ToggleReveal => "toggle-reveal",
|
||||
Self::GenerateOtp => "generate-otp",
|
||||
Self::CopyOtp => "copy-otp",
|
||||
Self::ImportOtp => "import-otp",
|
||||
Self::ShowOtpUri => "show-otp-uri",
|
||||
Self::CopyOtpUri => "copy-otp-uri",
|
||||
Self::ShowOtpQr => "show-otp-qr",
|
||||
Self::RemoveOtp => "remove-otp",
|
||||
Self::GitStatus => "git-status",
|
||||
Self::GitPull => "git-pull",
|
||||
Self::GitPush => "git-push",
|
||||
@@ -135,6 +149,7 @@ pub struct ActionContext {
|
||||
pub focused_field: bool,
|
||||
pub focused_sensitive: bool,
|
||||
pub focused_generatable: bool,
|
||||
pub focused_otp: bool,
|
||||
pub entry_path: bool,
|
||||
pub selected_object: bool,
|
||||
pub git_running: bool,
|
||||
@@ -237,6 +252,23 @@ pub const ACTIONS: &[ActionSpec] = &[
|
||||
"Reveal or Hide Field",
|
||||
None,
|
||||
),
|
||||
spec(
|
||||
UiAction::GenerateOtp,
|
||||
MenuGroup::Entry,
|
||||
"Generate OTP Code",
|
||||
None,
|
||||
),
|
||||
spec(UiAction::CopyOtp, MenuGroup::Entry, "Copy OTP Code", None),
|
||||
spec(
|
||||
UiAction::ImportOtp,
|
||||
MenuGroup::Entry,
|
||||
"Import OTP URI or QR…",
|
||||
None,
|
||||
),
|
||||
spec(UiAction::ShowOtpUri, MenuGroup::Entry, "Show OTP URI", None),
|
||||
spec(UiAction::CopyOtpUri, MenuGroup::Entry, "Copy OTP URI", None),
|
||||
spec(UiAction::ShowOtpQr, MenuGroup::Entry, "Show OTP QR", None),
|
||||
spec(UiAction::RemoveOtp, MenuGroup::Entry, "Remove OTP", None),
|
||||
spec(UiAction::GitStatus, MenuGroup::Tools, "Git Status…", None),
|
||||
spec(UiAction::GitPull, MenuGroup::Tools, "Pull", None),
|
||||
spec(UiAction::GitPush, MenuGroup::Tools, "Push", None),
|
||||
@@ -378,6 +410,28 @@ pub fn enabled(action: UiAction, context: ActionContext) -> bool {
|
||||
&& !context.switching_vault
|
||||
&& context.focused_sensitive
|
||||
}
|
||||
UiAction::GenerateOtp
|
||||
| UiAction::CopyOtp
|
||||
| UiAction::ShowOtpUri
|
||||
| UiAction::CopyOtpUri
|
||||
| UiAction::ShowOtpQr
|
||||
| UiAction::RemoveOtp => {
|
||||
context.unlocked
|
||||
&& context.document_open
|
||||
&& !context.editing
|
||||
&& context.focused_otp
|
||||
&& !context.saving
|
||||
&& !context.switching_vault
|
||||
&& !context.modal_open
|
||||
}
|
||||
UiAction::ImportOtp => {
|
||||
context.storage_ready
|
||||
&& context.unlocked
|
||||
&& !context.dirty
|
||||
&& !context.saving
|
||||
&& !context.switching_vault
|
||||
&& !context.modal_open
|
||||
}
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync => {
|
||||
context.storage_ready
|
||||
&& !context.saving
|
||||
@@ -497,6 +551,58 @@ pub fn disabled_reason(action: UiAction, context: ActionContext) -> Option<&'sta
|
||||
UiAction::ToggleReveal if !context.document_open => "Open an entry first",
|
||||
UiAction::ToggleReveal if !context.focused_sensitive => "Select a sensitive field first",
|
||||
UiAction::ToggleReveal => "Wait for vault validation",
|
||||
UiAction::GenerateOtp
|
||||
| UiAction::CopyOtp
|
||||
| UiAction::ShowOtpUri
|
||||
| UiAction::CopyOtpUri
|
||||
| UiAction::ShowOtpQr
|
||||
| UiAction::RemoveOtp
|
||||
if !context.unlocked =>
|
||||
{
|
||||
"Unlock an entry first"
|
||||
}
|
||||
UiAction::GenerateOtp
|
||||
| UiAction::CopyOtp
|
||||
| UiAction::ShowOtpUri
|
||||
| UiAction::CopyOtpUri
|
||||
| UiAction::ShowOtpQr
|
||||
| UiAction::RemoveOtp
|
||||
if !context.document_open =>
|
||||
{
|
||||
"Open an entry first"
|
||||
}
|
||||
UiAction::GenerateOtp
|
||||
| UiAction::CopyOtp
|
||||
| UiAction::ShowOtpUri
|
||||
| UiAction::CopyOtpUri
|
||||
| UiAction::ShowOtpQr
|
||||
| UiAction::RemoveOtp
|
||||
if !context.focused_otp =>
|
||||
{
|
||||
"Select an OTP URI field first"
|
||||
}
|
||||
UiAction::GenerateOtp
|
||||
| UiAction::CopyOtp
|
||||
| UiAction::ShowOtpUri
|
||||
| UiAction::CopyOtpUri
|
||||
| UiAction::ShowOtpQr
|
||||
| UiAction::RemoveOtp
|
||||
if context.editing =>
|
||||
{
|
||||
"Finish editing the entry first"
|
||||
}
|
||||
UiAction::GenerateOtp
|
||||
| UiAction::CopyOtp
|
||||
| UiAction::ShowOtpUri
|
||||
| UiAction::CopyOtpUri
|
||||
| UiAction::ShowOtpQr
|
||||
| UiAction::RemoveOtp => "Close the current screen first",
|
||||
UiAction::ImportOtp if !context.storage_ready => "Shared configuration is unavailable",
|
||||
UiAction::ImportOtp if !context.unlocked => "Unlock the password store first",
|
||||
UiAction::ImportOtp if context.dirty => "Save or discard the current draft first",
|
||||
UiAction::ImportOtp if context.saving => "Wait for the active save",
|
||||
UiAction::ImportOtp if context.switching_vault => "Wait for vault validation",
|
||||
UiAction::ImportOtp => "Close the current screen first",
|
||||
UiAction::GitStatus | UiAction::GitPull | UiAction::GitPush | UiAction::GitSync
|
||||
if !context.storage_ready =>
|
||||
{
|
||||
@@ -561,6 +667,13 @@ pub const fn aliases(action: UiAction) -> &'static [&'static str] {
|
||||
UiAction::CopyEntry => &["duplicate entry", "copy folder", "pass cp"],
|
||||
UiAction::DeleteEntry => &["remove", "rm", "delete folder"],
|
||||
UiAction::ToggleReveal => &["show password", "hide password", "reveal field"],
|
||||
UiAction::GenerateOtp => &["totp", "hotp", "one time password"],
|
||||
UiAction::CopyOtp => &["copy totp", "copy hotp", "otp clipboard"],
|
||||
UiAction::ImportOtp => &["add otp", "scan qr", "import otpauth"],
|
||||
UiAction::ShowOtpUri => &["show otpauth", "otp secret"],
|
||||
UiAction::CopyOtpUri => &["copy otpauth", "copy otp secret"],
|
||||
UiAction::ShowOtpQr => &["otp qr", "export otp"],
|
||||
UiAction::RemoveOtp => &["delete otp", "remove otpauth"],
|
||||
UiAction::GitStatus => &["repository status", "git history"],
|
||||
UiAction::GitPull => &["fetch", "download changes"],
|
||||
UiAction::GitPush => &["upload changes"],
|
||||
@@ -623,6 +736,7 @@ mod tests {
|
||||
focused_field: true,
|
||||
focused_sensitive: true,
|
||||
focused_generatable: true,
|
||||
focused_otp: true,
|
||||
entry_path: true,
|
||||
selected_object: true,
|
||||
git_running: false,
|
||||
@@ -672,6 +786,17 @@ mod tests {
|
||||
assert!(enabled(UiAction::InitializeStore, viewing));
|
||||
assert!(enabled(UiAction::NewFolder, viewing));
|
||||
assert!(enabled(UiAction::NewEntry, viewing));
|
||||
for action in [
|
||||
UiAction::GenerateOtp,
|
||||
UiAction::CopyOtp,
|
||||
UiAction::ShowOtpUri,
|
||||
UiAction::CopyOtpUri,
|
||||
UiAction::ShowOtpQr,
|
||||
UiAction::RemoveOtp,
|
||||
] {
|
||||
assert!(enabled(action, viewing), "{action:?}");
|
||||
}
|
||||
assert!(enabled(UiAction::ImportOtp, viewing));
|
||||
|
||||
let locked = ActionContext {
|
||||
unlocked: false,
|
||||
@@ -683,6 +808,13 @@ mod tests {
|
||||
UiAction::CopyEditedField,
|
||||
UiAction::ToggleReveal,
|
||||
UiAction::GeneratePassword,
|
||||
UiAction::GenerateOtp,
|
||||
UiAction::CopyOtp,
|
||||
UiAction::ImportOtp,
|
||||
UiAction::ShowOtpUri,
|
||||
UiAction::CopyOtpUri,
|
||||
UiAction::ShowOtpQr,
|
||||
UiAction::RemoveOtp,
|
||||
UiAction::Lock,
|
||||
] {
|
||||
assert!(!enabled(action, locked));
|
||||
|
||||
Reference in New Issue
Block a user