libqaul_types/
users.rs

1//! Network user and session management
2//!
3//! `libqaul` is an abstraction over a distributed network of users,
4//! meaning that it is impossible to tell the underlying device
5//! configuration.  When connecting to other applications on the
6//! network, this is always done between *users*.
7
8use crate::diff::{ItemDiff, SetDiff};
9use ratman_identity::Identity;
10use serde::{Deserialize, Serialize};
11use std::collections::{BTreeMap, BTreeSet};
12
13/// A random authentication token
14pub type Token = String;
15
16/// Wrapper to encode `User` authentication state
17///
18/// This structure can be aquired by challenging an authentication
19/// endpoint, such as `User::login` to yield a token. If a session for
20/// this `Identity` already exists, it will be re-used.
21#[derive(Serialize, Deserialize, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
22pub struct UserAuth(pub Identity, pub Token);
23
24/// A complete user profile with ID and metadata
25///
26/// This abstraction is used in the Service API (see `api` module),
27/// but is important beyond the API functions, and as such is not part
28/// of the API `models` module.
29///
30/// The user profile itself makes no destinction between local, remote
31/// or self users (the latter being the currently active user in a
32/// session)
33#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
34pub struct UserProfile {
35    /// A user's network (node) ID
36    pub id: Identity,
37    /// A human readable display-name (like @foobar)
38    pub handle: Option<String>,
39    /// A human's preferred call-sign ("Friends call me foo")
40    pub display_name: Option<String>,
41    /// A key-value list of things the user deems interesting about
42    /// themselves. This could be stuff like "gender", "preferred
43    /// languages" or whatever.
44    pub bio: BTreeMap<String, String>,
45    /// The set of services this user runs (should never be empty!)
46    pub services: BTreeSet<String>,
47    /// A users profile picture (some people like selfies)
48    pub avatar: Option<Vec<u8>>,
49}
50
51impl UserProfile {
52    /// Create a new user profile for a user ID
53    pub fn new(id: Identity) -> Self {
54        Self {
55            id,
56            handle: None,
57            display_name: None,
58            bio: BTreeMap::new(),
59            services: BTreeSet::new(),
60            avatar: None,
61        }
62    }
63
64    // /// Apply the given UserUpdate to this UserUpdate in-place
65    // pub fn apply(self, update: UserUpdate) -> Self {
66    //     let mut new = self;
67    //     update.apply_to(&mut new);
68    //     new
69    // }
70
71    /// Do a contains-query on names to facilitate searching
72    ///
73    /// This means that the query string needs to be contained in it's
74    /// entirety in the display or real name strings to return a
75    /// match.
76    pub fn contains_query(&self, query: &str) -> bool {
77        (match &self.display_name {
78            None => false,
79            Some(v) => v.contains(query),
80        }) || (match &self.display_name {
81            None => false,
82            Some(v) => v.contains(query),
83        })
84    }
85
86    /// Do a fully fuzzy query on names to facilitate searching
87    pub fn fuzzy_query(&self, _query: &str) -> bool {
88        unimplemented!()
89    }
90
91    #[doc(hidden)]
92    pub fn generate_updates(&self, new: Self) -> UserUpdate {
93        let mut update = UserUpdate::default();
94
95        match (&self.handle, new.handle) {
96            (None, Some(name)) => update.handle = ItemDiff::Set(name),
97            (Some(_), None) => update.handle = ItemDiff::Unset,
98            (_, _) => {} // Ignore is the default
99        }
100
101        match (&self.display_name, new.display_name) {
102            (None, Some(name)) => update.display_name = ItemDiff::Set(name),
103            (Some(_), None) => update.display_name = ItemDiff::Unset,
104            (_, _) => {} // Ignore is the default
105        }
106
107        // TODO: implement other user updates
108
109        update
110    }
111}
112
113/// All the ways a UserData can change, as individual events.
114#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Debug, Clone)]
115#[serde(default)]
116pub struct UserUpdate {
117    /// Set or blank the User's handle
118    pub handle: ItemDiff<String>,
119    /// Set or blank the User's display name
120    pub display_name: ItemDiff<String>,
121    /// Add or update a biography line with the given key to the given value.
122    pub add_to_bio: Vec<(String, String)>,
123    /// Remove a biography line with the given key, or do nothing if it does not exist.
124    pub rm_from_bio: BTreeSet<String>,
125    /// Add a service with the given name.
126    pub services: BTreeSet<SetDiff<String>>,
127    /// Set or blank the User's avatar.
128    pub avi_data: ItemDiff<Vec<u8>>,
129}