mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-22 02:36:38 +00:00
admin api: make all handlers impls of a single trait
This commit is contained in:
+298
-252
@@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
use hyper::{body::Incoming as IncomingBody, Request, Response, StatusCode};
|
||||
use async_trait::async_trait;
|
||||
|
||||
use garage_util::crdt::*;
|
||||
use garage_util::data::*;
|
||||
@@ -18,83 +18,93 @@ use garage_model::s3::object_table::*;
|
||||
|
||||
use crate::admin::api::ApiBucketKeyPerm;
|
||||
use crate::admin::api::{
|
||||
ApiBucketQuotas, BucketKeyPermChangeRequest, BucketLocalAlias, CreateBucketRequest,
|
||||
GetBucketInfoKey, GetBucketInfoResponse, GetBucketInfoWebsiteResponse, ListBucketsResponseItem,
|
||||
UpdateBucketRequest,
|
||||
ApiBucketQuotas, BucketAllowKeyRequest, BucketAllowKeyResponse, BucketDenyKeyRequest,
|
||||
BucketDenyKeyResponse, BucketKeyPermChangeRequest, BucketLocalAlias, CreateBucketRequest,
|
||||
CreateBucketResponse, DeleteBucketRequest, DeleteBucketResponse, GetBucketInfoKey,
|
||||
GetBucketInfoRequest, GetBucketInfoResponse, GetBucketInfoWebsiteResponse,
|
||||
GlobalAliasBucketRequest, GlobalAliasBucketResponse, GlobalUnaliasBucketRequest,
|
||||
GlobalUnaliasBucketResponse, ListBucketsRequest, ListBucketsResponse, ListBucketsResponseItem,
|
||||
LocalAliasBucketRequest, LocalAliasBucketResponse, LocalUnaliasBucketRequest,
|
||||
LocalUnaliasBucketResponse, UpdateBucketRequest, UpdateBucketResponse,
|
||||
};
|
||||
use crate::admin::api_server::ResBody;
|
||||
use crate::admin::error::*;
|
||||
use crate::admin::EndpointHandler;
|
||||
use crate::common_error::CommonError;
|
||||
use crate::helpers::*;
|
||||
|
||||
pub async fn handle_list_buckets(garage: &Arc<Garage>) -> Result<Response<ResBody>, Error> {
|
||||
let buckets = garage
|
||||
.bucket_table
|
||||
.get_range(
|
||||
&EmptyKey,
|
||||
None,
|
||||
Some(DeletedFilter::NotDeleted),
|
||||
10000,
|
||||
EnumerationOrder::Forward,
|
||||
)
|
||||
.await?;
|
||||
#[async_trait]
|
||||
impl EndpointHandler for ListBucketsRequest {
|
||||
type Response = ListBucketsResponse;
|
||||
|
||||
let res = buckets
|
||||
.into_iter()
|
||||
.map(|b| {
|
||||
let state = b.state.as_option().unwrap();
|
||||
ListBucketsResponseItem {
|
||||
id: hex::encode(b.id),
|
||||
global_aliases: state
|
||||
.aliases
|
||||
.items()
|
||||
.iter()
|
||||
.filter(|(_, _, a)| *a)
|
||||
.map(|(n, _, _)| n.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
local_aliases: state
|
||||
.local_aliases
|
||||
.items()
|
||||
.iter()
|
||||
.filter(|(_, _, a)| *a)
|
||||
.map(|((k, n), _, _)| BucketLocalAlias {
|
||||
access_key_id: k.to_string(),
|
||||
alias: n.to_string(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<ListBucketsResponse, Error> {
|
||||
let buckets = garage
|
||||
.bucket_table
|
||||
.get_range(
|
||||
&EmptyKey,
|
||||
None,
|
||||
Some(DeletedFilter::NotDeleted),
|
||||
10000,
|
||||
EnumerationOrder::Forward,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(json_ok_response(&res)?)
|
||||
let res = buckets
|
||||
.into_iter()
|
||||
.map(|b| {
|
||||
let state = b.state.as_option().unwrap();
|
||||
ListBucketsResponseItem {
|
||||
id: hex::encode(b.id),
|
||||
global_aliases: state
|
||||
.aliases
|
||||
.items()
|
||||
.iter()
|
||||
.filter(|(_, _, a)| *a)
|
||||
.map(|(n, _, _)| n.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
local_aliases: state
|
||||
.local_aliases
|
||||
.items()
|
||||
.iter()
|
||||
.filter(|(_, _, a)| *a)
|
||||
.map(|((k, n), _, _)| BucketLocalAlias {
|
||||
access_key_id: k.to_string(),
|
||||
alias: n.to_string(),
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(ListBucketsResponse(res))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_get_bucket_info(
|
||||
garage: &Arc<Garage>,
|
||||
id: Option<String>,
|
||||
global_alias: Option<String>,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let bucket_id = match (id, global_alias) {
|
||||
(Some(id), None) => parse_bucket_id(&id)?,
|
||||
(None, Some(ga)) => garage
|
||||
.bucket_helper()
|
||||
.resolve_global_bucket_name(&ga)
|
||||
.await?
|
||||
.ok_or_else(|| HelperError::NoSuchBucket(ga.to_string()))?,
|
||||
_ => {
|
||||
return Err(Error::bad_request(
|
||||
"Either id or globalAlias must be provided (but not both)",
|
||||
));
|
||||
}
|
||||
};
|
||||
#[async_trait]
|
||||
impl EndpointHandler for GetBucketInfoRequest {
|
||||
type Response = GetBucketInfoResponse;
|
||||
|
||||
bucket_info_results(garage, bucket_id).await
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<GetBucketInfoResponse, Error> {
|
||||
let bucket_id = match (self.id, self.global_alias) {
|
||||
(Some(id), None) => parse_bucket_id(&id)?,
|
||||
(None, Some(ga)) => garage
|
||||
.bucket_helper()
|
||||
.resolve_global_bucket_name(&ga)
|
||||
.await?
|
||||
.ok_or_else(|| HelperError::NoSuchBucket(ga.to_string()))?,
|
||||
_ => {
|
||||
return Err(Error::bad_request(
|
||||
"Either id or globalAlias must be provided (but not both)",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
bucket_info_results(garage, bucket_id).await
|
||||
}
|
||||
}
|
||||
|
||||
async fn bucket_info_results(
|
||||
garage: &Arc<Garage>,
|
||||
bucket_id: Uuid,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
) -> Result<GetBucketInfoResponse, Error> {
|
||||
let bucket = garage
|
||||
.bucket_helper()
|
||||
.get_existing_bucket(bucket_id)
|
||||
@@ -211,181 +221,203 @@ async fn bucket_info_results(
|
||||
},
|
||||
};
|
||||
|
||||
Ok(json_ok_response(&res)?)
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub async fn handle_create_bucket(
|
||||
garage: &Arc<Garage>,
|
||||
req: Request<IncomingBody>,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let req = parse_json_body::<CreateBucketRequest, _, Error>(req).await?;
|
||||
#[async_trait]
|
||||
impl EndpointHandler for CreateBucketRequest {
|
||||
type Response = CreateBucketResponse;
|
||||
|
||||
let helper = garage.locked_helper().await;
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<CreateBucketResponse, Error> {
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
if let Some(ga) = &req.global_alias {
|
||||
if !is_valid_bucket_name(ga) {
|
||||
return Err(Error::bad_request(format!(
|
||||
"{}: {}",
|
||||
ga, INVALID_BUCKET_NAME_MESSAGE
|
||||
)));
|
||||
}
|
||||
if let Some(ga) = &self.global_alias {
|
||||
if !is_valid_bucket_name(ga) {
|
||||
return Err(Error::bad_request(format!(
|
||||
"{}: {}",
|
||||
ga, INVALID_BUCKET_NAME_MESSAGE
|
||||
)));
|
||||
}
|
||||
|
||||
if let Some(alias) = garage.bucket_alias_table.get(&EmptyKey, ga).await? {
|
||||
if alias.state.get().is_some() {
|
||||
return Err(CommonError::BucketAlreadyExists.into());
|
||||
if let Some(alias) = garage.bucket_alias_table.get(&EmptyKey, ga).await? {
|
||||
if alias.state.get().is_some() {
|
||||
return Err(CommonError::BucketAlreadyExists.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(la) = &req.local_alias {
|
||||
if !is_valid_bucket_name(&la.alias) {
|
||||
return Err(Error::bad_request(format!(
|
||||
"{}: {}",
|
||||
la.alias, INVALID_BUCKET_NAME_MESSAGE
|
||||
)));
|
||||
if let Some(la) = &self.local_alias {
|
||||
if !is_valid_bucket_name(&la.alias) {
|
||||
return Err(Error::bad_request(format!(
|
||||
"{}: {}",
|
||||
la.alias, INVALID_BUCKET_NAME_MESSAGE
|
||||
)));
|
||||
}
|
||||
|
||||
let key = helper.key().get_existing_key(&la.access_key_id).await?;
|
||||
let state = key.state.as_option().unwrap();
|
||||
if matches!(state.local_aliases.get(&la.alias), Some(_)) {
|
||||
return Err(Error::bad_request("Local alias already exists"));
|
||||
}
|
||||
}
|
||||
|
||||
let key = helper.key().get_existing_key(&la.access_key_id).await?;
|
||||
let state = key.state.as_option().unwrap();
|
||||
if matches!(state.local_aliases.get(&la.alias), Some(_)) {
|
||||
return Err(Error::bad_request("Local alias already exists"));
|
||||
let bucket = Bucket::new();
|
||||
garage.bucket_table.insert(&bucket).await?;
|
||||
|
||||
if let Some(ga) = &self.global_alias {
|
||||
helper.set_global_bucket_alias(bucket.id, ga).await?;
|
||||
}
|
||||
|
||||
if let Some(la) = &self.local_alias {
|
||||
helper
|
||||
.set_local_bucket_alias(bucket.id, &la.access_key_id, &la.alias)
|
||||
.await?;
|
||||
|
||||
if la.allow.read || la.allow.write || la.allow.owner {
|
||||
helper
|
||||
.set_bucket_key_permissions(
|
||||
bucket.id,
|
||||
&la.access_key_id,
|
||||
BucketKeyPerm {
|
||||
timestamp: now_msec(),
|
||||
allow_read: la.allow.read,
|
||||
allow_write: la.allow.write,
|
||||
allow_owner: la.allow.owner,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(CreateBucketResponse(
|
||||
bucket_info_results(garage, bucket.id).await?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
let bucket = Bucket::new();
|
||||
garage.bucket_table.insert(&bucket).await?;
|
||||
#[async_trait]
|
||||
impl EndpointHandler for DeleteBucketRequest {
|
||||
type Response = DeleteBucketResponse;
|
||||
|
||||
if let Some(ga) = &req.global_alias {
|
||||
helper.set_global_bucket_alias(bucket.id, ga).await?;
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<DeleteBucketResponse, Error> {
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
let bucket_id = parse_bucket_id(&self.id)?;
|
||||
|
||||
let mut bucket = helper.bucket().get_existing_bucket(bucket_id).await?;
|
||||
let state = bucket.state.as_option().unwrap();
|
||||
|
||||
// Check bucket is empty
|
||||
if !helper.bucket().is_bucket_empty(bucket_id).await? {
|
||||
return Err(CommonError::BucketNotEmpty.into());
|
||||
}
|
||||
|
||||
// --- done checking, now commit ---
|
||||
// 1. delete authorization from keys that had access
|
||||
for (key_id, perm) in bucket.authorized_keys() {
|
||||
if perm.is_any() {
|
||||
helper
|
||||
.set_bucket_key_permissions(bucket.id, key_id, BucketKeyPerm::NO_PERMISSIONS)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
// 2. delete all local aliases
|
||||
for ((key_id, alias), _, active) in state.local_aliases.items().iter() {
|
||||
if *active {
|
||||
helper
|
||||
.unset_local_bucket_alias(bucket.id, key_id, alias)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
// 3. delete all global aliases
|
||||
for (alias, _, active) in state.aliases.items().iter() {
|
||||
if *active {
|
||||
helper.purge_global_bucket_alias(bucket.id, alias).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. delete bucket
|
||||
bucket.state = Deletable::delete();
|
||||
garage.bucket_table.insert(&bucket).await?;
|
||||
|
||||
Ok(DeleteBucketResponse)
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(la) = &req.local_alias {
|
||||
helper
|
||||
.set_local_bucket_alias(bucket.id, &la.access_key_id, &la.alias)
|
||||
#[async_trait]
|
||||
impl EndpointHandler for UpdateBucketRequest {
|
||||
type Response = UpdateBucketResponse;
|
||||
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<UpdateBucketResponse, Error> {
|
||||
let bucket_id = parse_bucket_id(&self.id)?;
|
||||
|
||||
let mut bucket = garage
|
||||
.bucket_helper()
|
||||
.get_existing_bucket(bucket_id)
|
||||
.await?;
|
||||
|
||||
if la.allow.read || la.allow.write || la.allow.owner {
|
||||
helper
|
||||
.set_bucket_key_permissions(
|
||||
bucket.id,
|
||||
&la.access_key_id,
|
||||
BucketKeyPerm {
|
||||
timestamp: now_msec(),
|
||||
allow_read: la.allow.read,
|
||||
allow_write: la.allow.write,
|
||||
allow_owner: la.allow.owner,
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
let state = bucket.state.as_option_mut().unwrap();
|
||||
|
||||
bucket_info_results(garage, bucket.id).await
|
||||
}
|
||||
|
||||
pub async fn handle_delete_bucket(
|
||||
garage: &Arc<Garage>,
|
||||
id: String,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
let bucket_id = parse_bucket_id(&id)?;
|
||||
|
||||
let mut bucket = helper.bucket().get_existing_bucket(bucket_id).await?;
|
||||
let state = bucket.state.as_option().unwrap();
|
||||
|
||||
// Check bucket is empty
|
||||
if !helper.bucket().is_bucket_empty(bucket_id).await? {
|
||||
return Err(CommonError::BucketNotEmpty.into());
|
||||
}
|
||||
|
||||
// --- done checking, now commit ---
|
||||
// 1. delete authorization from keys that had access
|
||||
for (key_id, perm) in bucket.authorized_keys() {
|
||||
if perm.is_any() {
|
||||
helper
|
||||
.set_bucket_key_permissions(bucket.id, key_id, BucketKeyPerm::NO_PERMISSIONS)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
// 2. delete all local aliases
|
||||
for ((key_id, alias), _, active) in state.local_aliases.items().iter() {
|
||||
if *active {
|
||||
helper
|
||||
.unset_local_bucket_alias(bucket.id, key_id, alias)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
// 3. delete all global aliases
|
||||
for (alias, _, active) in state.aliases.items().iter() {
|
||||
if *active {
|
||||
helper.purge_global_bucket_alias(bucket.id, alias).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. delete bucket
|
||||
bucket.state = Deletable::delete();
|
||||
garage.bucket_table.insert(&bucket).await?;
|
||||
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::NO_CONTENT)
|
||||
.body(empty_body())?)
|
||||
}
|
||||
|
||||
pub async fn handle_update_bucket(
|
||||
garage: &Arc<Garage>,
|
||||
id: String,
|
||||
req: Request<IncomingBody>,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let req = parse_json_body::<UpdateBucketRequest, _, Error>(req).await?;
|
||||
let bucket_id = parse_bucket_id(&id)?;
|
||||
|
||||
let mut bucket = garage
|
||||
.bucket_helper()
|
||||
.get_existing_bucket(bucket_id)
|
||||
.await?;
|
||||
|
||||
let state = bucket.state.as_option_mut().unwrap();
|
||||
|
||||
if let Some(wa) = req.website_access {
|
||||
if wa.enabled {
|
||||
state.website_config.update(Some(WebsiteConfig {
|
||||
index_document: wa.index_document.ok_or_bad_request(
|
||||
"Please specify indexDocument when enabling website access.",
|
||||
)?,
|
||||
error_document: wa.error_document,
|
||||
}));
|
||||
} else {
|
||||
if wa.index_document.is_some() || wa.error_document.is_some() {
|
||||
return Err(Error::bad_request(
|
||||
"Cannot specify indexDocument or errorDocument when disabling website access.",
|
||||
));
|
||||
if let Some(wa) = self.params.website_access {
|
||||
if wa.enabled {
|
||||
state.website_config.update(Some(WebsiteConfig {
|
||||
index_document: wa.index_document.ok_or_bad_request(
|
||||
"Please specify indexDocument when enabling website access.",
|
||||
)?,
|
||||
error_document: wa.error_document,
|
||||
}));
|
||||
} else {
|
||||
if wa.index_document.is_some() || wa.error_document.is_some() {
|
||||
return Err(Error::bad_request(
|
||||
"Cannot specify indexDocument or errorDocument when disabling website access.",
|
||||
));
|
||||
}
|
||||
state.website_config.update(None);
|
||||
}
|
||||
state.website_config.update(None);
|
||||
}
|
||||
|
||||
if let Some(q) = self.params.quotas {
|
||||
state.quotas.update(BucketQuotas {
|
||||
max_size: q.max_size,
|
||||
max_objects: q.max_objects,
|
||||
});
|
||||
}
|
||||
|
||||
garage.bucket_table.insert(&bucket).await?;
|
||||
|
||||
Ok(UpdateBucketResponse(
|
||||
bucket_info_results(garage, bucket_id).await?,
|
||||
))
|
||||
}
|
||||
|
||||
if let Some(q) = req.quotas {
|
||||
state.quotas.update(BucketQuotas {
|
||||
max_size: q.max_size,
|
||||
max_objects: q.max_objects,
|
||||
});
|
||||
}
|
||||
|
||||
garage.bucket_table.insert(&bucket).await?;
|
||||
|
||||
bucket_info_results(garage, bucket_id).await
|
||||
}
|
||||
|
||||
// ---- BUCKET/KEY PERMISSIONS ----
|
||||
|
||||
#[async_trait]
|
||||
impl EndpointHandler for BucketAllowKeyRequest {
|
||||
type Response = BucketAllowKeyResponse;
|
||||
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<BucketAllowKeyResponse, Error> {
|
||||
let res = handle_bucket_change_key_perm(garage, self.0, true).await?;
|
||||
Ok(BucketAllowKeyResponse(res))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EndpointHandler for BucketDenyKeyRequest {
|
||||
type Response = BucketDenyKeyResponse;
|
||||
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<BucketDenyKeyResponse, Error> {
|
||||
let res = handle_bucket_change_key_perm(garage, self.0, false).await?;
|
||||
Ok(BucketDenyKeyResponse(res))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_bucket_change_key_perm(
|
||||
garage: &Arc<Garage>,
|
||||
req: Request<IncomingBody>,
|
||||
req: BucketKeyPermChangeRequest,
|
||||
new_perm_flag: bool,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let req = parse_json_body::<BucketKeyPermChangeRequest, _, Error>(req).await?;
|
||||
|
||||
) -> Result<GetBucketInfoResponse, Error> {
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
let bucket_id = parse_bucket_id(&req.bucket_id)?;
|
||||
@@ -420,66 +452,80 @@ pub async fn handle_bucket_change_key_perm(
|
||||
|
||||
// ---- BUCKET ALIASES ----
|
||||
|
||||
pub async fn handle_global_alias_bucket(
|
||||
garage: &Arc<Garage>,
|
||||
bucket_id: String,
|
||||
alias: String,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let bucket_id = parse_bucket_id(&bucket_id)?;
|
||||
#[async_trait]
|
||||
impl EndpointHandler for GlobalAliasBucketRequest {
|
||||
type Response = GlobalAliasBucketResponse;
|
||||
|
||||
let helper = garage.locked_helper().await;
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<GlobalAliasBucketResponse, Error> {
|
||||
let bucket_id = parse_bucket_id(&self.id)?;
|
||||
|
||||
helper.set_global_bucket_alias(bucket_id, &alias).await?;
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
bucket_info_results(garage, bucket_id).await
|
||||
helper
|
||||
.set_global_bucket_alias(bucket_id, &self.alias)
|
||||
.await?;
|
||||
|
||||
Ok(GlobalAliasBucketResponse(
|
||||
bucket_info_results(garage, bucket_id).await?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_global_unalias_bucket(
|
||||
garage: &Arc<Garage>,
|
||||
bucket_id: String,
|
||||
alias: String,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let bucket_id = parse_bucket_id(&bucket_id)?;
|
||||
#[async_trait]
|
||||
impl EndpointHandler for GlobalUnaliasBucketRequest {
|
||||
type Response = GlobalUnaliasBucketResponse;
|
||||
|
||||
let helper = garage.locked_helper().await;
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<GlobalUnaliasBucketResponse, Error> {
|
||||
let bucket_id = parse_bucket_id(&self.id)?;
|
||||
|
||||
helper.unset_global_bucket_alias(bucket_id, &alias).await?;
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
bucket_info_results(garage, bucket_id).await
|
||||
helper
|
||||
.unset_global_bucket_alias(bucket_id, &self.alias)
|
||||
.await?;
|
||||
|
||||
Ok(GlobalUnaliasBucketResponse(
|
||||
bucket_info_results(garage, bucket_id).await?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_local_alias_bucket(
|
||||
garage: &Arc<Garage>,
|
||||
bucket_id: String,
|
||||
access_key_id: String,
|
||||
alias: String,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let bucket_id = parse_bucket_id(&bucket_id)?;
|
||||
#[async_trait]
|
||||
impl EndpointHandler for LocalAliasBucketRequest {
|
||||
type Response = LocalAliasBucketResponse;
|
||||
|
||||
let helper = garage.locked_helper().await;
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<LocalAliasBucketResponse, Error> {
|
||||
let bucket_id = parse_bucket_id(&self.id)?;
|
||||
|
||||
helper
|
||||
.set_local_bucket_alias(bucket_id, &access_key_id, &alias)
|
||||
.await?;
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
bucket_info_results(garage, bucket_id).await
|
||||
helper
|
||||
.set_local_bucket_alias(bucket_id, &self.access_key_id, &self.alias)
|
||||
.await?;
|
||||
|
||||
Ok(LocalAliasBucketResponse(
|
||||
bucket_info_results(garage, bucket_id).await?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_local_unalias_bucket(
|
||||
garage: &Arc<Garage>,
|
||||
bucket_id: String,
|
||||
access_key_id: String,
|
||||
alias: String,
|
||||
) -> Result<Response<ResBody>, Error> {
|
||||
let bucket_id = parse_bucket_id(&bucket_id)?;
|
||||
#[async_trait]
|
||||
impl EndpointHandler for LocalUnaliasBucketRequest {
|
||||
type Response = LocalUnaliasBucketResponse;
|
||||
|
||||
let helper = garage.locked_helper().await;
|
||||
async fn handle(self, garage: &Arc<Garage>) -> Result<LocalUnaliasBucketResponse, Error> {
|
||||
let bucket_id = parse_bucket_id(&self.id)?;
|
||||
|
||||
helper
|
||||
.unset_local_bucket_alias(bucket_id, &access_key_id, &alias)
|
||||
.await?;
|
||||
let helper = garage.locked_helper().await;
|
||||
|
||||
bucket_info_results(garage, bucket_id).await
|
||||
helper
|
||||
.unset_local_bucket_alias(bucket_id, &self.access_key_id, &self.alias)
|
||||
.await?;
|
||||
|
||||
Ok(LocalUnaliasBucketResponse(
|
||||
bucket_info_results(garage, bucket_id).await?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// ---- HELPER ----
|
||||
|
||||
Reference in New Issue
Block a user