authz

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 25, 2026 License: MIT Imports: 7 Imported by: 0

README

togo

togo-framework/authz

marketplace pkg.go.dev MIT

Authorization for togo — policies, gates & abilities, the layer above RBAC.

Install

togo install togo-framework/authz

authz is the togo answer to Laravel Policies / Pundit / django-guardian. RBAC tells you a user's roles; authz decides the specific question "may this subject perform this action on this resource?" — ownership, tenancy, state, and any custom rule.

  • Policies — per-resource-type, per-action rules (update a Post only if you authored it).
  • Gates — standalone abilities with no specific resource (access-admin).
  • Before hooks — short-circuit every check (super-admin bypass, maintenance lock).
  • Default deny — unknown action/resource is denied; nothing is allowed by omission.

Usage

// Policies — keyed by authz.TypeName(resource), e.g. "*models.Post".
authz.Policy("*models.Post", map[string]authz.PolicyFunc{
    "update": func(ctx context.Context, subject, resource any) (bool, error) {
        return resource.(*models.Post).AuthorID == subject.(*models.User).ID, nil
    },
    "delete": func(ctx context.Context, subject, resource any) (bool, error) {
        return subject.(*models.User).Admin, nil
    },
})

// Gates — standalone abilities.
authz.RegisterGate("access-admin", func(ctx context.Context, s any) (bool, error) {
    return s.(*models.User).Admin, nil
})

// Before — super-admin bypass.
authz.Before(func(ctx context.Context, s any, action string) (decided, allow bool) {
    if u, ok := s.(*models.User); ok && u.SuperAdmin {
        return true, true
    }
    return false, false
})

Checking access

ok, err := authz.Can(ctx, user, "update", post)       // policy (resource non-nil)
ok2     := authz.Allows(ctx, user, "access-admin", nil) // gate (resource nil); error → deny
if err := authz.Authorize(ctx, user, "update", post); err != nil {
    return err // authz.ErrForbidden when denied
}

Guarding routes

ctx := authz.WithSubject(r.Context(), currentUser) // usually set by your auth middleware
r.With(authz.Require("access-admin")).Get("/admin", adminHandler) // 403 if denied

REST + kernel

Endpoint
GET /api/authz/can?action=<gate> gate check for the context subject
GET /api/authz/abilities registered gates + policy types/actions

s, _ := authz.FromKernel(k) returns the service (Can / Allows / Authorize).

Configuration

No env required. Composes with togo install togo-framework/auth (read roles off the subject in your policies) but works standalone with any subject type.


Premium sponsors

ID8 Media  ·  One Studio

Support togo — become a sponsor.

Documentation

Overview

Package authz adds policy- and gate-based authorization to togo — the layer above RBAC (Laravel Policies / Pundit / django-guardian for togo).

A POLICY answers "may this subject perform ACTION on this RESOURCE?" and is registered per resource type. A GATE answers a standalone ability with no specific resource ("may this subject access-admin?"). BEFORE hooks run first and can short-circuit every check (e.g. a super-admin bypass).

authz.Policy("models.Post", map[string]authz.PolicyFunc{
    "update": func(ctx context.Context, subject, resource any) (bool, error) {
        return resource.(*Post).AuthorID == subject.(*User).ID, nil
    },
})
ok, _ := authz.Can(ctx, user, "update", post)

Index

Constants

This section is empty.

Variables

View Source
var ErrForbidden = fmt.Errorf("authz: forbidden")

ErrForbidden is returned by Authorize when access is denied.

Functions

func Allows

func Allows(ctx context.Context, subject any, action string, resource any) bool

Allows is Can with errors treated as deny — convenient in conditionals.

func Authorize

func Authorize(ctx context.Context, subject any, action string, resource any) error

Authorize returns ErrForbidden when the subject may not perform the action.

func Before

func Before(fn BeforeFunc)

Before registers a pre-check hook (evaluated in registration order).

func Can

func Can(ctx context.Context, subject any, action string, resource any) (bool, error)

Can reports whether subject may perform action. When resource is non-nil the decision uses the per-resource Policy registered for TypeName(resource); otherwise it uses the Gate named action. Unknown action/resource → deny. Before hooks are consulted first and can short-circuit.

func Denies

func Denies(ctx context.Context, subject any, action string, resource any) bool

Denies is the negation of Allows.

func Policy

func Policy(resourceType string, actions map[string]PolicyFunc)

Policy registers per-action policies for a resource type. The key should match TypeName(resource) for the resources you'll check (e.g. "*models.Post").

func RegisterGate

func RegisterGate(name string, fn GateFunc)

RegisterGate registers a standalone ability handler.

func Registry

func Registry() map[string]any

Registry returns a snapshot of registered gates and policy types/actions.

func Require

func Require(action string) func(http.Handler) http.Handler

Require is HTTP middleware that allows the request only if the context subject passes the gate ability; otherwise it responds 403.

func Reset

func Reset()

Reset clears all registered policies, gates and hooks (test helper).

func SubjectFrom

func SubjectFrom(ctx context.Context) any

SubjectFrom returns the subject stored by WithSubject (nil if none).

func TypeName

func TypeName(resource any) string

TypeName is the policy key derived from a resource value (e.g. "*models.Post"). Register policies under the same string TypeName(resource) produces.

func WithSubject

func WithSubject(ctx context.Context, subject any) context.Context

WithSubject stores the current subject (user) in the context. An auth middleware typically sets this; authz middleware reads it.

Types

type BeforeFunc

type BeforeFunc func(ctx context.Context, subject any, action string) (decided, allow bool)

BeforeFunc runs before any check. If it returns decided=true its allow value short-circuits the whole check (use it for super-admin bypass, global locks…).

type GateFunc

type GateFunc func(ctx context.Context, subject any) (bool, error)

GateFunc decides a standalone ability (no specific resource).

type PolicyFunc

type PolicyFunc func(ctx context.Context, subject, resource any) (bool, error)

PolicyFunc decides whether subject may perform action on a specific resource.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is the authz runtime stored on the kernel (k.Get("authz")). The policy/gate registries are package-global; the service exposes them over the kernel + REST and carries the kernel for integrations.

func FromKernel

func FromKernel(k *togo.Kernel) (*Service, bool)

FromKernel returns the authz Service registered on the kernel.

func (*Service) Allows

func (s *Service) Allows(ctx context.Context, subject any, action string, resource any) bool

func (*Service) Authorize

func (s *Service) Authorize(ctx context.Context, subject any, action string, resource any) error

func (*Service) Can

func (s *Service) Can(ctx context.Context, subject any, action string, resource any) (bool, error)

Can / Allows / Authorize on the service delegate to the package functions.

Jump to

Keyboard shortcuts

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