mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-25 16:17:56 +01:00
Make compile
This commit is contained in:
parent
d304ff40d4
commit
2027d9696e
128
src/db/access.rs
128
src/db/access.rs
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
@ -22,18 +23,19 @@ use crate::error::Result;
|
|||||||
|
|
||||||
mod adapter_lmdb;
|
mod adapter_lmdb;
|
||||||
|
|
||||||
|
use crate::db::user::User;
|
||||||
use adapter_lmdb::PermissionsDB;
|
use adapter_lmdb::PermissionsDB;
|
||||||
pub use adapter_lmdb::init;
|
pub use adapter_lmdb::init;
|
||||||
|
|
||||||
pub trait RoleDB {
|
pub trait RoleDB {
|
||||||
fn get_role(&self, roleID: RoleIdentifier) -> Result<Option<Role>>;
|
fn get_role(&self, roleID: &RoleIdentifier) -> Result<Option<Role>>;
|
||||||
|
|
||||||
/// Check if a given user has the given permission
|
/// Check if a given user has the given permission
|
||||||
///
|
///
|
||||||
/// Default implementation which adapter may overwrite with more efficient specialized
|
/// Default implementation which adapter may overwrite with more efficient specialized
|
||||||
/// implementations.
|
/// implementations.
|
||||||
fn check(&self, user: &User, permID: PermIdentifier) -> Result<bool> {
|
fn check(&self, user: &User, permID: &PermIdentifier) -> Result<bool> {
|
||||||
self.check_roles(user.roles)
|
self.check_roles(&user.roles, permID)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a given permission is granted by any of the given roles or their respective
|
/// Check if a given permission is granted by any of the given roles or their respective
|
||||||
@ -41,18 +43,17 @@ pub trait RoleDB {
|
|||||||
///
|
///
|
||||||
/// Default implementation which adapter may overwrite with more efficient specialized
|
/// Default implementation which adapter may overwrite with more efficient specialized
|
||||||
/// implementations.
|
/// implementations.
|
||||||
fn check_roles(&self, roles: &[RoleIdentifier], permID: PermIdentifier) -> Result<bool> {
|
fn check_roles(&self, roles: &[RoleIdentifier], permID: &PermIdentifier) -> Result<bool> {
|
||||||
// Tally all roles. Makes dependent roles easier
|
// Tally all roles. Makes dependent roles easier
|
||||||
let mut roles = HashSet::new();
|
let mut roleset = HashSet::new();
|
||||||
for roleID in roles {
|
for roleID in roles {
|
||||||
self.tally_role(txn, &mut roles, roleID)?;
|
self.tally_role(&mut roleset, roleID)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iter all unique role->permissions we've found and early return on match.
|
// Iter all unique role->permissions we've found and early return on match.
|
||||||
// TODO: Change this for negative permissions?
|
for role in roleset.iter() {
|
||||||
for role in roles.iter() {
|
|
||||||
for perm in role.permissions.iter() {
|
for perm in role.permissions.iter() {
|
||||||
if permID == *perm {
|
if permID == perm {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,13 +65,13 @@ pub trait RoleDB {
|
|||||||
/// Tally a role dependency tree into a set
|
/// Tally a role dependency tree into a set
|
||||||
///
|
///
|
||||||
/// Default implementation which adapter may overwrite with more efficient implementations
|
/// Default implementation which adapter may overwrite with more efficient implementations
|
||||||
fn tally_role(&self, roles: &mut HashSet<Role>, roleID: RoleIdentifier) -> Result<()> {
|
fn tally_role(&self, roles: &mut HashSet<Role>, roleID: &RoleIdentifier) -> Result<()> {
|
||||||
if let Some(role) = self.get_role(txn, roleID)? {
|
if let Some(role) = self.get_role(roleID)? {
|
||||||
// Only check and tally parents of a role at the role itself if it's the first time we
|
// Only check and tally parents of a role at the role itself if it's the first time we
|
||||||
// see it
|
// see it
|
||||||
if !roles.contains(&role) {
|
if !roles.contains(&role) {
|
||||||
for parent in role.parents.iter() {
|
for parent in role.parents.iter() {
|
||||||
self.tally_role(txn, roles, *parent)?;
|
self.tally_role(roles, parent)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
roles.insert(role);
|
roles.insert(role);
|
||||||
@ -108,8 +109,15 @@ pub struct Role {
|
|||||||
|
|
||||||
type SourceID = String;
|
type SourceID = String;
|
||||||
|
|
||||||
|
fn split_once(s: &str, split: char) -> Option<(&str, &str)> {
|
||||||
|
s
|
||||||
|
.find(split)
|
||||||
|
.map(|idx| s.split_at(idx))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
/// Universal (relative) id of a role
|
/// Universal (relative) id of a role
|
||||||
enum RoleIdentifier {
|
pub enum RoleIdentifier {
|
||||||
/// The role comes from this instance
|
/// The role comes from this instance
|
||||||
Local {
|
Local {
|
||||||
/// Locally unique name for the role. No other role at this instance no matter the source
|
/// Locally unique name for the role. No other role at this instance no matter the source
|
||||||
@ -127,16 +135,35 @@ enum RoleIdentifier {
|
|||||||
location: String,
|
location: String,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl fmt::Display for RoleID {
|
impl std::str::FromStr for RoleIdentifier {
|
||||||
|
type Err = RoleFromStrError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||||
|
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() })
|
||||||
|
} else {
|
||||||
|
Err(RoleFromStrError::Invalid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Display for RoleIdentifier {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match self {
|
||||||
RoleIdentifier::Local {name, source} => write!(f, "{}/{}@local", name, source),
|
RoleIdentifier::Local {name, source} => write!(f, "{}/{}@local", name, source),
|
||||||
RoleIdentifier::Remote {name, location} => write!(f, "{}@{}", name, location),
|
RoleIdentifier::Remote {name, location} => write!(f, "{}@{}", name, location),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum RoleFromStrError {
|
||||||
|
/// No '@' or '%' found. That's strange, huh?
|
||||||
|
Invalid
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
/// An identifier for a permission
|
/// An identifier for a permission
|
||||||
// XXX: Does remote permissions ever make sense?
|
// XXX: Does remote permissions ever make sense?
|
||||||
// I mean we kinda get them for free so maybe?
|
// I mean we kinda get them for free so maybe?
|
||||||
@ -146,7 +173,7 @@ pub enum PermIdentifier {
|
|||||||
}
|
}
|
||||||
impl fmt::Display for PermIdentifier {
|
impl fmt::Display for PermIdentifier {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match self {
|
||||||
PermIdentifier::Local(perm)
|
PermIdentifier::Local(perm)
|
||||||
=> write!(f, "{}", perm),
|
=> write!(f, "{}", perm),
|
||||||
PermIdentifier::Remote(perm, source)
|
PermIdentifier::Remote(perm, source)
|
||||||
@ -155,7 +182,11 @@ impl fmt::Display for PermIdentifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
fn is_sep_char(c: char) -> bool {
|
||||||
|
c == '.'
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
/// An owned permission string
|
/// An owned permission string
|
||||||
///
|
///
|
||||||
@ -173,13 +204,13 @@ impl PermissionBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Allocate a `PermissionBuf` with the given capacity given to the internal [`String`]
|
/// Allocate a `PermissionBuf` with the given capacity given to the internal [`String`]
|
||||||
pub fn with_capacity() -> Self {
|
pub fn with_capacity(cap: usize) -> Self {
|
||||||
PermissionBuf { inner: String::with_capacity() }
|
PermissionBuf { inner: String::with_capacity(cap) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn as_permission(&self) -> &Permission {
|
pub fn as_permission(&self) -> &Permission {
|
||||||
self
|
self.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push<P: AsRef<Permission>>(&mut self, perm: P) {
|
pub fn push<P: AsRef<Permission>>(&mut self, perm: P) {
|
||||||
@ -192,22 +223,39 @@ impl PermissionBuf {
|
|||||||
if need_sep {
|
if need_sep {
|
||||||
self.inner.push('.')
|
self.inner.push('.')
|
||||||
}
|
}
|
||||||
self.inner.push(perm.as_str())
|
self.inner.push_str(perm.as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_string(inner: String) -> Self {
|
pub fn from_string(inner: String) -> Self {
|
||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl AsRef<Permission> for PermissionBuf {
|
impl AsRef<str> for PermissionBuf {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
&self.inner[..]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl AsRef<Permission> for PermissionBuf {
|
||||||
|
#[inline]
|
||||||
fn as_ref(&self) -> &Permission {
|
fn as_ref(&self) -> &Permission {
|
||||||
self.as_permission()
|
Permission::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialOrd for PermissionBuf {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
let a: &Permission = self.as_ref();
|
||||||
|
a.partial_cmp(other.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl fmt::Display for PermissionBuf {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.inner.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(PartialEq, Eq)]
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
/// A borrowed permission string
|
/// A borrowed permission string
|
||||||
///
|
///
|
||||||
/// Permissions have total equality and partial ordering.
|
/// Permissions have total equality and partial ordering.
|
||||||
@ -218,21 +266,27 @@ pub struct Permission {
|
|||||||
inner: str
|
inner: str
|
||||||
}
|
}
|
||||||
impl Permission {
|
impl Permission {
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn new<S: AsRef<str> + ?Sized>(s: &S) -> &Permission {
|
||||||
self.inner
|
unsafe { &*(s.as_ref() as *const str as *const Permission) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> std::str::Split<Char> {
|
pub fn as_str(&self) -> &str {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> std::str::Split<char> {
|
||||||
self.inner.split('.')
|
self.inner.split('.')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Permission {
|
impl PartialOrd for Permission {
|
||||||
fn partial_cmp(&self, other: &Permission) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Permission) -> Option<Ordering> {
|
||||||
let (l,r) = (None, None);
|
let mut i = self.iter();
|
||||||
|
let mut j = other.iter();
|
||||||
|
let (mut l, mut r) = (None, None);
|
||||||
while {
|
while {
|
||||||
l = self.next();
|
l = i.next();
|
||||||
r = other.next();
|
r = j.next();
|
||||||
|
|
||||||
l.is_some() && r.is_some()
|
l.is_some() && r.is_some()
|
||||||
} {
|
} {
|
||||||
@ -243,7 +297,7 @@ impl PartialOrd for Permission {
|
|||||||
|
|
||||||
match (l,r) {
|
match (l,r) {
|
||||||
(None, None) => Some(Ordering::Equal),
|
(None, None) => Some(Ordering::Equal),
|
||||||
(Some(_), None) => Some(Ordering::Lesser),
|
(Some(_), None) => Some(Ordering::Less),
|
||||||
(None, Some(_)) => Some(Ordering::Greater),
|
(None, Some(_)) => Some(Ordering::Greater),
|
||||||
(Some(_), Some(_)) => panic!("Broken contract in Permission::partial_cmp: sides should never be both Some!"),
|
(Some(_), Some(_)) => panic!("Broken contract in Permission::partial_cmp: sides should never be both Some!"),
|
||||||
}
|
}
|
||||||
@ -251,7 +305,7 @@ impl PartialOrd for Permission {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
pub enum PermRule {
|
pub enum PermRule {
|
||||||
/// The permission is precise,
|
/// The permission is precise,
|
||||||
///
|
///
|
||||||
@ -277,16 +331,16 @@ impl PermRule {
|
|||||||
// Does this rule match that permission
|
// Does this rule match that permission
|
||||||
fn match_perm<P: AsRef<Permission>>(rule: &PermRule, perm: P) -> bool {
|
fn match_perm<P: AsRef<Permission>>(rule: &PermRule, perm: P) -> bool {
|
||||||
match rule {
|
match rule {
|
||||||
Base(base) => base == perm,
|
PermRule::Base(base) => base.as_permission() == perm.as_ref(),
|
||||||
Children(parent) => parent > perm ,
|
PermRule::Children(parent) => parent.as_permission() > perm.as_ref() ,
|
||||||
Subtree(parent) => parent >= perm,
|
PermRule::Subtree(parent) => parent.as_permission() >= perm.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PermRule {
|
impl fmt::Display for PermRule {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match self {
|
||||||
PermRule::Base(perm)
|
PermRule::Base(perm)
|
||||||
=> write!(f, "{}", perm),
|
=> write!(f, "{}", perm),
|
||||||
PermRule::Children(parent)
|
PermRule::Children(parent)
|
||||||
|
@ -34,21 +34,19 @@ impl PermissionsDB {
|
|||||||
|
|
||||||
/// Check if a given user has the given permission
|
/// Check if a given user has the given permission
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn _check<T: Transaction>(&self, txn: &T, userID: UserIdentifier, permID: PermIdentifier) -> Result<bool> {
|
pub fn _check<T: Transaction>(&self, txn: &T, user: &User, permID: &PermIdentifier) -> Result<bool> {
|
||||||
if let Some(user) = self.get_user(txn, userID)? {
|
// Tally all roles. Makes dependent roles easier
|
||||||
// Tally all roles. Makes dependent roles easier
|
let mut roles = HashSet::new();
|
||||||
let mut roles = HashSet::new();
|
for roleID in user.roles.iter() {
|
||||||
for roleID in user.roles {
|
self._tally_role(txn, &mut roles, roleID)?;
|
||||||
self.tally_role(txn, &mut roles, roleID)?;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Iter all unique role->permissions we've found and early return on match.
|
// Iter all unique role->permissions we've found and early return on match.
|
||||||
// TODO: Change this for negative permissions?
|
// TODO: Change this for negative permissions?
|
||||||
for role in roles.iter() {
|
for role in roles.iter() {
|
||||||
for perm in role.permissions.iter() {
|
for perm in role.permissions.iter() {
|
||||||
if permID == *perm {
|
if permID == perm {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,13 +54,13 @@ impl PermissionsDB {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tally_role<T: Transaction>(&self, txn: &T, roles: &mut HashSet<Role>, roleID: RoleIdentifier) -> Result<()> {
|
fn _tally_role<T: Transaction>(&self, txn: &T, roles: &mut HashSet<Role>, roleID: &RoleIdentifier) -> Result<()> {
|
||||||
if let Some(role) = self.get_role(txn, roleID)? {
|
if let Some(role) = self._get_role(txn, roleID)? {
|
||||||
// Only check and tally parents of a role at the role itself if it's the first time we
|
// Only check and tally parents of a role at the role itself if it's the first time we
|
||||||
// see it
|
// see it
|
||||||
if !roles.contains(&role) {
|
if !roles.contains(&role) {
|
||||||
for parent in role.parents.iter() {
|
for parent in role.parents.iter() {
|
||||||
self.tally_role(txn, roles, *parent)?;
|
self._tally_role(txn, roles, parent)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
roles.insert(role);
|
roles.insert(role);
|
||||||
@ -72,8 +70,9 @@ impl PermissionsDB {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _get_role<'txn, T: Transaction>(&self, txn: &'txn T, roleID: RoleIdentifier) -> Result<Option<Role>> {
|
pub fn _get_role<'txn, T: Transaction>(&self, txn: &'txn T, roleID: &RoleIdentifier) -> Result<Option<Role>> {
|
||||||
match txn.get(self.roledb, &roleID.to_ne_bytes()) {
|
let string = format!("{}", roleID);
|
||||||
|
match txn.get(self.roledb, &string.as_bytes()) {
|
||||||
Ok(bytes) => {
|
Ok(bytes) => {
|
||||||
Ok(Some(flexbuffers::from_slice(bytes)?))
|
Ok(Some(flexbuffers::from_slice(bytes)?))
|
||||||
},
|
},
|
||||||
@ -82,9 +81,10 @@ impl PermissionsDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_role(&self, txn: &mut RwTransaction, roleID: RoleIdentifier, role: Role) -> Result<()> {
|
fn put_role(&self, txn: &mut RwTransaction, roleID: &RoleIdentifier, role: Role) -> Result<()> {
|
||||||
let bytes = flexbuffers::to_vec(role)?;
|
let bytes = flexbuffers::to_vec(role)?;
|
||||||
txn.put(self.roledb, &roleID.to_ne_bytes(), &bytes, lmdb::WriteFlags::empty())?;
|
let string = format!("{}", roleID);
|
||||||
|
txn.put(self.roledb, &string.as_bytes(), &bytes, lmdb::WriteFlags::empty())?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -164,10 +164,10 @@ impl PermissionsDB {
|
|||||||
let roleID_str = path
|
let roleID_str = path
|
||||||
.file_stem().expect("Found a file with no filename?")
|
.file_stem().expect("Found a file with no filename?")
|
||||||
.to_str().expect("Found an OsStr that isn't valid Unicode. Fix your OS!");
|
.to_str().expect("Found an OsStr that isn't valid Unicode. Fix your OS!");
|
||||||
let roleID = match u64::from_str_radix(roleID_str, 16) {
|
let roleID = match str::parse(roleID_str) {
|
||||||
Ok(i) => i,
|
Ok(i) => i,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(self.log, "File {} had a invalid name. Expected an u64 in [0-9a-z] hex with optional file ending: {}. Skipping!", path.display(), e);
|
warn!(self.log, "File {} had a invalid name.", path.display());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -189,8 +189,8 @@ impl PermissionsDB {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.put_role(txn, roleID, role)?;
|
self.put_role(txn, &roleID, role)?;
|
||||||
debug!(self.log, "Loaded role {}", roleID);
|
debug!(self.log, "Loaded role {}", &roleID);
|
||||||
} else {
|
} else {
|
||||||
warn!(self.log, "Path {} is not a file, skipping!", path.display());
|
warn!(self.log, "Path {} is not a file, skipping!", path.display());
|
||||||
}
|
}
|
||||||
@ -201,21 +201,28 @@ impl PermissionsDB {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RoleDB for PermissionsDB {
|
impl RoleDB for PermissionsDB {
|
||||||
fn check(&self, userID: UserIdentifier, permID: PermIdentifier) -> Result<bool> {
|
fn check(&self, user: &User, permID: &PermIdentifier) -> Result<bool> {
|
||||||
let txn = self.env.begin_ro_txn()?;
|
let txn = self.env.begin_ro_txn()?;
|
||||||
self._check(&txn, userID, permID)
|
self._check(&txn, user, permID)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_role(&self, roleID: RoleIdentifier) -> Result<Option<Role>> {
|
fn get_role(&self, roleID: &RoleIdentifier) -> Result<Option<Role>> {
|
||||||
let txn = self.env.begin_ro_txn()?;
|
let txn = self.env.begin_ro_txn()?;
|
||||||
self._get_role(&txn, roleID)
|
self._get_role(&txn, roleID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tally_role(&self, roles: &mut HashSet<Role>, roleID: &RoleIdentifier) -> Result<()> {
|
||||||
|
let txn = self.env.begin_ro_txn()?;
|
||||||
|
self._tally_role(&txn, roles, roleID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Initialize the access db by loading all the lmdb databases
|
/// Initialize the access db by loading all the lmdb databases
|
||||||
pub fn init(log: Logger, config: &Settings, env: Arc<lmdb::Environment>) -> std::result::Result<Permissions, crate::error::Error> {
|
pub fn init(log: Logger, config: &Settings, env: Arc<lmdb::Environment>)
|
||||||
|
-> std::result::Result<PermissionsDB, crate::error::Error>
|
||||||
|
{
|
||||||
let mut flags = lmdb::DatabaseFlags::empty();
|
let mut flags = lmdb::DatabaseFlags::empty();
|
||||||
flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true);
|
flags.set(lmdb::DatabaseFlags::INTEGER_KEY, true);
|
||||||
let roledb = env.create_db(Some("role"), flags)?;
|
let roledb = env.create_db(Some("role"), flags)?;
|
||||||
|
@ -16,6 +16,8 @@ use crate::error::Result;
|
|||||||
use crate::config::Settings;
|
use crate::config::Settings;
|
||||||
use crate::access;
|
use crate::access;
|
||||||
|
|
||||||
|
use crate::db::user::UserIdentifier;
|
||||||
|
|
||||||
use capnp::Error;
|
use capnp::Error;
|
||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@ -27,6 +29,7 @@ use smol::channel::{Receiver, Sender};
|
|||||||
use futures_signals::signal::*;
|
use futures_signals::signal::*;
|
||||||
|
|
||||||
use crate::registries::StatusSignal;
|
use crate::registries::StatusSignal;
|
||||||
|
use crate::db::user::User;
|
||||||
|
|
||||||
pub type ID = Uuid;
|
pub type ID = Uuid;
|
||||||
|
|
||||||
@ -139,14 +142,13 @@ impl Machine {
|
|||||||
/// Requests to use a machine. Returns `true` if successful.
|
/// Requests to use a machine. Returns `true` if successful.
|
||||||
///
|
///
|
||||||
/// This will update the internal state of the machine, notifying connected actors, if any.
|
/// This will update the internal state of the machine, notifying connected actors, if any.
|
||||||
pub fn request_use<T: Transaction>
|
pub fn request_use<P: access::RoleDB>
|
||||||
( &mut self
|
( &mut self
|
||||||
, txn: &T
|
, pp: &P
|
||||||
, pp: &access::PermissionsDB
|
, who: &User
|
||||||
, who: access::UserIdentifier
|
|
||||||
) -> Result<bool>
|
) -> Result<bool>
|
||||||
{
|
{
|
||||||
if pp.check(txn, who, self.perm)? {
|
if pp.check(who, &self.perm)? {
|
||||||
self.state.set(Status::Occupied);
|
self.state.set(Status::Occupied);
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -20,7 +20,7 @@ pub struct User {
|
|||||||
|
|
||||||
|
|
||||||
/// Locally unique identifier for an user
|
/// Locally unique identifier for an user
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
pub struct UserIdentifier {
|
pub struct UserIdentifier {
|
||||||
/// Main UID. Must be unique in this instance so that the tuple (uid, location) is globally
|
/// Main UID. Must be unique in this instance so that the tuple (uid, location) is globally
|
||||||
/// unique.
|
/// unique.
|
||||||
@ -42,10 +42,10 @@ impl UserIdentifier {
|
|||||||
impl fmt::Display for UserIdentifier {
|
impl fmt::Display for UserIdentifier {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let r = write!(f, "{}", self.uid);
|
let r = write!(f, "{}", self.uid);
|
||||||
if let Some(s) = self.subuid {
|
if let Some(ref s) = self.subuid {
|
||||||
write!(f, "+{}", s)?;
|
write!(f, "+{}", s)?;
|
||||||
}
|
}
|
||||||
if let Some(l) = self.location {
|
if let Some(ref l) = self.location {
|
||||||
write!(f, "@{}", l)?;
|
write!(f, "@{}", l)?;
|
||||||
}
|
}
|
||||||
r
|
r
|
||||||
@ -70,10 +70,10 @@ mod tests {
|
|||||||
assert_eq!("testuser",
|
assert_eq!("testuser",
|
||||||
format!("{}", UserIdentifier::new(uid, None, None)));
|
format!("{}", UserIdentifier::new(uid, None, None)));
|
||||||
assert_eq!("testuser+testsuid",
|
assert_eq!("testuser+testsuid",
|
||||||
format!(UserIdentifier::new("testuser", Some(suid), None)));
|
format!("{}", UserIdentifier::new(uid, Some(suid), None)));
|
||||||
assert_eq!("testuser+testsuid",
|
assert_eq!("testuser+testsuid",
|
||||||
format!(UserIdentifier::new("testuser", Some(suid), None)));
|
format!("{}", UserIdentifier::new(uid, Some(suid), None)));
|
||||||
assert_eq!("testuser+testsuid@testloc",
|
assert_eq!("testuser+testsuid@testloc",
|
||||||
format!(UserIdentifier::new("testuser", Some(suid), Some(location))));
|
format!("{}", UserIdentifier::new(uid, Some(suid), Some(location))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
let mut txn = env.begin_rw_txn()?;
|
let mut txn = env.begin_rw_txn()?;
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
pdb?.inner.load_db(&mut txn, path.clone())?;
|
pdb?.load_db(&mut txn, path.clone())?;
|
||||||
mdb?.load_db(&mut txn, path)?;
|
mdb?.load_db(&mut txn, path)?;
|
||||||
txn.commit();
|
txn.commit();
|
||||||
} else {
|
} else {
|
||||||
@ -181,7 +181,7 @@ fn main() -> Result<(), Error> {
|
|||||||
|
|
||||||
let txn = env.begin_ro_txn()?;
|
let txn = env.begin_ro_txn()?;
|
||||||
let path = path.to_path_buf();
|
let path = path.to_path_buf();
|
||||||
pdb?.inner.dump_db(&txn, path.clone())?;
|
pdb?.dump_db(&txn, path.clone())?;
|
||||||
mdb?.dump_db(&txn, path)?;
|
mdb?.dump_db(&txn, path)?;
|
||||||
} else {
|
} else {
|
||||||
error!(log, "You must provide a directory path to dump into");
|
error!(log, "You must provide a directory path to dump into");
|
||||||
|
@ -35,5 +35,5 @@ impl Network {
|
|||||||
enum Event {
|
enum Event {
|
||||||
/// An user wants to use a machine
|
/// An user wants to use a machine
|
||||||
// TODO: Define /what/ an user wants to do with said machine?
|
// TODO: Define /what/ an user wants to do with said machine?
|
||||||
MachineRequest(machine::ID, access::UserIdentifier),
|
MachineRequest(machine::ID, UserIdentifier),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user