github.com/polarismesh/polaris@v1.17.8/auth/defaultauth/group.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 defaultauth 19 20 import ( 21 "context" 22 "fmt" 23 "time" 24 25 "github.com/gogo/protobuf/jsonpb" 26 apimodel "github.com/polarismesh/specification/source/go/api/v1/model" 27 apisecurity "github.com/polarismesh/specification/source/go/api/v1/security" 28 apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage" 29 "go.uber.org/zap" 30 31 api "github.com/polarismesh/polaris/common/api/v1" 32 "github.com/polarismesh/polaris/common/model" 33 authcommon "github.com/polarismesh/polaris/common/model/auth" 34 commonstore "github.com/polarismesh/polaris/common/store" 35 commontime "github.com/polarismesh/polaris/common/time" 36 "github.com/polarismesh/polaris/common/utils" 37 ) 38 39 type ( 40 // UserGroup2Api is the user group to api 41 UserGroup2Api func(user *model.UserGroup) *apisecurity.UserGroup 42 ) 43 44 var ( 45 // UserLinkGroupAttributes is the user link group attributes 46 UserLinkGroupAttributes = map[string]bool{ 47 "id": true, 48 "user_id": true, 49 "user_name": true, 50 "group_id": true, 51 "name": true, 52 "offset": true, 53 "limit": true, 54 } 55 ) 56 57 // CreateGroup create a group 58 func (svr *Server) CreateGroup(ctx context.Context, req *apisecurity.UserGroup) *apiservice.Response { 59 var ( 60 requestID = utils.ParseRequestID(ctx) 61 platformID = utils.ParsePlatformID(ctx) 62 ownerID = utils.ParseOwnerID(ctx) 63 ) 64 65 req.Owner = utils.NewStringValue(ownerID) 66 if checkErrResp := svr.checkCreateGroup(ctx, req); checkErrResp != nil { 67 return checkErrResp 68 } 69 70 // 根据 owner + groupname 确定唯一的用户组信息 71 group, err := svr.storage.GetGroupByName(req.Name.GetValue(), ownerID) 72 if err != nil { 73 log.Error("get group when create", utils.ZapRequestID(requestID), 74 utils.ZapPlatformID(platformID), zap.Error(err)) 75 return api.NewGroupResponse(commonstore.StoreCode2APICode(err), req) 76 } 77 78 if group != nil { 79 return api.NewGroupResponse(apimodel.Code_UserGroupExisted, req) 80 } 81 82 data, err := createGroupModel(req) 83 if err != nil { 84 log.Error("create group model", utils.ZapRequestID(requestID), 85 utils.ZapPlatformID(platformID), zap.Error(err)) 86 return api.NewAuthResponseWithMsg(apimodel.Code_ExecuteException, err.Error()) 87 } 88 89 if err := svr.storage.AddGroup(data); err != nil { 90 log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID)) 91 return api.NewAuthResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error()) 92 } 93 94 log.Info("create group", zap.String("name", req.Name.GetValue()), utils.ZapRequestID(requestID), 95 utils.ZapPlatformID(platformID)) 96 svr.RecordHistory(userGroupRecordEntry(ctx, req, data.UserGroup, model.OCreate)) 97 98 req.Id = utils.NewStringValue(data.ID) 99 100 return api.NewGroupResponse(apimodel.Code_ExecuteSuccess, req) 101 } 102 103 // UpdateGroups 批量修改用户组 104 func (svr *Server) UpdateGroups( 105 ctx context.Context, groups []*apisecurity.ModifyUserGroup) *apiservice.BatchWriteResponse { 106 resp := api.NewAuthBatchWriteResponse(apimodel.Code_ExecuteSuccess) 107 for index := range groups { 108 req := groups[index] 109 ret := svr.UpdateGroup(ctx, req) 110 api.Collect(resp, ret) 111 } 112 113 return resp 114 } 115 116 // UpdateGroup 更新用户组 117 func (svr *Server) UpdateGroup(ctx context.Context, req *apisecurity.ModifyUserGroup) *apiservice.Response { 118 var ( 119 requestID = utils.ParseRequestID(ctx) 120 platformID = utils.ParsePlatformID(ctx) 121 ) 122 123 if checkErrResp := svr.checkUpdateGroup(ctx, req); checkErrResp != nil { 124 return checkErrResp 125 } 126 127 data, errResp := svr.getGroupFromDB(req.Id.GetValue()) 128 if errResp != nil { 129 return errResp 130 } 131 132 modifyReq, needUpdate := updateGroupAttribute(ctx, data.UserGroup, req) 133 if !needUpdate { 134 log.Info("update group data no change, no need update", 135 utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID), zap.String("group", req.String())) 136 return api.NewModifyGroupResponse(apimodel.Code_NoNeedUpdate, req) 137 } 138 139 if err := svr.storage.UpdateGroup(modifyReq); err != nil { 140 log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID)) 141 return api.NewAuthResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error()) 142 } 143 144 log.Info("update group", zap.String("name", data.Name), utils.ZapRequestID(requestID), 145 utils.ZapPlatformID(platformID)) 146 svr.RecordHistory(modifyUserGroupRecordEntry(ctx, req, data.UserGroup, model.OUpdateGroup)) 147 148 return api.NewModifyGroupResponse(apimodel.Code_ExecuteSuccess, req) 149 } 150 151 // DeleteGroups 批量删除用户组 152 func (svr *Server) DeleteGroups(ctx context.Context, reqs []*apisecurity.UserGroup) *apiservice.BatchWriteResponse { 153 resp := api.NewAuthBatchWriteResponse(apimodel.Code_ExecuteSuccess) 154 for index := range reqs { 155 ret := svr.DeleteGroup(ctx, reqs[index]) 156 api.Collect(resp, ret) 157 } 158 159 return resp 160 } 161 162 // DeleteGroup 删除用户组 163 func (svr *Server) DeleteGroup(ctx context.Context, req *apisecurity.UserGroup) *apiservice.Response { 164 var ( 165 requestID = utils.ParseRequestID(ctx) 166 userID = utils.ParseUserID(ctx) 167 ) 168 169 group, err := svr.storage.GetGroup(req.GetId().GetValue()) 170 if err != nil { 171 log.Error("get group from store", utils.ZapRequestID(requestID), zap.Error(err)) 172 return api.NewGroupResponse(commonstore.StoreCode2APICode(err), req) 173 } 174 if group == nil { 175 return api.NewGroupResponse(apimodel.Code_ExecuteSuccess, req) 176 } 177 178 if authcommon.ParseUserRole(ctx) != model.AdminUserRole { 179 if group.Owner != userID { 180 return api.NewAuthResponse(apimodel.Code_NotAllowedAccess) 181 } 182 } 183 184 if err := svr.storage.DeleteGroup(group); err != nil { 185 log.Error("delete group from store", utils.ZapRequestID(requestID), zap.Error(err)) 186 return api.NewAuthResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error()) 187 } 188 189 log.Info("delete group", utils.ZapRequestID(requestID), zap.String("name", req.Name.GetValue())) 190 svr.RecordHistory(userGroupRecordEntry(ctx, req, group.UserGroup, model.ODelete)) 191 192 return api.NewGroupResponse(apimodel.Code_ExecuteSuccess, req) 193 } 194 195 // GetGroups 查看用户组 196 func (svr *Server) GetGroups(ctx context.Context, query map[string]string) *apiservice.BatchQueryResponse { 197 requestID := utils.ParseRequestID(ctx) 198 199 log.Info("[Auth][Group] origin get groups query params", 200 utils.ZapRequestID(requestID), zap.Any("query", query)) 201 202 var ( 203 offset, limit uint32 204 err error 205 ) 206 207 offset, limit, err = utils.ParseOffsetAndLimit(query) 208 if err != nil { 209 return api.NewAuthBatchQueryResponse(apimodel.Code_InvalidParameter) 210 } 211 212 searchFilters, errResp := parseGroupSearchArgs(ctx, query) 213 if errResp != nil { 214 return errResp 215 } 216 217 total, groups, err := svr.storage.GetGroups(searchFilters, offset, limit) 218 if err != nil { 219 log.Errorf("[Auth][Group] get groups req(%+v) store err: %s", query, err.Error()) 220 return api.NewAuthBatchQueryResponse(commonstore.StoreCode2APICode(err)) 221 } 222 223 resp := api.NewAuthBatchQueryResponse(apimodel.Code_ExecuteSuccess) 224 resp.Amount = utils.NewUInt32Value(total) 225 resp.Size = utils.NewUInt32Value(uint32(len(groups))) 226 resp.UserGroups = enhancedGroups2Api(groups, userGroup2Api) 227 228 svr.fillGroupUserCount(resp.UserGroups) 229 230 return resp 231 } 232 233 func parseGroupSearchArgs( 234 ctx context.Context, query map[string]string) (map[string]string, *apiservice.BatchQueryResponse) { 235 searchFilters := make(map[string]string, len(query)) 236 for key, value := range query { 237 if _, ok := UserLinkGroupAttributes[key]; !ok { 238 log.Errorf("[Auth][Group] get groups attribute(%s) it not allowed", key) 239 return nil, api.NewAuthBatchQueryResponseWithMsg(apimodel.Code_InvalidParameter, key+" is not allowed") 240 } 241 242 searchFilters[key] = value 243 } 244 245 if authcommon.ParseUserRole(ctx) != model.AdminUserRole { 246 // step 1: 设置 owner 信息,只能查看归属主帐户下的用户组 247 searchFilters["owner"] = utils.ParseOwnerID(ctx) 248 if authcommon.ParseUserRole(ctx) != model.OwnerUserRole { 249 // step 2: 非主帐户,只能查看自己所在的用户组 250 if _, ok := searchFilters["user_id"]; !ok { 251 searchFilters["user_id"] = utils.ParseUserID(ctx) 252 } 253 } 254 } 255 256 return searchFilters, nil 257 } 258 259 // GetGroup 查看对应用户组下的用户信息 260 func (svr *Server) GetGroup(ctx context.Context, req *apisecurity.UserGroup) *apiservice.Response { 261 if req.GetId().GetValue() == "" { 262 return api.NewAuthResponse(apimodel.Code_InvalidUserGroupID) 263 } 264 265 group, errResp := svr.getGroupFromDB(req.Id.Value) 266 if errResp != nil { 267 return errResp 268 } 269 270 if authcommon.ParseUserRole(ctx) != model.AdminUserRole { 271 userID := utils.ParseUserID(ctx) 272 isGroupOwner := group.Owner == userID 273 _, find := group.UserIds[userID] 274 if !isGroupOwner && !find { 275 log.Error("can't see group info", zap.String("user", userID), 276 zap.String("group", req.GetId().GetValue()), zap.Bool("group-owner", isGroupOwner), 277 zap.Bool("in-group", find)) 278 return api.NewAuthResponse(apimodel.Code_NotAllowedAccess) 279 } 280 } 281 282 return api.NewGroupResponse(apimodel.Code_ExecuteSuccess, svr.userGroupDetail2Api(group)) 283 } 284 285 // GetGroupToken 查看用户组的token 286 func (svr *Server) GetGroupToken(ctx context.Context, req *apisecurity.UserGroup) *apiservice.Response { 287 if req.GetId().GetValue() == "" { 288 return api.NewAuthResponse(apimodel.Code_InvalidUserGroupID) 289 } 290 291 groupCache, errResp := svr.getGroupFromCache(req) 292 if errResp != nil { 293 return errResp 294 } 295 296 if authcommon.ParseUserRole(ctx) != model.AdminUserRole { 297 userID := utils.ParseUserID(ctx) 298 isGroupOwner := groupCache.Owner == userID 299 _, find := groupCache.UserIds[userID] 300 if !isGroupOwner && !find { 301 log.Error("can't see group token", zap.String("user", userID), 302 zap.String("group", req.GetId().GetValue()), zap.Bool("group-owner", isGroupOwner), 303 zap.Bool("in-group", find)) 304 return api.NewAuthResponse(apimodel.Code_NotAllowedAccess) 305 } 306 } 307 308 req.AuthToken = utils.NewStringValue(groupCache.Token) 309 req.TokenEnable = utils.NewBoolValue(groupCache.TokenEnable) 310 311 return api.NewGroupResponse(apimodel.Code_ExecuteSuccess, req) 312 } 313 314 // UpdateGroupToken 调整用户组 token 的使用状态 (禁用|开启) 315 func (svr *Server) UpdateGroupToken(ctx context.Context, req *apisecurity.UserGroup) *apiservice.Response { 316 var ( 317 requestID = utils.ParseRequestID(ctx) 318 platformID = utils.ParsePlatformID(ctx) 319 group, errResp = svr.getGroupFromDB(req.Id.GetValue()) 320 ) 321 322 if errResp != nil { 323 return errResp 324 } 325 326 if authcommon.ParseUserRole(ctx) != model.AdminUserRole { 327 userID := utils.ParseUserID(ctx) 328 if group.Owner != userID { 329 return api.NewAuthResponse(apimodel.Code_NotAllowedAccess) 330 } 331 } 332 333 group.TokenEnable = req.TokenEnable.GetValue() 334 335 modifyReq := &model.ModifyUserGroup{ 336 ID: group.ID, 337 Owner: group.Owner, 338 Token: group.Token, 339 TokenEnable: group.TokenEnable, 340 Comment: group.Comment, 341 } 342 343 if err := svr.storage.UpdateGroup(modifyReq); err != nil { 344 log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID)) 345 return api.NewAuthResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error()) 346 } 347 348 log.Info("update group token", zap.String("id", req.Id.GetValue()), 349 zap.Bool("enable", group.TokenEnable), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID)) 350 svr.RecordHistory(userGroupRecordEntry(ctx, req, group.UserGroup, model.OUpdateToken)) 351 352 return api.NewGroupResponse(apimodel.Code_ExecuteSuccess, req) 353 } 354 355 // ResetGroupToken 刷新用户组的token 356 func (svr *Server) ResetGroupToken(ctx context.Context, req *apisecurity.UserGroup) *apiservice.Response { 357 var ( 358 requestID = utils.ParseRequestID(ctx) 359 platformID = utils.ParsePlatformID(ctx) 360 group, errResp = svr.getGroupFromDB(req.Id.GetValue()) 361 ) 362 363 if errResp != nil { 364 return errResp 365 } 366 367 if !utils.ParseIsOwner(ctx) || (group.Owner != utils.ParseUserID(ctx)) { 368 return api.NewAuthResponse(apimodel.Code_NotAllowedAccess) 369 } 370 371 newToken, err := createGroupToken(group.ID) 372 if err != nil { 373 log.Error("reset group token", utils.ZapRequestID(requestID), 374 utils.ZapPlatformID(platformID), zap.Error(err)) 375 return api.NewAuthResponseWithMsg(apimodel.Code_ExecuteException, err.Error()) 376 } 377 378 group.Token = newToken 379 modifyReq := &model.ModifyUserGroup{ 380 ID: group.ID, 381 Owner: group.Owner, 382 Token: group.Token, 383 TokenEnable: group.TokenEnable, 384 Comment: group.Comment, 385 } 386 387 if err := svr.storage.UpdateGroup(modifyReq); err != nil { 388 log.Error(err.Error(), utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID)) 389 return api.NewAuthResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error()) 390 } 391 392 log.Info("reset group token", zap.String("group-id", req.Id.GetValue()), 393 utils.ZapRequestID(requestID), utils.ZapPlatformID(platformID)) 394 svr.RecordHistory(userGroupRecordEntry(ctx, req, group.UserGroup, model.OUpdate)) 395 396 req.AuthToken = utils.NewStringValue(newToken) 397 398 return api.NewGroupResponse(apimodel.Code_ExecuteSuccess, req) 399 } 400 401 // getGroupFromDB 获取用户组 402 func (svr *Server) getGroupFromDB(id string) (*model.UserGroupDetail, *apiservice.Response) { 403 group, err := svr.storage.GetGroup(id) 404 if err != nil { 405 log.Error("get group from store", zap.Error(err)) 406 return nil, api.NewAuthResponseWithMsg(commonstore.StoreCode2APICode(err), err.Error()) 407 } 408 if group == nil { 409 return nil, api.NewAuthResponse(apimodel.Code_NotFoundUserGroup) 410 } 411 412 return group, nil 413 } 414 415 // getGroupFromCache 从缓存中获取用户组信息数据 416 func (svr *Server) getGroupFromCache(req *apisecurity.UserGroup) (*model.UserGroupDetail, *apiservice.Response) { 417 group := svr.cacheMgn.User().GetGroup(req.Id.GetValue()) 418 if group == nil { 419 return nil, api.NewGroupResponse(apimodel.Code_NotFoundUserGroup, req) 420 } 421 422 return group, nil 423 } 424 425 // preCheckGroupRelation 检查用户-用户组关联关系中,对应的用户信息是否存在,即不能添加一个不存在的用户到用户组 426 func (svr *Server) preCheckGroupRelation(groupID string, req *apisecurity.UserGroupRelation) (*model.UserGroupDetail, 427 *apiservice.Response) { 428 group := svr.cacheMgn.User().GetGroup(groupID) 429 if group == nil { 430 return nil, api.NewAuthResponse(apimodel.Code_NotFoundUserGroup) 431 } 432 433 // 检查该关系中所有的用户是否存在 434 uIDs := make([]string, len(req.GetUsers())) 435 for i := range req.GetUsers() { 436 uIDs[i] = req.GetUsers()[i].GetId().GetValue() 437 } 438 439 uIDs = utils.StringSliceDeDuplication(uIDs) 440 for i := range uIDs { 441 user := svr.cacheMgn.User().GetUserByID(uIDs[i]) 442 if user == nil { 443 return group, api.NewGroupRelationResponse(apimodel.Code_NotFoundUser, req) 444 } 445 } 446 447 return group, nil 448 } 449 450 // checkCreateGroup 检查创建用户组的请求 451 func (svr *Server) checkCreateGroup(_ context.Context, req *apisecurity.UserGroup) *apiservice.Response { 452 if req == nil { 453 return api.NewGroupResponse(apimodel.Code_EmptyRequest, req) 454 } 455 456 users := req.GetRelation().GetUsers() 457 for i := range users { 458 user := svr.cacheMgn.User().GetUserByID(users[i].GetId().GetValue()) 459 if user == nil { 460 return api.NewGroupRelationResponse(apimodel.Code_NotFoundUser, req.GetRelation()) 461 } 462 } 463 464 return nil 465 } 466 467 // checkUpdateGroup 检查用户组的更新请求 468 func (svr *Server) checkUpdateGroup(ctx context.Context, req *apisecurity.ModifyUserGroup) *apiservice.Response { 469 userID := utils.ParseUserID(ctx) 470 isOwner := utils.ParseIsOwner(ctx) 471 472 if req == nil { 473 return api.NewModifyGroupResponse(apimodel.Code_EmptyRequest, req) 474 } 475 476 if req.Id == nil || req.Id.GetValue() == "" { 477 return api.NewModifyGroupResponse(apimodel.Code_InvalidUserGroupID, req) 478 } 479 480 group, checkErrResp := svr.preCheckGroupRelation(req.GetId().GetValue(), req.GetAddRelations()) 481 if checkErrResp != nil { 482 return checkErrResp 483 } 484 485 // 满足以下情况才可以进行操作 486 // 1.管理员 487 // 2.自己在这个用户组里面 488 // 3.自己是这个用户组的owner角色 489 if authcommon.ParseUserRole(ctx) != model.AdminUserRole { 490 _, inGroup := group.UserIds[userID] 491 if !inGroup && group.Owner != userID { 492 return api.NewAuthResponse(apimodel.Code_NotAllowedAccess) 493 } 494 495 // 如果当前用户只是在这个组里面,但不是该用户组的owner,那只能添加用户,不能删除用户 496 if inGroup && !isOwner && len(req.GetRemoveRelations().GetUsers()) != 0 { 497 return api.NewAuthResponseWithMsg( 498 apimodel.Code_NotAllowedAccess, "only main account can remove user from usergroup") 499 } 500 } 501 return nil 502 } 503 504 func (svr *Server) fillGroupUserCount(groups []*apisecurity.UserGroup) { 505 groupCache := svr.cacheMgn.User() 506 507 for index := range groups { 508 group := groups[index] 509 cacheVal := groupCache.GetGroup(group.Id.Value) 510 if cacheVal == nil { 511 group.UserCount = utils.NewUInt32Value(0) 512 } else { 513 group.UserCount = utils.NewUInt32Value(uint32(len(cacheVal.UserIds))) 514 } 515 } 516 } 517 518 // updateGroupAttribute 更新计算用户组更新时的结构体数据,并判断是否需要执行更新操作 519 func updateGroupAttribute(ctx context.Context, old *model.UserGroup, newUser *apisecurity.ModifyUserGroup) ( 520 *model.ModifyUserGroup, bool) { 521 var ( 522 needUpdate bool 523 ret = &model.ModifyUserGroup{ 524 ID: old.ID, 525 Token: old.Token, 526 TokenEnable: old.TokenEnable, 527 Comment: old.Comment, 528 } 529 ) 530 531 // 只有 owner 可以修改这个属性 532 if utils.ParseIsOwner(ctx) { 533 if newUser.Comment.GetValue() != "" && old.Comment != newUser.Comment.GetValue() { 534 needUpdate = true 535 ret.Comment = newUser.Comment.GetValue() 536 } 537 } 538 539 // 用户组成员变更计算 540 if len(newUser.GetAddRelations().GetUsers()) != 0 { 541 needUpdate = true 542 ids := make([]string, 0, len(newUser.GetAddRelations().GetUsers())) 543 for index := range newUser.GetAddRelations().GetUsers() { 544 ids = append(ids, newUser.GetAddRelations().GetUsers()[index].GetId().GetValue()) 545 } 546 ret.AddUserIds = ids 547 } 548 549 if len(newUser.GetRemoveRelations().GetUsers()) != 0 { 550 needUpdate = true 551 ids := make([]string, 0, len(newUser.GetRemoveRelations().GetUsers())) 552 for index := range newUser.GetRemoveRelations().GetUsers() { 553 ids = append(ids, newUser.GetRemoveRelations().GetUsers()[index].GetId().GetValue()) 554 } 555 ret.RemoveUserIds = ids 556 } 557 558 return ret, needUpdate 559 } 560 561 // enhancedGroups2Api 数组专为 []*apisecurity.UserGroup 562 func enhancedGroups2Api(groups []*model.UserGroup, handler UserGroup2Api) []*apisecurity.UserGroup { 563 out := make([]*apisecurity.UserGroup, 0, len(groups)) 564 for k := range groups { 565 out = append(out, handler(groups[k])) 566 } 567 568 return out 569 } 570 571 // createGroupModel 创建用户组的存储模型 572 func createGroupModel(req *apisecurity.UserGroup) (group *model.UserGroupDetail, err error) { 573 ids := make(map[string]struct{}, len(req.GetRelation().GetUsers())) 574 for index := range req.GetRelation().GetUsers() { 575 ids[req.GetRelation().GetUsers()[index].GetId().GetValue()] = struct{}{} 576 } 577 578 group = &model.UserGroupDetail{ 579 UserGroup: &model.UserGroup{ 580 ID: utils.NewUUID(), 581 Name: req.GetName().GetValue(), 582 Owner: req.GetOwner().GetValue(), 583 TokenEnable: true, 584 Valid: true, 585 Comment: req.GetComment().GetValue(), 586 CreateTime: time.Now(), 587 ModifyTime: time.Now(), 588 }, 589 UserIds: ids, 590 } 591 592 if group.Token, err = createGroupToken(group.ID); err != nil { 593 return nil, err 594 } 595 return group, nil 596 } 597 598 // model.UserGroup 转为 api.UserGroup 599 func userGroup2Api(group *model.UserGroup) *apisecurity.UserGroup { 600 if group == nil { 601 return nil 602 } 603 604 // note: 不包括token,token比较特殊 605 out := &apisecurity.UserGroup{ 606 Id: utils.NewStringValue(group.ID), 607 Name: utils.NewStringValue(group.Name), 608 Owner: utils.NewStringValue(group.Owner), 609 TokenEnable: utils.NewBoolValue(group.TokenEnable), 610 Comment: utils.NewStringValue(group.Comment), 611 Ctime: utils.NewStringValue(commontime.Time2String(group.CreateTime)), 612 Mtime: utils.NewStringValue(commontime.Time2String(group.ModifyTime)), 613 } 614 615 return out 616 } 617 618 // model.UserGroupDetail 转为 api.UserGroup,并且主动填充 user 的信息数据 619 func (svr *Server) userGroupDetail2Api(group *model.UserGroupDetail) *apisecurity.UserGroup { 620 if group == nil { 621 return nil 622 } 623 624 users := make([]*apisecurity.User, 0, len(group.UserIds)) 625 for id := range group.UserIds { 626 user := svr.cacheMgn.User().GetUserByID(id) 627 users = append(users, &apisecurity.User{ 628 Id: utils.NewStringValue(user.ID), 629 Name: utils.NewStringValue(user.Name), 630 Source: utils.NewStringValue(user.Source), 631 Comment: utils.NewStringValue(user.Comment), 632 TokenEnable: utils.NewBoolValue(user.TokenEnable), 633 Ctime: utils.NewStringValue(commontime.Time2String(user.CreateTime)), 634 Mtime: utils.NewStringValue(commontime.Time2String(user.ModifyTime)), 635 }) 636 } 637 638 // note: 不包括token,token比较特殊 639 out := &apisecurity.UserGroup{ 640 Id: utils.NewStringValue(group.ID), 641 Name: utils.NewStringValue(group.Name), 642 Owner: utils.NewStringValue(group.Owner), 643 TokenEnable: utils.NewBoolValue(group.TokenEnable), 644 Comment: utils.NewStringValue(group.Comment), 645 Ctime: utils.NewStringValue(commontime.Time2String(group.CreateTime)), 646 Mtime: utils.NewStringValue(commontime.Time2String(group.ModifyTime)), 647 Relation: &apisecurity.UserGroupRelation{ 648 Users: users, 649 }, 650 UserCount: utils.NewUInt32Value(uint32(len(users))), 651 } 652 653 return out 654 } 655 656 // userGroupRecordEntry 生成用户组的记录entry 657 func userGroupRecordEntry(ctx context.Context, req *apisecurity.UserGroup, md *model.UserGroup, 658 operationType model.OperationType) *model.RecordEntry { 659 660 marshaler := jsonpb.Marshaler{} 661 datail, _ := marshaler.MarshalToString(req) 662 663 entry := &model.RecordEntry{ 664 ResourceType: model.RUserGroup, 665 ResourceName: fmt.Sprintf("%s(%s)", md.Name, md.ID), 666 OperationType: operationType, 667 Operator: utils.ParseOperator(ctx), 668 Detail: datail, 669 HappenTime: time.Now(), 670 } 671 672 return entry 673 } 674 675 // 生成修改用户组的记录entry 676 func modifyUserGroupRecordEntry(ctx context.Context, req *apisecurity.ModifyUserGroup, md *model.UserGroup, 677 operationType model.OperationType) *model.RecordEntry { 678 679 marshaler := jsonpb.Marshaler{} 680 detail, _ := marshaler.MarshalToString(req) 681 682 entry := &model.RecordEntry{ 683 ResourceType: model.RUserGroup, 684 ResourceName: fmt.Sprintf("%s(%s)", md.Name, md.ID), 685 OperationType: operationType, 686 Operator: utils.ParseOperator(ctx), 687 Detail: detail, 688 HappenTime: time.Now(), 689 } 690 691 return entry 692 } 693 694 // 生成用户-用户组关联关系的记录entry 695 func userRelationRecordEntry(ctx context.Context, req *apisecurity.UserGroupRelation, md *model.UserGroup, 696 operationType model.OperationType) *model.RecordEntry { 697 698 marshaler := jsonpb.Marshaler{} 699 detail, _ := marshaler.MarshalToString(req) 700 701 entry := &model.RecordEntry{ 702 ResourceType: model.RUserGroupRelation, 703 ResourceName: fmt.Sprintf("%s(%s)", md.Name, md.ID), 704 OperationType: operationType, 705 Operator: utils.ParseOperator(ctx), 706 Detail: detail, 707 HappenTime: time.Now(), 708 } 709 710 return entry 711 }