roles

package
v0.0.8-beta Latest Latest
Warning

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

Go to latest
Published: Jun 6, 2022 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package roles manages user's permissions depending on its roles. Roles are organized hierarchically and are implicitely or explicitely inherited.

From implicit inheritance a user receives the union of all capabilities of transitively inherited roles. This inheritance is transparent to both the user's current active role and code that does checks upon a possibly inherited role to allow/prohibid an action that requires authorization.

From explicit inheritance a user does not transparently inherit any capabilities. The are only signalers to which role a user might switch to receive those (and implicitely) inherited capabilities.

Some syntactic sugar for gin.Context is provided to allow simple authorization checks like

roles.CanActIn(ctx, roles.RoleTeacher)

roles.CanActFor(ctx, instanceID)

and permanent switching to another role

roles.SwitchTo(ctx, roles.RoleInstanceAdmin)
Example (SuccessfulCheck)

Demonstrates the parsing of the current instance and user's role and a successful authorization check.

package main

import (
	"fmt"
	"net/http/httptest"

	"github.com/gin-gonic/gin"
	"github.com/smartnuance/saas-kit/pkg/lib/roles"
)

func main() {
	// Create dummy context
	r := httptest.NewRecorder()
	ctx, _ := gin.CreateTestContext(r)
	ctx.Set("user", "user-guid")
	ctx.Set("role", "teacher")
	ctx.Set("instance", "instance-guid")

	// Check permission to revoke token for potentially different user
	if !(roles.CanActFor(ctx, "instance-guid") && roles.CanActIn(ctx, roles.RoleTeacher)) {
		fmt.Println("unauthorized")
		return
	}

	// Do something a teacher can do
	fmt.Println("authorized")

}
Output:

authorized
Example (SwitchRole)

Demonstrates the parsing of the current instance and user's role and a successful authorization check.

package main

import (
	"fmt"
	"net/http/httptest"

	"github.com/gin-gonic/gin"
	"github.com/smartnuance/saas-kit/pkg/lib/roles"
)

func main() {
	// Create dummy context
	r := httptest.NewRecorder()
	ctx, _ := gin.CreateTestContext(r)
	ctx.Set("user", "user-guid")
	ctx.Set("role", "super admin")
	ctx.Set("instance", "instance-guid")

	// Check permission to revoke token for potentially different user
	if !roles.CanActFor(ctx, "instance-guid") {
		fmt.Println("instance unauthorized")
		return
	}

	if !roles.CanActIn(ctx, roles.RoleTeacher) {
		fmt.Println("unauthorized to act as teacher")
	}

	err := roles.SwitchTo(ctx, roles.RoleInstanceAdmin)
	if err != nil {
		fmt.Print(err)
		return
	}

	fmt.Println("switched to instance admin")

	if !roles.CanActIn(ctx, roles.RoleTeacher) {
		fmt.Println("still unauthorized to act as teacher")
		return
	}

	// Do something a teacher can do
	fmt.Println("authorized")

}
Output:

unauthorized to act as teacher
switched to instance admin
authorized

Index

Examples

Constants

View Source
const (
	RoleHeader     = "role"
	InstanceHeader = "instance"

	UserKey     = "user"
	RoleKey     = "role"
	InstanceKey = "instance"
)

Variables

View Source
var (
	ErrMissingUser      = errors.New("missing user")
	ErrInvalidRole      = errors.New("invalid role provided")
	ErrMissingInstance  = errors.New("missing instance")
	ErrSwitchNotAllowed = errors.New("role switch not allowed")
	ErrUnauthorized     = errors.New("role insufficient to act on desired instance")
)

Functions

func CanActAs

func CanActAs(ctx *gin.Context, targetUserID string) bool

CanActAs checks if the user can act as a desired user.

func CanActFor

func CanActFor(ctx *gin.Context, instanceID string) bool

CanActFor checks if the user can act for the desired instance.

func CanActIn

func CanActIn(ctx *gin.Context, targetRole Role) bool

CanActIn checks if the user can act in the desired targetRole without switching to that role.

func CanSwitchTo

func CanSwitchTo(userRole Role, targetRole Role) bool

CanSwitchTo checks if the user's role can switch to a targetRole acquiring those role's permissions. Switching is allowed when there is an implicit path from userRole to role or userrole directly, explicitly inherits targetRole.

func Instance

func Instance(ctx *gin.Context) (string, error)

Instance retrieves the instance to act for from context. There is no default instance. An invalid instance results in ErrMissingInstance.

func RolesSpec

func RolesSpec(userRole Role) (spec rolesSpec)

RolesSpec returns a RolesSpec for the given user role.

func SwitchTo

func SwitchTo(ctx *gin.Context, targetRole Role) error

SwitchTo attempts to switch to a temporary targetRole. The user's role defined in context is checked against the rules defining if switching is allowed. The temporary role is set on the context under the "role" key, overwriting the original role.

func User

func User(ctx *gin.Context) (string, error)

User retrieves the user from context. There is no default user. When no user is registerd in context, this results in ErrMissingUser.

Types

type Role

type Role string
const (
	RoleSuperAdmin     Role = "super admin"
	RoleInstanceAdmin  Role = "instance admin"
	RoleEventOrganizer Role = "event organizer"
	RoleTeacher        Role = "teacher"
	NoRole             Role = ""
)

func FromContext

func FromContext(ctx *gin.Context) (Role, error)

FromContext retrieves the role from context. The default role is NoRole. An invalid role results in ErrInvalidRole.

func InheritedRoles

func InheritedRoles(userRole Role) []Role

InheritedRoles returns an unordered list of roles a given user role can act in, without switching. The returned list is a copy and can be safely modified.

Jump to

Keyboard shortcuts

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