rewrite group handler

This commit is contained in:
weisd
2025-01-21 16:44:55 +08:00
parent 4f1cbf72c6
commit 9535a9a7ad
6 changed files with 172 additions and 43 deletions
+9 -11
View File
@@ -97,19 +97,19 @@ pub async fn collect_local_metrics(types: MetricType, opts: &CollectMetricsOpts)
real_time_metrics.aggregated.scanner = Some(metrics);
}
if types.contains(&MetricType::OS) {}
// if types.contains(&MetricType::OS) {}
if types.contains(&MetricType::BATCH_JOBS) {}
// if types.contains(&MetricType::BATCH_JOBS) {}
if types.contains(&MetricType::SITE_RESYNC) {}
// if types.contains(&MetricType::SITE_RESYNC) {}
if types.contains(&MetricType::NET) {}
// if types.contains(&MetricType::NET) {}
if types.contains(&MetricType::MEM) {}
// if types.contains(&MetricType::MEM) {}
if types.contains(&MetricType::CPU) {}
// if types.contains(&MetricType::CPU) {}
if types.contains(&MetricType::RPC) {}
// if types.contains(&MetricType::RPC) {}
real_time_metrics
.by_host
@@ -128,10 +128,8 @@ async fn collect_local_disks_metrics(disks: &HashSet<String>) -> HashMap<String,
let mut metrics = HashMap::new();
let storage_info = store.local_storage_info().await;
for d in storage_info.disks.iter() {
if !disks.is_empty() {
if !disks.contains(&d.endpoint) {
continue;
}
if !disks.is_empty() && !disks.contains(&d.endpoint) {
continue;
}
if d.state != *DRIVE_STATE_OK && d.state != *DRIVE_STATE_UNFORMATTED {
+1 -1
View File
@@ -8,7 +8,7 @@ use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::collections::HashMap;
use time::{Duration, OffsetDateTime};
use time::OffsetDateTime;
const ACCESS_KEY_MIN_LEN: usize = 3;
const ACCESS_KEY_MAX_LEN: usize = 20;
+1 -1
View File
@@ -11,7 +11,7 @@ pub enum GroupStatus {
#[derive(Debug, Serialize, Deserialize)]
pub struct GroupAddRemove {
group: String,
pub group: String,
pub members: Vec<String>,
#[serde(rename = "groupStatus")]
pub status: GroupStatus,
+127 -21
View File
@@ -1,11 +1,22 @@
use http::StatusCode;
use iam::{error::is_err_no_such_user, get_global_action_cred};
use http::{HeaderMap, StatusCode};
use iam::{
error::{is_err_no_such_group, is_err_no_such_user},
get_global_action_cred,
};
use madmin::GroupAddRemove;
use matchit::Params;
use s3s::{s3_error, Body, S3Error, S3ErrorCode, S3Request, S3Response, S3Result};
use s3s::{header::CONTENT_TYPE, s3_error, Body, S3Error, S3ErrorCode, S3Request, S3Response, S3Result};
use serde::Deserialize;
use serde_urlencoded::from_bytes;
use tracing::warn;
use crate::admin::router::Operation;
use crate::admin::{router::Operation, utils::has_space_be};
#[derive(Debug, Deserialize, Default)]
pub struct GroupQuery {
pub group: String,
pub status: Option<String>,
}
pub struct ListGroups {}
#[async_trait::async_trait]
@@ -13,17 +24,101 @@ impl Operation for ListGroups {
async fn call(&self, _req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
warn!("handle ListGroups");
Err(s3_error!(NotImplemented))
let Ok(iam_store) = iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };
let groups = iam_store.list_groups().await.map_err(|e| {
warn!("list groups failed, e: {:?}", e);
S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
})?;
let body = serde_json::to_vec(&groups).map_err(|e| s3_error!(InternalError, "marshal body failed, e: {:?}", e))?;
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
Ok(S3Response::with_headers((StatusCode::OK, Body::from(body)), header))
}
}
pub struct Group {}
pub struct GetGroup {}
#[async_trait::async_trait]
impl Operation for Group {
async fn call(&self, _req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
warn!("handle Group");
impl Operation for GetGroup {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
warn!("handle GetGroup");
Err(s3_error!(NotImplemented))
let query = {
if let Some(query) = req.uri.query() {
let input: GroupQuery =
from_bytes(query.as_bytes()).map_err(|_e| s3_error!(InvalidArgument, "get body failed1"))?;
input
} else {
GroupQuery::default()
}
};
let Ok(iam_store) = iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };
let g = iam_store.get_group_description(&query.group).await.map_err(|e| {
warn!("get group failed, e: {:?}", e);
S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
})?;
let body = serde_json::to_vec(&g).map_err(|e| s3_error!(InternalError, "marshal body failed, e: {:?}", e))?;
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
Ok(S3Response::with_headers((StatusCode::OK, Body::from(body)), header))
}
}
pub struct SetGroupStatus {}
#[async_trait::async_trait]
impl Operation for SetGroupStatus {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
warn!("handle SetGroupStatus");
let query = {
if let Some(query) = req.uri.query() {
let input: GroupQuery =
from_bytes(query.as_bytes()).map_err(|_e| s3_error!(InvalidArgument, "get body failed1"))?;
input
} else {
GroupQuery::default()
}
};
if query.group.is_empty() {
return Err(s3_error!(InvalidArgument, "group is required"));
}
let Ok(iam_store) = iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };
if let Some(status) = query.status {
match status.as_str() {
"enabled" => {
iam_store.set_group_status(&query.group, true).await.map_err(|e| {
warn!("enable group failed, e: {:?}", e);
S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
})?;
}
"disabled" => {
iam_store.set_group_status(&query.group, false).await.map_err(|e| {
warn!("enable group failed, e: {:?}", e);
S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
})?;
}
_ => {
return Err(s3_error!(InvalidArgument, "invalid status"));
}
}
} else {
return Err(s3_error!(InvalidArgument, "status is required"));
}
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header))
}
}
@@ -83,20 +178,31 @@ impl Operation for UpdateGroupMembers {
if args.is_remove {
warn!("remove group members");
iam_store
.remove_users_from_group(&args.group, args.members)
.await
.map_err(|e| {
warn!("remove group members failed, e: {:?}", e);
S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
})?;
} else {
warn!("add group members");
if let Err(err) = iam_store.get_group_description(&args.group).await {
if is_err_no_such_group(&err) && has_space_be(&args.group) {
return Err(s3_error!(InvalidArgument, "not such group"));
}
}
iam_store.add_users_to_group(&args.group, args.members).await.map_err(|e| {
warn!("add group members failed, e: {:?}", e);
S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
})?;
}
Err(s3_error!(NotImplemented))
}
}
pub struct SetGroupStatus {}
#[async_trait::async_trait]
impl Operation for SetGroupStatus {
async fn call(&self, _req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
warn!("handle SetGroupStatus");
Err(s3_error!(NotImplemented))
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header))
}
}
+30 -5
View File
@@ -156,17 +156,42 @@ impl Operation for SetUserStatus {
}
}
#[derive(Debug, Deserialize, Default)]
pub struct BucketQuery {
#[serde(rename = "bucket")]
pub bucket: String,
}
pub struct ListUsers {}
#[async_trait::async_trait]
impl Operation for ListUsers {
async fn call(&self, _req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
async fn call(&self, req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
warn!("handle ListUsers");
let query = {
if let Some(query) = req.uri.query() {
let input: BucketQuery =
from_bytes(query.as_bytes()).map_err(|_e| s3_error!(InvalidArgument, "get body failed"))?;
input
} else {
BucketQuery::default()
}
};
let Ok(iam_store) = iam::get() else { return Err(s3_error!(InvalidRequest, "iam not init")) };
let users = iam_store
.list_users()
.await
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?;
let users = {
if !query.bucket.is_empty() {
iam_store
.list_bucket_users(query.bucket.as_str())
.await
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?
} else {
iam_store
.list_users()
.await
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?
}
};
let data = serde_json::to_vec(&users)
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("marshal users err {}", e)))?;
+4 -4
View File
@@ -171,7 +171,7 @@ fn regist_user_route(r: &mut S3Router<AdminOperation>) -> Result<()> {
r.insert(
Method::GET,
format!("{}{}", ADMIN_PREFIX, "/v3/group").as_str(),
AdminOperation(&group::Group {}),
AdminOperation(&group::GetGroup {}),
)?;
r.insert(
@@ -192,7 +192,7 @@ fn regist_user_route(r: &mut S3Router<AdminOperation>) -> Result<()> {
format!("{}{}", ADMIN_PREFIX, "/v3/update-service-account").as_str(),
AdminOperation(&UpdateServiceAccount {}),
)?;
// 1
r.insert(
Method::GET,
format!("{}{}", ADMIN_PREFIX, "/v3/info-service-account").as_str(),
@@ -205,13 +205,13 @@ fn regist_user_route(r: &mut S3Router<AdminOperation>) -> Result<()> {
format!("{}{}", ADMIN_PREFIX, "/v3/list-service-accounts").as_str(),
AdminOperation(&ListServiceAccount {}),
)?;
// 1
r.insert(
Method::DELETE,
format!("{}{}", ADMIN_PREFIX, "/v3/delete-service-accounts").as_str(),
AdminOperation(&DeleteServiceAccount {}),
)?;
// 1
r.insert(
Method::PUT,
format!("{}{}", ADMIN_PREFIX, "/v3/add-service-accounts").as_str(),