Skip to main content

opensubsonic/api/
user_management.rs

1//! User Management API endpoints.
2
3use crate::Client;
4use crate::data::User;
5use crate::error::Error;
6
7impl Client {
8    /// Get details about a specific user.
9    ///
10    /// See <https://opensubsonic.netlify.app/docs/endpoints/getuser/>
11    pub async fn get_user(&self, username: &str) -> Result<User, Error> {
12        let data = self
13            .get_response("getUser", &[("username", username)])
14            .await?;
15        let user = data
16            .get("user")
17            .ok_or_else(|| Error::Parse("Missing 'user' in response".into()))?;
18        Ok(serde_json::from_value(user.clone())?)
19    }
20
21    /// Get details about all users (admin only).
22    ///
23    /// See <https://opensubsonic.netlify.app/docs/endpoints/getusers/>
24    pub async fn get_users(&self) -> Result<Vec<User>, Error> {
25        let data = self.get_response("getUsers", &[]).await?;
26        let users = data
27            .get("users")
28            .and_then(|v| v.get("user"))
29            .cloned()
30            .unwrap_or_else(|| serde_json::Value::Array(vec![]));
31        Ok(serde_json::from_value(users)?)
32    }
33
34    /// Create a new user (admin only).
35    ///
36    /// See <https://opensubsonic.netlify.app/docs/endpoints/createuser/>
37    #[allow(clippy::too_many_arguments)]
38    pub async fn create_user(
39        &self,
40        username: &str,
41        password: &str,
42        email: &str,
43        ldap_authenticated: Option<bool>,
44        admin_role: Option<bool>,
45        settings_role: Option<bool>,
46        stream_role: Option<bool>,
47        jukebox_role: Option<bool>,
48        download_role: Option<bool>,
49        upload_role: Option<bool>,
50        playlist_role: Option<bool>,
51        cover_art_role: Option<bool>,
52        comment_role: Option<bool>,
53        podcast_role: Option<bool>,
54        share_role: Option<bool>,
55        video_conversion_role: Option<bool>,
56        music_folder_ids: &[i64],
57    ) -> Result<(), Error> {
58        let mut params = vec![
59            ("username", username.to_string()),
60            ("password", password.to_string()),
61            ("email", email.to_string()),
62        ];
63        if let Some(v) = ldap_authenticated {
64            params.push(("ldapAuthenticated", v.to_string()));
65        }
66        if let Some(v) = admin_role {
67            params.push(("adminRole", v.to_string()));
68        }
69        if let Some(v) = settings_role {
70            params.push(("settingsRole", v.to_string()));
71        }
72        if let Some(v) = stream_role {
73            params.push(("streamRole", v.to_string()));
74        }
75        if let Some(v) = jukebox_role {
76            params.push(("jukeboxRole", v.to_string()));
77        }
78        if let Some(v) = download_role {
79            params.push(("downloadRole", v.to_string()));
80        }
81        if let Some(v) = upload_role {
82            params.push(("uploadRole", v.to_string()));
83        }
84        if let Some(v) = playlist_role {
85            params.push(("playlistRole", v.to_string()));
86        }
87        if let Some(v) = cover_art_role {
88            params.push(("coverArtRole", v.to_string()));
89        }
90        if let Some(v) = comment_role {
91            params.push(("commentRole", v.to_string()));
92        }
93        if let Some(v) = podcast_role {
94            params.push(("podcastRole", v.to_string()));
95        }
96        if let Some(v) = share_role {
97            params.push(("shareRole", v.to_string()));
98        }
99        if let Some(v) = video_conversion_role {
100            params.push(("videoConversionRole", v.to_string()));
101        }
102        for folder_id in music_folder_ids {
103            params.push(("musicFolderId", folder_id.to_string()));
104        }
105        let param_refs: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
106        self.get_response("createUser", &param_refs).await?;
107        Ok(())
108    }
109
110    /// Update an existing user (admin only).
111    ///
112    /// See <https://opensubsonic.netlify.app/docs/endpoints/updateuser/>
113    #[allow(clippy::too_many_arguments)]
114    pub async fn update_user(
115        &self,
116        username: &str,
117        password: Option<&str>,
118        email: Option<&str>,
119        ldap_authenticated: Option<bool>,
120        admin_role: Option<bool>,
121        settings_role: Option<bool>,
122        stream_role: Option<bool>,
123        jukebox_role: Option<bool>,
124        download_role: Option<bool>,
125        upload_role: Option<bool>,
126        playlist_role: Option<bool>,
127        cover_art_role: Option<bool>,
128        comment_role: Option<bool>,
129        podcast_role: Option<bool>,
130        share_role: Option<bool>,
131        video_conversion_role: Option<bool>,
132        max_bit_rate: Option<i32>,
133        music_folder_ids: &[i64],
134    ) -> Result<(), Error> {
135        let mut params = vec![("username", username.to_string())];
136        if let Some(v) = password {
137            params.push(("password", v.to_string()));
138        }
139        if let Some(v) = email {
140            params.push(("email", v.to_string()));
141        }
142        if let Some(v) = ldap_authenticated {
143            params.push(("ldapAuthenticated", v.to_string()));
144        }
145        if let Some(v) = admin_role {
146            params.push(("adminRole", v.to_string()));
147        }
148        if let Some(v) = settings_role {
149            params.push(("settingsRole", v.to_string()));
150        }
151        if let Some(v) = stream_role {
152            params.push(("streamRole", v.to_string()));
153        }
154        if let Some(v) = jukebox_role {
155            params.push(("jukeboxRole", v.to_string()));
156        }
157        if let Some(v) = download_role {
158            params.push(("downloadRole", v.to_string()));
159        }
160        if let Some(v) = upload_role {
161            params.push(("uploadRole", v.to_string()));
162        }
163        if let Some(v) = playlist_role {
164            params.push(("playlistRole", v.to_string()));
165        }
166        if let Some(v) = cover_art_role {
167            params.push(("coverArtRole", v.to_string()));
168        }
169        if let Some(v) = comment_role {
170            params.push(("commentRole", v.to_string()));
171        }
172        if let Some(v) = podcast_role {
173            params.push(("podcastRole", v.to_string()));
174        }
175        if let Some(v) = share_role {
176            params.push(("shareRole", v.to_string()));
177        }
178        if let Some(v) = video_conversion_role {
179            params.push(("videoConversionRole", v.to_string()));
180        }
181        if let Some(v) = max_bit_rate {
182            params.push(("maxBitRate", v.to_string()));
183        }
184        for folder_id in music_folder_ids {
185            params.push(("musicFolderId", folder_id.to_string()));
186        }
187        let param_refs: Vec<(&str, &str)> = params.iter().map(|(k, v)| (*k, v.as_str())).collect();
188        self.get_response("updateUser", &param_refs).await?;
189        Ok(())
190    }
191
192    /// Delete a user (admin only).
193    ///
194    /// See <https://opensubsonic.netlify.app/docs/endpoints/deleteuser/>
195    pub async fn delete_user(&self, username: &str) -> Result<(), Error> {
196        self.get_response("deleteUser", &[("username", username)])
197            .await?;
198        Ok(())
199    }
200
201    /// Change a user's password.
202    ///
203    /// See <https://opensubsonic.netlify.app/docs/endpoints/changepassword/>
204    pub async fn change_password(&self, username: &str, password: &str) -> Result<(), Error> {
205        self.get_response(
206            "changePassword",
207            &[("username", username), ("password", password)],
208        )
209        .await?;
210        Ok(())
211    }
212}