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:
163
server/pkg/rbac/resource.go
Normal file
163
server/pkg/rbac/resource.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package rbac
|
||||
|
||||
import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
type (
|
||||
resource string
|
||||
Resource interface {
|
||||
RbacResource() string
|
||||
}
|
||||
|
||||
resourceDicter interface {
|
||||
Dict() map[string]interface{}
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
nsSep = "::"
|
||||
cmpSep = ":"
|
||||
pathSep = "/"
|
||||
wildcard = "*"
|
||||
)
|
||||
|
||||
// NewResource constructs untyped resource from the given string
|
||||
//
|
||||
// This is a utility method that should not be used for standard permission checking and granting
|
||||
// it's intended to be used for testing end permission evaluation where we do not have access to the resource struct
|
||||
func NewResource(s string) Resource {
|
||||
return resource(s)
|
||||
}
|
||||
|
||||
// RbacResource returns string of an untyped resource
|
||||
func (t resource) RbacResource() string {
|
||||
return string(t)
|
||||
}
|
||||
|
||||
// HasWildcards returns true if the given resource has wildcards
|
||||
func (t resource) HasWildcards() bool {
|
||||
return hasWildcards(string(t))
|
||||
}
|
||||
|
||||
// ResourceType extracts 1st part of the resource
|
||||
//
|
||||
// ns::cmp:res/c returns ns::cmp:res
|
||||
// ns::cmp:res/ returns ns::cmp:res
|
||||
// ns::cmp:res returns ns::cmp:res
|
||||
func ResourceType(r string) string {
|
||||
if p := strings.Index(r, pathSep); p > 0 {
|
||||
return r[:p]
|
||||
} else {
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
func ResourceComponent(r string) string {
|
||||
var (
|
||||
t = ResourceType(r)
|
||||
ns = strings.Index(t, nsSep)
|
||||
c = strings.LastIndex(t, cmpSep)
|
||||
)
|
||||
|
||||
// make sure that we have both namespace + component separators
|
||||
if c > ns+1 && ns > -1 {
|
||||
return t[:c]
|
||||
} else {
|
||||
return t
|
||||
}
|
||||
}
|
||||
|
||||
func ParseResourceID(r string) (string, []uint64) {
|
||||
const sep = "/"
|
||||
var (
|
||||
pp = strings.Split(r, sep)
|
||||
ids = make([]uint64, 0)
|
||||
)
|
||||
|
||||
for i := 1; i < len(pp); i++ {
|
||||
ids = append(ids, cast.ToUint64(pp[i]))
|
||||
}
|
||||
return pp[0], ids
|
||||
}
|
||||
|
||||
// match returns true if the given resource matches the given pattern
|
||||
func matchResource(matcher, resource string) (m bool) {
|
||||
if matcher == resource {
|
||||
return true
|
||||
}
|
||||
|
||||
m, _ = path.Match(matcher, resource)
|
||||
return
|
||||
}
|
||||
|
||||
func hasWildcards(resource string) bool {
|
||||
return strings.Contains(resource, wildcard)
|
||||
}
|
||||
|
||||
// returns level for the given resource match
|
||||
// In a nutshell, level indicates number of wildcard characters
|
||||
//
|
||||
// More defined resources use less wildcards and are on a lower level
|
||||
func level(r string) (score int) {
|
||||
var nl bool
|
||||
for l := len(r) - 1; l > strings.Index(r, pathSep); l-- {
|
||||
switch r[l] {
|
||||
case wildcard[0]:
|
||||
// nop
|
||||
case pathSep[0]:
|
||||
// found next resource reference level
|
||||
score *= 10
|
||||
nl = false
|
||||
default:
|
||||
if !nl {
|
||||
score += 1
|
||||
nl = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// isSpecific will return true if rule relates to a specific resource
|
||||
//
|
||||
// ns::cmp:res/xx/* returns true
|
||||
// ns::cmp:res/xx/xx returns true
|
||||
// ns::cmp:res/ returns false
|
||||
// ns::cmp:res/*/* returns false
|
||||
func isSpecific(r string) (out bool) {
|
||||
out = false
|
||||
parts := strings.Split(r, pathSep)
|
||||
// remove resource name part
|
||||
parts = parts[1:]
|
||||
|
||||
// check parts for wildcard if it's not empty otherwise return false
|
||||
for _, p := range parts {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if p != wildcard && !out {
|
||||
out = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func ResourceID(res string) uint64 {
|
||||
pp := strings.Split(res, pathSep)
|
||||
if len(pp) < 2 {
|
||||
return 0
|
||||
}
|
||||
|
||||
if pp[len(pp)-1] == wildcard {
|
||||
return 0
|
||||
}
|
||||
|
||||
return cast.ToUint64(pp[len(pp)-1])
|
||||
}
|
||||
Reference in New Issue
Block a user