Documentation
¶
Overview ¶
Package permz provides a framework for scoped permission handling.
The motivation is that permissions can be global (IsAdmin, CanRead, CanValidate) or scoped (a specific user/group has permissions on specific items). Thus, we redifine the notion of permission as: "a Right on a specific scope".
The package defines two primitives: PermissionResolver, that returns true if the permission is granted, and ResolverFactory that fetches a permission resolver with a scope.
The package provides a threadsafe pool of ResolverFactory with internal cache.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type PermissionResolver ¶
PermissionResolver describes a function that returns wheter the Right is granted or not.
Example ¶
// Given a very simple InArray function
InArray := func(haystack []int, needle int) bool {
for _, v := range haystack {
if v == needle {
return true
}
}
return false
}
// And a set of rights
var permissions = []int{1, 2, 3}
// This resolver returns true if the right is granted.
var Resolve PermissionResolver
Resolve = func(right Right) bool {
if v, ok := right.(int); ok {
return InArray(permissions, v)
}
return false
}
fmt.Println(Resolve(1))
fmt.Println(Resolve(7))
Output: true false
func And ¶
func And(fns ...PermissionResolver) PermissionResolver
And is a resolver that returns true when all resolvers return true. nil fns are ignored.
func Or ¶
func Or(fns ...PermissionResolver) PermissionResolver
Or is a resolver that returns true when at least one resolver returns true. nil fns are ignored.
type Pool ¶
type Pool struct {
// contains filtered or unexported fields
}
Pool caches PermissionResolvers that are generated with the same factory. It is threadsafe. The cache key is the scope used to create the factory.
func NewPool ¶
func NewPool(fn ResolverFactory) *Pool
NewPool creates a pool with a factory. See Pool documentation.
func (*Pool) GetResolver ¶
GetResolver retreives a resolver from the pool or fetches it. The scope must be comparable
type ResolverFactory ¶
type ResolverFactory = func(ctx context.Context, scope Scope) (PermissionResolver, error)
ResolverFactory is a function that takes the parameters of a scope and returns a permission resolver. usualy, the resolver is a set of right stored in database. The factory is the function that retreives it.
Example ¶
var GetUserProjectPermissions func(context.Context, int, int) ([]int, error)
var NewResolverFromPermissions func([]int) PermissionResolver
type Pair struct {
UserID, ProjectID int
}
var factory ResolverFactory
factory = func(ctx context.Context, scope Scope) (PermissionResolver, error) {
// fetch the set of permissions of this user on this project
p, ok := scope.(Pair)
if !ok {
return nil, errors.New("invalid scope type")
}
perms, err := GetUserProjectPermissions(ctx, p.UserID, p.ProjectID)
if err != nil {
return nil, err
}
// the resolver is now scoped for the userID and projectID
resolver := NewResolverFromPermissions(perms)
return resolver, nil
}
resolver, err := factory(context.TODO(), Pair{4, 1})
if err != nil {
// ...
}
_ = resolver // this is the permission resolver for the user 4 on the project 1
type Scope ¶
type Scope = interface{}
Scope is an interface of any type that is aliases for documentation purpose. The scope must be comparable according to the language specification: https://golang.org/ref/spec#Comparison_operators