1use std::sync::Arc;
15use std::time::Duration;
16
17use crate::core::{LifecycleState, OperationGuard};
18use crate::database::Database;
19use crate::error::{MongrelError, Result};
20use crate::service_principal::ServicePrincipalDefinition;
21
22pub struct SecretString(zeroize::Zeroizing<String>);
25
26impl SecretString {
27 pub fn new(secret: impl Into<String>) -> Self {
28 Self(zeroize::Zeroizing::new(secret.into()))
29 }
30
31 pub(crate) fn expose(&self) -> &str {
32 self.0.as_str()
33 }
34}
35
36impl std::fmt::Debug for SecretString {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 f.write_str("SecretString([REDACTED])")
39 }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
50pub enum HandleIdentity {
51 Credentialless,
53 CatalogUser {
57 username: String,
58 user_id: u64,
59 created_version: u64,
60 },
61 ServicePrincipal {
65 token_id: String,
66 principal_id: [u8; 16],
67 creation_version: u64,
68 },
69}
70
71#[derive(Debug)]
82pub enum OpenIdentity {
83 Credentialless,
86 ServiceCredentials {
88 token_id: String,
89 secret: SecretString,
90 },
91 CatalogCredentials {
93 username: String,
94 password: SecretString,
95 },
96}
97
98#[derive(Debug, Clone)]
105pub(crate) struct InternalServiceCapability {
106 pub principal_id: [u8; 16],
107 pub permissions: Vec<crate::auth::Permission>,
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
114pub struct HandleAccess {
115 read_only: bool,
116}
117
118impl HandleAccess {
119 pub fn read_write() -> Self {
121 Self { read_only: false }
122 }
123
124 pub fn read_only() -> Self {
126 Self { read_only: true }
127 }
128
129 pub fn is_read_only(&self) -> bool {
131 self.read_only
132 }
133}
134
135pub struct DatabaseHandle {
142 database: Database,
144 identity: HandleIdentity,
145 access: HandleAccess,
146 internal_capability: Option<InternalServiceCapability>,
149}
150
151impl DatabaseHandle {
152 pub(crate) fn new(
153 database: Database,
154 identity: HandleIdentity,
155 access: HandleAccess,
156 internal_capability: Option<InternalServiceCapability>,
157 ) -> Self {
158 Self {
159 database,
160 identity,
161 access,
162 internal_capability,
163 }
164 }
165
166 #[allow(dead_code)] pub(crate) fn with_internal_capability(
170 database: Database,
171 capability: InternalServiceCapability,
172 access: HandleAccess,
173 ) -> Self {
174 let identity = HandleIdentity::ServicePrincipal {
175 token_id: format!("internal:{:02x?}", capability.principal_id),
176 principal_id: capability.principal_id,
177 creation_version: 0,
178 };
179 Self::new(database, identity, access, Some(capability))
180 }
181
182 pub fn identity(&self) -> &HandleIdentity {
184 &self.identity
185 }
186
187 pub fn access(&self) -> HandleAccess {
189 self.access
190 }
191
192 pub fn shares_core_with(&self, other: &Self) -> bool {
194 Arc::ptr_eq(&self.database.core(), &other.database.core())
195 }
196
197 pub fn lifecycle_state(&self) -> LifecycleState {
199 self.database.lifecycle_state()
200 }
201
202 pub fn operation_guard(&self) -> Result<OperationGuard> {
206 self.database.operation_guard()
207 }
208
209 fn authorize_write(&self, operation: &'static str) -> Result<()> {
210 if self.access.is_read_only() {
211 Err(MongrelError::ReadOnlyHandle { operation })
212 } else {
213 Ok(())
214 }
215 }
216
217 fn resolve_service_authority(&self) -> Result<()> {
221 if self.internal_capability.is_some() {
222 return Ok(());
223 }
224 let HandleIdentity::ServicePrincipal {
225 token_id,
226 principal_id,
227 creation_version,
228 } = &self.identity
229 else {
230 return Ok(());
231 };
232 let def = self.database.core().service_principals.resolve_live(
233 token_id,
234 *principal_id,
235 *creation_version,
236 )?;
237 self.database.rebind_service_principal(&def);
238 Ok(())
239 }
240
241 fn authorize_permission(&self, permission: &crate::auth::Permission) -> Result<()> {
242 if let Some(capability) = &self.internal_capability {
243 if !capability
244 .permissions
245 .iter()
246 .any(|granted| granted.satisfies(permission))
247 {
248 return Err(MongrelError::PermissionDenied {
249 required: permission.clone(),
250 principal: format!("service:{:02x?}", capability.principal_id),
251 });
252 }
253 return Ok(());
254 }
255 if let HandleIdentity::ServicePrincipal {
256 token_id,
257 principal_id,
258 creation_version,
259 } = &self.identity
260 {
261 let def = self.database.core().service_principals.resolve_live(
262 token_id,
263 *principal_id,
264 *creation_version,
265 )?;
266 self.database.rebind_service_principal(&def);
267 if !def
268 .permissions
269 .iter()
270 .any(|granted| granted.satisfies(permission))
271 {
272 return Err(MongrelError::PermissionDenied {
273 required: permission.clone(),
274 principal: format!("service:{token_id}"),
275 });
276 }
277 return Ok(());
278 }
279 self.database.require(permission)
280 }
281
282 pub fn query(
285 &self,
286 table: &str,
287 query: &crate::query::Query,
288 projection: Option<&[u16]>,
289 ) -> Result<Vec<crate::memtable::Row>> {
290 self.resolve_service_authority()?;
291 self.database
292 .query_for_current_principal(table, query, projection)
293 }
294
295 pub fn count(&self, table: &str) -> Result<u64> {
297 self.resolve_service_authority()?;
298 self.database
299 .count_for(table, self.database.principal().as_ref())
300 }
301
302 pub fn rows(&self, table: &str) -> Result<Vec<crate::memtable::Row>> {
304 self.resolve_service_authority()?;
305 self.database
306 .rows_for(table, self.database.principal().as_ref())
307 }
308
309 pub fn create_table(&self, name: &str, schema: crate::schema::Schema) -> Result<u64> {
311 self.authorize_write("create table")?;
312 self.authorize_permission(&crate::auth::Permission::Ddl)?;
313 self.database.create_table(name, schema)
314 }
315
316 pub fn put(
318 &self,
319 table: &str,
320 cells: Vec<(u16, crate::memtable::Value)>,
321 ) -> Result<Option<i64>> {
322 self.authorize_write("put")?;
323 self.resolve_service_authority()?;
324 self.database
325 .transaction_for_current_principal(|transaction| transaction.put(table, cells))
326 }
327
328 pub fn put_batch(
330 &self,
331 table: &str,
332 rows: Vec<Vec<(u16, crate::memtable::Value)>>,
333 ) -> Result<Vec<Option<i64>>> {
334 self.authorize_write("put_batch")?;
335 self.resolve_service_authority()?;
336 self.database
337 .transaction_for_current_principal(|transaction| transaction.put_batch(table, rows))
338 }
339
340 pub fn update(
342 &self,
343 table: &str,
344 row_id: crate::RowId,
345 cells: Vec<(u16, crate::memtable::Value)>,
346 ) -> Result<crate::txn::OwnedRow> {
347 self.authorize_write("update")?;
348 self.resolve_service_authority()?;
349 self.database
350 .transaction_for_current_principal(|transaction| {
351 let mut images = transaction.update_many(table, vec![(row_id, cells)])?;
352 images.pop().ok_or_else(|| {
353 MongrelError::NotFound(format!("row {row_id:?} not found for update"))
354 })
355 })
356 }
357
358 pub fn session(&self) -> Result<AuthorizedMongrelSession<'_>> {
364 self.resolve_service_authority()?;
365 Ok(AuthorizedMongrelSession { handle: self })
366 }
367
368 pub fn begin(&self) -> Result<AuthorizedTransaction<'_>> {
373 self.authorize_write("begin")?;
374 self.resolve_service_authority()?;
375 let principal = self.database.principal();
376 let txn = self.database.begin_as(principal);
377 Ok(AuthorizedTransaction {
378 handle: self,
379 txn: Some(txn),
380 })
381 }
382
383 pub fn delete(&self, table: &str, row_id: crate::RowId) -> Result<()> {
385 self.authorize_write("delete")?;
386 self.resolve_service_authority()?;
387 self.database
388 .transaction_for_current_principal(|transaction| transaction.delete(table, row_id))
389 }
390
391 pub fn create_index(&self, table: &str, definition: crate::schema::IndexDef) -> Result<u64> {
396 self.authorize_write("create index")?;
397 self.authorize_permission(&crate::auth::Permission::Ddl)?;
398 self.database.create_index(table, definition)
399 }
400
401 pub fn drop_index(&self, table: &str, name: &str) -> Result<()> {
403 self.authorize_write("drop index")?;
404 self.authorize_permission(&crate::auth::Permission::Ddl)?;
405 self.database.drop_index(table, name)
406 }
407
408 pub fn create_procedure(
410 &self,
411 procedure: crate::procedure::StoredProcedure,
412 ) -> Result<crate::procedure::StoredProcedure> {
413 self.authorize_write("create procedure")?;
414 self.authorize_permission(&crate::auth::Permission::Ddl)?;
415 self.resolve_service_authority()?;
416 self.database.create_procedure(procedure)
417 }
418
419 pub fn drop_procedure(&self, name: &str) -> Result<()> {
421 self.authorize_write("drop procedure")?;
422 self.authorize_permission(&crate::auth::Permission::Ddl)?;
423 self.resolve_service_authority()?;
424 self.database.drop_procedure(name)
425 }
426
427 pub fn call_procedure(
429 &self,
430 name: &str,
431 args: std::collections::HashMap<String, crate::memtable::Value>,
432 ) -> Result<crate::procedure::ProcedureCallResult> {
433 self.resolve_service_authority()?;
436 self.database.call_procedure(name, args)
437 }
438
439 pub fn create_trigger(
441 &self,
442 trigger: crate::trigger::StoredTrigger,
443 ) -> Result<crate::trigger::StoredTrigger> {
444 self.authorize_write("create trigger")?;
445 self.authorize_permission(&crate::auth::Permission::Ddl)?;
446 self.resolve_service_authority()?;
447 self.database.create_trigger(trigger)
448 }
449
450 pub fn drop_trigger(&self, name: &str) -> Result<()> {
452 self.authorize_write("drop trigger")?;
453 self.authorize_permission(&crate::auth::Permission::Ddl)?;
454 self.resolve_service_authority()?;
455 self.database.drop_trigger(name)
456 }
457
458 pub fn rows_at_epoch(
460 &self,
461 table: &str,
462 snapshot: crate::epoch::Snapshot,
463 ) -> Result<Vec<crate::memtable::Row>> {
464 self.resolve_service_authority()?;
465 self.database
466 .rows_at_epoch_for_current_principal(table, snapshot)
467 }
468
469 pub fn create_user(&self, username: &str, password: &str) -> Result<crate::auth::UserEntry> {
471 self.authorize_write("create user")?;
472 self.authorize_permission(&crate::auth::Permission::Admin)?;
473 self.database.create_user(username, password)
474 }
475
476 pub fn drop_user(&self, username: &str) -> Result<()> {
478 self.authorize_write("drop user")?;
479 self.authorize_permission(&crate::auth::Permission::Admin)?;
480 self.database.drop_user(username)
481 }
482
483 pub fn create_role(&self, role: &str) -> Result<crate::auth::RoleEntry> {
485 self.authorize_write("create role")?;
486 self.authorize_permission(&crate::auth::Permission::Admin)?;
487 self.database.create_role(role)
488 }
489
490 pub fn grant_role(&self, username: &str, role: &str) -> Result<()> {
492 self.authorize_write("grant role")?;
493 self.authorize_permission(&crate::auth::Permission::Admin)?;
494 self.database.grant_role(username, role)
495 }
496
497 pub fn revoke_role(&self, username: &str, role: &str) -> Result<()> {
499 self.authorize_write("revoke role")?;
500 self.authorize_permission(&crate::auth::Permission::Admin)?;
501 self.database.revoke_role(username, role)
502 }
503
504 pub fn grant_permission(&self, role: &str, permission: crate::auth::Permission) -> Result<()> {
506 self.authorize_write("grant permission")?;
507 self.authorize_permission(&crate::auth::Permission::Admin)?;
508 self.database.grant_permission(role, permission)
509 }
510
511 pub fn revoke_permission(&self, role: &str, permission: crate::auth::Permission) -> Result<()> {
513 self.authorize_write("revoke permission")?;
514 self.authorize_permission(&crate::auth::Permission::Admin)?;
515 self.database.revoke_permission(role, permission)
516 }
517
518 pub fn register_service_principal(
522 &self,
523 token_id: impl Into<String>,
524 principal_id: [u8; 16],
525 permissions: Vec<crate::auth::Permission>,
526 raw_secret: &str,
527 expires_unix: u64,
528 ) -> Result<ServicePrincipalDefinition> {
529 self.authorize_write("register service principal")?;
530 self.authorize_permission(&crate::auth::Permission::Admin)?;
531 self.database.core().service_principals.register(
532 token_id,
533 principal_id,
534 permissions,
535 raw_secret,
536 expires_unix,
537 )
538 }
539
540 pub fn revoke_service_principal(&self, token_id: &str) -> Result<()> {
543 self.authorize_write("revoke service principal")?;
544 self.authorize_permission(&crate::auth::Permission::Admin)?;
545 self.database.core().service_principals.revoke(token_id)
546 }
547
548 pub fn set_service_principal_permissions(
552 &self,
553 token_id: &str,
554 permissions: Vec<crate::auth::Permission>,
555 ) -> Result<()> {
556 self.authorize_write("set service principal permissions")?;
557 self.authorize_permission(&crate::auth::Permission::Admin)?;
558 self.database
559 .core()
560 .service_principals
561 .set_permissions(token_id, permissions)
562 }
563
564 pub fn shutdown(&self, drain_deadline: Duration) -> Result<()> {
570 self.authorize_write("shutdown")?;
571 self.authorize_permission(&crate::auth::Permission::Admin)?;
572 self.database.core().shutdown(drain_deadline)
573 }
574}
575
576pub struct AuthorizedMongrelSession<'a> {
582 handle: &'a DatabaseHandle,
583}
584
585pub type AuthorizedSession<'a> = AuthorizedMongrelSession<'a>;
587
588impl<'a> AuthorizedMongrelSession<'a> {
589 pub fn begin(&self) -> Result<AuthorizedTransaction<'a>> {
590 self.handle.begin()
591 }
592
593 pub fn put(
594 &self,
595 table: &str,
596 cells: Vec<(u16, crate::memtable::Value)>,
597 ) -> Result<Option<i64>> {
598 self.handle.put(table, cells)
599 }
600
601 pub fn update(
602 &self,
603 table: &str,
604 row_id: crate::RowId,
605 cells: Vec<(u16, crate::memtable::Value)>,
606 ) -> Result<crate::txn::OwnedRow> {
607 self.handle.update(table, row_id, cells)
608 }
609
610 pub fn delete(&self, table: &str, row_id: crate::RowId) -> Result<()> {
611 self.handle.delete(table, row_id)
612 }
613
614 pub fn query(
615 &self,
616 table: &str,
617 query: &crate::query::Query,
618 projection: Option<&[u16]>,
619 ) -> Result<Vec<crate::memtable::Row>> {
620 self.handle.query(table, query, projection)
621 }
622
623 pub fn count(&self, table: &str) -> Result<u64> {
624 self.handle.count(table)
625 }
626
627 pub fn put_batch(
628 &self,
629 table: &str,
630 rows: Vec<Vec<(u16, crate::memtable::Value)>>,
631 ) -> Result<Vec<Option<i64>>> {
632 self.handle.put_batch(table, rows)
633 }
634
635 pub fn create_index(&self, table: &str, definition: crate::schema::IndexDef) -> Result<u64> {
637 self.handle.create_index(table, definition)
638 }
639
640 pub fn drop_index(&self, table: &str, name: &str) -> Result<()> {
642 self.handle.drop_index(table, name)
643 }
644
645 pub fn create_procedure(
647 &self,
648 procedure: crate::procedure::StoredProcedure,
649 ) -> Result<crate::procedure::StoredProcedure> {
650 self.handle.create_procedure(procedure)
651 }
652
653 pub fn drop_procedure(&self, name: &str) -> Result<()> {
655 self.handle.drop_procedure(name)
656 }
657
658 pub fn call_procedure(
660 &self,
661 name: &str,
662 args: std::collections::HashMap<String, crate::memtable::Value>,
663 ) -> Result<crate::procedure::ProcedureCallResult> {
664 self.handle.call_procedure(name, args)
665 }
666
667 pub fn create_trigger(
669 &self,
670 trigger: crate::trigger::StoredTrigger,
671 ) -> Result<crate::trigger::StoredTrigger> {
672 self.handle.create_trigger(trigger)
673 }
674
675 pub fn drop_trigger(&self, name: &str) -> Result<()> {
677 self.handle.drop_trigger(name)
678 }
679
680 pub fn rows_at_epoch(
682 &self,
683 table: &str,
684 snapshot: crate::epoch::Snapshot,
685 ) -> Result<Vec<crate::memtable::Row>> {
686 self.handle.rows_at_epoch(table, snapshot)
687 }
688
689 pub fn aggregate_count(&self, table: &str) -> Result<u64> {
691 self.handle.count(table)
692 }
693}
694
695pub struct AuthorizedTransaction<'a> {
701 handle: &'a DatabaseHandle,
702 txn: Option<crate::txn::Transaction<'a>>,
703}
704
705impl<'a> AuthorizedTransaction<'a> {
706 fn txn_mut(&mut self) -> Result<&mut crate::txn::Transaction<'a>> {
707 self.txn
708 .as_mut()
709 .ok_or_else(|| MongrelError::InvalidArgument("transaction already finished".into()))
710 }
711
712 pub fn put(
714 &mut self,
715 table: &str,
716 cells: Vec<(u16, crate::memtable::Value)>,
717 ) -> Result<Option<i64>> {
718 self.handle.authorize_write("put")?;
719 self.handle.resolve_service_authority()?;
720 self.txn_mut()?.put(table, cells)
721 }
722
723 pub fn put_batch(
725 &mut self,
726 table: &str,
727 rows: Vec<Vec<(u16, crate::memtable::Value)>>,
728 ) -> Result<Vec<Option<i64>>> {
729 self.handle.authorize_write("put_batch")?;
730 self.handle.resolve_service_authority()?;
731 self.txn_mut()?.put_batch(table, rows)
732 }
733
734 pub fn update(
736 &mut self,
737 table: &str,
738 row_id: crate::RowId,
739 cells: Vec<(u16, crate::memtable::Value)>,
740 ) -> Result<crate::txn::OwnedRow> {
741 self.handle.authorize_write("update")?;
742 self.handle.resolve_service_authority()?;
743 let mut images = self.txn_mut()?.update_many(table, vec![(row_id, cells)])?;
744 images
745 .pop()
746 .ok_or_else(|| MongrelError::NotFound(format!("row {row_id:?} not found for update")))
747 }
748
749 pub fn delete(&mut self, table: &str, row_id: crate::RowId) -> Result<()> {
751 self.handle.authorize_write("delete")?;
752 self.handle.resolve_service_authority()?;
753 self.txn_mut()?.delete(table, row_id)
754 }
755
756 pub fn commit(mut self) -> Result<crate::epoch::Epoch> {
758 self.handle.authorize_write("commit")?;
759 let txn = self
760 .txn
761 .take()
762 .ok_or_else(|| MongrelError::InvalidArgument("transaction already finished".into()))?;
763 txn.commit()
764 }
765
766 pub fn rollback(mut self) {
768 if let Some(txn) = self.txn.take() {
769 txn.rollback();
770 }
771 }
772}
773
774impl Drop for AuthorizedTransaction<'_> {
775 fn drop(&mut self) {
776 if let Some(txn) = self.txn.take() {
777 txn.rollback();
778 }
779 }
780}
781
782impl std::fmt::Debug for DatabaseHandle {
783 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
784 f.debug_struct("DatabaseHandle")
785 .field("identity", &self.identity)
786 .field("access", &self.access)
787 .field("database", &self.database)
788 .finish()
789 }
790}