2 Star 0 Fork 0

wangyuguo/console

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
admin_users.go 23.25 KB
一键复制 编辑 原始数据 按行查看 历史
wangyuguo 提交于 2年前 . 更新
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
// 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"
"fmt"
"sort"
"strings"
"gitee.com/whubbledb/console/pkg/utils"
"github.com/go-openapi/swag"
"gitee.com/whubbledb/console/models"
"gitee.com/whubbledb/console/restapi/operations"
accountApi "gitee.com/whubbledb/console/restapi/operations/account"
bucketApi "gitee.com/whubbledb/console/restapi/operations/bucket"
userApi "gitee.com/whubbledb/console/restapi/operations/user"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime/middleware"
"github.com/minio/madmin-go/v2"
iampolicy "github.com/minio/pkg/iam/policy"
)
// Policy evaluated constants
const (
Unknown = 0
Allow = 1
Deny = -1
)
func registerUsersHandlers(api *operations.ConsoleAPI) {
// List Users
api.UserListUsersHandler = userApi.ListUsersHandlerFunc(func(params userApi.ListUsersParams, session *models.Principal) middleware.Responder {
listUsersResponse, err := getListUsersResponse(session, params)
if err != nil {
return userApi.NewListUsersDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewListUsersOK().WithPayload(listUsersResponse)
})
// Add User
api.UserAddUserHandler = userApi.AddUserHandlerFunc(func(params userApi.AddUserParams, session *models.Principal) middleware.Responder {
userResponse, err := getUserAddResponse(session, params)
if err != nil {
return userApi.NewAddUserDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewAddUserCreated().WithPayload(userResponse)
})
// Remove User
api.UserRemoveUserHandler = userApi.RemoveUserHandlerFunc(func(params userApi.RemoveUserParams, session *models.Principal) middleware.Responder {
err := getRemoveUserResponse(session, params)
if err != nil {
return userApi.NewRemoveUserDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewRemoveUserNoContent()
})
// Update User-Groups
api.UserUpdateUserGroupsHandler = userApi.UpdateUserGroupsHandlerFunc(func(params userApi.UpdateUserGroupsParams, session *models.Principal) middleware.Responder {
userUpdateResponse, err := getUpdateUserGroupsResponse(session, params)
if err != nil {
return userApi.NewUpdateUserGroupsDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewUpdateUserGroupsOK().WithPayload(userUpdateResponse)
})
// Get User
api.UserGetUserInfoHandler = userApi.GetUserInfoHandlerFunc(func(params userApi.GetUserInfoParams, session *models.Principal) middleware.Responder {
userInfoResponse, err := getUserInfoResponse(session, params)
if err != nil {
return userApi.NewGetUserInfoDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewGetUserInfoOK().WithPayload(userInfoResponse)
})
// Update User
api.UserUpdateUserInfoHandler = userApi.UpdateUserInfoHandlerFunc(func(params userApi.UpdateUserInfoParams, session *models.Principal) middleware.Responder {
userUpdateResponse, err := getUpdateUserResponse(session, params)
if err != nil {
return userApi.NewUpdateUserInfoDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewUpdateUserInfoOK().WithPayload(userUpdateResponse)
})
// Update User-Groups Bulk
api.UserBulkUpdateUsersGroupsHandler = userApi.BulkUpdateUsersGroupsHandlerFunc(func(params userApi.BulkUpdateUsersGroupsParams, session *models.Principal) middleware.Responder {
err := getAddUsersListToGroupsResponse(session, params)
if err != nil {
return userApi.NewBulkUpdateUsersGroupsDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewBulkUpdateUsersGroupsOK()
})
api.BucketListUsersWithAccessToBucketHandler = bucketApi.ListUsersWithAccessToBucketHandlerFunc(func(params bucketApi.ListUsersWithAccessToBucketParams, session *models.Principal) middleware.Responder {
response, err := getListUsersWithAccessToBucketResponse(session, params)
if err != nil {
return bucketApi.NewListUsersWithAccessToBucketDefault(int(err.Code)).WithPayload(err)
}
return bucketApi.NewListUsersWithAccessToBucketOK().WithPayload(response)
})
// Change User Password
api.AccountChangeUserPasswordHandler = accountApi.ChangeUserPasswordHandlerFunc(func(params accountApi.ChangeUserPasswordParams, session *models.Principal) middleware.Responder {
err := getChangeUserPasswordResponse(session, params)
if err != nil {
return accountApi.NewChangeUserPasswordDefault(int(err.Code)).WithPayload(err)
}
return accountApi.NewChangeUserPasswordCreated()
})
// Check number of Service Accounts for listed users
api.UserCheckUserServiceAccountsHandler = userApi.CheckUserServiceAccountsHandlerFunc(func(params userApi.CheckUserServiceAccountsParams, session *models.Principal) middleware.Responder {
userSAList, err := getCheckUserSAResponse(session, params)
if err != nil {
return userApi.NewCheckUserServiceAccountsDefault(int(err.Code)).WithPayload(err)
}
return userApi.NewCheckUserServiceAccountsOK().WithPayload(userSAList)
})
}
func listUsers(ctx context.Context, client MinioAdmin) ([]*models.User, error) {
// Get list of all users in the MinIO
// This call requires explicit authentication, no anonymous requests are
// allowed for listing users.
userMap, err := client.listUsers(ctx)
if err != nil {
return []*models.User{}, err
}
var users []*models.User
for accessKey, user := range userMap {
userElem := &models.User{
AccessKey: accessKey,
Status: string(user.Status),
Policy: strings.Split(user.PolicyName, ","),
MemberOf: user.MemberOf,
}
users = append(users, userElem)
}
return users, nil
}
// getListUsersResponse performs listUsers() and serializes it to the handler's output
func getListUsersResponse(session *models.Principal, params userApi.ListUsersParams) (*models.ListUsersResponse, *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 minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
users, err := listUsers(ctx, adminClient)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
// serialize output
listUsersResponse := &models.ListUsersResponse{
Users: users,
}
return listUsersResponse, nil
}
// addUser invokes adding a users on `MinioAdmin` and builds the response `models.User`
func addUser(ctx context.Context, client MinioAdmin, accessKey, secretKey *string, groups []string, policies []string) (*models.User, error) {
// Calls into MinIO to add a new user if there's an errors return it
if err := client.addUser(ctx, *accessKey, *secretKey); err != nil {
return nil, err
}
// set groups for the newly created user
var userWithGroups *models.User
if len(groups) > 0 {
var errUG error
userWithGroups, errUG = updateUserGroups(ctx, client, *accessKey, groups)
if errUG != nil {
return nil, errUG
}
}
// set policies for the newly created user
if len(policies) > 0 {
policyString := strings.Join(policies, ",")
if err := SetPolicy(ctx, client, policyString, *accessKey, "user"); err != nil {
return nil, err
}
}
memberOf := []string{}
status := "enabled"
if userWithGroups != nil {
memberOf = userWithGroups.MemberOf
status = userWithGroups.Status
}
userRet := &models.User{
AccessKey: *accessKey,
MemberOf: memberOf,
Policy: policies,
Status: status,
}
return userRet, nil
}
func getUserAddResponse(session *models.Principal, params userApi.AddUserParams) (*models.User, *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 minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
var userExists bool
_, err = adminClient.getUserInfo(ctx, *params.Body.AccessKey)
userExists = err == nil
if userExists {
return nil, ErrorWithContext(ctx, ErrNonUniqueAccessKey)
}
user, err := addUser(
ctx,
adminClient,
params.Body.AccessKey,
params.Body.SecretKey,
params.Body.Groups,
params.Body.Policies,
)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
return user, nil
}
// removeUser invokes removing an user on `MinioAdmin`, then we return the response from API
func removeUser(ctx context.Context, client MinioAdmin, accessKey string) error {
return client.removeUser(ctx, accessKey)
}
func getRemoveUserResponse(session *models.Principal, params userApi.RemoveUserParams) *models.Error {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return ErrorWithContext(ctx, err)
}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return ErrorWithContext(ctx, err)
}
if session.AccountAccessKey == userName {
return ErrorWithContext(ctx, ErrAvoidSelfAccountDelete)
}
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
if err := removeUser(ctx, adminClient, userName); err != nil {
return ErrorWithContext(ctx, err)
}
return nil
}
// getUserInfo calls MinIO server get the User Information
func getUserInfo(ctx context.Context, client MinioAdmin, accessKey string) (*madmin.UserInfo, error) {
userInfo, err := client.getUserInfo(ctx, accessKey)
if err != nil {
return nil, err
}
return &userInfo, nil
}
func getUserInfoResponse(session *models.Principal, params userApi.GetUserInfoParams) (*models.User, *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 minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
user, err := getUserInfo(ctx, adminClient, userName)
if err != nil {
// User doesn't exist, return 404
if madmin.ToErrorResponse(err).Code == "XMinioAdminNoSuchUser" {
var errorCode int32 = 404
errorMessage := "User doesn't exist"
return nil, &models.Error{Code: errorCode, Message: swag.String(errorMessage), DetailedMessage: swag.String(err.Error())}
}
return nil, ErrorWithContext(ctx, err)
}
var policies []string
if user.PolicyName == "" {
policies = []string{}
} else {
policies = strings.Split(user.PolicyName, ",")
}
hasPolicy := true
if len(policies) == 0 {
hasPolicy = false
for i := 0; i < len(user.MemberOf); i++ {
group, err := adminClient.getGroupDescription(ctx, user.MemberOf[i])
if err != nil {
continue
}
if group.Policy != "" {
hasPolicy = true
break
}
}
}
userInformation := &models.User{
AccessKey: userName,
MemberOf: user.MemberOf,
Policy: policies,
Status: string(user.Status),
HasPolicy: hasPolicy,
}
return userInformation, nil
}
// updateUserGroups invokes getUserInfo() to get the old groups from the user,
// then we merge the list with the new groups list to have a shorter iteration between groups and we do a comparison between the current and old groups.
// We delete or update the groups according the location in each list and send the user with the new groups from `MinioAdmin` to the client
func updateUserGroups(ctx context.Context, client MinioAdmin, user string, groupsToAssign []string) (*models.User, error) {
parallelUserUpdate := func(groupName string, originGroups []string) chan error {
chProcess := make(chan error)
go func() error {
defer close(chProcess)
// Compare if groupName is in the arrays
isGroupPersistent := IsElementInArray(groupsToAssign, groupName)
isInOriginGroups := IsElementInArray(originGroups, groupName)
if isGroupPersistent && isInOriginGroups { // Group is already assigned and doesn't need to be updated
chProcess <- nil
return nil
}
isRemove := false // User is added by default
// User is deleted from the group
if !isGroupPersistent {
isRemove = true
}
userToAddRemove := []string{user}
updateReturn := updateGroupMembers(ctx, client, groupName, userToAddRemove, isRemove)
chProcess <- updateReturn
return updateReturn
}()
return chProcess
}
userInfoOr, err := getUserInfo(ctx, client, user)
if err != nil {
return nil, err
}
memberOf := userInfoOr.MemberOf
mergedGroupArray := UniqueKeys(append(memberOf, groupsToAssign...))
var listOfUpdates []chan error
// Each group must be updated individually because there is no way to update all the groups at once for a user,
// we are using the same logic as 'mc admin group add' command
for _, groupN := range mergedGroupArray {
proc := parallelUserUpdate(groupN, memberOf)
listOfUpdates = append(listOfUpdates, proc)
}
channelHasError := false
for _, chanRet := range listOfUpdates {
locError := <-chanRet
if locError != nil {
channelHasError = true
}
}
if channelHasError {
errRt := errors.New(500, "there was an error updating the groups")
return nil, errRt
}
userInfo, err := getUserInfo(ctx, client, user)
if err != nil {
return nil, err
}
policies := strings.Split(userInfo.PolicyName, ",")
userReturn := &models.User{
AccessKey: user,
MemberOf: userInfo.MemberOf,
Policy: policies,
Status: string(userInfo.Status),
}
return userReturn, nil
}
func getUpdateUserGroupsResponse(session *models.Principal, params userApi.UpdateUserGroupsParams) (*models.User, *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 minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
user, err := updateUserGroups(ctx, adminClient, userName, params.Body.Groups)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
return user, nil
}
// setUserStatus invokes setUserStatus from madmin to update user status
func setUserStatus(ctx context.Context, client MinioAdmin, user string, status string) error {
var setStatus madmin.AccountStatus
switch status {
case "enabled":
setStatus = madmin.AccountEnabled
case "disabled":
setStatus = madmin.AccountDisabled
default:
return errors.New(500, "status not valid")
}
return client.setUserStatus(ctx, user, setStatus)
}
func getUpdateUserResponse(session *models.Principal, params userApi.UpdateUserInfoParams) (*models.User, *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 minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
userName, err := utils.DecodeBase64(params.Name)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
status := *params.Body.Status
groups := params.Body.Groups
if err := setUserStatus(ctx, adminClient, userName, status); err != nil {
return nil, ErrorWithContext(ctx, err)
}
userElem, errUG := updateUserGroups(ctx, adminClient, userName, groups)
if errUG != nil {
return nil, ErrorWithContext(ctx, errUG)
}
return userElem, nil
}
// addUsersListToGroups iterates over the user list & assigns the requested groups to each user.
func addUsersListToGroups(ctx context.Context, client MinioAdmin, usersToUpdate []string, groupsToAssign []string) error {
// We update each group with the complete usersList
parallelGroupsUpdate := func(groupToAssign string) chan error {
groupProcess := make(chan error)
go func() {
defer close(groupProcess)
// We add the users array to the group.
err := updateGroupMembers(ctx, client, groupToAssign, usersToUpdate, false)
groupProcess <- err
}()
return groupProcess
}
var groupsUpdateList []chan error
// We get each group name & add users accordingly
for _, groupName := range groupsToAssign {
// We update the group
proc := parallelGroupsUpdate(groupName)
groupsUpdateList = append(groupsUpdateList, proc)
}
errorsList := []string{} // We get the errors list because we want to have all errors at once.
for _, err := range groupsUpdateList {
errorFromUpdate := <-err // We store the errors to avoid Data Race
if errorFromUpdate != nil {
// If there is an errors, we store the errors strings so we can join them after we receive all errors
errorsList = append(errorsList, errorFromUpdate.Error()) // We wait until all the channels have been closed.
}
}
// If there are errors, we throw the final errors with the errors inside
if len(errorsList) > 0 {
errGen := fmt.Errorf("error in users-groups assignation: %q", strings.Join(errorsList, ","))
return errGen
}
return nil
}
func getAddUsersListToGroupsResponse(session *models.Principal, params userApi.BulkUpdateUsersGroupsParams) *models.Error {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return ErrorWithContext(ctx, err)
}
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
usersList := params.Body.Users
groupsList := params.Body.Groups
if err := addUsersListToGroups(ctx, adminClient, usersList, groupsList); err != nil {
return ErrorWithContext(ctx, err)
}
return nil
}
func getListUsersWithAccessToBucketResponse(session *models.Principal, params bucketApi.ListUsersWithAccessToBucketParams) ([]string, *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 minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
list, err := listUsersWithAccessToBucket(ctx, adminClient, params.Bucket)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
return list, nil
}
func policyAllowsAndMatchesBucket(policy *iampolicy.Policy, bucket string) int {
policyStatements := policy.Statements
for i := 0; i < len(policyStatements); i++ {
resources := policyStatements[i].Resources
effect := policyStatements[i].Effect
if resources.Match(bucket, map[string][]string{}) {
if effect.IsValid() {
if effect.IsAllowed(true) {
return Allow
}
return Deny
}
}
}
return Unknown
}
func listUsersWithAccessToBucket(ctx context.Context, adminClient MinioAdmin, bucket string) ([]string, error) {
users, err := adminClient.listUsers(ctx)
if err != nil {
return nil, err
}
var retval []string
akHasAccess := make(map[string]struct{})
akIsDenied := make(map[string]struct{})
for k, v := range users {
for _, policyName := range strings.Split(v.PolicyName, ",") {
policyName = strings.TrimSpace(policyName)
if policyName == "" {
continue
}
policy, err := adminClient.getPolicy(ctx, policyName)
if err != nil {
ErrorWithContext(ctx, fmt.Errorf("unable to fetch policy %s: %v", policyName, err))
continue
}
if _, ok := akIsDenied[k]; !ok {
switch policyAllowsAndMatchesBucket(policy, bucket) {
case Allow:
if _, ok := akHasAccess[k]; !ok {
akHasAccess[k] = struct{}{}
}
case Deny:
akIsDenied[k] = struct{}{}
delete(akHasAccess, k)
}
}
}
}
groups, err := adminClient.listGroups(ctx)
if err != nil {
ErrorWithContext(ctx, fmt.Errorf("unable to list groups: %v", err))
return retval, nil
}
for _, groupName := range groups {
info, err := groupInfo(ctx, adminClient, groupName)
if err != nil {
ErrorWithContext(ctx, fmt.Errorf("unable to fetch group info %s: %v", groupName, err))
continue
}
policy, err := adminClient.getPolicy(ctx, info.Policy)
if err != nil {
ErrorWithContext(ctx, fmt.Errorf("unable to fetch group policy %s: %v", info.Policy, err))
continue
}
for _, member := range info.Members {
if _, ok := akIsDenied[member]; !ok {
switch policyAllowsAndMatchesBucket(policy, bucket) {
case Allow:
if _, ok := akHasAccess[member]; !ok {
akHasAccess[member] = struct{}{}
}
case Deny:
akIsDenied[member] = struct{}{}
delete(akHasAccess, member)
}
}
}
}
for k := range akHasAccess {
retval = append(retval, k)
}
sort.Strings(retval)
return retval, nil
}
// changeUserPassword changes password of selectedUser to newSecretKey
func changeUserPassword(ctx context.Context, client MinioAdmin, selectedUser string, newSecretKey string) error {
return client.changePassword(ctx, selectedUser, newSecretKey)
}
// getChangeUserPasswordResponse will change the password of selctedUser to newSecretKey
func getChangeUserPasswordResponse(session *models.Principal, params accountApi.ChangeUserPasswordParams) *models.Error {
ctx, cancel := context.WithCancel(params.HTTPRequest.Context())
defer cancel()
mAdmin, err := NewMinioAdminClient(session)
if err != nil {
return ErrorWithContext(ctx, err)
}
// create a minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
// params will contain selectedUser and newSecretKey credentials for the user
user := *params.Body.SelectedUser
newSecretKey := *params.Body.NewSecretKey
// changes password of user to newSecretKey
if err := changeUserPassword(ctx, adminClient, user, newSecretKey); err != nil {
return ErrorWithContext(ctx, err)
}
return nil
}
func getCheckUserSAResponse(session *models.Principal, params userApi.CheckUserServiceAccountsParams) (*models.UserServiceAccountSummary, *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 minioClient interface implementation
// defining the client to be used
adminClient := AdminClient{Client: mAdmin}
var userServiceAccountList []*models.UserServiceAccountItem
hasSA := false
for _, user := range params.SelectedUsers {
listServAccs, err := adminClient.listServiceAccounts(ctx, user)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
numSAs := int64(len(listServAccs.Accounts))
if numSAs > 0 {
hasSA = true
}
userAccountItem := &models.UserServiceAccountItem{
UserName: user,
NumSAs: numSAs,
}
userServiceAccountList = append(userServiceAccountList, userAccountItem)
}
userAccountList := &models.UserServiceAccountSummary{
UserServiceAccountList: userServiceAccountList,
HasSA: hasSA,
}
return userAccountList, nil
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/whubbledb/console.git
git@gitee.com:whubbledb/console.git
whubbledb
console
console
v1.0.6

搜索帮助