From 9c87c192fa29b6b110a53d7c553654a72bb02f9d Mon Sep 17 00:00:00 2001 From: Gregor Reitzenstein Date: Wed, 27 Jan 2021 14:40:33 +0000 Subject: [PATCH] We don't use remote roles for now --- examples/roles.toml | 7 ++- schema | 2 +- src/api/machines.rs | 3 +- src/db/access.rs | 94 +++++++++++++++++++++------------------ src/db/access/internal.rs | 7 ++- 5 files changed, 62 insertions(+), 51 deletions(-) diff --git a/examples/roles.toml b/examples/roles.toml index cc61b71..2c91a30 100644 --- a/examples/roles.toml +++ b/examples/roles.toml @@ -1,18 +1,17 @@ +[anotherrole] + [testrole] -name = "Testrole" permissions = [ "lab.test.*" ] [somerole] -name = "Somerole" -parents = ["testparent%lmdb"] +parents = ["testparent/lmdb"] permissions = [ "lab.some.admin" ] [testparent] -name = "Testparent" permissions = [ "lab.some.write", "lab.some.read", diff --git a/schema b/schema index 83cd61e..4adb053 160000 --- a/schema +++ b/schema @@ -1 +1 @@ -Subproject commit 83cd61e299230f33474e2efa950667d1acfbe085 +Subproject commit 4adb05341763b96a43440a6a96e0d9959ba71e89 diff --git a/src/api/machines.rs b/src/api/machines.rs index 86f3389..602e194 100644 --- a/src/api/machines.rs +++ b/src/api/machines.rs @@ -42,7 +42,8 @@ impl machines::Server for Machines { let res = results.get(); let mut machines = res.init_machines(v.len() as u32); - for (i, (_name, machine)) in v.into_iter().enumerate() { + for (i, (name, machine)) in v.into_iter().enumerate() { + debug!(self.session.log, "Adding machine {}: {:?}", name, machine); let machine = Arc::new(Machine::new(self.session.clone(), machine, self.db.clone())); let mut builder = machines.reborrow().get(i as u32); Machine::fill(machine, &mut builder); diff --git a/src/db/access.rs b/src/db/access.rs index c34bd90..a47be69 100644 --- a/src/db/access.rs +++ b/src/db/access.rs @@ -50,6 +50,10 @@ impl AccessControl { pub fn dump_roles(&self) -> Result> { self.internal.dump_roles() } + + pub fn get_role(&self, role_id: &RoleIdentifier) -> Result> { + self.internal.get_role(role_id) + } } impl fmt::Debug for AccessControl { @@ -162,37 +166,24 @@ type SourceID = String; fn split_once(s: &str, split: char) -> Option<(&str, &str)> { s .find(split) - .map(|idx| s.split_at(idx)) + .map(|idx| (&s[..idx], &s[(idx+1)..])) } #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(try_from = "String")] +#[serde(into = "String")] /// Universal (relative) id of a role -pub enum RoleIdentifier { - /// The role comes from this instance - Local { - /// Locally unique name for the role. No other role at this instance no matter the source - /// may have the same name - name: String, - /// Role Source, i.e. the database the role comes from - source: SourceID, - }, - /// The role comes from a federated instance - Remote { - /// Name of the role. This role is unique in that instance so the tuple (name, location) - /// refers to a unique role - name: String, - /// The federated instance this role comes from - location: String, - } +pub struct RoleIdentifier { + /// Locally unique name for the role. No other role at this instance no matter the source + /// may have the same name + name: String, + /// Role Source, i.e. the database the role comes from + source: SourceID, } impl fmt::Display for RoleIdentifier { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - RoleIdentifier::Local {name, source} => write!(f, "{}/{}@local", name, source), - RoleIdentifier::Remote {name, location} => write!(f, "{}@{}", name, location), - } + write!(f, "{}/{}", self.name, self.source) } } @@ -200,10 +191,8 @@ impl std::str::FromStr for RoleIdentifier { type Err = RoleFromStrError; fn from_str(s: &str) -> std::result::Result { - if let Some((name, location)) = split_once(s, '@') { - Ok(RoleIdentifier::Remote { name: name.to_string(), location: location.to_string() }) - } else if let Some((name, source)) = split_once(s, '%') { - Ok(RoleIdentifier::Local { name: name.to_string(), source: source.to_string() }) + if let Some((name, source)) = split_once(s, '/') { + Ok(RoleIdentifier { name: name.to_string(), source: source.to_string() }) } else { Err(RoleFromStrError::Invalid) } @@ -214,21 +203,18 @@ impl TryFrom for RoleIdentifier { type Error = RoleFromStrError; fn try_from(s: String) -> std::result::Result { - if let Some((name, location)) = split_once(&s, '@') { - let location = &location[1..]; - Ok(RoleIdentifier::Remote { name: name.to_string(), location: location.to_string() }) - } else if let Some((name, source)) = split_once(&s, '%') { - let source = &source[1..]; - Ok(RoleIdentifier::Local { name: name.to_string(), source: source.to_string() }) - } else { - Err(RoleFromStrError::Invalid) - } + ::from_str(&s) + } +} +impl Into for RoleIdentifier { + fn into(self) -> String { + format!("{}", self) } } impl RoleIdentifier { pub fn local_from_str(source: String, name: String) -> Self { - RoleIdentifier::Local { name, source } + RoleIdentifier { name, source } } } @@ -505,7 +491,7 @@ impl TryFrom for PermRule { } } -#[cfg(test_DISABLED)] +#[cfg(test)] mod tests { use super::*; @@ -532,23 +518,46 @@ mod tests { assert!(rule.match_perm(&perm)); } + #[test] + fn format_and_read_compatible() { + use std::convert::TryInto; + + let testdata = vec![ + ("testrole", "testsource"), + ("", "norole"), + ("nosource", "") + ].into_iter().map(|(n,s)| (n.to_string(), s.to_string())); + + for (name, source) in testdata { + let role = RoleIdentifier { name, source }; + + let fmt_string = format!("{}", &role); + + println!("{:?} is formatted: {}", &role, &fmt_string); + + let parsed: RoleIdentifier = fmt_string.try_into().unwrap(); + + println!("Which parses into {:?}", &parsed); + + assert_eq!(role, parsed); + } + } + #[test] fn load_examples_roles_test() { let mut roles = Role::load_file("examples/roles.toml") .expect("Couldn't load the example role defs. Does `examples/roles.toml` exist?"); let expected = vec![ - (RoleIdentifier::Local { name: "testrole".to_string(), source: "lmdb".to_string() }, + (RoleIdentifier { name: "testrole".to_string(), source: "lmdb".to_string() }, Role { - name: "Testrole".to_string(), parents: vec![], permissions: vec![ PermRule::Subtree(PermissionBuf::from_string("lab.test".to_string())) ], }), - (RoleIdentifier::Local { name: "somerole".to_string(), source: "lmdb".to_string() }, + (RoleIdentifier { name: "somerole".to_string(), source: "lmdb".to_string() }, Role { - name: "Somerole".to_string(), parents: vec![ RoleIdentifier::local_from_str("lmdb".to_string(), "testparent".to_string()), ], @@ -556,9 +565,8 @@ mod tests { PermRule::Base(PermissionBuf::from_string("lab.some.admin".to_string())) ], }), - (RoleIdentifier::Local { name: "testparent".to_string(), source: "lmdb".to_string() }, + (RoleIdentifier { name: "testparent".to_string(), source: "lmdb".to_string() }, Role { - name: "Testparent".to_string(), parents: vec![], permissions: vec![ PermRule::Base(PermissionBuf::from_string("lab.some.write".to_string())), diff --git a/src/db/access/internal.rs b/src/db/access/internal.rs index 1f8213b..f149c3f 100644 --- a/src/db/access/internal.rs +++ b/src/db/access/internal.rs @@ -77,6 +77,7 @@ impl Internal { pub fn _get_role<'txn, T: Transaction>(&self, txn: &'txn T, role_id: &RoleIdentifier) -> Result> { let string = format!("{}", role_id); + debug!(self.log, "Reading role '{}'", &string); match txn.get(self.roledb, &string.as_bytes()) { Ok(bytes) => { Ok(Some(flexbuffers::from_slice(bytes)?)) @@ -108,8 +109,10 @@ impl Internal { Ok( (k,v) ) => { let role_id_str = unsafe { std::str::from_utf8_unchecked(k) }; let role_id = role_id_str.parse::().unwrap(); - let role = flexbuffers::from_slice(v)?; - vec.push((role_id, role)); + match flexbuffers::from_slice(v) { + Ok(role) => vec.push((role_id, role)), + Err(e) => error!(self.log, "Bad format for roleid {}: {}", role_id, e), + } }, Err(e) => return Err(e.into()), }