2 Star 0 Fork 0

wangyuguo/console

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
admin_groups.go 11.78 KB
一键复制 编辑 原始数据 按行查看 历史
wangyuguo 提交于 2年前 . 更新
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package restapi
import (
"context"
"gitee.com/whubbledb/console/pkg/utils"
"gitee.com/whubbledb/console/restapi/operations"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/madmin-go/v2"
groupApi "gitee.com/whubbledb/console/restapi/operations/group"
"gitee.com/whubbledb/console/models"
)
func registerGroupsHandlers(api *operations.ConsoleAPI) {
// List Groups
api.GroupListGroupsHandler = groupApi.ListGroupsHandlerFunc(func(params groupApi.ListGroupsParams, session *models.Principal) middleware.Responder {
listGroupsResponse, err := getListGroupsResponse(session, params)
if err != nil {
return groupApi.NewListGroupsDefault(int(err.Code)).WithPayload(err)
}
return groupApi.NewListGroupsOK().WithPayload(listGroupsResponse)
})
// Group Info
api.GroupGroupInfoHandler = groupApi.GroupInfoHandlerFunc(func(params groupApi.GroupInfoParams, session *models.Principal) middleware.Responder {
groupInfo, err := getGroupInfoResponse(session, params)
if err != nil {
return groupApi.NewGroupInfoDefault(int(err.Code)).WithPayload(err)
}
return groupApi.NewGroupInfoOK().WithPayload(groupInfo)
})
// Add Group
api.GroupAddGroupHandler = groupApi.AddGroupHandlerFunc(func(params groupApi.AddGroupParams, session *models.Principal) middleware.Responder {
if err := getAddGroupResponse(session, params); err != nil {
return groupApi.NewAddGroupDefault(int(err.Code)).WithPayload(err)
}
return groupApi.NewAddGroupCreated()
})
// Remove Group
api.GroupRemoveGroupHandler = groupApi.RemoveGroupHandlerFunc(func(params groupApi.RemoveGroupParams, session *models.Principal) middleware.Responder {
if err := getRemoveGroupResponse(session, params); err != nil {
return groupApi.NewRemoveGroupDefault(int(err.Code)).WithPayload(err)
}
return groupApi.NewRemoveGroupNoContent()
})
// Update Group
api.GroupUpdateGroupHandler = groupApi.UpdateGroupHandlerFunc(func(params groupApi.UpdateGroupParams, session *models.Principal) middleware.Responder {
groupUpdateResp, err := getUpdateGroupResponse(session, params)
if err != nil {
return groupApi.NewUpdateGroupDefault(int(err.Code)).WithPayload(err)
}
return groupApi.NewUpdateGroupOK().WithPayload(groupUpdateResp)
})
}
// getListGroupsResponse performs listGroups() and serializes it to the handler's output
func getListGroupsResponse(session *models.Principal, params groupApi.ListGroupsParams) (*models.ListGroupsResponse, *models.Error) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
// create a MinIO Admin Client interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groups, err := adminClient.listGroups(ctx)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
// serialize output
listGroupsResponse := &models.ListGroupsResponse{
Groups: groups,
Total: int64(len(groups)),
}
return listGroupsResponse, nil
}
// groupInfo calls MinIO server get Group's info
func groupInfo(ctx context.Context, client MinioAdmin, group string) (*madmin.GroupDesc, error) {
groupDesc, err := client.getGroupDescription(ctx, group)
if err != nil {
return nil, err
}
return groupDesc, nil
}
// getGroupInfoResponse performs groupInfo() and serializes it to the handler's output
func getGroupInfoResponse(session *models.Principal, params groupApi.GroupInfoParams) (*models.Group, *models.Error) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
// create a MinIO Admin Client interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groupName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
groupDesc, err := groupInfo(ctx, adminClient, groupName)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
groupResponse := &models.Group{
Members: groupDesc.Members,
Name: groupDesc.Name,
Policy: groupDesc.Policy,
Status: groupDesc.Status,
}
return groupResponse, nil
}
// addGroupAdd a MinIO group with the defined members
func addGroup(ctx context.Context, client MinioAdmin, group string, members []string) error {
gAddRemove := madmin.GroupAddRemove{
Group: group,
Members: members,
IsRemove: false,
}
err := client.updateGroupMembers(ctx, gAddRemove)
if err != nil {
return err
}
return nil
}
// getAddGroupResponse performs addGroup() and serializes it to the handler's output
func getAddGroupResponse(session *models.Principal, params groupApi.AddGroupParams) *models.Error {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
// AddGroup request needed to proceed
if params.Body == nil {
return ErrorWithContext(ctx, ErrGroupBodyNotInRequest)
}
groupRequest := params.Body
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return ErrorWithContext(ctx, err)
}
// create a MinIO Admin Client interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groupList, _ := adminClient.listGroups(ctx)
for _, b := range groupList {
if b == *groupRequest.Group {
return ErrorWithContext(ctx, ErrGroupAlreadyExists)
}
}
if err := addGroup(ctx, adminClient, *groupRequest.Group, groupRequest.Members); err != nil {
return ErrorWithContext(ctx, err)
}
return nil
}
// removeGroup deletes a minIO group only if it has no members
func removeGroup(ctx context.Context, client MinioAdmin, group string) error {
gAddRemove := madmin.GroupAddRemove{
Group: group,
Members: []string{},
IsRemove: true,
}
err := client.updateGroupMembers(ctx, gAddRemove)
if err != nil {
return err
}
return nil
}
// getRemoveGroupResponse performs removeGroup() and serializes it to the handler's output
func getRemoveGroupResponse(session *models.Principal, params groupApi.RemoveGroupParams) *models.Error {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
if params.Name == "" {
return ErrorWithContext(ctx, ErrGroupNameNotInRequest)
}
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return ErrorWithContext(ctx, err)
}
// Create a MinIO Admin Client interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groupName, err := utils.DecodeBase64(params.Name)
if err != nil {
return ErrorWithContext(ctx, err)
}
if err := removeGroup(ctx, adminClient, groupName); err != nil {
minioError := madmin.ToErrorResponse(err)
err2 := ErrorWithContext(ctx, err)
if minioError.Code == "XMinioAdminNoSuchGroup" {
err2.Code = 404
}
return err2
}
return nil
}
// updateGroup updates a group by adding/removing members and setting the status to the desired one
//
// isRemove: whether remove members or not
func updateGroupMembers(ctx context.Context, client MinioAdmin, group string, members []string, isRemove bool) error {
gAddRemove := madmin.GroupAddRemove{
Group: group,
Members: members,
IsRemove: isRemove,
}
err := client.updateGroupMembers(ctx, gAddRemove)
if err != nil {
return err
}
return nil
}
// addOrDeleteMembers updates a group members by adding or deleting them based on the expectedMembers
func addOrDeleteMembers(ctx context.Context, client MinioAdmin, group *madmin.GroupDesc, expectedMembers []string) error {
// get members to delete/add
membersToDelete := DifferenceArrays(group.Members, expectedMembers)
membersToAdd := DifferenceArrays(expectedMembers, group.Members)
// delete members if any to be deleted
if len(membersToDelete) > 0 {
err := updateGroupMembers(ctx, client, group.Name, membersToDelete, true)
if err != nil {
return err
}
}
// add members if any to be added
if len(membersToAdd) > 0 {
err := updateGroupMembers(ctx, client, group.Name, membersToAdd, false)
if err != nil {
return err
}
}
return nil
}
func setGroupStatus(ctx context.Context, client MinioAdmin, group, status string) error {
var setStatus madmin.GroupStatus
switch status {
case "enabled":
setStatus = madmin.GroupEnabled
case "disabled":
setStatus = madmin.GroupDisabled
default:
return errors.New(500, "status not valid")
}
return client.setGroupStatus(ctx, group, setStatus)
}
// getUpdateGroupResponse updates a group by adding or removing it's members depending on the request,
// also sets the group's status if status in the request is different than the current one.
// Then serializes the output to be used by the handler.
func getUpdateGroupResponse(session *models.Principal, params groupApi.UpdateGroupParams) (*models.Group, *models.Error) {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
if params.Name == "" {
return nil, ErrorWithContext(ctx, ErrGroupNameNotInRequest)
}
if params.Body == nil {
return nil, ErrorWithContext(ctx, ErrGroupBodyNotInRequest)
}
expectedGroupUpdate := params.Body
groupName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
// create a MinIO Admin Client interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
groupUpdated, err := groupUpdate(ctx, adminClient, groupName, expectedGroupUpdate)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
groupResponse := &models.Group{
Name: groupUpdated.Name,
Members: groupUpdated.Members,
Policy: groupUpdated.Policy,
Status: groupUpdated.Status,
}
return groupResponse, nil
}
// groupUpdate updates a group given the expected parameters, compares the expected parameters against the current ones
// and updates them accordingly, status is only updated if the expected status is different than the current one.
// Then fetches the group again to return the object updated.
func groupUpdate(ctx context.Context, client MinioAdmin, groupName string, expectedGroup *models.UpdateGroupRequest) (*madmin.GroupDesc, error) {
expectedMembers := expectedGroup.Members
expectedStatus := *expectedGroup.Status
// get current members and status
groupDescription, err := groupInfo(ctx, client, groupName)
if err != nil {
LogInfo("error getting group info: %v", err)
return nil, err
}
// update group members
err = addOrDeleteMembers(ctx, client, groupDescription, expectedMembers)
if err != nil {
LogInfo("error updating group: %v", err)
return nil, err
}
// update group status only if different from current status
if expectedStatus != groupDescription.Status {
err = setGroupStatus(ctx, client, groupDescription.Name, expectedStatus)
if err != nil {
LogInfo("error updating group's status: %v", err)
return nil, err
}
}
// return latest group info to verify that changes were applied correctly
groupDescription, err = groupInfo(ctx, client, groupName)
if err != nil {
LogInfo("error getting group info: %v", err)
return nil, err
}
return groupDescription, nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/whubbledb/console.git
git@gitee.com:whubbledb/console.git
whubbledb
console
console
v1.0.6

搜索帮助