fabaccess-bffh/src/db/user.rs

80 lines
2.4 KiB
Rust
Raw Normal View History

2020-10-26 12:58:55 +01:00
use serde::{Serialize, Deserialize};
use std::fmt;
use crate::db::access::RoleIdentifier;
2020-10-28 16:25:33 +01:00
use std::collections::HashMap;
2020-10-26 12:58:55 +01:00
/// A Person, from the Authorization perspective
2020-10-28 16:25:33 +01:00
#[derive(Debug, Clone, Serialize, Deserialize)]
2020-10-26 12:58:55 +01:00
pub struct User {
2020-10-28 16:25:33 +01:00
/// The identification of this user.
pub id: UserIdentifier,
2020-10-26 12:58:55 +01:00
/// A Person has N ≥ 0 roles.
/// Persons are only ever given roles, not permissions directly
2020-10-28 16:25:33 +01:00
pub roles: Vec<RoleIdentifier>,
/// Additional data storage
#[serde(flatten)]
kv: HashMap<Box<[u8]>, Box<[u8]>>,
2020-10-26 12:58:55 +01:00
}
/// Locally unique identifier for an user
2020-10-28 23:24:02 +01:00
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
2020-10-26 12:58:55 +01:00
pub struct UserIdentifier {
/// Main UID. Must be unique in this instance so that the tuple (uid, location) is globally
/// unique.
uid: String,
/// Subordinate ID. Must be unique for this user, i.e. the tuple (uid, subuid) must be unique
/// but two different uids can have the same subuid. `None` means no subuid is set and the ID
/// refers to the main users
subuid: Option<String>,
/// Location of the instance the user comes from. `None` means the local instance.
location: Option<String>,
}
impl UserIdentifier {
pub fn new(uid: String, subuid: Option<String>, location: Option<String>) -> Self {
Self { uid, subuid, location }
}
}
impl fmt::Display for UserIdentifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let r = write!(f, "{}", self.uid);
2020-10-28 23:24:02 +01:00
if let Some(ref s) = self.subuid {
2020-10-26 12:58:55 +01:00
write!(f, "+{}", s)?;
}
2020-10-28 23:24:02 +01:00
if let Some(ref l) = self.location {
2020-10-26 12:58:55 +01:00
write!(f, "@{}", l)?;
}
r
}
}
/// User Database Trait
pub trait UserDB {
fn get_user(&self, uid: UserIdentifier) -> Option<User>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn format_uid_test() {
2020-10-28 16:25:33 +01:00
let uid = "testuser".to_string();
let suid = "testsuid".to_string();
let location = "testloc".to_string();
assert_eq!("testuser",
format!("{}", UserIdentifier::new(uid, None, None)));
assert_eq!("testuser+testsuid",
2020-10-28 23:24:02 +01:00
format!("{}", UserIdentifier::new(uid, Some(suid), None)));
2020-10-28 16:25:33 +01:00
assert_eq!("testuser+testsuid",
2020-10-28 23:24:02 +01:00
format!("{}", UserIdentifier::new(uid, Some(suid), None)));
2020-10-28 16:25:33 +01:00
assert_eq!("testuser+testsuid@testloc",
2020-10-28 23:24:02 +01:00
format!("{}", UserIdentifier::new(uid, Some(suid), Some(location))));
2020-10-26 12:58:55 +01:00
}
}