github.com/polarismesh/polaris@v1.17.8/store/boltdb/user.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package boltdb
    19  
    20  import (
    21  	"errors"
    22  	"sort"
    23  	"strings"
    24  	"time"
    25  
    26  	bolt "go.etcd.io/bbolt"
    27  	"go.uber.org/zap"
    28  
    29  	"github.com/polarismesh/polaris/common/model"
    30  	"github.com/polarismesh/polaris/common/utils"
    31  	"github.com/polarismesh/polaris/store"
    32  )
    33  
    34  const (
    35  	// 用户数据 scope
    36  	tblUser string = "user"
    37  
    38  	// UserFieldID 用户ID字段
    39  	UserFieldID string = "ID"
    40  	// UserFieldName 用户名字段
    41  	UserFieldName string = "Name"
    42  	// UserFieldPassword 用户密码字段
    43  	UserFieldPassword string = "Password"
    44  	// UserFieldOwner 用户Owner字段
    45  	UserFieldOwner string = "Owner"
    46  	// UserFieldSource 用户来源字段
    47  	UserFieldSource string = "Source"
    48  	// UserFieldType 用户类型字段
    49  	UserFieldType string = "Type"
    50  	// UserFieldToken 用户Token字段
    51  	UserFieldToken string = "Token"
    52  	// UserFieldTokenEnable 用户Token是否可用字段
    53  	UserFieldTokenEnable string = "TokenEnable"
    54  	// UserFieldValid 用户逻辑删除字段
    55  	UserFieldValid string = "Valid"
    56  	// UserFieldComment 用户备注字段
    57  	UserFieldComment string = "Comment"
    58  	// UserFieldCreateTime 用户创建时间字段
    59  	UserFieldCreateTime string = "CreateTime"
    60  	// UserFieldModifyTime 用户修改时间字段
    61  	UserFieldModifyTime string = "ModifyTime"
    62  	// UserFieldMobile 用户手机号信息
    63  	UserFieldMobile string = "Mobile"
    64  	// UserFieldEmail 用户邮箱信息
    65  	UserFieldEmail string = "Email"
    66  )
    67  
    68  var (
    69  	// ErrMultipleUserFound 多个用户
    70  	ErrMultipleUserFound = errors.New("multiple user found")
    71  )
    72  
    73  // userStore
    74  type userStore struct {
    75  	handler BoltHandler
    76  }
    77  
    78  // AddUser 添加用户
    79  func (us *userStore) AddUser(user *model.User) error {
    80  
    81  	initUser(user)
    82  
    83  	if user.ID == "" || user.Name == "" || user.Source == "" ||
    84  		user.Owner == "" || user.Token == "" {
    85  		return store.NewStatusError(store.EmptyParamsErr, "add user missing some params")
    86  	}
    87  
    88  	return us.addUser(user)
    89  }
    90  
    91  func (us *userStore) addUser(user *model.User) error {
    92  	proxy, err := us.handler.StartTx()
    93  	if err != nil {
    94  		return err
    95  	}
    96  	tx := proxy.GetDelegateTx().(*bolt.Tx)
    97  
    98  	defer func() {
    99  		_ = tx.Rollback()
   100  	}()
   101  
   102  	owner := user.Owner
   103  	if owner == "" {
   104  		owner = user.ID
   105  	}
   106  
   107  	// 添加用户信息
   108  	if err := us.addUserMain(tx, user); err != nil {
   109  		return err
   110  	}
   111  
   112  	// 添加用户的默认策略
   113  	if err := createDefaultStrategy(tx, model.PrincipalUser, user.ID, user.Name, owner); err != nil {
   114  		log.Error("[Store][User] create user default strategy fail", zap.Error(err),
   115  			zap.String("name", user.Name))
   116  		return err
   117  	}
   118  
   119  	if err := tx.Commit(); err != nil {
   120  		log.Error("[Store][User] save user tx commit fail", zap.Error(err),
   121  			zap.String("name", user.Name))
   122  		return err
   123  	}
   124  	return nil
   125  }
   126  
   127  func (us *userStore) addUserMain(tx *bolt.Tx, user *model.User) error {
   128  	// 添加用户信息
   129  	if err := saveValue(tx, tblUser, user.ID, converToUserStore(user)); err != nil {
   130  		log.Error("[Store][User] save user fail", zap.Error(err), zap.String("name", user.Name))
   131  		return err
   132  	}
   133  	return nil
   134  }
   135  
   136  // UpdateUser
   137  func (us *userStore) UpdateUser(user *model.User) error {
   138  	if user.ID == "" || user.Token == "" {
   139  		return store.NewStatusError(store.EmptyParamsErr, "update user missing some params")
   140  	}
   141  
   142  	properties := make(map[string]interface{})
   143  	properties[UserFieldComment] = user.Comment
   144  	properties[UserFieldToken] = user.Token
   145  	properties[UserFieldTokenEnable] = user.TokenEnable
   146  	properties[UserFieldEmail] = user.Email
   147  	properties[UserFieldMobile] = user.Mobile
   148  	properties[UserFieldPassword] = user.Password
   149  	properties[UserFieldModifyTime] = time.Now()
   150  
   151  	err := us.handler.UpdateValue(tblUser, user.ID, properties)
   152  	if err != nil {
   153  		log.Error("[Store][User] update user fail", zap.Error(err), zap.String("id", user.ID))
   154  		return err
   155  	}
   156  
   157  	return nil
   158  }
   159  
   160  // DeleteUser 删除用户
   161  func (us *userStore) DeleteUser(user *model.User) error {
   162  	if user.ID == "" {
   163  		return store.NewStatusError(store.EmptyParamsErr, "delete user missing some params")
   164  	}
   165  
   166  	return us.deleteUser(user)
   167  }
   168  
   169  func (us *userStore) deleteUser(user *model.User) error {
   170  	proxy, err := us.handler.StartTx()
   171  	if err != nil {
   172  		return err
   173  	}
   174  	tx := proxy.GetDelegateTx().(*bolt.Tx)
   175  
   176  	defer func() {
   177  		_ = tx.Rollback()
   178  	}()
   179  
   180  	properties := make(map[string]interface{})
   181  	properties[UserFieldValid] = false
   182  	properties[UserFieldModifyTime] = time.Now()
   183  
   184  	if err := updateValue(tx, tblUser, user.ID, properties); err != nil {
   185  		log.Error("[Store][User] delete user by id", zap.Error(err), zap.String("id", user.ID))
   186  		return err
   187  	}
   188  
   189  	owner := user.Owner
   190  	if owner == "" {
   191  		owner = user.ID
   192  	}
   193  
   194  	if err := cleanLinkStrategy(tx, model.PrincipalUser, user.ID, user.Owner); err != nil {
   195  		return err
   196  	}
   197  
   198  	if err := tx.Commit(); err != nil {
   199  		log.Error("[Store][User] delete user tx commit", zap.Error(err), zap.String("id", user.ID))
   200  		return err
   201  	}
   202  	return nil
   203  }
   204  
   205  // GetUser 获取用户
   206  func (us *userStore) GetUser(id string) (*model.User, error) {
   207  	if id == "" {
   208  		return nil, store.NewStatusError(store.EmptyParamsErr, "get user missing some params")
   209  	}
   210  
   211  	proxy, err := us.handler.StartTx()
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  	tx := proxy.GetDelegateTx().(*bolt.Tx)
   216  	defer func() {
   217  		_ = tx.Rollback()
   218  	}()
   219  
   220  	return us.getUser(tx, id)
   221  }
   222  
   223  // GetUser 获取用户
   224  func (us *userStore) getUser(tx *bolt.Tx, id string) (*model.User, error) {
   225  	if id == "" {
   226  		return nil, store.NewStatusError(store.EmptyParamsErr, "get user missing id params")
   227  	}
   228  
   229  	ret := make(map[string]interface{})
   230  	if err := loadValues(tx, tblUser, []string{id}, &userForStore{}, ret); err != nil {
   231  		log.Error("[Store][User] get user by id", zap.Error(err), zap.String("id", id))
   232  		return nil, err
   233  	}
   234  	if len(ret) == 0 {
   235  		return nil, nil
   236  	}
   237  	user := ret[id].(*userForStore)
   238  	if !user.Valid {
   239  		return nil, nil
   240  	}
   241  
   242  	return converToUserModel(user), nil
   243  }
   244  
   245  // GetUserByName 获取用户
   246  func (us *userStore) GetUserByName(name, ownerId string) (*model.User, error) {
   247  	if name == "" {
   248  		return nil, store.NewStatusError(store.EmptyParamsErr, "get user missing name params")
   249  	}
   250  	fields := []string{UserFieldName, UserFieldOwner, UserFieldValid}
   251  	ret, err := us.handler.LoadValuesByFilter(tblUser, fields, &userForStore{},
   252  		func(m map[string]interface{}) bool {
   253  			valid, ok := m[UserFieldValid].(bool)
   254  			if ok && !valid {
   255  				return false
   256  			}
   257  			saveName, _ := m[UserFieldName].(string)
   258  			saveOwner, _ := m[UserFieldOwner].(string)
   259  			return saveName == name && saveOwner == ownerId
   260  		})
   261  	if err != nil {
   262  		log.Error("[Store][User] get user by name", zap.Error(err), zap.String("name", name),
   263  			zap.String("owner", ownerId))
   264  		return nil, err
   265  	}
   266  	if len(ret) == 0 {
   267  		return nil, nil
   268  	}
   269  	if len(ret) > 1 {
   270  		return nil, ErrMultipleUserFound
   271  	}
   272  
   273  	var id string
   274  	for k := range ret {
   275  		id = k
   276  		break
   277  	}
   278  
   279  	user := ret[id].(*userForStore)
   280  	if !user.Valid {
   281  		return nil, nil
   282  	}
   283  
   284  	return converToUserModel(user), nil
   285  }
   286  
   287  // GetUserByIds 通过用户ID批量获取用户
   288  func (us *userStore) GetUserByIds(ids []string) ([]*model.User, error) {
   289  	if len(ids) == 0 {
   290  		return nil, nil
   291  	}
   292  
   293  	ret, err := us.handler.LoadValues(tblUser, ids, &userForStore{})
   294  	if err != nil {
   295  		log.Error("[Store][User] get user by ids", zap.Error(err), zap.Any("ids", ids))
   296  		return nil, err
   297  	}
   298  	if len(ret) == 0 {
   299  		return nil, nil
   300  	}
   301  
   302  	users := make([]*model.User, 0, len(ids))
   303  	for k := range ret {
   304  		user := ret[k].(*userForStore)
   305  		if !user.Valid {
   306  			continue
   307  		}
   308  		users = append(users, converToUserModel(user))
   309  	}
   310  
   311  	return users, nil
   312  }
   313  
   314  // GetSubCount 获取子账户的个数
   315  func (us *userStore) GetSubCount(user *model.User) (uint32, error) {
   316  	ownerId := user.ID
   317  	ret, err := us.handler.LoadValuesByFilter(tblUser, []string{UserFieldOwner, UserFieldValid}, &userForStore{},
   318  		func(m map[string]interface{}) bool {
   319  			valid, ok := m[UserFieldValid].(bool)
   320  			if ok && !valid {
   321  				return false
   322  			}
   323  
   324  			saveOwner, _ := m[UserFieldOwner].(string)
   325  			return saveOwner == ownerId
   326  		})
   327  
   328  	if err != nil {
   329  		log.Error("[Store][User] get user sub count", zap.Error(err), zap.String("id", user.ID))
   330  		return 0, err
   331  	}
   332  
   333  	return uint32(len(ret)), nil
   334  }
   335  
   336  // GetUsers 获取用户列表
   337  func (us *userStore) GetUsers(filters map[string]string, offset uint32, limit uint32) (uint32, []*model.User, error) {
   338  	if _, ok := filters["group_id"]; ok {
   339  		return us.getGroupUsers(filters, offset, limit)
   340  	}
   341  
   342  	return us.getUsers(filters, offset, limit)
   343  }
   344  
   345  // getUsers
   346  // "name":   1,
   347  // "owner":  1,
   348  // "source": 1,
   349  func (us *userStore) getUsers(filters map[string]string, offset uint32, limit uint32) (uint32, []*model.User, error) {
   350  	fields := []string{UserFieldID, UserFieldName, UserFieldOwner, UserFieldSource, UserFieldValid, UserFieldType}
   351  	ret, err := us.handler.LoadValuesByFilter(tblUser, fields, &userForStore{},
   352  		func(m map[string]interface{}) bool {
   353  
   354  			valid, ok := m[UserFieldValid].(bool)
   355  			if ok && !valid {
   356  				return false
   357  			}
   358  
   359  			saveId, _ := m[UserFieldID].(string)
   360  			saveName, _ := m[UserFieldName].(string)
   361  			saveOwner, _ := m[UserFieldOwner].(string)
   362  			saveSource, _ := m[UserFieldSource].(string)
   363  			saveType, _ := m[UserFieldType].(int64)
   364  
   365  			// 超级账户不做展示
   366  			if model.UserRoleType(saveType) == model.AdminUserRole &&
   367  				strings.Compare("true", filters["hide_admin"]) == 0 {
   368  				return false
   369  			}
   370  
   371  			if name, ok := filters["name"]; ok {
   372  				if utils.IsPrefixWildName(name) {
   373  					if !strings.Contains(saveName, name[:len(name)-1]) {
   374  						return false
   375  					}
   376  				} else {
   377  					if saveName != name {
   378  						return false
   379  					}
   380  				}
   381  			}
   382  
   383  			if owner, ok := filters["owner"]; ok {
   384  				if owner != saveOwner && saveId != owner {
   385  					return false
   386  				}
   387  			}
   388  
   389  			if source, ok := filters["source"]; ok {
   390  				if source != saveSource {
   391  					return false
   392  				}
   393  			}
   394  
   395  			if queryId, ok := filters["id"]; ok {
   396  				if queryId != saveId {
   397  					return false
   398  				}
   399  			}
   400  
   401  			return true
   402  		})
   403  
   404  	if err != nil {
   405  		log.Error("[Store][User] get users", zap.Error(err), zap.Any("filters", filters))
   406  		return 0, nil, err
   407  	}
   408  	if len(ret) == 0 {
   409  		return 0, nil, nil
   410  	}
   411  
   412  	return uint32(len(ret)), doUserPage(ret, offset, limit), nil
   413  }
   414  
   415  // getGroupUsers 获取某个用户组下的所有用户列表数据信息
   416  func (us *userStore) getGroupUsers(filters map[string]string, offset uint32, limit uint32) (uint32,
   417  	[]*model.User, error) {
   418  
   419  	groupId := filters["group_id"]
   420  	delete(filters, "group_id")
   421  
   422  	ret, err := us.handler.LoadValues(tblGroup, []string{groupId}, &groupForStore{})
   423  	if err != nil {
   424  		log.Error("[Store][User] get user groups", zap.Error(err), zap.Any("filters", filters))
   425  		return 0, nil, err
   426  	}
   427  	if len(ret) == 0 {
   428  		return 0, nil, nil
   429  	}
   430  	if len(ret) > 1 {
   431  		return 0, nil, ErrorMultipleGroupFound
   432  	}
   433  	group := ret[groupId].(*groupForStore)
   434  
   435  	userIds := make([]string, 0, len(group.UserIds))
   436  	for k := range group.UserIds {
   437  		userIds = append(userIds, k)
   438  	}
   439  
   440  	ret, err = us.handler.LoadValues(tblUser, userIds, &userForStore{})
   441  	if err != nil {
   442  		log.Error("[Store][User] get all users", zap.Error(err))
   443  		return 0, nil, err
   444  	}
   445  
   446  	predicate := func(user *userForStore) bool {
   447  		if !user.Valid {
   448  			return false
   449  		}
   450  
   451  		if model.UserRoleType(user.Type) == model.AdminUserRole {
   452  			return false
   453  		}
   454  
   455  		if name, ok := filters["name"]; ok {
   456  			if utils.IsPrefixWildName(name) {
   457  				if !strings.Contains(user.Name, name[:len(name)-1]) {
   458  					return false
   459  				}
   460  			} else {
   461  				if user.Name != name {
   462  					return false
   463  				}
   464  			}
   465  		}
   466  
   467  		if owner, ok := filters["owner"]; ok {
   468  			if owner != user.Owner {
   469  				return false
   470  			}
   471  		}
   472  
   473  		if source, ok := filters["source"]; ok {
   474  			if source != user.Source {
   475  				return false
   476  			}
   477  		}
   478  
   479  		return true
   480  	}
   481  
   482  	users := make(map[string]interface{})
   483  	for k := range ret {
   484  		val := ret[k]
   485  		if predicate(val.(*userForStore)) {
   486  			users[k] = val.(*userForStore)
   487  		}
   488  	}
   489  
   490  	return uint32(len(ret)), doUserPage(users, offset, limit), err
   491  }
   492  
   493  // GetUsersForCache 获取所有用户信息
   494  func (us *userStore) GetUsersForCache(mtime time.Time, firstUpdate bool) ([]*model.User, error) {
   495  	ret, err := us.handler.LoadValuesByFilter(tblUser, []string{UserFieldModifyTime}, &userForStore{},
   496  		func(m map[string]interface{}) bool {
   497  			mt := m[UserFieldModifyTime].(time.Time)
   498  			isBefore := mt.Before(mtime)
   499  			return !isBefore
   500  		})
   501  	if err != nil {
   502  		log.Error("[Store][User] get users for cache", zap.Error(err))
   503  		return nil, err
   504  	}
   505  
   506  	users := make([]*model.User, 0, len(ret))
   507  	for k := range ret {
   508  		val := ret[k]
   509  		users = append(users, converToUserModel(val.(*userForStore)))
   510  	}
   511  
   512  	return users, nil
   513  }
   514  
   515  // doPage 进行分页
   516  func doUserPage(ret map[string]interface{}, offset, limit uint32) []*model.User {
   517  	users := make([]*model.User, 0, len(ret))
   518  	beginIndex := offset
   519  	endIndex := beginIndex + limit
   520  	totalCount := uint32(len(ret))
   521  
   522  	if totalCount == 0 {
   523  		return users
   524  	}
   525  	if beginIndex >= endIndex {
   526  		return users
   527  	}
   528  	if beginIndex >= totalCount {
   529  		return users
   530  	}
   531  	if endIndex > totalCount {
   532  		endIndex = totalCount
   533  	}
   534  	for k := range ret {
   535  		users = append(users, converToUserModel(ret[k].(*userForStore)))
   536  	}
   537  
   538  	sort.Slice(users, func(i, j int) bool {
   539  		return users[i].ModifyTime.After(users[j].ModifyTime)
   540  	})
   541  
   542  	return users[beginIndex:endIndex]
   543  }
   544  
   545  func converToUserStore(user *model.User) *userForStore {
   546  	return &userForStore{
   547  		ID:          user.ID,
   548  		Name:        user.Name,
   549  		Password:    user.Password,
   550  		Owner:       user.Owner,
   551  		Source:      user.Source,
   552  		Type:        int(user.Type),
   553  		Token:       user.Token,
   554  		TokenEnable: user.TokenEnable,
   555  		Valid:       user.Valid,
   556  		Comment:     user.Comment,
   557  		CreateTime:  user.CreateTime,
   558  		ModifyTime:  user.ModifyTime,
   559  	}
   560  }
   561  
   562  func converToUserModel(user *userForStore) *model.User {
   563  	return &model.User{
   564  		ID:          user.ID,
   565  		Name:        user.Name,
   566  		Password:    user.Password,
   567  		Owner:       user.Owner,
   568  		Source:      user.Source,
   569  		Type:        model.UserRoleType(user.Type),
   570  		Token:       user.Token,
   571  		TokenEnable: user.TokenEnable,
   572  		Valid:       user.Valid,
   573  		Comment:     user.Comment,
   574  		CreateTime:  user.CreateTime,
   575  		ModifyTime:  user.ModifyTime,
   576  	}
   577  }
   578  
   579  func initUser(user *model.User) {
   580  	if user != nil {
   581  		tn := time.Now()
   582  		user.Valid = true
   583  		user.CreateTime = tn
   584  		user.ModifyTime = tn
   585  	}
   586  }
   587  
   588  type userForStore struct {
   589  	ID          string
   590  	Name        string
   591  	Password    string
   592  	Owner       string
   593  	Source      string
   594  	Type        int
   595  	Mobile      string
   596  	Email       string
   597  	Token       string
   598  	TokenEnable bool
   599  	Valid       bool
   600  	Comment     string
   601  	CreateTime  time.Time
   602  	ModifyTime  time.Time
   603  }