1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::storage::{StorageBackend, StorageEntry, StorageError};
6
7const LEASE_PREFIX: &str = "sys/leases/";
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Lease {
11 pub id: Uuid,
12 pub token_id_hash: String,
13 pub engine_mount: String,
16 pub internal_data: serde_json::Value,
17 pub issued_at: DateTime<Utc>,
18 pub expires_at: DateTime<Utc>,
19}
20
21pub async fn store_lease(storage: &dyn StorageBackend, lease: &Lease) -> Result<(), StorageError> {
22 let path = format!("{LEASE_PREFIX}{}", lease.id);
23 let value = serde_json::to_vec(lease).map_err(|e| StorageError::Backend(e.to_string()))?;
24 storage
25 .put(
26 &path,
27 StorageEntry {
28 value,
29 expires_at: Some(lease.expires_at),
30 },
31 )
32 .await
33}
34
35pub async fn get_lease(storage: &dyn StorageBackend, id: Uuid) -> Result<Option<Lease>, StorageError> {
36 let path = format!("{LEASE_PREFIX}{id}");
37 let Some(entry) = storage.get(&path).await? else {
38 return Ok(None);
39 };
40 let lease: Lease =
41 serde_json::from_slice(&entry.value).map_err(|e| StorageError::Backend(e.to_string()))?;
42 Ok(Some(lease))
43}
44
45pub async fn delete_lease(storage: &dyn StorageBackend, id: Uuid) -> Result<(), StorageError> {
46 storage.delete(&format!("{LEASE_PREFIX}{id}")).await
47}
48
49pub async fn list_leases(storage: &dyn StorageBackend) -> Result<Vec<Lease>, StorageError> {
53 let keys = storage.list(LEASE_PREFIX).await?;
54 let mut leases = Vec::with_capacity(keys.len());
55 for key in keys {
56 if let Some(entry) = storage.get(&key).await?
57 && let Ok(lease) = serde_json::from_slice::<Lease>(&entry.value)
58 {
59 leases.push(lease);
60 }
61 }
62 Ok(leases)
63}