]> git.proxmox.com Git - proxmox-backup.git/blob - src/bin/proxmox_backup_manager/user.rs
tree-wide: fix needless borrows
[proxmox-backup.git] / src / bin / proxmox_backup_manager / user.rs
1 use anyhow::Error;
2 use serde_json::Value;
3
4 use std::collections::HashMap;
5
6 use proxmox_router::{cli::*, ApiHandler, RpcEnvironment};
7 use proxmox_schema::api;
8
9 use pbs_api_types::{ACL_PATH_SCHEMA, Authid, Userid};
10
11 use proxmox_backup::api2;
12
13 fn render_expire(value: &Value, _record: &Value) -> Result<String, Error> {
14 let never = String::from("never");
15 if value.is_null() { return Ok(never); }
16 let text = match value.as_i64() {
17 Some(epoch) if epoch == 0 => never,
18 Some(epoch) => {
19 if let Ok(epoch_string) = proxmox_time::strftime_local("%c", epoch as i64) {
20 epoch_string
21 } else {
22 epoch.to_string()
23 }
24 },
25 None => value.to_string(),
26 };
27 Ok(text)
28 }
29
30 #[api(
31 input: {
32 properties: {
33 "output-format": {
34 schema: OUTPUT_FORMAT,
35 optional: true,
36 },
37 }
38 }
39 )]
40 /// List configured users.
41 fn list_users(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
42
43 let output_format = get_output_format(&param);
44
45 let info = &api2::access::user::API_METHOD_LIST_USERS;
46 let mut data = match info.handler {
47 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
48 _ => unreachable!(),
49 };
50
51 let options = default_table_format_options()
52 .column(ColumnConfig::new("userid"))
53 .column(
54 ColumnConfig::new("enable")
55 .renderer(pbs_tools::format::render_bool_with_default_true)
56 )
57 .column(
58 ColumnConfig::new("expire")
59 .renderer(render_expire)
60 )
61 .column(ColumnConfig::new("firstname"))
62 .column(ColumnConfig::new("lastname"))
63 .column(ColumnConfig::new("email"))
64 .column(ColumnConfig::new("comment"));
65
66 format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
67
68 Ok(Value::Null)
69 }
70
71 #[api(
72 input: {
73 properties: {
74 "output-format": {
75 schema: OUTPUT_FORMAT,
76 optional: true,
77 },
78 userid: {
79 type: Userid,
80 }
81 }
82 }
83 )]
84 /// List tokens associated with user.
85 fn list_tokens(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
86
87 let output_format = get_output_format(&param);
88
89 let info = &api2::access::user::API_METHOD_LIST_TOKENS;
90 let mut data = match info.handler {
91 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
92 _ => unreachable!(),
93 };
94
95 let options = default_table_format_options()
96 .column(ColumnConfig::new("tokenid"))
97 .column(
98 ColumnConfig::new("enable")
99 .renderer(pbs_tools::format::render_bool_with_default_true)
100 )
101 .column(
102 ColumnConfig::new("expire")
103 .renderer(render_expire)
104 )
105 .column(ColumnConfig::new("comment"));
106
107 format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
108
109 Ok(Value::Null)
110 }
111
112
113 #[api(
114 input: {
115 properties: {
116 "output-format": {
117 schema: OUTPUT_FORMAT,
118 optional: true,
119 },
120 "auth-id": {
121 type: Authid,
122 },
123 path: {
124 schema: ACL_PATH_SCHEMA,
125 optional: true,
126 },
127 }
128 }
129 )]
130 /// List permissions of user/token.
131 fn list_permissions(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
132
133 let output_format = get_output_format(&param);
134
135 let info = &api2::access::API_METHOD_LIST_PERMISSIONS;
136 let data = match info.handler {
137 ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
138 _ => unreachable!(),
139 };
140
141 if output_format == "text" {
142 println!("Privileges with (*) have the propagate flag set\n");
143 let data:HashMap<String, HashMap<String, bool>> = serde_json::from_value(data)?;
144 let mut paths:Vec<String> = data.keys().cloned().collect();
145 paths.sort_unstable();
146 for path in paths {
147 println!("Path: {}", path);
148 let priv_map = data.get(&path).unwrap();
149 let mut privs:Vec<String> = priv_map.keys().cloned().collect();
150 if privs.is_empty() {
151 println!("- NoAccess");
152 } else {
153 privs.sort_unstable();
154 for privilege in privs {
155 if *priv_map.get(&privilege).unwrap() {
156 println!("- {} (*)", privilege);
157 } else {
158 println!("- {}", privilege);
159 }
160 }
161 }
162 }
163 } else {
164 format_and_print_result(&data, &output_format);
165 }
166
167 Ok(Value::Null)
168 }
169
170
171 pub fn user_commands() -> CommandLineInterface {
172
173 let cmd_def = CliCommandMap::new()
174 .insert("list", CliCommand::new(&API_METHOD_LIST_USERS))
175 .insert(
176 "create",
177 // fixme: howto handle password parameter?
178 CliCommand::new(&api2::access::user::API_METHOD_CREATE_USER)
179 .arg_param(&["userid"])
180 )
181 .insert(
182 "update",
183 CliCommand::new(&api2::access::user::API_METHOD_UPDATE_USER)
184 .arg_param(&["userid"])
185 .completion_cb("userid", pbs_config::user::complete_userid)
186 )
187 .insert(
188 "remove",
189 CliCommand::new(&api2::access::user::API_METHOD_DELETE_USER)
190 .arg_param(&["userid"])
191 .completion_cb("userid", pbs_config::user::complete_userid)
192 )
193 .insert(
194 "list-tokens",
195 CliCommand::new(&API_METHOD_LIST_TOKENS)
196 .arg_param(&["userid"])
197 .completion_cb("userid", pbs_config::user::complete_userid)
198 )
199 .insert(
200 "generate-token",
201 CliCommand::new(&api2::access::user::API_METHOD_GENERATE_TOKEN)
202 .arg_param(&["userid", "token-name"])
203 .completion_cb("userid", pbs_config::user::complete_userid)
204 )
205 .insert(
206 "delete-token",
207 CliCommand::new(&api2::access::user::API_METHOD_DELETE_TOKEN)
208 .arg_param(&["userid", "token-name"])
209 .completion_cb("userid", pbs_config::user::complete_userid)
210 .completion_cb("token-name", pbs_config::user::complete_token_name)
211 )
212 .insert(
213 "permissions",
214 CliCommand::new(&API_METHOD_LIST_PERMISSIONS)
215 .arg_param(&["auth-id"])
216 .completion_cb("auth-id", pbs_config::user::complete_authid)
217 .completion_cb("path", pbs_config::datastore::complete_acl_path)
218 );
219
220 cmd_def.into()
221 }