mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-04 04:17:44 +00:00
rewrite group handler
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)))?;
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user