permz

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2019 License: MIT Imports: 2 Imported by: 0

README

Permz

Godoc license

permz is a Golang permission framework.

Motivation

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.

See package documentation for details.

Usage

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

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

func False

func False(Right) bool

False is a resolver that always returns false.

func True

func True(Right) bool

True is a resolver that always returns true.

Types

type PermissionResolver

type PermissionResolver = func(Right) bool

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

And is a resolver that returns true when all resolvers return true. nil fns are ignored.

func Or

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

func (p *Pool) GetResolver(ctx context.Context, scope Scope) (PermissionResolver, error)

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 Right = interface{}

Right aliases an interface{} for documentation purpose.

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL