4 use proxmox
::api
::{api, ApiMethod, Router, RpcEnvironment}
;
5 use proxmox
::api
::schema
::{Schema, StringSchema}
;
7 use crate::api2
::types
::*;
8 use crate::config
::user
;
10 pub const PBS_PASSWORD_SCHEMA
: Schema
= StringSchema
::new("User Password.")
11 .format(&PASSWORD_FORMAT
)
21 description
: "List users (with config digest).",
25 description
: "User configuration (without password).",
28 schema
: PROXMOX_USER_ID_SCHEMA
,
31 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
35 schema
: user
::ENABLE_USER_SCHEMA
,
39 schema
: user
::EXPIRE_USER_SCHEMA
,
43 schema
: user
::FIRST_NAME_SCHEMA
,
47 schema
: user
::LAST_NAME_SCHEMA
,
51 schema
: user
::EMAIL_SCHEMA
,
62 _rpcenv
: &mut dyn RpcEnvironment
,
63 ) -> Result
<Value
, Error
> {
65 let (config
, digest
) = user
::config()?
;
67 let value
= config
.convert_to_array("userid", Some(&digest
), &[]);
77 schema
: PROXMOX_USER_ID_SCHEMA
,
80 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
84 schema
: PBS_PASSWORD_SCHEMA
,
88 schema
: user
::ENABLE_USER_SCHEMA
,
92 schema
: user
::EXPIRE_USER_SCHEMA
,
96 schema
: user
::FIRST_NAME_SCHEMA
,
100 schema
: user
::LAST_NAME_SCHEMA
,
104 schema
: user
::EMAIL_SCHEMA
,
111 pub fn create_user(userid
: String
, password
: Option
<String
>, param
: Value
) -> Result
<(), Error
> {
113 let _lock
= crate::tools
::open_file_locked(user
::USER_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0))?
;
115 let user
: user
::User
= serde_json
::from_value(param
.clone())?
;
117 let (mut config
, _digest
) = user
::config()?
;
119 if let Some(_
) = config
.sections
.get(&userid
) {
120 bail
!("user '{}' already exists.", userid
);
123 let (username
, realm
) = crate::auth
::parse_userid(&userid
)?
;
124 let authenticator
= crate::auth
::lookup_authenticator(&realm
)?
;
126 config
.set_data(&userid
, "user", &user
)?
;
128 user
::save_config(&config
)?
;
130 if let Some(password
) = password
{
131 authenticator
.store_password(&username
, &password
)?
;
141 schema
: PROXMOX_USER_ID_SCHEMA
,
146 description
: "The user configuration (with config digest).",
150 /// Read user configuration data.
151 pub fn read_user(userid
: String
) -> Result
<Value
, Error
> {
152 let (config
, digest
) = user
::config()?
;
153 let mut data
= config
.lookup_json("user", &userid
)?
;
154 data
.as_object_mut().unwrap()
155 .insert("digest".into(), proxmox
::tools
::digest_to_hex(&digest
).into());
164 schema
: PROXMOX_USER_ID_SCHEMA
,
168 schema
: SINGLE_LINE_COMMENT_SCHEMA
,
171 schema
: PBS_PASSWORD_SCHEMA
,
175 schema
: user
::ENABLE_USER_SCHEMA
,
179 schema
: user
::EXPIRE_USER_SCHEMA
,
183 schema
: user
::FIRST_NAME_SCHEMA
,
187 schema
: user
::LAST_NAME_SCHEMA
,
191 schema
: user
::EMAIL_SCHEMA
,
196 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
201 /// Update user configuration.
204 comment
: Option
<String
>,
205 enable
: Option
<bool
>,
207 password
: Option
<String
>,
208 firstname
: Option
<String
>,
209 lastname
: Option
<String
>,
210 email
: Option
<String
>,
211 digest
: Option
<String
>,
212 ) -> Result
<(), Error
> {
214 let _lock
= crate::tools
::open_file_locked(user
::USER_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0))?
;
216 let (mut config
, expected_digest
) = user
::config()?
;
218 if let Some(ref digest
) = digest
{
219 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
220 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
223 let mut data
: user
::User
= config
.lookup("user", &userid
)?
;
225 if let Some(comment
) = comment
{
226 let comment
= comment
.trim().to_string();
227 if comment
.is_empty() {
230 data
.comment
= Some(comment
);
234 if let Some(enable
) = enable
{
235 data
.enable
= if enable { None }
else { Some(false) }
;
238 if let Some(expire
) = expire
{
239 data
.expire
= if expire
> 0 { Some(expire) }
else { None }
;
242 if let Some(password
) = password
{
243 let (username
, realm
) = crate::auth
::parse_userid(&userid
)?
;
244 let authenticator
= crate::auth
::lookup_authenticator(&realm
)?
;
245 authenticator
.store_password(&username
, &password
)?
;
248 if let Some(firstname
) = firstname
{
249 data
.firstname
= if firstname
.is_empty() { None }
else { Some(firstname) }
;
252 if let Some(lastname
) = lastname
{
253 data
.lastname
= if lastname
.is_empty() { None }
else { Some(lastname) }
;
255 if let Some(email
) = email
{
256 data
.email
= if email
.is_empty() { None }
else { Some(email) }
;
259 config
.set_data(&userid
, "user", &data
)?
;
261 user
::save_config(&config
)?
;
271 schema
: PROXMOX_USER_ID_SCHEMA
,
275 schema
: PROXMOX_CONFIG_DIGEST_SCHEMA
,
280 /// Remove a user from the configuration file.
281 pub fn delete_user(userid
: String
, digest
: Option
<String
>) -> Result
<(), Error
> {
283 let _lock
= crate::tools
::open_file_locked(user
::USER_CFG_LOCKFILE
, std
::time
::Duration
::new(10, 0))?
;
285 let (mut config
, expected_digest
) = user
::config()?
;
287 if let Some(ref digest
) = digest
{
288 let digest
= proxmox
::tools
::hex_to_digest(digest
)?
;
289 crate::tools
::detect_modified_configuration_file(&digest
, &expected_digest
)?
;
292 match config
.sections
.get(&userid
) {
293 Some(_
) => { config.sections.remove(&userid); }
,
294 None
=> bail
!("user '{}' does not exist.", userid
),
297 user
::save_config(&config
)?
;
302 const ITEM_ROUTER
: Router
= Router
::new()
303 .get(&API_METHOD_READ_USER
)
304 .put(&API_METHOD_UPDATE_USER
)
305 .delete(&API_METHOD_DELETE_USER
);
307 pub const ROUTER
: Router
= Router
::new()
308 .get(&API_METHOD_LIST_USERS
)
309 .post(&API_METHOD_CREATE_USER
)
310 .match_all("userid", &ITEM_ROUTER
);