Repository: rustfs/rustfs
File: rustfs/src/admin/handlers/group.rs (Rust)

Code before:
            S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
        })?;

        let mut header = HeaderMap::new();
        header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
        header.insert(CONTENT_LENGTH, "0".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");

        let Some(input_cred) = req.credentials else {
            return Err(s3_error!(InvalidRequest, "get cred failed"));
        };

        let (cred, owner) =
            check_key_valid(get_session_token(&req.uri, &req.headers).unwrap_or_default(), &input_cred.access_key).await?;

        validate_admin_request(
            &req.headers,
            &cred,
            owner,
            false,
            vec![Action::AdminAction(AdminAction::EnableGroupAdminAction)],
            req.extensions.get::<Option<RemoteAddr>>().and_then(|opt| opt.map(|a| a.0)),
        )
        .await?;

        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) = rustfs_iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };

        if let Some(status) = query.status {
            match status.as_str() {

Review comment (bug):
```
iam_store.remove_users_from_group(group, vec![]).await.map_err(|e| {
    warn!("delete group failed, e: {:?}", e);
    match e {
        rustfs_iam::error::Error::GroupNotEmpty => {
            S3Error::with_message(S3ErrorCode::Conflict, "group is not empty")
        }
        rustfs_iam::error::Error::InvalidArgument => {
            s3_error!(InvalidArgument, e.to_string())
        }
        _ => S3Error::with_message(S3ErrorCode::InternalError, e.to_string())
    }
})?;
```

Code after:
            &cred,
            owner,
            false,
            vec![Action::AdminAction(AdminAction::RemoveUserFromGroupAdminAction)],
            req.extensions.get::<Option<RemoteAddr>>().and_then(|opt| opt.map(|a| a.0)),
        )
        .await?;

        let group = params
            .get("group")
            .ok_or_else(|| s3_error!(InvalidArgument, "missing group name in request"))?
            .trim();

        // Validate the group name format
        if group.is_empty() || group.len() > 256 {
            return Err(s3_error!(InvalidArgument, "invalid group name"));
        }

        // Sanity check the group name
        if group.contains(['/', '\\', '\0']) {
            return Err(s3_error!(InvalidArgument, "group name contains invalid characters"));
        }

        let Ok(iam_store) = rustfs_iam::get() else { return Err(s3_error!(InternalError, "iam not init")) };

        iam_store.remove_users_from_group(group, vec![]).await.map_err(|e| {
            warn!("delete group failed, e: {:?}", e);
            match e {
                rustfs_iam::error::Error::GroupNotEmpty => {
                    s3_error!(InvalidRequest, "group is not empty")
                }
                rustfs_iam::error::Error::InvalidArgument => {
                    s3_error!(InvalidArgument, "{e}")
                }
                _ => {
                    if is_err_no_such_group(&e) {
                        s3_error!(NoSuchKey, "group '{group}' does not exist")
                    } else {
                        s3_error!(InternalError, "{e}")
                    }
                }
            }
        })?;

        let mut header = HeaderMap::new();
        header.insert(CONTENT_TYPE, "application/json".parse().unwrap());
        header.insert(CONTENT_LENGTH, "0".parse().unwrap());
        Ok(S3Response::with_headers((StatusCode::OK, Body::empty()), header))
    }
}