Skip to content
This repository has been archived by the owner on Dec 18, 2024. It is now read-only.

Commit

Permalink
[databroker] Fix permissions bug. (#655)
Browse files Browse the repository at this point in the history
Fix permissions bug inadvertently introduced when adding
`iter_entries()`.
  • Loading branch information
argerus authored Sep 14, 2023
1 parent bb81698 commit ab6ac64
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 13 deletions.
69 changes: 58 additions & 11 deletions kuksa_databroker/databroker/src/broker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub enum UpdateError {
PermissionExpired,
}

#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum ReadError {
NotFound,
PermissionDenied,
Expand Down Expand Up @@ -850,16 +850,59 @@ pub struct DatabaseWriteAccess<'a, 'b> {
permissions: &'b Permissions,
}

pub struct EntryIterator<'a> {
pub enum EntryReadAccess<'a> {
Entry(&'a Entry),
Err(&'a Metadata, ReadError),
}

impl<'a> EntryReadAccess<'a> {
pub fn datapoint(&self) -> Result<&Datapoint, ReadError> {
match self {
Self::Entry(entry) => Ok(&entry.datapoint),
Self::Err(_, err) => Err(err.clone()),
}
}

pub fn actuator_target(&self) -> Result<&Option<Datapoint>, ReadError> {
match self {
Self::Entry(entry) => Ok(&entry.actuator_target),
Self::Err(_, err) => Err(err.clone()),
}
}

pub fn metadata(&self) -> &Metadata {
match self {
Self::Entry(entry) => &entry.metadata,
Self::Err(metadata, _) => metadata,
}
}
}

impl<'a> EntryReadAccess<'a> {
fn new(entry: &'a Entry, permissions: &Permissions) -> Self {
match permissions.can_read(&entry.metadata.path) {
Ok(()) => Self::Entry(entry),
Err(PermissionError::Denied) => Self::Err(&entry.metadata, ReadError::PermissionDenied),
Err(PermissionError::Expired) => {
Self::Err(&entry.metadata, ReadError::PermissionExpired)
}
}
}
}

pub struct EntryReadIterator<'a, 'b> {
inner: std::collections::hash_map::Values<'a, i32, Entry>,
permissions: &'b Permissions,
}

impl<'a> Iterator for EntryIterator<'a> {
type Item = &'a Entry;
impl<'a, 'b> Iterator for EntryReadIterator<'a, 'b> {
type Item = EntryReadAccess<'a>;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
self.inner
.next()
.map(|entry| EntryReadAccess::new(entry, self.permissions))
}

#[inline]
Expand Down Expand Up @@ -910,9 +953,10 @@ impl<'a, 'b> DatabaseReadAccess<'a, 'b> {
self.get_metadata_by_id(*id)
}

pub fn iter_entries(&self) -> EntryIterator {
EntryIterator {
pub fn iter_entries(&self) -> EntryReadIterator {
EntryReadIterator {
inner: self.db.entries.values(),
permissions: self.permissions,
}
}
}
Expand Down Expand Up @@ -1206,7 +1250,7 @@ impl<'a, 'b> AuthorizedAccess<'a, 'b> {
.cloned()
}

pub async fn for_each_entry(&self, f: impl FnMut(&Entry)) {
pub async fn for_each_entry(&self, f: impl FnMut(EntryReadAccess)) {
self.broker
.database
.read()
Expand All @@ -1216,7 +1260,7 @@ impl<'a, 'b> AuthorizedAccess<'a, 'b> {
.for_each(f)
}

pub async fn map_entries<T>(&self, f: impl FnMut(&Entry) -> T) -> Vec<T> {
pub async fn map_entries<T>(&self, f: impl FnMut(EntryReadAccess) -> T) -> Vec<T> {
self.broker
.database
.read()
Expand All @@ -1227,7 +1271,10 @@ impl<'a, 'b> AuthorizedAccess<'a, 'b> {
.collect()
}

pub async fn filter_map_entries<T>(&self, f: impl FnMut(&Entry) -> Option<T>) -> Vec<T> {
pub async fn filter_map_entries<T>(
&self,
f: impl FnMut(EntryReadAccess) -> Option<T>,
) -> Vec<T> {
self.broker
.database
.read()
Expand Down Expand Up @@ -2880,7 +2927,7 @@ mod tests {
// No permissions
let permissions = Permissions::builder().build().unwrap();
let broker = db.authorized_access(&permissions);
let metadata = broker.map_entries(|entry| entry.metadata.clone()).await;
let metadata = broker.map_entries(|entry| entry.metadata().clone()).await;
for entry in metadata {
match entry.path.as_str() {
"Vehicle.Test1" => assert_eq!(entry.id, id1),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl proto::broker_server::Broker for broker::DataBroker {

let list = if request.names.is_empty() {
broker
.map_entries(|entry| proto::Metadata::from(&entry.metadata))
.map_entries(|entry| proto::Metadata::from(entry.metadata()))
.await
} else {
broker
Expand Down
2 changes: 1 addition & 1 deletion kuksa_databroker/databroker/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
Arg::new("dummy-metadata")
.display_order(10)
.long("dummy-metadata")
.action(ArgAction::Set)
.action(ArgAction::SetTrue)
.help("Populate data broker with dummy metadata")
.required(false),
);
Expand Down

0 comments on commit ab6ac64

Please sign in to comment.