mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-01 01:38:18 +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);
|
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
|
real_time_metrics
|
||||||
.by_host
|
.by_host
|
||||||
@@ -128,10 +128,8 @@ async fn collect_local_disks_metrics(disks: &HashSet<String>) -> HashMap<String,
|
|||||||
let mut metrics = HashMap::new();
|
let mut metrics = HashMap::new();
|
||||||
let storage_info = store.local_storage_info().await;
|
let storage_info = store.local_storage_info().await;
|
||||||
for d in storage_info.disks.iter() {
|
for d in storage_info.disks.iter() {
|
||||||
if !disks.is_empty() {
|
if !disks.is_empty() && !disks.contains(&d.endpoint) {
|
||||||
if !disks.contains(&d.endpoint) {
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.state != *DRIVE_STATE_OK && d.state != *DRIVE_STATE_UNFORMATTED {
|
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::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use time::{Duration, OffsetDateTime};
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
const ACCESS_KEY_MIN_LEN: usize = 3;
|
const ACCESS_KEY_MIN_LEN: usize = 3;
|
||||||
const ACCESS_KEY_MAX_LEN: usize = 20;
|
const ACCESS_KEY_MAX_LEN: usize = 20;
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ pub enum GroupStatus {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct GroupAddRemove {
|
pub struct GroupAddRemove {
|
||||||
group: String,
|
pub group: String,
|
||||||
pub members: Vec<String>,
|
pub members: Vec<String>,
|
||||||
#[serde(rename = "groupStatus")]
|
#[serde(rename = "groupStatus")]
|
||||||
pub status: GroupStatus,
|
pub status: GroupStatus,
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
use http::StatusCode;
|
use http::{HeaderMap, StatusCode};
|
||||||
use iam::{error::is_err_no_such_user, get_global_action_cred};
|
use iam::{
|
||||||
|
error::{is_err_no_such_group, is_err_no_such_user},
|
||||||
|
get_global_action_cred,
|
||||||
|
};
|
||||||
use madmin::GroupAddRemove;
|
use madmin::GroupAddRemove;
|
||||||
use matchit::Params;
|
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 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 {}
|
pub struct ListGroups {}
|
||||||
#[async_trait::async_trait]
|
#[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)>> {
|
async fn call(&self, _req: S3Request<Body>, _params: Params<'_, '_>) -> S3Result<S3Response<(StatusCode, Body)>> {
|
||||||
warn!("handle ListGroups");
|
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]
|
#[async_trait::async_trait]
|
||||||
impl Operation for Group {
|
impl Operation for GetGroup {
|
||||||
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 Group");
|
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 {
|
if args.is_remove {
|
||||||
warn!("remove group members");
|
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 {
|
} else {
|
||||||
warn!("add group members");
|
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))
|
let mut header = HeaderMap::new();
|
||||||
}
|
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
|
||||||
}
|
|
||||||
|
Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), 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");
|
|
||||||
|
|
||||||
Err(s3_error!(NotImplemented))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,17 +156,42 @@ impl Operation for SetUserStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Default)]
|
||||||
|
pub struct BucketQuery {
|
||||||
|
#[serde(rename = "bucket")]
|
||||||
|
pub bucket: String,
|
||||||
|
}
|
||||||
pub struct ListUsers {}
|
pub struct ListUsers {}
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
impl Operation for ListUsers {
|
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");
|
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 Ok(iam_store) = iam::get() else { return Err(s3_error!(InvalidRequest, "iam not init")) };
|
||||||
|
|
||||||
let users = iam_store
|
let users = {
|
||||||
.list_users()
|
if !query.bucket.is_empty() {
|
||||||
.await
|
iam_store
|
||||||
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?;
|
.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)
|
let data = serde_json::to_vec(&users)
|
||||||
.map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("marshal users err {}", e)))?;
|
.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(
|
r.insert(
|
||||||
Method::GET,
|
Method::GET,
|
||||||
format!("{}{}", ADMIN_PREFIX, "/v3/group").as_str(),
|
format!("{}{}", ADMIN_PREFIX, "/v3/group").as_str(),
|
||||||
AdminOperation(&group::Group {}),
|
AdminOperation(&group::GetGroup {}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
r.insert(
|
r.insert(
|
||||||
@@ -192,7 +192,7 @@ fn regist_user_route(r: &mut S3Router<AdminOperation>) -> Result<()> {
|
|||||||
format!("{}{}", ADMIN_PREFIX, "/v3/update-service-account").as_str(),
|
format!("{}{}", ADMIN_PREFIX, "/v3/update-service-account").as_str(),
|
||||||
AdminOperation(&UpdateServiceAccount {}),
|
AdminOperation(&UpdateServiceAccount {}),
|
||||||
)?;
|
)?;
|
||||||
|
// 1
|
||||||
r.insert(
|
r.insert(
|
||||||
Method::GET,
|
Method::GET,
|
||||||
format!("{}{}", ADMIN_PREFIX, "/v3/info-service-account").as_str(),
|
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(),
|
format!("{}{}", ADMIN_PREFIX, "/v3/list-service-accounts").as_str(),
|
||||||
AdminOperation(&ListServiceAccount {}),
|
AdminOperation(&ListServiceAccount {}),
|
||||||
)?;
|
)?;
|
||||||
|
// 1
|
||||||
r.insert(
|
r.insert(
|
||||||
Method::DELETE,
|
Method::DELETE,
|
||||||
format!("{}{}", ADMIN_PREFIX, "/v3/delete-service-accounts").as_str(),
|
format!("{}{}", ADMIN_PREFIX, "/v3/delete-service-accounts").as_str(),
|
||||||
AdminOperation(&DeleteServiceAccount {}),
|
AdminOperation(&DeleteServiceAccount {}),
|
||||||
)?;
|
)?;
|
||||||
|
// 1
|
||||||
r.insert(
|
r.insert(
|
||||||
Method::PUT,
|
Method::PUT,
|
||||||
format!("{}{}", ADMIN_PREFIX, "/v3/add-service-accounts").as_str(),
|
format!("{}{}", ADMIN_PREFIX, "/v3/add-service-accounts").as_str(),
|
||||||
|
|||||||
Reference in New Issue
Block a user