covert_system/system/
lease.rs

1use covert_framework::extract::{Extension, Json, Path};
2use covert_types::{
3    methods::system::{
4        LeaseEntry as LeaseEntryDTO, ListLeasesResponse, LookupLeaseResponse, RenewLeaseParams,
5        RenewLeaseResponse, RevokedLeaseResponse, RevokedLeasesResponse,
6    },
7    response::Response,
8};
9
10use crate::{
11    context::Context,
12    error::{Error, ErrorType},
13    expiration_manager::LeaseEntry,
14    repos::namespace::Namespace,
15};
16
17impl From<&LeaseEntry> for LeaseEntryDTO {
18    fn from(le: &LeaseEntry) -> Self {
19        Self {
20            id: le.id.clone(),
21            issued_mount_path: le.issued_mount_path.clone(),
22            issue_time: le.issued_at.to_rfc3339(),
23            expire_time: le.expires_at.to_rfc3339(),
24            last_renewal_time: le.expires_at.to_rfc3339(),
25        }
26    }
27}
28
29pub async fn handle_lease_revocation_by_mount(
30    Extension(ctx): Extension<Context>,
31    Extension(ns): Extension<Namespace>,
32    Path(prefix): Path<String>,
33) -> Result<Response, Error> {
34    let revoked_leases = ctx
35        .expiration_manager
36        .revoke_leases_by_mount_prefix(&prefix, &ns.id)
37        .await?;
38    let resp = RevokedLeasesResponse {
39        leases: revoked_leases.iter().map(LeaseEntryDTO::from).collect(),
40    };
41    Response::raw(resp).map_err(|err| ErrorType::BadResponseData(err).into())
42}
43
44pub async fn handle_lease_revocation(
45    Extension(ctx): Extension<Context>,
46    Extension(ns): Extension<Namespace>,
47    Path(lease_id): Path<String>,
48) -> Result<Response, Error> {
49    let revoked_lease = ctx
50        .expiration_manager
51        .revoke_lease_entry_by_id(&lease_id, &ns.id)
52        .await?;
53    let resp = RevokedLeaseResponse {
54        lease: LeaseEntryDTO::from(&revoked_lease),
55    };
56    Response::raw(resp).map_err(|err| ErrorType::BadResponseData(err).into())
57}
58
59pub async fn handle_list_leases(
60    Extension(ctx): Extension<Context>,
61    Extension(ns): Extension<Namespace>,
62    Path(prefix): Path<String>,
63) -> Result<Response, Error> {
64    let leases = ctx
65        .expiration_manager
66        .list_by_mount_prefix(&prefix, &ns.id)
67        .await?;
68    let resp = ListLeasesResponse {
69        leases: leases.iter().map(LeaseEntryDTO::from).collect(),
70    };
71    Response::raw(resp).map_err(|err| ErrorType::BadResponseData(err).into())
72}
73
74pub async fn handle_lease_lookup(
75    Extension(ctx): Extension<Context>,
76    Extension(ns): Extension<Namespace>,
77    Path(lease_id): Path<String>,
78) -> Result<Response, Error> {
79    let lease = ctx
80        .expiration_manager
81        .lookup(&lease_id, &ns.id)
82        .await?
83        .ok_or_else(|| ErrorType::NotFound(format!("Lease `{lease_id}` not found")))?;
84    let resp = LookupLeaseResponse {
85        lease: LeaseEntryDTO::from(&lease),
86    };
87    Response::raw(resp).map_err(|err| ErrorType::BadResponseData(err).into())
88}
89
90pub async fn handle_lease_renew(
91    Extension(ctx): Extension<Context>,
92    Extension(ns): Extension<Namespace>,
93    Json(body): Json<RenewLeaseParams>,
94    Path(lease_id): Path<String>,
95) -> Result<Response, Error> {
96    let lease = ctx
97        .expiration_manager
98        .renew_lease_entry(&lease_id, &ns.id, body.ttl)
99        .await?;
100    let resp = RenewLeaseResponse {
101        lease: LeaseEntryDTO::from(&lease),
102    };
103    Response::raw(resp).map_err(|err| ErrorType::BadResponseData(err).into())
104}