package role type GrantChange struct { Key string `json:"key"` From Scope `json:"from"` To Scope `json:"to"` } type GrantDiff struct { Added []Grant `json:"added"` Removed []Grant `json:"removed"` Changed []GrantChange `json:"changed"` } func (d GrantDiff) Empty() bool { return len(d.Added) == 0 && len(d.Removed) == 0 && len(d.Changed) == 0 } func DiffGrants(before []Grant, after []Grant) GrantDiff { diff := GrantDiff{Added: []Grant{}, Removed: []Grant{}, Changed: []GrantChange{}} previous := scopesByKey(before) current := scopesByKey(after) for _, grant := range after { held, present := previous[grant.Key] if !present { diff.Added = append(diff.Added, grant) } else if held != grant.Scope { diff.Changed = append(diff.Changed, GrantChange{Key: grant.Key, From: held, To: grant.Scope}) } } for _, grant := range before { if _, present := current[grant.Key]; !present { diff.Removed = append(diff.Removed, grant) } } return diff } func scopesByKey(grants []Grant) map[string]Scope { scopes := make(map[string]Scope, len(grants)) for _, grant := range grants { scopes[grant.Key] = grant.Scope } return scopes }