Skip to content

Commit

Permalink
server: Add Lock and Unlock implementation
Browse files Browse the repository at this point in the history
Issuing a prompt to lock/unlock objects is not implemented in this change.

Signed-off-by: Dhanuka Warusadura <dhanuka@gnome.org>
  • Loading branch information
warusadura authored and bilelmoussaoui committed Nov 27, 2024
1 parent 50f07b1 commit b30cdba
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 14 deletions.
35 changes: 31 additions & 4 deletions server/src/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ use oo7::{
portal::Keyring,
};
use tokio::sync::{Mutex, RwLock};
use zbus::{interface, object_server::SignalEmitter, zvariant};
use zbus::{interface, object_server::SignalEmitter, proxy::Defaults, zvariant};
use zvariant::{ObjectPath, OwnedObjectPath};

use crate::{error::Error, item, service_manager::ServiceManager};
use crate::{error::Error, item, service_manager::ServiceManager, Service};

#[derive(Debug, Clone)]
pub struct Collection {
Expand Down Expand Up @@ -130,9 +130,9 @@ impl Collection {
) -> zbus::Result<()>;

#[zbus(signal, name = "ItemChanged")]
async fn item_changed(
pub async fn item_changed(
signal_emitter: &SignalEmitter<'_>,
item: OwnedObjectPath,
item: &OwnedObjectPath,
) -> zbus::Result<()>;
}

Expand Down Expand Up @@ -205,6 +205,33 @@ impl Collection {
None
}

pub async fn set_locked(&self, locked: bool) -> Result<(), ServiceError> {
let items = self.items.lock().await;

for item in items.iter() {
item.set_locked(locked).await?;
}

let manager = self.manager.lock().await;

self.locked
.store(locked, std::sync::atomic::Ordering::Relaxed);
let signal_emitter = manager.signal_emitter(&self.path)?;
self.locked_changed(&signal_emitter).await?;

let service_path = oo7::dbus::api::Service::PATH.as_ref().unwrap();
let signal_emitter = manager.signal_emitter(service_path)?;
Service::collection_changed(&signal_emitter, &self.path).await?;

tracing::debug!(
"Collection: {} is {}.",
self.path,
if locked { "locked" } else { "unlocked" }
);

Ok(())
}

pub async fn dispatch_items(&self) -> Result<(), Error> {
let keyring_items = self.keyring.items().await;
let mut items = self.items.lock().await;
Expand Down
24 changes: 23 additions & 1 deletion server/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use oo7::{
use tokio::sync::Mutex;
use zbus::zvariant::{ObjectPath, OwnedObjectPath};

use crate::service_manager::ServiceManager;
use crate::{collection::Collection, service_manager::ServiceManager};

#[derive(Debug, Clone)]
pub struct Item {
Expand All @@ -21,6 +21,7 @@ pub struct Item {
inner: Arc<Mutex<oo7::portal::Item>>,
// Other attributes
manager: Arc<Mutex<ServiceManager>>,
collection_path: OwnedObjectPath,
path: OwnedObjectPath,
}

Expand Down Expand Up @@ -160,6 +161,7 @@ impl Item {
Self {
locked: Arc::new(AtomicBool::new(locked)),
inner: Arc::new(Mutex::new(item)),
collection_path: collection_path.clone(),
path: OwnedObjectPath::try_from(format!("{}/{}", collection_path, item_index)).unwrap(),
manager,
}
Expand All @@ -168,4 +170,24 @@ impl Item {
pub fn path(&self) -> &OwnedObjectPath {
&self.path
}

pub async fn set_locked(&self, locked: bool) -> Result<(), ServiceError> {
let manager = self.manager.lock().await;

self.locked
.store(locked, std::sync::atomic::Ordering::Relaxed);
let signal_emitter = manager.signal_emitter(&self.path)?;
self.locked_changed(&signal_emitter).await?;

let signal_emitter = manager.signal_emitter(&self.collection_path)?;
Collection::item_changed(&signal_emitter, &self.path).await?;

tracing::debug!(
"Item: {} is {}.",
self.path,
if locked { "locked" } else { "unlocked" }
);

Ok(())
}
}
73 changes: 65 additions & 8 deletions server/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,21 @@ impl Service {
#[zbus(out_args("unlocked", "prompt"))]
pub async fn unlock(
&mut self,
_objects: Vec<OwnedObjectPath>,
) -> Result<(Vec<OwnedObjectPath>, ObjectPath), ServiceError> {
todo!()
objects: Vec<OwnedObjectPath>,
) -> Result<(Vec<OwnedObjectPath>, OwnedObjectPath), ServiceError> {
let (unlocked, _not_unlocked) = self.set_locked(false, &objects).await?;

Ok((unlocked, OwnedObjectPath::default()))
}

#[zbus(out_args("locked", "prompt"))]
pub async fn lock(
&mut self,
_objects: Vec<OwnedObjectPath>,
) -> Result<(Vec<OwnedObjectPath>, ObjectPath), ServiceError> {
todo!()
objects: Vec<OwnedObjectPath>,
) -> Result<(Vec<OwnedObjectPath>, OwnedObjectPath), ServiceError> {
let (locked, _not_locked) = self.set_locked(true, &objects).await?;

Ok((locked, OwnedObjectPath::default()))
}

#[zbus(out_args("secrets"))]
Expand Down Expand Up @@ -231,9 +235,9 @@ impl Service {
) -> zbus::Result<()>;

#[zbus(signal, name = "CollectionChanged")]
async fn collection_changed(
pub async fn collection_changed(
signal_emitter: &SignalEmitter<'_>,
collection: OwnedObjectPath,
collection: &OwnedObjectPath,
) -> zbus::Result<()>;
}

Expand Down Expand Up @@ -293,4 +297,57 @@ impl Service {

Ok(())
}

pub async fn set_locked(
&self,
locked: bool,
objects: &[OwnedObjectPath],
) -> Result<(Vec<OwnedObjectPath>, Vec<OwnedObjectPath>), ServiceError> {
let mut without_prompt = Vec::new();
let mut with_prompt = Vec::new();
let collections = self.collections.lock().await;

for object in objects {
for collection in collections.iter() {
let collection_locked = collection.is_locked().await;
if object == collection.path() {
if collection_locked == locked {
tracing::debug!(
"Collection: {} is already {}.",
object,
if locked { "locked" } else { "unlocked" }
);
without_prompt.push(object.clone());
} else {
// TODO: remove this once the prompt implementation is complete.
collection.set_locked(locked).await?;
with_prompt.push(object.clone());
}
break;
} else if let Some(item) = collection.item_from_path(object).await {
if locked == item.is_locked().await {
tracing::debug!(
"Item: {} is already {}.",
object,
if locked { "locked" } else { "unlocked" }
);
without_prompt.push(object.clone());
// If the collection is in a similar state, update the Item
// without a prompt.
} else if collection_locked == locked {
item.set_locked(locked).await?;
without_prompt.push(object.clone());
} else {
// TODO: remove this once the prompt implementation is complete.
item.set_locked(locked).await?;
with_prompt.push(object.clone());
}
break;
}
tracing::warn!("Object: {} does not exist.", object);
}
}

Ok((without_prompt, with_prompt))
}
}
15 changes: 14 additions & 1 deletion server/src/service_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::{collections::HashMap, sync::Arc};

use tokio::sync::RwLock;
use zbus::zvariant::OwnedObjectPath;
use zbus::zvariant::{ObjectPath, OwnedObjectPath};

use crate::session::Session;

Expand Down Expand Up @@ -40,6 +40,19 @@ impl ServiceManager {
self.sessions.remove(path);
}

pub fn signal_emitter<'a, P>(
&self,
path: P,
) -> Result<zbus::object_server::SignalEmitter<'a>, oo7::dbus::ServiceError>
where
P: TryInto<ObjectPath<'a>>,
P::Error: Into<zbus::Error>,
{
let signal_emitter = zbus::object_server::SignalEmitter::new(&self.connection, path)?;

Ok(signal_emitter)
}

pub async fn session_index(&self) -> u32 {
let n_sessions = *self.session_index.read().await + 1;
*self.session_index.write().await = n_sessions;
Expand Down

0 comments on commit b30cdba

Please sign in to comment.