Skip to main content

typedb_driver/user/
user_manager.rs

1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements.  See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership.  The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License.  You may obtain a copy of the License at
9 *
10 *   http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied.  See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#[cfg(not(feature = "sync"))]
21use std::future::Future;
22
23use crate::{
24    common::Result, connection::ServerConnection, error::ConnectionError, Connection, DatabaseManager, Error, User,
25};
26
27/// Provides access to all user management methods.
28#[derive(Clone, Debug)]
29pub struct UserManager {
30    // FIXME: currently required to be `pub` because we refer to it in bindings and over FFI
31    #[doc(hidden)]
32    pub connection: Connection,
33}
34
35impl UserManager {
36    const SYSTEM_DB: &'static str = "_system";
37
38    pub fn new(connection: Connection) -> Self {
39        Self { connection }
40    }
41
42    /// Returns the logged-in user for the connection.
43    ///
44    /// # Examples
45    ///
46    /// ```rust
47    /// driver.users.current_user().await;
48    /// ```
49    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
50    pub async fn current_user(&self) -> Result<Option<User>> {
51        match self.connection.username() {
52            Some(username) => self.get(username).await,
53            None => Ok(None), // FIXME error
54        }
55    }
56
57    /// Retrieves all users which exist on the TypeDB server.
58    ///
59    /// # Examples
60    ///
61    /// ```rust
62    /// driver.users.all().await;
63    /// ```
64    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
65    pub async fn all(&self) -> Result<Vec<User>> {
66        self.run_any_node(|server_connection: ServerConnection| async move { server_connection.all_users().await })
67            .await
68    }
69
70    /// Checks if a user with the given name exists.
71    ///
72    /// # Arguments
73    ///
74    /// * `username` -- The user name to be checked
75    ///
76    /// # Examples
77    ///
78    /// ```rust
79    /// driver.users.contains(username).await;
80    /// ```
81    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
82    pub async fn contains(&self, username: impl Into<String>) -> Result<bool> {
83        let username = username.into();
84        self.run_any_node(|server_connection: ServerConnection| {
85            let username = username.clone();
86            async move { server_connection.contains_user(username).await }
87        })
88        .await
89    }
90
91    /// Create a user with the given name &amp; password.
92    ///
93    /// # Arguments
94    ///
95    /// * `username` -- The name of the user to be created
96    /// * `password` -- The password of the user to be created
97    ///
98    /// # Examples
99    ///
100    /// ```rust
101    /// driver.users.create(username, password).await;
102    /// ```
103    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
104    pub async fn create(&self, username: impl Into<String>, password: impl Into<String>) -> Result {
105        let username = username.into();
106        let password = password.into();
107        self.run_any_node(|server_connection: ServerConnection| {
108            let username = username.clone();
109            let password = password.clone();
110            async move { server_connection.create_user(username, password).await }
111        })
112        .await
113    }
114
115    /// Deletes a user with the given name.
116    ///
117    /// # Arguments
118    ///
119    /// * `username` -- The name of the user to be deleted
120    ///
121    /// # Examples
122    ///
123    /// ```rust
124    /// driver.users.delete(username).await;
125    /// ```
126    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
127    pub async fn delete(&self, username: impl Into<String>) -> Result {
128        let username = username.into();
129        self.run_any_node(|server_connection: ServerConnection| {
130            let username = username.clone();
131            async move { server_connection.delete_user(username).await }
132        })
133        .await
134    }
135
136    /// Retrieve a user with the given name.
137    ///
138    /// # Arguments
139    ///
140    /// * `username` -- The name of the user to retrieve
141    ///
142    /// # Examples
143    ///
144    /// ```rust
145    /// driver.users.get(username).await;
146    /// ```
147    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
148    pub async fn get(&self, username: impl Into<String>) -> Result<Option<User>> {
149        let username = username.into();
150        self.run_any_node(|server_connection: ServerConnection| {
151            let username = username.clone();
152            async move { server_connection.get_user(username).await }
153        })
154        .await
155    }
156
157    /// Sets a new password for a user. This operation can only be performed by administrators.
158    ///
159    /// # Arguments
160    ///
161    /// * `username` -- The name of the user to set the password of
162    /// * `password` -- The new password
163    ///
164    /// # Examples
165    ///
166    /// ```rust
167    /// driver.users.password_set(username, password).await;
168    /// ```
169    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
170    pub async fn set_password(&self, username: impl Into<String>, password: impl Into<String>) -> Result {
171        let username = username.into();
172        let password = password.into();
173        self.run_any_node(|server_connection: ServerConnection| {
174            let username = username.clone();
175            let password = password.clone();
176            async move { server_connection.set_user_password(username, password).await }
177        })
178        .await
179    }
180
181    #[cfg_attr(feature = "sync", maybe_async::must_be_sync)]
182    async fn run_any_node<F, P, R>(&self, task: F) -> Result<R>
183    where
184        F: Fn(ServerConnection) -> P,
185        P: Future<Output = Result<R>>,
186    {
187        if !self.connection.is_cloud() {
188            Err(Error::Connection(ConnectionError::UserManagementCloudOnly))
189        } else {
190            DatabaseManager::new(self.connection.clone())
191                .get(Self::SYSTEM_DB)
192                .await?
193                .run_failsafe(|database| task(database.connection().clone()))
194                .await
195        }
196    }
197}