Alerting: fix conflicting folder and dashboard permissions during migration (#35967)

* Alerting: Fix conflicting user and team permissions

* Avoid duplicate perrmissions

* Fix lint

Signed-off-by: Ganesh Vernekar <ganeshvern@gmail.com>

Co-authored-by: Ganesh Vernekar <ganeshvern@gmail.com>
This commit is contained in:
Sofia Papagiannaki 2021-06-22 09:37:52 +03:00 committed by GitHub
parent cd1c7530a8
commit 91cf062d0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -133,11 +133,80 @@ func (m *migration) setACL(orgID int64, dashboardID int64, items []*dashboardAcl
if dashboardID <= 0 {
return fmt.Errorf("folder id must be greater than zero for a folder permission")
}
// userPermissionsMap is a map keeping the highest permission per user
// for handling conficting inherited (folder) and non-inherited (dashboard) user permissions
userPermissionsMap := make(map[int64]*dashboardAcl, len(items))
// teamPermissionsMap is a map keeping the highest permission per team
// for handling conficting inherited (folder) and non-inherited (dashboard) team permissions
teamPermissionsMap := make(map[int64]*dashboardAcl, len(items))
for _, item := range items {
if item.UserID != 0 {
acl, ok := userPermissionsMap[item.UserID]
if !ok {
userPermissionsMap[item.UserID] = item
} else {
if item.Permission > acl.Permission {
// the higher permission wins
userPermissionsMap[item.UserID] = item
}
}
}
if item.TeamID != 0 {
acl, ok := teamPermissionsMap[item.TeamID]
if !ok {
teamPermissionsMap[item.TeamID] = item
} else {
if item.Permission > acl.Permission {
// the higher permission wins
teamPermissionsMap[item.TeamID] = item
}
}
}
}
type keyType struct {
UserID int64 `xorm:"user_id"`
TeamID int64 `xorm:"team_id"`
Role roleType
Permission permissionType
}
// seen keeps track of inserted perrmissions to avoid duplicates (due to inheritance)
seen := make(map[keyType]struct{}, len(items))
for _, item := range items {
if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) {
return models.ErrDashboardAclInfoMissing
}
// ignore duplicate user permissions
if item.UserID != 0 {
acl, ok := userPermissionsMap[item.UserID]
if ok {
if acl.Id != item.Id {
continue
}
}
}
// ignore duplicate team permissions
if item.TeamID != 0 {
acl, ok := teamPermissionsMap[item.TeamID]
if ok {
if acl.Id != item.Id {
continue
}
}
}
key := keyType{UserID: item.UserID, TeamID: item.TeamID, Role: "", Permission: item.Permission}
if item.Role != nil {
key.Role = *item.Role
}
if _, ok := seen[key]; ok {
continue
}
// unset Id so that the new record will get a different one
item.Id = 0
item.OrgID = orgID
@ -149,6 +218,7 @@ func (m *migration) setACL(orgID int64, dashboardID int64, items []*dashboardAcl
if _, err := m.sess.Insert(item); err != nil {
return err
}
seen[key] = struct{}{}
}
// Update dashboard HasAcl flag