1
// org.freedesktop.Secret.Session
2

            
3
use std::sync::Arc;
4

            
5
use oo7::{Key, dbus::ServiceError};
6
use zbus::{
7
    interface,
8
    names::UniqueName,
9
    zvariant::{ObjectPath, OwnedObjectPath},
10
};
11

            
12
use crate::Service;
13

            
14
#[derive(Debug, Clone)]
15
pub struct Session {
16
    aes_key: Option<Arc<Key>>,
17
    service: Service,
18
    path: OwnedObjectPath,
19
    sender: UniqueName<'static>,
20
}
21

            
22
#[interface(name = "org.freedesktop.Secret.Session")]
23
impl Session {
24
8
    pub async fn close(&self) -> Result<(), ServiceError> {
25
4
        self.service.remove_session(&self.path).await;
26
8
        self.service
27
            .object_server()
28
2
            .remove::<Self, _>(&self.path)
29
6
            .await?;
30

            
31
2
        Ok(())
32
    }
33
}
34

            
35
impl Session {
36
6
    pub async fn new(
37
        aes_key: Option<Arc<Key>>,
38
        service: Service,
39
        sender: UniqueName<'static>,
40
    ) -> Self {
41
6
        let index = service.session_index().await;
42
        Self {
43
5
            path: OwnedObjectPath::try_from(format!("/org/freedesktop/secrets/session/s{index}"))
44
                .unwrap(),
45
            aes_key,
46
            service,
47
            sender,
48
        }
49
    }
50

            
51
    pub fn sender(&self) -> &UniqueName<'static> {
52
        &self.sender
53
    }
54

            
55
5
    pub fn path(&self) -> &ObjectPath<'_> {
56
4
        &self.path
57
    }
58

            
59
2
    pub fn aes_key(&self) -> Option<Arc<Key>> {
60
2
        self.aes_key.as_ref().map(Arc::clone)
61
    }
62
}
63

            
64
#[cfg(test)]
65
mod tests {
66
    use crate::tests::TestServiceSetup;
67

            
68
    #[tokio::test]
69
    async fn close() -> Result<(), Box<dyn std::error::Error>> {
70
        let setup = TestServiceSetup::plain_session(true).await?;
71
        let path = setup.session.inner().path().to_owned();
72

            
73
        // Verify session exists on the server
74
        let session_check = setup.server.session(&path).await;
75
        assert!(
76
            session_check.is_some(),
77
            "Session should exist on server before close"
78
        );
79

            
80
        // Close the session
81
        setup.session.close().await?;
82

            
83
        // Verify session no longer exists on the server
84
        let session_check_after = setup.server.session(&path).await;
85
        assert!(
86
            session_check_after.is_none(),
87
            "Session should not exist on server after close"
88
        );
89

            
90
        Ok(())
91
    }
92
}