snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
184
server/pkg/rbac/ruleset_utils.go
Normal file
184
server/pkg/rbac/ruleset_utils.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package rbac
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza/server/pkg/auth"
|
||||
"github.com/cortezaproject/corteza/server/pkg/slice"
|
||||
)
|
||||
|
||||
func merge(base RuleSet, new ...*Rule) (out RuleSet) {
|
||||
var (
|
||||
o int
|
||||
blen = len(base)
|
||||
)
|
||||
|
||||
if blen == 0 {
|
||||
// Nothing exists yet, mark all as dirty
|
||||
for r := range new {
|
||||
new[r].dirty = true
|
||||
}
|
||||
|
||||
return new
|
||||
} else {
|
||||
out = base
|
||||
|
||||
newRules:
|
||||
for _, rule := range new {
|
||||
// Never go beyond the last base rule (blen)
|
||||
for o = 0; o < blen; o++ {
|
||||
if eq(out[o], rule) {
|
||||
out[o].dirty = out[o].Access != rule.Access
|
||||
out[o].Access = rule.Access
|
||||
|
||||
// only one rule can match so proceed with next new rule
|
||||
continue newRules
|
||||
}
|
||||
}
|
||||
|
||||
// none of the base new matched, append
|
||||
var c = *rule
|
||||
c.dirty = true
|
||||
|
||||
out = append(out, &c)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func eq(a, b *Rule) bool {
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return a.RoleID == b.RoleID &&
|
||||
a.Resource == b.Resource &&
|
||||
a.Operation == b.Operation
|
||||
}
|
||||
|
||||
func ruleByRole(base RuleSet, roleID uint64) (out RuleSet) {
|
||||
for _, r := range base {
|
||||
if r.RoleID == roleID {
|
||||
out = append(out, r)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Dirty returns list of deleted (Access==Inherit) and changed (dirty) rules
|
||||
func flushable(set RuleSet) (deletable, updatable, final RuleSet) {
|
||||
deletable, updatable, final = RuleSet{}, RuleSet{}, RuleSet{}
|
||||
|
||||
for _, r := range set {
|
||||
var c = *r
|
||||
if r.Access == Inherit {
|
||||
deletable = append(deletable, &c)
|
||||
continue
|
||||
}
|
||||
|
||||
if r.dirty {
|
||||
updatable = append(updatable, &c)
|
||||
}
|
||||
|
||||
final = append(final, &c)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Significant roles (sigRoles) returns two list of significant roles.
|
||||
//
|
||||
// First slice are roles that are allowed to perform an operation on a specific resource (directly or indirectly),
|
||||
// 2nd slice are roles that are denied the op.
|
||||
func (set RuleSet) sigRoles(res string, op string) (aRR, dRR []uint64) {
|
||||
if hasWildcards(res) {
|
||||
// nothing to do here, we need a direct resource id (level=0)
|
||||
return
|
||||
}
|
||||
|
||||
const (
|
||||
dirRes = 0
|
||||
indRes = 1
|
||||
)
|
||||
|
||||
var (
|
||||
rr = map[Access]map[int][]uint64{
|
||||
Allow: {
|
||||
dirRes: make([]uint64, 0),
|
||||
indRes: make([]uint64, 0),
|
||||
},
|
||||
Deny: {
|
||||
dirRes: make([]uint64, 0),
|
||||
indRes: make([]uint64, 0),
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Extract all relevant rules (by op and resource) and group them by
|
||||
// access and distance (rules for direct resources and rules for indirect resources)
|
||||
for _, r := range set {
|
||||
if r.Operation != op {
|
||||
continue
|
||||
}
|
||||
|
||||
if r.Resource == res {
|
||||
// direct rules
|
||||
rr[r.Access][dirRes] = append(rr[r.Access][dirRes], r.RoleID)
|
||||
}
|
||||
|
||||
if matchResource(r.Resource, res) {
|
||||
// rules on all resources of this type
|
||||
rr[r.Access][indRes] = append(rr[r.Access][indRes], r.RoleID)
|
||||
}
|
||||
}
|
||||
|
||||
// Process all extracted roles and make sure that are filtered and ordered by relevance:
|
||||
// 1. list of roles with denied operation directly on the resource
|
||||
dRoles := slice.ToUint64BoolMap(rr[Deny][dirRes])
|
||||
|
||||
// 2. list of roles with allowed operation directly on the resource
|
||||
aRoles := make(map[uint64]bool)
|
||||
for _, r := range rr[Allow][dirRes] {
|
||||
aRoles[r] = !dRoles[r]
|
||||
}
|
||||
|
||||
// 3. list of roles with denied operation indirectly on the resource
|
||||
for _, r := range rr[Deny][indRes] {
|
||||
dRoles[r] = true
|
||||
}
|
||||
|
||||
// 4. list of roles with allowed operation indirectly on the resource
|
||||
for _, r := range rr[Allow][indRes] {
|
||||
aRoles[r] = !dRoles[r]
|
||||
}
|
||||
|
||||
for r, chk := range aRoles {
|
||||
if chk {
|
||||
aRR = append(aRR, r)
|
||||
}
|
||||
}
|
||||
|
||||
for r, chk := range dRoles {
|
||||
if chk {
|
||||
dRR = append(dRR, r)
|
||||
}
|
||||
}
|
||||
|
||||
// add bypass roles
|
||||
for _, r := range auth.BypassRoles() {
|
||||
if r == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
aRR = append(aRR, r.ID)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func clear(set []*Rule) {
|
||||
for _, r := range set {
|
||||
r.dirty = false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user