Skip to content

Commit 486d88f

Browse files
committed
Implement a simple password manager
1 parent 4599e1b commit 486d88f

File tree

8 files changed

+720
-27
lines changed

8 files changed

+720
-27
lines changed

Cargo.lock

Lines changed: 93 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ i18n-embed-fl = "0.10"
2929
icu = { version = "2.0.0", features = ["compiled_data"] }
3030
rust-embed = "8"
3131
url = "2.5"
32+
secret-service = { version = "5.0.0", features = ["rt-tokio-crypto-rust"], optional = true }
33+
thiserror = { version = "2.0", optional = true }
34+
secstr = { version = "0.5", optional = true }
3235

3336
[dependencies.cosmic-files]
3437
git = "https://github.com/pop-os/cosmic-files.git"
@@ -48,10 +51,11 @@ features = ["about", "multi-window", "tokio", "winit", "surface-message"]
4851
fork = "0.2"
4952

5053
[features]
51-
default = ["dbus-config", "wgpu", "wayland"]
54+
default = ["dbus-config", "wgpu", "wayland", "password_manager"]
5255
dbus-config = ["libcosmic/dbus-config"]
5356
wgpu = ["libcosmic/wgpu", "cosmic-files/wgpu"]
5457
wayland = ["libcosmic/wayland", "cosmic-files/wayland"]
58+
password_manager = [ "secret-service", "thiserror", "secstr" ]
5559

5660
[profile.release-with-debug]
5761
inherits = "release"

i18n/en/cosmic_term.ftl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,10 @@ pane-toggle-maximize = Toggle maximized
9999
menu-color-schemes = Color schemes...
100100
menu-settings = Settings...
101101
menu-about = About COSMIC Terminal...
102+
103+
# Password Manager
104+
menu-password-manager = Passwords...
105+
password-manager = Manage Passwords
106+
add-password = Add Password
107+
password-input = Password
108+
password-input-description = Description

i18n/sv-SE/cosmic_term.ftl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,10 @@ menu-settings = Inställningar…
112112
menu-about = Om COSMIC Terminal…
113113
repository = Källkod
114114
support = Support
115+
116+
# Lösenordshanterare
117+
menu-password-manager = Lösenord…
118+
password-manager = Hantera lösenord
119+
add-password = Lägg till lösenord
120+
password-input = Lösenord
121+
password-input-description = Beskrivning

src/key_bind.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub fn key_binds() -> HashMap<KeyBind, Action> {
4545
Key::Character("X".into()),
4646
PaneToggleMaximized
4747
);
48+
#[cfg(feature = "password_manager")]
49+
bind!([Ctrl, Alt], Key::Character("p".into()), PasswordManager);
4850

4951
// Ctrl+Tab and Ctrl+Shift+Tab cycle through tabs
5052
// Ctrl+Tab is not a special key for terminals and is free to use

src/main.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ use terminal_box::terminal_box;
6565
use crate::dnd::DndDrop;
6666
mod terminal_box;
6767

68+
#[cfg(feature = "password_manager")]
69+
mod password_manager;
6870
mod terminal_theme;
6971

