Skip to content

Commit 1249854

Browse files
committed
server: kde plasma prompter support
going to be part of the upcoming Plasma 6.6 release
1 parent aa78bde commit 1249854

10 files changed

Lines changed: 1146 additions & 506 deletions

File tree

server/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ zbus = { workspace = true, features = ["p2p"] }
3636
zeroize.workspace = true
3737

3838
[features]
39-
default = ["native_crypto"]
39+
default = ["gnome_native_crypto", "plasma"]
40+
gnome = []
41+
gnome_native_crypto = ["gnome", "native_crypto"]
42+
gnome_openssl_crypto = ["gnome", "openssl_crypto"]
4043
native_crypto = [
4144
"dep:hkdf",
4245
"dep:sha2",
@@ -46,6 +49,7 @@ openssl_crypto = [
4649
"dep:openssl",
4750
"oo7/openssl_crypto"
4851
]
52+
plasma = []
4953

5054
[dev-dependencies]
5155
serial_test = "3.3"

server/src/collection/tests.rs

Lines changed: 165 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::Arc;
33
use oo7::dbus;
44
use tokio_stream::StreamExt;
55

6-
use crate::tests::TestServiceSetup;
6+
use crate::tests::{TestServiceSetup, prompters};
77

88
#[tokio::test]
99
async fn create_item_plain() -> Result<(), Box<dyn std::error::Error>> {
@@ -547,162 +547,182 @@ async fn collection_deleted_signal() -> Result<(), Box<dyn std::error::Error>> {
547547

548548
#[tokio::test]
549549
async fn create_item_in_locked_collection() -> Result<(), Box<dyn std::error::Error>> {
550-
let setup = TestServiceSetup::plain_session(true).await?;
551-
552-
let collection = setup
553-
.server
554-
.collection_from_path(setup.collections[0].inner().path())
555-
.await
556-
.expect("Collection should exist");
557-
collection
558-
.set_locked(true, setup.keyring_secret.clone())
559-
.await?;
560-
561-
assert!(
562-
setup.collections[0].is_locked().await?,
563-
"Collection should be locked"
564-
);
565-
566-
let secret = oo7::Secret::text("test-password");
567-
let dbus_secret = dbus::api::DBusSecret::new(Arc::clone(&setup.session), secret.clone());
568-
569-
let item = setup.collections[0]
570-
.create_item(
571-
"Test Item",
572-
&[("app", "test"), ("type", "password")],
573-
&dbus_secret,
574-
false,
575-
None,
576-
)
577-
.await?;
578-
579-
assert!(
580-
!setup.collections[0].is_locked().await?,
581-
"Collection should be unlocked after prompt"
582-
);
583-
584-
let items = setup.collections[0].items().await?;
585-
assert_eq!(items.len(), 1, "Collection should have one item");
586-
assert_eq!(
587-
items[0].inner().path(),
588-
item.inner().path(),
589-
"Created item should be in the collection"
590-
);
591-
592-
let label = item.label().await?;
593-
assert_eq!(label, "Test Item", "Item should have correct label");
594-
595-
let attributes = item.attributes().await?;
596-
assert_eq!(attributes.get("app"), Some(&"test".to_string()));
597-
assert_eq!(attributes.get("type"), Some(&"password".to_string()));
598-
599-
let retrieved_secret = item.secret(&setup.session).await?;
600-
assert_eq!(retrieved_secret.value(), secret.as_bytes());
550+
for prompt_activator in prompters().await {
551+
prompt_activator.activate();
552+
553+
let setup = TestServiceSetup::plain_session(true).await?;
554+
555+
let collection = setup
556+
.server
557+
.collection_from_path(setup.collections[0].inner().path())
558+
.await
559+
.expect("Collection should exist");
560+
collection
561+
.set_locked(true, setup.keyring_secret.clone())
562+
.await?;
563+
564+
assert!(
565+
setup.collections[0].is_locked().await?,
566+
"Collection should be locked"
567+
);
568+
569+
let secret = oo7::Secret::text("test-password");
570+
let dbus_secret = dbus::api::DBusSecret::new(Arc::clone(&setup.session), secret.clone());
571+
572+
let item = setup.collections[0]
573+
.create_item(
574+
"Test Item",
575+
&[("app", "test"), ("type", "password")],
576+
&dbus_secret,
577+
false,
578+
None,
579+
)
580+
.await?;
581+
582+
assert!(
583+
!setup.collections[0].is_locked().await?,
584+
"Collection should be unlocked after prompt"
585+
);
586+
587+
let items = setup.collections[0].items().await?;
588+
assert_eq!(items.len(), 1, "Collection should have one item");
589+
assert_eq!(
590+
items[0].inner().path(),
591+
item.inner().path(),
592+
"Created item should be in the collection"
593+
);
594+
595+
let label = item.label().await?;
596+
assert_eq!(label, "Test Item", "Item should have correct label");
597+
598+
let attributes = item.attributes().await?;
599+
assert_eq!(attributes.get("app"), Some(&"test".to_string()));
600+
assert_eq!(attributes.get("type"), Some(&"password".to_string()));
601+
602+
let retrieved_secret = item.secret(&setup.session).await?;
603+
assert_eq!(retrieved_secret.value(), secret.as_bytes());
604+
}
601605

602606
Ok(())
603607
}
604608

605609
#[tokio::test]
606610
async fn delete_locked_collection_with_prompt() -> Result<(), Box<dyn std::error::Error>> {
607-
let setup = TestServiceSetup::plain_session(true).await?;
608-
let default_collection = setup.default_collection().await?;
609-
610-
let collection = setup
611-
.server
612-
.collection_from_path(default_collection.inner().path())
613-
.await
614-
.expect("Collection should exist");
615-
collection
616-
.set_locked(true, setup.keyring_secret.clone())
617-
.await?;
618-
619-
assert!(
620-
default_collection.is_locked().await?,
621-
"Collection should be locked"
622-
);
623-
624-
let collection_path = default_collection.inner().path().to_owned();
625-
626-
// Get initial collection count
627-
let collections_before = setup.service_api.collections().await?;
628-
let initial_count = collections_before.len();
629-
630-
// Delete the locked collection
631-
default_collection.delete(None).await?;
632-
633-
// Give the system a moment to process the deletion
634-
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
635-
636-
// Verify collection was deleted
637-
let collections_after = setup.service_api.collections().await?;
638-
assert_eq!(
639-
collections_after.len(),
640-
initial_count - 1,
641-
"Collection should be deleted after prompt"
642-
);
643-
644-
// Verify the specific collection is not in the list
645-
let collection_paths: Vec<_> = collections_after
646-
.iter()
647-
.map(|c| c.inner().path().as_str())
648-
.collect();
649-
assert!(
650-
!collection_paths.contains(&collection_path.as_str()),
651-
"Deleted collection should not be in service collections list"
652-
);
611+
for prompt_activator in prompters().await {
612+
prompt_activator.activate();
613+
614+
let setup = TestServiceSetup::plain_session(true).await?;
615+
let default_collection = setup.default_collection().await?;
616+
617+
let collection = setup
618+
.server
619+
.collection_from_path(default_collection.inner().path())
620+
.await
621+
.expect("Collection should exist");
622+
collection
623+
.set_locked(true, setup.keyring_secret.clone())
624+
.await?;
625+
626+
assert!(
627+
default_collection.is_locked().await?,
628+
"Collection should be locked"
629+
);
630+
631+
let collection_path = default_collection.inner().path().to_owned();
632+
633+
// Get initial collection count
634+
let collections_before = setup.service_api.collections().await?;
635+
let initial_count = collections_before.len();
636+
637+
// Delete the locked collection
638+
default_collection.delete(None).await?;
639+
640+
// Give the system a moment to process the deletion
641+
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
642+
643+
// Verify collection was deleted
644+
let collections_after = setup.service_api.collections().await?;
645+
assert_eq!(
646+
collections_after.len(),
647+
initial_count - 1,
648+
"Collection should be deleted after prompt"
649+
);
650+
651+
// Verify the specific collection is not in the list
652+
let collection_paths: Vec<_> = collections_after
653+
.iter()
654+
.map(|c| c.inner().path().as_str())
655+
.collect();
656+
assert!(
657+
!collection_paths.contains(&collection_path.as_str()),
658+
"Deleted collection should not be in service collections list"
659+
);
660+
}
653661

654662
Ok(())
655663
}
656664

657665
#[tokio::test]
658666
async fn unlock_retry() -> Result<(), Box<dyn std::error::Error>> {
659-
let setup = TestServiceSetup::plain_session(true).await?;
660-
let default_collection = setup.default_collection().await?;
661-
662-
let secret = oo7::Secret::text("test-secret-data");
663-
let dbus_secret = dbus::api::DBusSecret::new(Arc::clone(&setup.session), secret);
664-
default_collection
665-
.create_item("Test Item", &[("app", "test")], &dbus_secret, false, None)
666-
.await?;
667-
668-
let collection = setup
669-
.server
670-
.collection_from_path(default_collection.inner().path())
671-
.await
672-
.expect("Collection should exist");
673-
collection
674-
.set_locked(true, setup.keyring_secret.clone())
675-
.await?;
676-
677-
assert!(
678-
default_collection.is_locked().await?,
679-
"Collection should be locked"
680-
);
681-
682-
setup
683-
.mock_prompter
684-
.set_password_queue(vec![
685-
oo7::Secret::from("wrong-password"),
686-
oo7::Secret::from("wrong-password2"),
687-
oo7::Secret::from("test-password-long-enough"),
688-
])
689-
.await;
690-
691-
let unlocked = setup
692-
.service_api
693-
.unlock(&[default_collection.inner().path()], None)
694-
.await?;
695-
696-
assert_eq!(unlocked.len(), 1, "Should have unlocked 1 collection");
697-
assert_eq!(
698-
unlocked[0].as_str(),
699-
default_collection.inner().path().as_str(),
700-
"Should return the collection path"
701-
);
702-
assert!(
703-
!default_collection.is_locked().await?,
704-
"Collection should be unlocked after retry with correct password"
705-
);
667+
for prompt_activator in prompters().await {
668+
prompt_activator.activate();
669+
670+
let setup = TestServiceSetup::plain_session(true).await?;
671+
let default_collection = setup.default_collection().await?;
672+
673+
let secret = oo7::Secret::text("test-secret-data");
674+
let dbus_secret = dbus::api::DBusSecret::new(Arc::clone(&setup.session), secret);
675+
default_collection
676+
.create_item("Test Item", &[("app", "test")], &dbus_secret, false, None)
677+
.await?;
678+
679+
let collection = setup
680+
.server
681+
.collection_from_path(default_collection.inner().path())
682+
.await
683+
.expect("Collection should exist");
684+
collection
685+
.set_locked(true, setup.keyring_secret.clone())
686+
.await?;
687+
688+
assert!(
689+
default_collection.is_locked().await?,
690+
"Collection should be locked"
691+
);
692+
693+
setup
694+
.mock_prompter
695+
.set_password_queue(vec![
696+
oo7::Secret::from("wrong-password"),
697+
oo7::Secret::from("wrong-password2"),
698+
oo7::Secret::from("test-password-long-enough"),
699+
])
700+
.await;
701+
setup
702+
.mock_prompter_plasma
703+
.set_password_queue(vec![
704+
oo7::Secret::from("wrong-password"),
705+
oo7::Secret::from("wrong-password2"),
706+
oo7::Secret::from("test-password-long-enough"),
707+
])
708+
.await;
709+
710+
let unlocked = setup
711+
.service_api
712+
.unlock(&[default_collection.inner().path()], None)
713+
.await?;
714+
715+
assert_eq!(unlocked.len(), 1, "Should have unlocked 1 collection");
716+
assert_eq!(
717+
unlocked[0].as_str(),
718+
default_collection.inner().path().as_str(),
719+
"Should return the collection path"
720+
);
721+
assert!(
722+
!default_collection.is_locked().await?,
723+
"Collection should be unlocked after retry with correct password"
724+
);
725+
}
706726

707727
Ok(())
708728
}

0 commit comments

Comments
 (0)