github.com/polarismesh/polaris@v1.17.8/store/mysql/strategy.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 sqldb 19 20 import ( 21 "database/sql" 22 "fmt" 23 "strings" 24 "time" 25 26 "go.uber.org/zap" 27 28 "github.com/polarismesh/polaris/common/model" 29 "github.com/polarismesh/polaris/common/utils" 30 "github.com/polarismesh/polaris/store" 31 ) 32 33 var ( 34 RuleFilters map[string]string = map[string]string{ 35 "res_id": "ar.res_id", 36 "res_type": "ar.res_type", 37 "default": "ag.default", 38 "owner": "ag.owner", 39 "name": "ag.name", 40 "principal_id": "ap.principal_id", 41 "principal_type": "ap.principal_role", 42 } 43 44 RuleNeedLikeFilters map[string]struct{} = map[string]struct{}{ 45 "name": {}, 46 } 47 ) 48 49 type strategyStore struct { 50 master *BaseDB 51 slave *BaseDB 52 } 53 54 func (s *strategyStore) AddStrategy(strategy *model.StrategyDetail) error { 55 if strategy.ID == "" || strategy.Name == "" || strategy.Owner == "" { 56 return store.NewStatusError(store.EmptyParamsErr, fmt.Sprintf( 57 "add auth_strategy missing some params, id is %s, name is %s, owner is %s", 58 strategy.ID, strategy.Name, strategy.Owner)) 59 } 60 61 // 先清理无效数据 62 if err := s.cleanInvalidStrategy(strategy.Name, strategy.Owner); err != nil { 63 return store.Error(err) 64 } 65 66 err := RetryTransaction("addStrategy", func() error { 67 return s.addStrategy(strategy) 68 }) 69 return store.Error(err) 70 } 71 72 func (s *strategyStore) addStrategy(strategy *model.StrategyDetail) error { 73 tx, err := s.master.Begin() 74 if err != nil { 75 return err 76 } 77 defer func() { _ = tx.Rollback() }() 78 79 isDefault := 0 80 if strategy.Default { 81 isDefault = 1 82 } 83 84 if err := s.addStrategyPrincipals(tx, strategy.ID, strategy.Principals); err != nil { 85 log.Error("[Store][Strategy] add auth_strategy principals", zap.Error(err)) 86 return err 87 } 88 89 if err := s.addStrategyResources(tx, strategy.ID, strategy.Resources); err != nil { 90 log.Error("[Store][Strategy] add auth_strategy resources", zap.Error(err)) 91 return err 92 } 93 94 // 保存策略主信息 95 saveMainSql := "INSERT INTO auth_strategy(`id`, `name`, `action`, `owner`, `comment`, `flag`, " + 96 " `default`, `revision`) VALUES (?,?,?,?,?,?,?,?)" 97 if _, err = tx.Exec(saveMainSql, 98 []interface{}{ 99 strategy.ID, strategy.Name, strategy.Action, strategy.Owner, strategy.Comment, 100 0, isDefault, strategy.Revision}..., 101 ); err != nil { 102 log.Error("[Store][Strategy] add auth_strategy main info", zap.Error(err)) 103 return err 104 } 105 106 if err := tx.Commit(); err != nil { 107 log.Errorf("[Store][Strategy] add auth_strategy tx commit err: %s", err.Error()) 108 return err 109 } 110 111 return nil 112 } 113 114 // UpdateStrategy 更新鉴权规则 115 func (s *strategyStore) UpdateStrategy(strategy *model.ModifyStrategyDetail) error { 116 if strategy.ID == "" { 117 return store.NewStatusError(store.EmptyParamsErr, fmt.Sprintf( 118 "update auth_strategy missing some params, id is %s", strategy.ID)) 119 } 120 121 err := RetryTransaction("updateStrategy", func() error { 122 return s.updateStrategy(strategy) 123 }) 124 return store.Error(err) 125 } 126 127 func (s *strategyStore) updateStrategy(strategy *model.ModifyStrategyDetail) error { 128 tx, err := s.master.Begin() 129 if err != nil { 130 return err 131 } 132 defer func() { _ = tx.Rollback() }() 133 134 // 调整 principal 信息 135 if err := s.addStrategyPrincipals(tx, strategy.ID, strategy.AddPrincipals); err != nil { 136 log.Errorf("[Store][Strategy] add strategy principal err: %s", err.Error()) 137 return err 138 } 139 if err := s.deleteStrategyPrincipals(tx, strategy.ID, strategy.RemovePrincipals); err != nil { 140 log.Errorf("[Store][Strategy] remove strategy principal err: %s", err.Error()) 141 return err 142 } 143 144 // 调整鉴权资源信息 145 if err := s.addStrategyResources(tx, strategy.ID, strategy.AddResources); err != nil { 146 log.Errorf("[Store][Strategy] add strategy resource err: %s", err.Error()) 147 return err 148 } 149 if err := s.deleteStrategyResources(tx, strategy.ID, strategy.RemoveResources); err != nil { 150 log.Errorf("[Store][Strategy] remove strategy resource err: %s", err.Error()) 151 return err 152 } 153 154 // 保存策略主信息 155 saveMainSql := "UPDATE auth_strategy SET action = ?, comment = ?, mtime = sysdate() WHERE id = ?" 156 if _, err = tx.Exec(saveMainSql, []interface{}{strategy.Action, strategy.Comment, strategy.ID}...); err != nil { 157 log.Error("[Store][Strategy] update strategy main info", zap.Error(err)) 158 return err 159 } 160 161 if err := tx.Commit(); err != nil { 162 log.Errorf("[Store][Strategy] update auth_strategy tx commit err: %s", err.Error()) 163 return err 164 } 165 166 return nil 167 } 168 169 func (s *strategyStore) DeleteStrategy(id string) error { 170 if id == "" { 171 return store.NewStatusError(store.EmptyParamsErr, fmt.Sprintf( 172 "delete auth_strategy missing some params, id is %s", id)) 173 } 174 175 err := RetryTransaction("deleteStrategy", func() error { 176 return s.deleteStrategy(id) 177 }) 178 return store.Error(err) 179 } 180 181 func (s *strategyStore) deleteStrategy(id string) error { 182 tx, err := s.master.Begin() 183 if err != nil { 184 return err 185 } 186 187 defer func() { _ = tx.Rollback() }() 188 189 if _, err = tx.Exec("UPDATE auth_strategy SET flag = 1, mtime = sysdate() WHERE id = ?", []interface{}{ 190 id, 191 }...); err != nil { 192 return err 193 } 194 195 if _, err = tx.Exec("DELETE FROM auth_strategy_resource WHERE strategy_id = ?", []interface{}{ 196 id, 197 }...); err != nil { 198 return err 199 } 200 201 if _, err = tx.Exec("DELETE FROM auth_principal WHERE strategy_id = ?", []interface{}{ 202 id, 203 }...); err != nil { 204 return err 205 } 206 207 if err := tx.Commit(); err != nil { 208 log.Errorf("[Store][Strategy] delete auth_strategy tx commit err: %s", err.Error()) 209 return err 210 } 211 return nil 212 } 213 214 // addStrategyPrincipals 215 func (s *strategyStore) addStrategyPrincipals(tx *BaseTx, id string, principals []model.Principal) error { 216 if len(principals) == 0 { 217 return nil 218 } 219 220 savePrincipalSql := "INSERT IGNORE INTO auth_principal(strategy_id, principal_id, principal_role) VALUES " 221 values := make([]string, 0) 222 args := make([]interface{}, 0) 223 224 for i := range principals { 225 principal := principals[i] 226 values = append(values, "(?,?,?)") 227 args = append(args, id, principal.PrincipalID, principal.PrincipalRole) 228 } 229 230 savePrincipalSql += strings.Join(values, ",") 231 232 log.Debug("[Store][Strategy] add strategy principal", zap.String("sql", savePrincipalSql), 233 zap.Any("args", args)) 234 235 _, err := tx.Exec(savePrincipalSql, args...) 236 return err 237 } 238 239 // deleteStrategyPrincipals 240 func (s *strategyStore) deleteStrategyPrincipals(tx *BaseTx, id string, 241 principals []model.Principal) error { 242 if len(principals) == 0 { 243 return nil 244 } 245 246 savePrincipalSql := "DELETE FROM auth_principal WHERE strategy_id = ? AND principal_id = ? " + 247 " AND principal_role = ?" 248 for i := range principals { 249 principal := principals[i] 250 if _, err := tx.Exec(savePrincipalSql, []interface{}{ 251 id, principal.PrincipalID, principal.PrincipalRole, 252 }...); err != nil { 253 return err 254 } 255 } 256 257 return nil 258 } 259 260 func (s *strategyStore) addStrategyResources(tx *BaseTx, id string, resources []model.StrategyResource) error { 261 if len(resources) == 0 { 262 return nil 263 } 264 265 saveResSql := "REPLACE INTO auth_strategy_resource(strategy_id, res_type, res_id) VALUES " 266 values := make([]string, 0) 267 args := make([]interface{}, 0) 268 269 for i := range resources { 270 resource := resources[i] 271 values = append(values, "(?,?,?)") 272 args = append(args, resource.StrategyID, resource.ResType, resource.ResID) 273 } 274 275 if len(values) == 0 { 276 return nil 277 } 278 279 saveResSql += strings.Join(values, ",") 280 log.Debug("[Store][Strategy] add strategy resources", zap.String("sql", saveResSql), 281 zap.Any("args", args)) 282 _, err := tx.Exec(saveResSql, args...) 283 return err 284 } 285 286 func (s *strategyStore) deleteStrategyResources(tx *BaseTx, id string, 287 resources []model.StrategyResource) error { 288 289 if len(resources) == 0 { 290 return nil 291 } 292 293 for i := range resources { 294 resource := resources[i] 295 296 saveResSql := "DELETE FROM auth_strategy_resource WHERE strategy_id = ? AND res_id = ? AND res_type = ?" 297 if _, err := tx.Exec( 298 saveResSql, 299 []interface{}{resource.StrategyID, resource.ResID, resource.ResType}..., 300 ); err != nil { 301 return err 302 } 303 } 304 return nil 305 } 306 307 // LooseAddStrategyResources loose add strategy resources 308 func (s *strategyStore) LooseAddStrategyResources(resources []model.StrategyResource) error { 309 tx, err := s.master.Begin() 310 if err != nil { 311 return err 312 } 313 defer func() { _ = tx.Rollback() }() 314 315 // 保存策略的资源信息 316 for i := range resources { 317 resource := resources[i] 318 319 saveResSql := "REPLACE INTO auth_strategy_resource(strategy_id, res_type, res_id) VALUES (?,?,?)" 320 args := make([]interface{}, 0) 321 args = append(args, resource.StrategyID, resource.ResType, resource.ResID) 322 323 if _, err = tx.Exec(saveResSql, args...); err != nil { 324 err = store.Error(err) 325 if store.Code(err) == store.DuplicateEntryErr { 326 continue 327 } 328 return err 329 } 330 331 // 主要是为了能够触发 StrategyCache 的刷新逻辑 332 updateStrategySql := "UPDATE auth_strategy SET mtime = sysdate() WHERE id = ?" 333 if _, err = tx.Exec(updateStrategySql, resource.StrategyID); err != nil { 334 return err 335 } 336 } 337 338 if err := tx.Commit(); err != nil { 339 log.Errorf("[Store][Strategy] add auth_strategy tx commit err: %s", err.Error()) 340 return err 341 } 342 343 return nil 344 } 345 346 // RemoveStrategyResources 删除策略的资源 347 func (s *strategyStore) RemoveStrategyResources(resources []model.StrategyResource) error { 348 tx, err := s.master.Begin() 349 if err != nil { 350 return err 351 } 352 defer func() { _ = tx.Rollback() }() 353 for i := range resources { 354 resource := resources[i] 355 356 args := make([]interface{}, 0) 357 saveResSql := "DELETE FROM auth_strategy_resource WHERE strategy_id = ? AND res_id = ? AND res_type = ?" 358 args = append(args, resource.StrategyID, resource.ResID, resource.ResType) 359 if resource.StrategyID == "" { 360 saveResSql = "DELETE FROM auth_strategy_resource WHERE res_id = ? AND res_type = ?" 361 args = append(args, resource.ResID, resource.ResType) 362 } 363 if _, err := tx.Exec(saveResSql, args...); err != nil { 364 return err 365 } 366 // 主要是为了能够触发 StrategyCache 的刷新逻辑 367 updateStrategySql := "UPDATE auth_strategy SET mtime = sysdate() WHERE id = ?" 368 if _, err = tx.Exec(updateStrategySql, resource.StrategyID); err != nil { 369 return err 370 } 371 } 372 373 if err := tx.Commit(); err != nil { 374 log.Errorf("[Store][Strategy] add auth_strategy tx commit err: %s", err.Error()) 375 return err 376 } 377 378 return nil 379 } 380 381 // GetStrategyDetail 获取策略详情 382 func (s *strategyStore) GetStrategyDetail(id string) (*model.StrategyDetail, error) { 383 if id == "" { 384 return nil, store.NewStatusError(store.EmptyParamsErr, fmt.Sprintf( 385 "get auth_strategy missing some params, id is %s", id)) 386 } 387 388 querySql := "SELECT ag.id, ag.name, ag.action, ag.owner, ag.default, ag.comment, ag.revision, ag.flag, " + 389 " UNIX_TIMESTAMP(ag.ctime), UNIX_TIMESTAMP(ag.mtime) FROM auth_strategy AS ag WHERE ag.flag = 0 AND ag.id = ?" 390 391 row := s.master.QueryRow(querySql, id) 392 393 return s.getStrategyDetail(row) 394 } 395 396 // GetDefaultStrategyDetailByPrincipal 获取默认策略 397 func (s *strategyStore) GetDefaultStrategyDetailByPrincipal(principalId string, 398 principalType model.PrincipalType) (*model.StrategyDetail, error) { 399 400 if principalId == "" { 401 return nil, store.NewStatusError(store.EmptyParamsErr, fmt.Sprintf( 402 "get auth_strategy missing some params, principal_id is %s", principalId)) 403 } 404 405 querySql := ` 406 SELECT ag.id, ag.name, ag.action, ag.owner, ag.default 407 , ag.comment, ag.revision, ag.flag, UNIX_TIMESTAMP(ag.ctime) 408 , UNIX_TIMESTAMP(ag.mtime) 409 FROM auth_strategy ag 410 WHERE ag.flag = 0 411 AND ag.default = 1 412 AND ag.id IN ( 413 SELECT DISTINCT strategy_id 414 FROM auth_principal 415 WHERE principal_id = ? 416 AND principal_role = ? 417 ) 418 ` 419 420 row := s.master.QueryRow(querySql, principalId, int(principalType)) 421 return s.getStrategyDetail(row) 422 } 423 424 // getStrategyDetail 425 func (s *strategyStore) getStrategyDetail(row *sql.Row) (*model.StrategyDetail, error) { 426 var ( 427 ctime, mtime int64 428 isDefault, flag int16 429 ) 430 ret := new(model.StrategyDetail) 431 if err := row.Scan(&ret.ID, &ret.Name, &ret.Action, &ret.Owner, &isDefault, &ret.Comment, 432 &ret.Revision, &flag, &ctime, &mtime); err != nil { 433 switch err { 434 case sql.ErrNoRows: 435 return nil, nil 436 default: 437 return nil, store.Error(err) 438 } 439 } 440 441 ret.CreateTime = time.Unix(ctime, 0) 442 ret.ModifyTime = time.Unix(mtime, 0) 443 ret.Valid = flag == 0 444 ret.Default = isDefault == 1 445 446 resArr, err := s.getStrategyResources(s.slave.Query, ret.ID) 447 if err != nil { 448 return nil, store.Error(err) 449 } 450 principals, err := s.getStrategyPrincipals(s.slave.Query, ret.ID) 451 if err != nil { 452 return nil, store.Error(err) 453 } 454 455 ret.Resources = resArr 456 ret.Principals = principals 457 return ret, nil 458 } 459 460 // GetStrategies 获取策略列表 461 func (s *strategyStore) GetStrategies(filters map[string]string, offset uint32, limit uint32) (uint32, 462 []*model.StrategyDetail, error) { 463 showDetail := filters["show_detail"] 464 delete(filters, "show_detail") 465 466 filters["ag.flag"] = "0" 467 468 return s.listStrategies(filters, offset, limit, showDetail == "true") 469 } 470 471 // listStrategies 472 func (s *strategyStore) listStrategies(filters map[string]string, offset uint32, limit uint32, 473 showDetail bool) (uint32, []*model.StrategyDetail, error) { 474 475 querySql := 476 `SELECT 477 ag.id, 478 ag.name, 479 ag.action, 480 ag.owner, 481 ag.comment, 482 ag.default, 483 ag.revision, 484 ag.flag, 485 UNIX_TIMESTAMP(ag.ctime), 486 UNIX_TIMESTAMP(ag.mtime) 487 FROM 488 ( 489 auth_strategy ag 490 LEFT JOIN auth_strategy_resource ar ON ag.id = ar.strategy_id 491 ) 492 LEFT JOIN auth_principal ap ON ag.id = ap.strategy_id ` 493 countSql := ` 494 SELECT COUNT(DISTINCT ag.id) 495 FROM 496 ( 497 auth_strategy ag 498 LEFT JOIN auth_strategy_resource ar ON ag.id = ar.strategy_id 499 ) 500 LEFT JOIN auth_principal ap ON ag.id = ap.strategy_id 501 ` 502 503 return s.queryStrategies(s.master.Query, filters, RuleFilters, querySql, countSql, 504 offset, limit, showDetail) 505 } 506 507 // queryStrategies 通用的查询策略列表 508 func (s *strategyStore) queryStrategies( 509 handler QueryHandler, 510 filters map[string]string, mapping map[string]string, 511 querySqlPrefix string, countSqlPrefix string, 512 offset uint32, limit uint32, showDetail bool) (uint32, []*model.StrategyDetail, error) { 513 querySql := querySqlPrefix 514 countSql := countSqlPrefix 515 516 args := make([]interface{}, 0) 517 if len(filters) != 0 { 518 querySql += " WHERE " 519 countSql += " WHERE " 520 firstIndex := true 521 for k, v := range filters { 522 needLike := false 523 if !firstIndex { 524 querySql += " AND " 525 countSql += " AND " 526 } 527 firstIndex = false 528 529 if val, ok := mapping[k]; ok { 530 if _, exist := RuleNeedLikeFilters[k]; exist { 531 needLike = true 532 } 533 k = val 534 } 535 536 if needLike { 537 if utils.IsPrefixWildName(v) { 538 v = v[:len(v)-1] 539 } 540 querySql += (" " + k + " like ? ") 541 countSql += (" " + k + " like ? ") 542 args = append(args, "%"+v+"%") 543 } else if k == "ag.owner" { 544 querySql += " (ag.owner = ? OR (ap.principal_id = ? AND ap.principal_role = 1 )) " 545 countSql += " (ag.owner = ? OR (ap.principal_id = ? AND ap.principal_role = 1 )) " 546 args = append(args, v, v) 547 } else { 548 querySql += (" " + k + " = ? ") 549 countSql += (" " + k + " = ? ") 550 args = append(args, v) 551 } 552 } 553 } 554 555 count, err := queryEntryCount(s.master, countSql, args) 556 if err != nil { 557 return 0, nil, store.Error(err) 558 } 559 560 querySql += " GROUP BY ag.id ORDER BY ag.mtime LIMIT ?, ? " 561 args = append(args, offset, limit) 562 563 ret, err := s.collectStrategies(s.master.Query, querySql, args, showDetail) 564 if err != nil { 565 return 0, nil, err 566 } 567 568 return count, ret, nil 569 } 570 571 // collectStrategies 执行真正的 sql 并从 rows 中获取策略列表 572 func (s *strategyStore) collectStrategies(handler QueryHandler, querySql string, 573 args []interface{}, showDetail bool) ([]*model.StrategyDetail, error) { 574 log.Debug("[Store][Strategy] get simple strategies", zap.String("query sql", querySql), 575 zap.Any("args", args)) 576 577 rows, err := handler(querySql, args...) 578 if err != nil { 579 log.Error("[Store][Strategy] get simple strategies", zap.String("query sql", querySql), 580 zap.Any("args", args)) 581 return nil, store.Error(err) 582 } 583 defer func() { 584 _ = rows.Close() 585 }() 586 587 idMap := make(map[string]struct{}) 588 589 ret := make([]*model.StrategyDetail, 0, 16) 590 for rows.Next() { 591 detail, err := fetchRown2StrategyDetail(rows) 592 if err != nil { 593 return nil, store.Error(err) 594 } 595 596 // 为了避免数据重复被加入到 slice 中,做一个 map 去重 597 if _, ok := idMap[detail.ID]; ok { 598 continue 599 } 600 idMap[detail.ID] = struct{}{} 601 602 if showDetail { 603 resArr, err := s.getStrategyResources(s.slave.Query, detail.ID) 604 if err != nil { 605 return nil, store.Error(err) 606 } 607 principals, err := s.getStrategyPrincipals(s.slave.Query, detail.ID) 608 if err != nil { 609 return nil, store.Error(err) 610 } 611 612 detail.Resources = resArr 613 detail.Principals = principals 614 } 615 616 ret = append(ret, detail) 617 } 618 619 return ret, nil 620 } 621 622 func (s *strategyStore) GetStrategyDetailsForCache(mtime time.Time, 623 firstUpdate bool) ([]*model.StrategyDetail, error) { 624 tx, err := s.slave.Begin() 625 if err != nil { 626 return nil, store.Error(err) 627 } 628 defer func() { _ = tx.Commit() }() 629 630 args := make([]interface{}, 0) 631 querySql := "SELECT ag.id, ag.name, ag.action, ag.owner, ag.comment, ag.default, ag.revision, ag.flag, " + 632 " UNIX_TIMESTAMP(ag.ctime), UNIX_TIMESTAMP(ag.mtime) FROM auth_strategy ag " 633 634 if !firstUpdate { 635 querySql += " WHERE ag.mtime >= FROM_UNIXTIME(?)" 636 args = append(args, timeToTimestamp(mtime)) 637 } 638 639 rows, err := tx.Query(querySql, args...) 640 if err != nil { 641 return nil, store.Error(err) 642 } 643 defer func() { 644 _ = rows.Close() 645 }() 646 647 ret := make([]*model.StrategyDetail, 0) 648 for rows.Next() { 649 detail, err := fetchRown2StrategyDetail(rows) 650 if err != nil { 651 return nil, store.Error(err) 652 } 653 654 resArr, err := s.getStrategyResources(s.slave.Query, detail.ID) 655 if err != nil { 656 return nil, store.Error(err) 657 } 658 principals, err := s.getStrategyPrincipals(s.slave.Query, detail.ID) 659 if err != nil { 660 return nil, store.Error(err) 661 } 662 663 detail.Resources = resArr 664 detail.Principals = principals 665 666 ret = append(ret, detail) 667 } 668 669 return ret, nil 670 } 671 672 // GetStrategyResources 获取对应 principal 能操作的所有资源 673 func (s *strategyStore) GetStrategyResources(principalId string, 674 principalRole model.PrincipalType) ([]model.StrategyResource, error) { 675 676 querySql := "SELECT res_id, res_type FROM auth_strategy_resource WHERE strategy_id IN (SELECT DISTINCT " + 677 " ap.strategy_id FROM auth_principal ap join auth_strategy ar ON ap.strategy_id = ar.id WHERE ar.flag = 0 " + 678 " AND ap.principal_id = ? AND ap.principal_role = ? )" 679 680 rows, err := s.master.Query(querySql, principalId, principalRole) 681 if err != nil { 682 switch err { 683 case sql.ErrNoRows: 684 return nil, nil 685 default: 686 log.Error("[Store][Strategy] get principal link resource", zap.String("sql", querySql), 687 zap.String("principal-id", principalId), zap.Any("principal-type", principalRole)) 688 return nil, store.Error(err) 689 } 690 } 691 692 defer rows.Close() 693 694 resArr := make([]model.StrategyResource, 0) 695 696 for rows.Next() { 697 res := new(model.StrategyResource) 698 if err := rows.Scan(&res.ResID, &res.ResType); err != nil { 699 return nil, store.Error(err) 700 } 701 resArr = append(resArr, *res) 702 } 703 704 return resArr, nil 705 } 706 707 func (s *strategyStore) getStrategyPrincipals(queryHander QueryHandler, id string) ([]model.Principal, error) { 708 709 rows, err := queryHander("SELECT principal_id, principal_role FROM auth_principal WHERE strategy_id = ?", id) 710 if err != nil { 711 switch err { 712 case sql.ErrNoRows: 713 log.Info("[Store][Strategy] not found link principals", zap.String("strategy-id", id)) 714 return nil, nil 715 default: 716 return nil, store.Error(err) 717 } 718 } 719 defer rows.Close() 720 721 principals := make([]model.Principal, 0) 722 723 for rows.Next() { 724 res := new(model.Principal) 725 if err := rows.Scan(&res.PrincipalID, &res.PrincipalRole); err != nil { 726 return nil, store.Error(err) 727 } 728 principals = append(principals, *res) 729 } 730 731 return principals, nil 732 } 733 734 func (s *strategyStore) getStrategyResources(queryHander QueryHandler, id string) ([]model.StrategyResource, error) { 735 querySql := "SELECT res_id, res_type FROM auth_strategy_resource WHERE strategy_id = ?" 736 rows, err := queryHander(querySql, id) 737 if err != nil { 738 switch err { 739 case sql.ErrNoRows: 740 log.Info("[Store][Strategy] not found link resources", zap.String("strategy-id", id)) 741 return nil, nil 742 default: 743 return nil, store.Error(err) 744 } 745 } 746 defer rows.Close() 747 748 resArr := make([]model.StrategyResource, 0) 749 750 for rows.Next() { 751 res := new(model.StrategyResource) 752 if err := rows.Scan(&res.ResID, &res.ResType); err != nil { 753 return nil, store.Error(err) 754 } 755 resArr = append(resArr, *res) 756 } 757 758 return resArr, nil 759 } 760 761 func fetchRown2StrategyDetail(rows *sql.Rows) (*model.StrategyDetail, error) { 762 var ( 763 ctime, mtime int64 764 isDefault, flag int16 765 ) 766 ret := &model.StrategyDetail{ 767 Resources: make([]model.StrategyResource, 0), 768 } 769 770 if err := rows.Scan(&ret.ID, &ret.Name, &ret.Action, &ret.Owner, &ret.Comment, &isDefault, &ret.Revision, &flag, 771 &ctime, &mtime); err != nil { 772 return nil, store.Error(err) 773 } 774 775 ret.CreateTime = time.Unix(ctime, 0) 776 ret.ModifyTime = time.Unix(mtime, 0) 777 ret.Valid = flag == 0 778 779 if isDefault == 1 { 780 ret.Default = true 781 } 782 783 return ret, nil 784 } 785 786 // cleanInvalidStrategy 按名称清理鉴权策略 787 func (s *strategyStore) cleanInvalidStrategy(name, owner string) error { 788 log.Info("[Store][Strategy] clean invalid auth_strategy", 789 zap.String("name", name), zap.String("owner", owner)) 790 791 tx, err := s.master.Begin() 792 if err != nil { 793 return err 794 } 795 defer func() { _ = tx.Rollback() }() 796 797 str := "delete from auth_strategy where name = ? and owner = ? and flag = 1" 798 if _, err = tx.Exec(str, name, owner); err != nil { 799 log.Errorf("[Store][Strategy] clean invalid auth_strategy(%s) err: %s", name, err.Error()) 800 return err 801 } 802 if err := tx.Commit(); err != nil { 803 log.Errorf("[Store][Strategy] clean invalid auth_strategy tx commit err: %s", err.Error()) 804 return err 805 } 806 return nil 807 } 808 809 // cleanLinkStrategy 清理与自己相关联的鉴权信息 810 // step 1. 清理用户/用户组默认策略所关联的所有资源信息(直接走delete删除) 811 // step 2. 清理用户/用户组默认策略 812 // step 3. 清理用户/用户组所关联的其他鉴权策略的关联关系(直接走delete删除) 813 func cleanLinkStrategy(tx *BaseTx, role model.PrincipalType, principalId, owner string) error { 814 815 // 清理默认策略对应的所有鉴权关联资源 816 removeResSql := ` 817 DELETE FROM auth_strategy_resource 818 WHERE strategy_id IN ( 819 SELECT DISTINCT ag.id 820 FROM auth_strategy ag 821 WHERE ag.default = 1 822 AND ag.owner = ? 823 AND ag.id IN ( 824 SELECT DISTINCT strategy_id 825 FROM auth_principal 826 WHERE principal_id = ? 827 AND principal_role = ? 828 ) 829 ) 830 ` 831 832 if _, err := tx.Exec(removeResSql, []interface{}{owner, principalId, role}...); err != nil { 833 return err 834 } 835 836 // 清理默认策略 837 cleanaRuleSql := ` 838 UPDATE auth_strategy AS ag 839 SET ag.flag = 1 840 WHERE ag.id IN ( 841 SELECT DISTINCT strategy_id 842 FROM auth_principal 843 WHERE principal_id = ? 844 AND principal_role = ? 845 ) 846 AND ag.default = 1 847 AND ag.owner = ? 848 ` 849 850 if _, err := tx.Exec(cleanaRuleSql, []interface{}{principalId, role, owner}...); err != nil { 851 return err 852 } 853 854 // 调整所关联的鉴权策略的 mtime 数据,保证cache刷新可以获取到变更的数据信息 855 updateStrategySql := "UPDATE auth_strategy SET mtime = sysdate() WHERE id IN (SELECT DISTINCT " + 856 " strategy_id FROM auth_principal WHERE principal_id = ? AND principal_role = ?)" 857 if _, err := tx.Exec(updateStrategySql, []interface{}{principalId, role}...); err != nil { 858 return err 859 } 860 861 // 清理所在的所有鉴权principal 862 cleanPrincipalSql := "DELETE FROM auth_principal WHERE principal_id = ? AND principal_role = ?" 863 if _, err := tx.Exec(cleanPrincipalSql, []interface{}{principalId, role}...); err != nil { 864 return err 865 } 866 867 return nil 868 }