7072
mod dnd;
@@ -236,6 +238,8 @@ pub enum Action {
236238
Profiles,
237239
SelectAll,
238240
Settings,
241+
#[cfg(feature = "password_manager")]
242+
PasswordManager,
239243
ShowHeaderBar(bool),
240244
TabActivate0,
241245
TabActivate1,
@@ -278,6 +282,8 @@ impl Action {
278282
Self::PaneSplitHorizontal => Message::PaneSplit(pane_grid::Axis::Horizontal),
279283
Self::PaneSplitVertical => Message::PaneSplit(pane_grid::Axis::Vertical),
280284
Self::PaneToggleMaximized => Message::PaneToggleMaximized,
285+
#[cfg(feature = "password_manager")]
286+
Self::PasswordManager => Message::ToggleContextPage(ContextPage::PasswordManager),
281287
Self::Paste => Message::Paste(entity_opt),
282288
Self::PastePrimary => Message::PastePrimary(entity_opt),
283289
Self::ProfileOpen(profile_id) => Message::ProfileOpen(*profile_id),
@@ -362,6 +368,10 @@ pub enum Message {
362368
PaneResized(pane_grid::ResizeEvent),
363369
PaneSplit(pane_grid::Axis),
364370
PaneToggleMaximized,
371+
#[cfg(feature = "password_manager")]
372+
PasswordManager(password_manager::PasswordManagerMessage),
373+
#[cfg(feature = "password_manager")]
374+
PasswordPaste(secstr::SecUtf8, pane_grid::Pane),
365375
Paste(Option<segmented_button::Entity>),
366376
PastePrimary(Option<segmented_button::Entity>),
367377
PasteValue(Option<segmented_button::Entity>, String),
@@ -412,6 +422,8 @@ pub enum ContextPage {
412422
ColorSchemes(ColorSchemeKind),
413423
Profiles,
414424
Settings,
425+
#[cfg(feature = "password_manager")]
426+
PasswordManager,
415427
}
416428

417429
/// The [`App`] stores application-specific state.
@@ -456,6 +468,8 @@ pub struct App {
456468
profile_expanded: Option<ProfileId>,
457469
show_advanced_font_settings: bool,
458470
modifiers: Modifiers,
471+
#[cfg(feature = "password_manager")]
472+
password_mgr: password_manager::PasswordManager,
459473
}
460474

461475
impl App {
@@ -1569,6 +1583,8 @@ impl Application for App {
15691583
profile_expanded: None,
15701584
show_advanced_font_settings: false,
15711585
modifiers: Modifiers::empty(),
1586+
#[cfg(feature = "password_manager")]
1587+
password_mgr: Default::default(),
15721588
};
15731589

15741590
app.set_curr_font_weights_and_stretches();
@@ -1582,6 +1598,10 @@ impl Application for App {
15821598
if self.core.window.show_context {
15831599
// Close context drawer if open
15841600
self.core.window.show_context = false;
1601+
#[cfg(feature = "password_manager")]
1602+
if self.context_page == ContextPage::PasswordManager {
1603+
self.password_mgr.clear();
1604+
}
15851605
} else if self.find {
15861606
// Close find if open
15871607
self.find = false;
@@ -1596,6 +1616,10 @@ impl Application for App {
15961616
if self.core.window.show_context {
15971617
Task::none()
15981618
} else {
1619+
#[cfg(feature = "password_manager")]
1620+
if self.context_page == ContextPage::PasswordManager {
1621+
self.password_mgr.clear();
1622+
}
15991623
self.update_focus()
16001624
}
16011625
}
@@ -2147,6 +2171,23 @@ impl Application for App {
21472171
self.pane_model.panes.drop(pane, target);
21482172
}
21492173
Message::PaneDragged(_) => {}
2174+
#[cfg(feature = "password_manager")]
2175+
Message::PasswordManager(msg) => {
2176+
return self.password_mgr.update(msg);
2177+
}
2178+
#[cfg(feature = "password_manager")]
2179+
Message::PasswordPaste(password, pane) => {
2180+
if let Some(tab_model) = self.pane_model.panes.get(pane) {
2181+
let entity = tab_model.active();
2182+
if let Some(terminal) = tab_model.data::<Mutex<Terminal>>(entity) {
2183+
let terminal = terminal.lock().unwrap();
2184+
terminal.paste(password.into_unsecure());
2185+
terminal.input_scroll(b"\n".as_slice());
2186+
self.core.window.show_context = false;
2187+
self.password_mgr.clear();
2188+
}
2189+
}
2190+
}
21502191
Message::Paste(entity_opt) => {
21512192
return clipboard::read().map(move |value_opt| match value_opt {
21522193
Some(value) => action::app(Message::PasteValue(entity_opt, value)),
@@ -2612,6 +2653,16 @@ impl Application for App {
26122653
ColorSchemeKind::Light => light_entity,
26132654
});
26142655
}
2656+
2657+
#[cfg(feature = "password_manager")]
2658+
if ContextPage::PasswordManager == context_page {
2659+
if self.core.window.show_context {
2660+
self.password_mgr.pane = Some(self.pane_model.focused());
2661+
return self.password_mgr.refresh_password_list();
2662+
} else {
2663+
self.password_mgr.clear();
2664+
}
2665+
}
26152666
}
26162667
Message::UpdateDefaultProfile((default, profile_id)) => {
26172668
config_set!(default_profile, default.then_some(profile_id));
@@ -2685,6 +2736,12 @@ impl Application for App {
26852736
Message::ToggleContextPage(ContextPage::Settings),
26862737
)
26872738
.title(fl!("settings")),
2739+
#[cfg(feature = "password_manager")]
2740+
ContextPage::PasswordManager => context_drawer::context_drawer(
2741+
self.password_mgr.context_page(self.core.system_theme()),
2742+
Message::ToggleContextPage(ContextPage::PasswordManager),
2743+
)
2744+
.title(fl!("password-manager")),
26882745
})
26892746
}
26902747

0 commit comments

Comments
 (0)