ddmw_client/mgmt/
acc.rs

1use std::collections::HashSet;
2
3use tokio::io::{AsyncRead, AsyncWrite};
4
5use tokio_util::codec::Framed;
6
7use crate::conn::sendrecv;
8use crate::types::ObjRef;
9
10use crate::err::Error;
11
12
13#[derive(Debug)]
14pub struct Account {
15  pub id: i64,
16  pub name: String,
17  pub lock: bool,
18  pub perms: HashSet<String>
19}
20
21
22/// Get information about an account.
23///
24/// If `acc` is `None` the current connection's owner will be returned.
25pub async fn rd<T>(
26  conn: &mut Framed<T, blather::Codec>,
27  acc: Option<ObjRef>
28) -> Result<Account, Error>
29where
30  T: AsyncRead + AsyncWrite + Unpin
31{
32  let mut tg = blather::Telegram::new_topic("RdAcc")?;
33
34  if let Some(acc) = acc {
35    match acc {
36      ObjRef::Id(id) => {
37        tg.add_param("Id", id)?;
38      }
39      ObjRef::Name(nm) => {
40        tg.add_str("Name", &nm)?;
41      }
42    }
43  }
44
45  let params = sendrecv(conn, &tg).await?;
46
47  let id = params.get_int::<i64>("Id")?;
48  let name = params.get_param::<String>("Name")?;
49  let lock = params.get_bool("Lock")?;
50  let perms = params.get_hashset("Perms")?;
51
52  let acc = Account {
53    id,
54    name,
55    lock,
56    perms
57  };
58
59  Ok(acc)
60}
61
62
63#[derive(Debug)]
64pub struct LsEntry {
65  pub id: i64,
66  pub name: String
67}
68
69
70/// Get a list of accounts.
71///
72/// This will only retreive a list of numeric account identifiers and the
73/// associated unique account name.  To get detailed information about each
74/// account the application needs to call [`rd`](self::rd) for each
75/// entry.
76pub async fn ls<T>(
77  conn: &mut Framed<T, blather::Codec>,
78  inclock: bool
79) -> Result<Vec<LsEntry>, Error>
80where
81  T: AsyncRead + AsyncWrite + Unpin
82{
83  let mut tg = blather::Telegram::new_topic("LsAcc")?;
84
85  if inclock {
86    tg.add_bool("All", true)?;
87  }
88
89  let params = sendrecv(conn, &tg).await?;
90
91  let num_entries = params.get_int::<usize>("#")?;
92
93  let mut acclist = Vec::with_capacity(num_entries);
94  for i in 0..num_entries {
95    let id = format!("{}.Id", i);
96    let name = format!("{}.Name", i);
97
98    acclist.push(LsEntry {
99      id: params.get_int::<i64>(&id).unwrap(),
100      name: params.get_str(&name).unwrap().to_string()
101    });
102  }
103
104  Ok(acclist)
105}
106
107
108/// Enumeration of account permission change methods.
109pub enum ModPerms {
110  /// Reset the account's permissions to the ones passed in the supplied
111  /// HashSet.
112  Set(HashSet<String>),
113
114  /// Add the supplied permissions to the account's permissions.  Collisions
115  /// are ignored.
116  Grant(HashSet<String>),
117
118  /// Remove the supplied permissions from the account's permissions.  Removal
119  /// of permissions the account doesn't have are silently ignored.
120  Revoke(HashSet<String>),
121
122  /// First grant permissions to the account, then remove permissions.
123  GrantRevoke(HashSet<String>, HashSet<String>)
124}
125
126
127/// Account fields to update.
128pub struct WrAccount {
129  /// New account name.
130  /// This is currently not supported.
131  pub name: Option<String>,
132
133  /// New real name field.  Set to empty field to remove the current value.
134  pub username: Option<String>,
135
136  /// Whether account should be locked or unlocked.
137  pub lock: Option<bool>,
138
139  /// Account permissions.  If the `set` field is used, then `grant` and
140  /// `revoke` are ignored.
141  pub perms: Option<ModPerms>
142}
143
144
145/// Update an account.
146pub async fn wr<T>(
147  conn: &mut Framed<T, blather::Codec>,
148  acc: ObjRef,
149  ai: WrAccount
150) -> Result<(), Error>
151where
152  T: AsyncRead + AsyncWrite + Unpin
153{
154  let mut tg = blather::Telegram::new_topic("WrAcc")?;
155
156  match acc {
157    ObjRef::Id(id) => {
158      tg.add_param("Id", id)?;
159    }
160    ObjRef::Name(nm) => {
161      tg.add_str("Name", &nm)?;
162    }
163  }
164
165  if let Some(name) = ai.name {
166    tg.add_str("NewName", &name)?;
167  }
168  if let Some(username) = ai.username {
169    tg.add_str("UserName", &username)?;
170  }
171  if let Some(lck) = ai.lock {
172    tg.add_bool("Lock", lck)?;
173  }
174
175  if let Some(perms) = ai.perms {
176    match perms {
177      ModPerms::Set(set) => {
178        tg.add_strit("Perms", set.iter())?;
179      }
180      ModPerms::Grant(set) => {
181        tg.add_strit("Grant", set.iter())?;
182      }
183      ModPerms::Revoke(set) => {
184        tg.add_strit("Revoke", set.iter())?;
185      }
186      ModPerms::GrantRevoke(grant, revoke) => {
187        tg.add_strit("Grant", grant.iter())?;
188        tg.add_strit("Revoke", revoke.iter())?;
189      }
190    }
191  }
192
193  sendrecv(conn, &tg).await?;
194
195  Ok(())
196}
197
198
199/// Remove an account.
200pub async fn rm<T>(
201  conn: &mut Framed<T, blather::Codec>,
202  acc: ObjRef
203) -> Result<(), Error>
204where
205  T: AsyncRead + AsyncWrite + Unpin
206{
207  let mut tg = blather::Telegram::new_topic("RmAcc")?;
208
209  match acc {
210    ObjRef::Id(id) => {
211      tg.add_param("Id", id)?;
212    }
213    ObjRef::Name(nm) => {
214      tg.add_str("Name", &nm)?;
215    }
216  }
217
218  sendrecv(conn, &tg).await?;
219
220  Ok(())
221}
222
223// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :