Skip to content

Commit

Permalink
update: add subject template group update expried_at api
Browse files Browse the repository at this point in the history
  • Loading branch information
zhu327 committed Nov 8, 2023
1 parent 7b630b6 commit e2f88fe
Show file tree
Hide file tree
Showing 17 changed files with 438 additions and 121 deletions.
3 changes: 2 additions & 1 deletion build/support-files/sql/0031_iam_20231025-1600_mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ CREATE TABLE `bkiam`.`subject_template_group` (
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pk`),
UNIQUE KEY `idx_uk_subject_template_group` (`subject_pk`,`group_pk`,`template_id`)
UNIQUE KEY `idx_uk_subject_template_group` (`subject_pk`,`group_pk`,`template_id`),
INDEX `idx_group_template_subject` (`group_pk`, `template_id`,`subject_pk`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
90 changes: 89 additions & 1 deletion pkg/abac/pap/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type GroupController interface {
DeleteGroupMembers(_type, id string, members []Subject) (map[string]int64, error)
BulkCreateSubjectTemplateGroup(subjectTemplateGroups []SubjectTemplateGroup) error
BulkDeleteSubjectTemplateGroup(subjectTemplateGroups []SubjectTemplateGroup) error
UpdateSubjectTemplateGroupExpiredAt(subjectTemplateGroups []SubjectTemplateGroup) error

ListRbacGroupByResource(systemID string, resource abacTypes.Resource) ([]Subject, error)
ListRbacGroupByActionResource(systemID, actionID string, resource abacTypes.Resource) ([]Subject, error)
Expand Down Expand Up @@ -606,6 +607,89 @@ func (c *groupController) BulkCreateSubjectTemplateGroup(subjectTemplateGroups [
return nil
}

func (c *groupController) UpdateSubjectTemplateGroupExpiredAt(subjectTemplateGroups []SubjectTemplateGroup) error {
errorWrapf := errorx.NewLayerFunctionErrorWrapf(GroupCTL, "BulkRenewSubjectTemplateGroup")

relations, err := c.convertToSubjectTemplateGroups(subjectTemplateGroups)
if err != nil {
return errorWrapf(err, "convertToSubjectTemplateGroups subjectTemplateGroups=`%+v` fail", subjectTemplateGroups)
}

subjectGroupHelper := newSubjectGroupHelper(c.service)

noAuthorizedRelations := make([]types.SubjectTemplateGroup, 0, len(relations))
for i := range relations {
relation := &relations[i]

authorized, subjectGroup, err := subjectGroupHelper.getSubjectGroup(relation.SubjectPK, relation.GroupPK)
if err != nil {
return errorWrapf(
err,
"getSubjectGroup subjectPK=`%d`, groupPK=`%d` fail",
relation.SubjectPK,
relation.GroupPK,
)
}

// 1. 如果group未授权
if !authorized {
noAuthorizedRelations = append(noAuthorizedRelations, *relation)
continue
}

// 2. 如果已授权并且过期时间大于当前时间, 不需要更新
if subjectGroup != nil && subjectGroup.ExpiredAt > relation.ExpiredAt {
continue
}

// 3. 其余场景需要更新
relation.NeedUpdate = true
}

tx, err := database.GenerateDefaultDBTx()
defer database.RollBackWithLog(tx)
if err != nil {
return errorWrapf(err, "define tx error")
}

if len(noAuthorizedRelations) > 0 {
// 只更新subject template group的过期时间
err = c.service.UpdateSubjectTemplateGroupExpiredAtWithTx(tx, noAuthorizedRelations)
if err != nil {
return errorWrapf(
err, "service.UpdateSubjectTemplateGroupExpiredAtWithTx relations=`%+v` fail", noAuthorizedRelations,
)
}
}

// 更新subject system group
err = c.service.BulkUpdateSubjectSystemGroupBySubjectTemplateGroupWithTx(tx, relations)
if err != nil {
return errorWrapf(
err,
"service.BulkUpdateSubjectSystemGroupBySubjectTemplateGroupWithTx relations=`%+v` fail",
relations,
)
}

// 更新除了subject system group之外的subject group
err = c.updateSubjectGroupExpiredAtWithTx(tx, relations, true)
if err != nil {
return errorWrapf(err, "updateSubjectGroupExpiredAtWithTx relations=`%+v` fail", relations)
}

// 提交事务
err = tx.Commit()
if err != nil {
return errorWrapf(err, "tx commit error")
}

// 清理subject system group 缓存
c.deleteSubjectTemplateGroupCache(relations)

return nil
}

func (*groupController) convertToSubjectTemplateGroups(
subjectTemplateGroups []SubjectTemplateGroup,
) ([]types.SubjectTemplateGroup, error) {
Expand Down Expand Up @@ -649,7 +733,11 @@ func (c *groupController) BulkDeleteSubjectTemplateGroup(subjectTemplateGroups [
for i := range relations {
relation := &relations[i]

expiredAt, err := c.service.GetMaxExpiredAtBySubjectGroup(relation.SubjectPK, relation.GroupPK)
expiredAt, err := c.service.GetMaxExpiredAtBySubjectGroup(
relation.SubjectPK,
relation.GroupPK,
relation.TemplateID,
)
if err != nil && !errors.Is(err, service.ErrGroupMemberNotFound) {
return errorWrapf(
err, "GetMaxExpiredAtBySubjectGroup subjectPK=`%d`, groupPK=`%d` fail",
Expand Down
12 changes: 9 additions & 3 deletions pkg/abac/pap/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,9 @@ var _ = Describe("GroupController", func() {

It("GetMaxExpiredAtBySubjectGroup fail", func() {
mockService := mock.NewMockGroupService(ctl)
mockService.EXPECT().GetMaxExpiredAtBySubjectGroup(int64(1), int64(2)).Return(int64(0), errors.New("err"))
mockService.EXPECT().
GetMaxExpiredAtBySubjectGroup(int64(1), int64(2), int64(1)).
Return(int64(0), errors.New("err"))

manager := &groupController{
service: mockService,
Expand All @@ -1099,7 +1101,9 @@ var _ = Describe("GroupController", func() {

It("BulkDeleteSubjectTemplateGroupWithTx fail", func() {
mockService := mock.NewMockGroupService(ctl)
mockService.EXPECT().GetMaxExpiredAtBySubjectGroup(int64(1), int64(2)).Return(time.Now().Unix()+10, nil)
mockService.EXPECT().
GetMaxExpiredAtBySubjectGroup(int64(1), int64(2), int64(1)).
Return(time.Now().Unix()+10, nil)
mockService.EXPECT().
BulkDeleteSubjectTemplateGroupWithTx(gomock.Any(), gomock.Any()).
Return(errors.New("err"))
Expand Down Expand Up @@ -1132,7 +1136,9 @@ var _ = Describe("GroupController", func() {

It("ok", func() {
mockService := mock.NewMockGroupService(ctl)
mockService.EXPECT().GetMaxExpiredAtBySubjectGroup(int64(1), int64(2)).Return(time.Now().Unix()+10, nil)
mockService.EXPECT().
GetMaxExpiredAtBySubjectGroup(int64(1), int64(2), int64(1)).
Return(time.Now().Unix()+10, nil)
mockService.EXPECT().BulkDeleteSubjectTemplateGroupWithTx(gomock.Any(), gomock.Any()).Return(nil)

db, mock := database.NewMockSqlxDB()
Expand Down
14 changes: 14 additions & 0 deletions pkg/abac/pap/mock/group.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pkg/abac/pap/subject.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ func (c *subjectController) BulkUpdateName(subjects []Subject) error {
func (c *subjectController) BulkDeleteGroup(subjects []Subject) error {
errorWrapf := errorx.NewLayerFunctionErrorWrapf(SubjectCTL, "BulkDeleteGroup")

// NOTE 用户组关联的subject template group由SaaS删除

svcSubjects := convertToServiceSubjects(subjects)

pks, err := c.service.ListPKsBySubjects(svcSubjects)
Expand Down
70 changes: 48 additions & 22 deletions pkg/api/web/handler/subject_template_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,7 @@ func BatchCreateSubjectTemplateGroup(c *gin.Context) {
return
}

// 数据转换, subject -> subjectPK, groupID -> groupPK
papSubjectTemplateGroups := make([]pap.SubjectTemplateGroup, 0, len(body))
for _, m := range body {
papSubjectTemplateGroups = append(papSubjectTemplateGroups, pap.SubjectTemplateGroup{
Type: m.Type,
ID: m.ID,
TemplateID: m.TemplateID,
GroupID: m.GroupID,
ExpiredAt: m.ExpiredAt,
})
}
papSubjectTemplateGroups := convertToPapSubjectTemplateGroup(body)

ctl := pap.NewGroupController()
err := ctl.BulkCreateSubjectTemplateGroup(papSubjectTemplateGroups)
Expand Down Expand Up @@ -74,17 +64,7 @@ func BatchDeleteSubjectTemplateGroup(c *gin.Context) {
return
}

// 数据转换, subject -> subjectPK, groupID -> groupPK
papSubjectTemplateGroups := make([]pap.SubjectTemplateGroup, 0, len(body))
for _, m := range body {
papSubjectTemplateGroups = append(papSubjectTemplateGroups, pap.SubjectTemplateGroup{
Type: m.Type,
ID: m.ID,
TemplateID: m.TemplateID,
GroupID: m.GroupID,
ExpiredAt: m.ExpiredAt,
})
}
papSubjectTemplateGroups := convertToPapSubjectTemplateGroup(body)

ctl := pap.NewGroupController()
err := ctl.BulkDeleteSubjectTemplateGroup(papSubjectTemplateGroups)
Expand All @@ -101,3 +81,49 @@ func BatchDeleteSubjectTemplateGroup(c *gin.Context) {

util.SuccessJSONResponse(c, "ok", nil)
}

// BatchUpdateSubjectTemplateGroupExpiredAt 批量更新subject-template-group过期时间
func BatchUpdateSubjectTemplateGroupExpiredAt(c *gin.Context) {
errorWrapf := errorx.NewLayerFunctionErrorWrapf("Handler", "BatchUpdateSubjectTemplateGroupExpiredAt")

var body []subjectTemplateGroupSerializer
if err := c.ShouldBindJSON(&body); err != nil {
util.BadRequestErrorJSONResponse(c, util.ValidationErrorMessage(err))
return
}
if ok, message := common.ValidateArray(body); !ok {
util.BadRequestErrorJSONResponse(c, message)
return
}

papSubjectTemplateGroups := convertToPapSubjectTemplateGroup(body)

ctl := pap.NewGroupController()
err := ctl.UpdateSubjectTemplateGroupExpiredAt(papSubjectTemplateGroups)
if err != nil {
err = errorWrapf(
err,
"ctl.UpdateSubjectTemplateGroupExpiredAt",
"subjectTemplateGroups=`%+v`",
papSubjectTemplateGroups,
)
util.SystemErrorJSONResponse(c, err)
return
}

util.SuccessJSONResponse(c, "ok", nil)
}

func convertToPapSubjectTemplateGroup(body []subjectTemplateGroupSerializer) []pap.SubjectTemplateGroup {
papSubjectTemplateGroups := make([]pap.SubjectTemplateGroup, 0, len(body))
for _, m := range body {
papSubjectTemplateGroups = append(papSubjectTemplateGroups, pap.SubjectTemplateGroup{
Type: m.Type,
ID: m.ID,
TemplateID: m.TemplateID,
GroupID: m.GroupID,
ExpiredAt: m.ExpiredAt,
})
}
return papSubjectTemplateGroups
}
4 changes: 3 additions & 1 deletion pkg/api/web/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ func Register(r *gin.RouterGroup) {
// 创建subject-template-group
r.POST("/subject-template-groups", handler.BatchCreateSubjectTemplateGroup)
// 删除subject-template-group
r.DELETE("/subject-template-groups", handler.BatchDeleteSubjectTemplateGroup)
r.DELETE("/subject-template-groups", handler.BatchDeleteSubjectTemplateGroup) // NEED FIX
// 批量subject-template-group成员过期时间
r.PUT("/subject-template-groups/expired_at", handler.BatchUpdateSubjectTemplateGroupExpiredAt)
}

// Resource: subject-departments
Expand Down
39 changes: 34 additions & 5 deletions pkg/database/dao/mock/subject_template_group.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e2f88fe

Please sign in to comment.