1use std::sync::Arc;
15use std::time::Duration;
16
17use crate::core::{LifecycleState, OperationGuard};
18use crate::database::Database;
19use crate::error::{MongrelError, Result};
20
21pub struct SecretString(zeroize::Zeroizing<String>);
24
25impl SecretString {
26 pub fn new(secret: impl Into<String>) -> Self {
27 Self(zeroize::Zeroizing::new(secret.into()))
28 }
29
30 pub(crate) fn expose(&self) -> &str {
31 self.0.as_str()
32 }
33}
34
35impl std::fmt::Debug for SecretString {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 f.write_str("SecretString([REDACTED])")
38 }
39}
40
41#[derive(Debug, Clone, PartialEq, Eq)]
47pub enum HandleIdentity {
48 Credentialless,
50 CatalogUser {
54 username: String,
55 user_id: u64,
56 created_version: u64,
57 },
58 ServicePrincipal { principal_id: [u8; 16] },
60}
61
62#[derive(Debug)]
67pub enum OpenIdentity {
68 Credentialless,
71 ServicePrincipal { principal_id: [u8; 16] },
73 ScopedServicePrincipal {
75 principal_id: [u8; 16],
76 permissions: Vec<crate::auth::Permission>,
77 },
78 CatalogCredentials {
80 username: String,
81 password: SecretString,
82 },
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
89pub struct HandleAccess {
90 read_only: bool,
91}
92
93impl HandleAccess {
94 pub fn read_write() -> Self {
96 Self { read_only: false }
97 }
98
99 pub fn read_only() -> Self {
101 Self { read_only: true }
102 }
103
104 pub fn is_read_only(&self) -> bool {
106 self.read_only
107 }
108}
109
110pub struct DatabaseHandle {
117 database: Database,
119 identity: HandleIdentity,
120 access: HandleAccess,
121 service_permissions: Option<Vec<crate::auth::Permission>>,
122}
123
124impl DatabaseHandle {
125 pub(crate) fn new(
126 database: Database,
127 identity: HandleIdentity,
128 access: HandleAccess,
129 service_permissions: Option<Vec<crate::auth::Permission>>,
130 ) -> Self {
131 Self {
132 database,
133 identity,
134 access,
135 service_permissions,
136 }
137 }
138
139 pub fn identity(&self) -> &HandleIdentity {
141 &self.identity
142 }
143
144 pub fn access(&self) -> HandleAccess {
146 self.access
147 }
148
149 pub fn shares_core_with(&self, other: &Self) -> bool {
151 Arc::ptr_eq(&self.database.core(), &other.database.core())
152 }
153
154 pub fn lifecycle_state(&self) -> LifecycleState {
156 self.database.lifecycle_state()
157 }
158
159 pub fn operation_guard(&self) -> Result<OperationGuard> {
163 self.database.operation_guard()
164 }
165
166 fn authorize_write(&self, operation: &'static str) -> Result<()> {
167 if self.access.is_read_only() {
168 Err(MongrelError::ReadOnlyHandle { operation })
169 } else {
170 Ok(())
171 }
172 }
173
174 fn authorize_permission(&self, permission: &crate::auth::Permission) -> Result<()> {
175 if let Some(permissions) = &self.service_permissions {
176 if !permissions
177 .iter()
178 .any(|granted| granted.satisfies(permission))
179 {
180 return Err(MongrelError::PermissionDenied {
181 required: permission.clone(),
182 principal: match &self.identity {
183 HandleIdentity::ServicePrincipal { principal_id } => {
184 format!("service:{principal_id:02x?}")
185 }
186 _ => "service".into(),
187 },
188 });
189 }
190 }
191 self.database.require(permission)
192 }
193
194 pub fn query(
197 &self,
198 table: &str,
199 query: &crate::query::Query,
200 projection: Option<&[u16]>,
201 ) -> Result<Vec<crate::memtable::Row>> {
202 self.database
203 .query_for_current_principal(table, query, projection)
204 }
205
206 pub fn count(&self, table: &str) -> Result<u64> {
208 self.database
209 .count_for(table, self.database.principal().as_ref())
210 }
211
212 pub fn rows(&self, table: &str) -> Result<Vec<crate::memtable::Row>> {
214 self.database
215 .rows_for(table, self.database.principal().as_ref())
216 }
217
218 pub fn create_table(&self, name: &str, schema: crate::schema::Schema) -> Result<u64> {
220 self.authorize_write("create table")?;
221 self.authorize_permission(&crate::auth::Permission::Ddl)?;
222 self.database.create_table(name, schema)
223 }
224
225 pub fn put(
227 &self,
228 table: &str,
229 cells: Vec<(u16, crate::memtable::Value)>,
230 ) -> Result<Option<i64>> {
231 self.authorize_write("put")?;
232 self.database
233 .transaction_for_current_principal(|transaction| transaction.put(table, cells))
234 }
235
236 pub fn delete(&self, table: &str, row_id: crate::RowId) -> Result<()> {
238 self.authorize_write("delete")?;
239 self.database
240 .transaction_for_current_principal(|transaction| transaction.delete(table, row_id))
241 }
242
243 pub fn create_user(&self, username: &str, password: &str) -> Result<crate::auth::UserEntry> {
245 self.authorize_write("create user")?;
246 self.authorize_permission(&crate::auth::Permission::Admin)?;
247 self.database.create_user(username, password)
248 }
249
250 pub fn drop_user(&self, username: &str) -> Result<()> {
252 self.authorize_write("drop user")?;
253 self.authorize_permission(&crate::auth::Permission::Admin)?;
254 self.database.drop_user(username)
255 }
256
257 pub fn create_role(&self, role: &str) -> Result<crate::auth::RoleEntry> {
259 self.authorize_write("create role")?;
260 self.authorize_permission(&crate::auth::Permission::Admin)?;
261 self.database.create_role(role)
262 }
263
264 pub fn grant_role(&self, username: &str, role: &str) -> Result<()> {
266 self.authorize_write("grant role")?;
267 self.authorize_permission(&crate::auth::Permission::Admin)?;
268 self.database.grant_role(username, role)
269 }
270
271 pub fn revoke_role(&self, username: &str, role: &str) -> Result<()> {
273 self.authorize_write("revoke role")?;
274 self.authorize_permission(&crate::auth::Permission::Admin)?;
275 self.database.revoke_role(username, role)
276 }
277
278 pub fn grant_permission(&self, role: &str, permission: crate::auth::Permission) -> Result<()> {
280 self.authorize_write("grant permission")?;
281 self.authorize_permission(&crate::auth::Permission::Admin)?;
282 self.database.grant_permission(role, permission)
283 }
284
285 pub fn revoke_permission(&self, role: &str, permission: crate::auth::Permission) -> Result<()> {
287 self.authorize_write("revoke permission")?;
288 self.authorize_permission(&crate::auth::Permission::Admin)?;
289 self.database.revoke_permission(role, permission)
290 }
291
292 pub fn shutdown(&self, drain_deadline: Duration) -> Result<()> {
298 self.authorize_write("shutdown")?;
299 self.authorize_permission(&crate::auth::Permission::Admin)?;
300 self.database.core().shutdown(drain_deadline)
301 }
302}
303
304impl std::fmt::Debug for DatabaseHandle {
305 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
306 f.debug_struct("DatabaseHandle")
307 .field("identity", &self.identity)
308 .field("access", &self.access)
309 .field("database", &self.database)
310 .finish()
311 }
312}