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 & 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}