rbac

package module
v0.0.0-...-bbe5d74 Latest Latest
Warning

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

Go to latest
Published: Aug 1, 2025 License: GPL-3.0 Imports: 7 Imported by: 0

README

RBAC Framework for Go The RBAC Framework is a high-performance, Redis-cached Role-Based Access Control (RBAC) system for Go applications. Built with GORM and Fiber, it provides robust permission management with roles, permissions, and audit logging, optimized for minimal database calls and efficient caching. 📋 Table of Contents

Features Installation Quick Start API Overview Cache Management Audit Logging Contributing License

✨ Features

Role-based permission management Redis caching with automatic invalidation Audit logging for all operations Bulk permission validation Fiber middleware for route protection GORM integration (PostgreSQL, MySQL, SQLite) Comprehensive APIs for permission and role management

📦 Installation Prerequisites

Go 1.19+ Redis Server GORM-compatible database (PostgreSQL, MySQL, SQLite) Fiber v2

Install the Module go get github.com/your-org/rbac

Database Schema Ensure your database has the following schema (auto-migration is supported): CREATE TABLE permissions ( permission_id SERIAL PRIMARY KEY, name VARCHAR(255) UNIQUE NOT NULL, description TEXT );

CREATE TABLE roles ( role_id SERIAL PRIMARY KEY, name VARCHAR(255) UNIQUE NOT NULL, description TEXT );

CREATE TABLE role_permissions ( role_id INTEGER REFERENCES roles(role_id), permission_id INTEGER REFERENCES permissions(permission_id), PRIMARY KEY (role_id, permission_id) );

CREATE TABLE employee_roles ( employee_id INTEGER NOT NULL, role_id INTEGER REFERENCES roles(role_id), PRIMARY KEY (employee_id, role_id) );

CREATE TABLE audits ( employee_id INTEGER, action VARCHAR(255), resource TEXT, success BOOLEAN, timestamp TIMESTAMP );

🚀 Quick Start

Set Up DependenciesInitialize your Go project and install dependencies: go mod init my-project go get github.com/your-org/rbac github.com/redis/go-redis/v9 gorm.io/gorm gorm.io/driver/postgres github.com/gofiber/fiber/v2

Initialize the RBAC ServiceCreate a main.go file with the following: package main

import ( "context" "log" "time"

"github.com/gofiber/fiber/v2"
"github.com/redis/go-redis/v9"
"github.com/your-org/rbac"
"gorm.io/driver/postgres"
"gorm.io/gorm"

)

func main() { // Initialize database dsn := "host=localhost user=rbac_user password=rbac_password dbname=rbac_db port=5432 sslmode=disable" db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) if err != nil { log.Fatalf("Failed to connect to database: %v", err) }

// Initialize Redis
redisDB := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
if _, err := redisDB.Ping(context.Background()).Result(); err != nil {
    log.Fatalf("Failed to connect to Redis: %v", err)
}

// Configure RBAC
rbacConfig := rbac.Config{
    DB:                      db,
    RedisClient:             redisDB,
    CacheTTL:                30 * time.Minute,
    CachePrefix:             "rbac:",
    AutoMigrate:             true,
    AutoMigrateCompositeKeys: true,
    EnableAuditLogging:      true,
}

// Initialize RBAC service
rbacService, err := rbac.NewRBACService(rbacConfig)
if err != nil {
    log.Fatalf("Failed to initialize RBAC service: %v", err)
}

// Set up Fiber app
app := fiber.New()

// Mock auth middleware (set employee_id)
app.Use(func(c *fiber.Ctx) error {
    c.Locals("employee_id", 123)
    return c.Next()
})

// Example protected route
app.Get("/users", rbacService.RbacMiddleware("users.read"), func(c *fiber.Ctx) error {
    return c.SendString("User data")
})

// Start server
log.Fatal(app.Listen(":8080"))

}

Run the Application go run .

Test the RBAC Service

Add permissions: rbacService.AddNewPermission(ctx, "users.read", "Read user data", 1) Add roles: rbacService.AddNewRole(ctx, "Admin", "Administrator role", []string{"users.read"}, 1) Assign roles: rbacService.AssignRolesToEmployeeByNames(ctx, 123, []string{"Admin"}, 1) Validate permissions: rbacService.ValidatePermission(ctx, 123, "users.read")

📚 API Overview Permission Management

AddNewPermission(ctx, name, description string, employeeID int) (int, error) DeletePermission(ctx, permissionName string, employeeID int) error ListAllPermissions(ctx context.Context, employeeID int) ([]Permission, error) GetAllPermissionsByRoleName(ctx, roleName string, employeeID int) ([]string, error)

Role Management

AddNewRole(ctx, name, description string, permissionNames []string, employeeID int) (int, error) ModifyRolePermissions(ctx, roleID int, permissionNames []string, employeeID int) error DeleteRole(ctx, roleName string, employeeID int) error ListAllRoles(ctx context.Context, employeeID int) ([]Role, error) GetRoleIDByRoleName(ctx, roleName string, employeeID int) (int, error) GetRoleNameByRoleID(ctx, roleID int, employeeID int) (string, error)

Employee Role Management

AssignRolesToEmployeeByNames(ctx, employeeID int, roleNames []string, actorID int) error AssignRolesToEmployee(ctx, employeeID int, roleIDs []int, actorID int) error RemoveRolesFromEmployee(ctx, employeeID int, roleIDs []int, actorID int) error GetEmployeeRoles(ctx, employeeID, actorID int) ([]int, error) GetEmployeeRoleNames(ctx, employeeID, actorID int) ([]string, error) GetEmployeePermissions(ctx, employeeID, actorID int) ([]string, error) GetEmployeesByRoleName(ctx, roleName string, employeeID int) ([]int, error)

Permission Validation

ValidatePermission(ctx, employeeID int, requiredPermission string) error ValidateAnyPermission(ctx, employeeID int, required []string) error ValidateAllPermissions(ctx, employeeID int, required []string) error CompareEmpByRoleName(ctx, employeeID int, roleName string) error ValidatePermissionsBulk(ctx, employeeIDs []int, requiredPermission string, actorID int) (map[int]bool, error)

Cache Management

RefreshAllCaches(ctx context.Context, employeeID int) error GetCacheStats(employeeID int) map[string]interface{} GetCacheMemoryUsage(ctx context.Context, employeeID int) (map[string]int64, error)

Audit Logging

AuditLog(ctx context.Context, employeeID int, action, resource string, success bool) error GetAuditLogs(ctx context.Context, employeeID *int, action *string, startTime, endTime *time.Time, actorID int) ([]map[string]interface{}, error)

Middleware

RbacMiddleware(permission string) fiber.Handler

🗄️ Cache Management

Keys: rbac:permissions:all, rbac:roles:all, rbac:role::permissions, rbac:employee::roles, rbac:employee::permissions Invalidation: Automatic on create/update/delete TTL: Configurable via Config.CacheTTL Monitoring: Use GetCacheStats and GetCacheMemoryUsage

📝 Audit Logging

Enabled via Config.EnableAuditLogging Logs all API operations (e.g., permission/role creation, validation) Query logs with GetAuditLogs by employee ID, action, or time range

🤝 Contributing

Clone: git clone github.com/your-org/rbac Install: go mod tidy Test: go test -v ./... or go test -race ./... Submit issues/pull requests: GitHub Issues

📄 License MIT License. See LICENSE.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidInput     = errors.New("invalid input")
	ErrNotFound         = errors.New("resource not found")
	ErrPermissionDenied = errors.New("permission denied")
)

Custom errors

Functions

This section is empty.

Types

type AuditLog

type AuditLog struct {
	ID         uint   `gorm:"primaryKey"`
	ActorEmpID uint   `gorm:"index;not null"`
	Action     string `gorm:"not null"`
	TargetType string `gorm:"not null"`
	TargetID   uint   `gorm:"index;not null"`
	Details    string
	CreatedAt  time.Time
	UpdatedAt  time.Time
	DeletedAt  gorm.DeletedAt `gorm:"index"`
}

AuditLog tracks permission/role-related events.

type BulkEmployeePermission

type BulkEmployeePermission struct {
	EmployeeID       uint
	Permission       string
	DepartmentID     *uint
	TargetEmployeeID *uint
}

BulkEmployeePermission represents employee-permission pairs for bulk operations

type BulkPermissionResult

type BulkPermissionResult struct {
	EmployeeID uint
	Permission string
	Allowed    bool
	Error      error
}

BulkPermissionResult represents the result of bulk permission checks

type Config

type Config struct {
	DB      *gorm.DB
	Redis   *redis.Client // Optional; nil disables caching
	AppName string        // For Redis key prefixing
}

Config holds configuration for initializing the RBAC system.

type Department

type Department struct {
	ID        uint   `gorm:"primaryKey"`
	Name      string `gorm:"unique;not null"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt gorm.DeletedAt `gorm:"index"`
}

Department represents a logical group (e.g., Sales, HR).

type EmployeeRole

type EmployeeRole struct {
	EmployeeID uint `gorm:"primaryKey;autoIncrement:false"`
	RoleID     uint `gorm:"primaryKey;autoIncrement:false"`
	CreatedAt  time.Time
	UpdatedAt  time.Time
	DeletedAt  gorm.DeletedAt `gorm:"index"`
}

EmployeeRole maps an employee to a role.

type Permission

type Permission struct {
	ID        uint   `gorm:"primaryKey"`
	Name      string `gorm:"unique;not null"`
	IsGlobal  bool   `gorm:"default:false"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt gorm.DeletedAt `gorm:"index"`
}

Permission represents a named access action.

type RBAC

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

RBAC is the main struct for the RBAC system.

func Init

func Init(config Config) *RBAC

Init initializes the RBAC system with the provided configuration.

func (*RBAC) AddScopedPermission

func (r *RBAC) AddScopedPermission(roleID, permID uint, deptID, targetEmpID *uint) error

AddScopedPermission grants a permission to a role with optional scoping.

func (*RBAC) AssignRole

func (r *RBAC) AssignRole(empID, roleID uint) error

AssignRole creates a new employee-role mapping.

func (*RBAC) BulkAssignRoles

func (r *RBAC) BulkAssignRoles(assignments map[uint][]uint) error

BulkAssignRoles assigns multiple roles to multiple employees efficiently

func (*RBAC) BulkRemoveRoles

func (r *RBAC) BulkRemoveRoles(removals map[uint][]uint) error

BulkRemoveRoles removes multiple roles from multiple employees efficiently

func (*RBAC) CacheBulkPermissions

func (r *RBAC) CacheBulkPermissions(permissions map[string][]uint) error

CacheBulkPermissions caches permission results for multiple employees

func (*RBAC) CheckBulkPermissions

func (r *RBAC) CheckBulkPermissions(checks []BulkEmployeePermission) []BulkPermissionResult

CheckBulkPermissions checks multiple permissions for multiple employees efficiently

func (*RBAC) CheckPermission

func (r *RBAC) CheckPermission(empID uint, permName string, deptID, targetEmpID *uint) error

CheckPermission verifies if an employee has a specific permission.

func (*RBAC) ClearAllCache

func (r *RBAC) ClearAllCache() error

ClearAllCache clears all cache entries

func (*RBAC) Close

func (r *RBAC) Close()

Close cleans up resources

func (*RBAC) CreateDepartment

func (r *RBAC) CreateDepartment(name string) (*Department, error)

CreateDepartment creates a new department.

func (*RBAC) CreatePermission

func (r *RBAC) CreatePermission(name string, isGlobal bool) (*Permission, error)

CreatePermission creates a new permission.

func (*RBAC) CreateRole

func (r *RBAC) CreateRole(name string, deptID uint, parentRoleID *uint, isGlobal bool) (*Role, error)

CreateRole creates a new role in a department with optional parent role.

func (*RBAC) DeleteDepartment

func (r *RBAC) DeleteDepartment(id uint) error

DeleteDepartment soft-deletes a department by ID.

func (*RBAC) DeleteEmployeeRole

func (r *RBAC) DeleteEmployeeRole(empID, roleID uint) error

DeleteEmployeeRole soft-deletes an employee-role mapping.

func (*RBAC) DeletePermission

func (r *RBAC) DeletePermission(id uint) error

DeletePermission soft-deletes a permission by ID.

func (*RBAC) DeleteRole

func (r *RBAC) DeleteRole(id uint) error

DeleteRole soft-deletes a role by ID.

func (*RBAC) DeleteScopedPermission

func (r *RBAC) DeleteScopedPermission(id uint) error

DeleteScopedPermission soft-deletes a scoped permission by ID.

func (*RBAC) GetAuditLog

func (r *RBAC) GetAuditLog(id uint) (*AuditLog, error)

GetAuditLog retrieves an audit log by ID.

func (*RBAC) GetCacheStats

func (r *RBAC) GetCacheStats() map[string]interface{}

GetCacheStats returns cache statistics

func (*RBAC) GetContext

func (r *RBAC) GetContext() context.Context

GetContext returns the current context

func (*RBAC) GetDepartment

func (r *RBAC) GetDepartment(id uint) (*Department, error)

GetDepartment retrieves a department by ID.

func (*RBAC) GetEmployeePermissionsBulk

func (r *RBAC) GetEmployeePermissionsBulk(employeeIDs []uint) map[uint][]string

GetEmployeePermissionsBulk efficiently retrieves permissions for multiple employees

func (*RBAC) GetEmployeeRole

func (r *RBAC) GetEmployeeRole(empID, roleID uint) (*EmployeeRole, error)

GetEmployeeRole retrieves an employee-role mapping.

func (*RBAC) GetPermission

func (r *RBAC) GetPermission(id uint) (*Permission, error)

GetPermission retrieves a permission by ID.

func (*RBAC) GetRole

func (r *RBAC) GetRole(id uint) (*Role, error)

GetRole retrieves a role by ID.

func (*RBAC) GetScopedPermission

func (r *RBAC) GetScopedPermission(id uint) (*ScopedPermission, error)

GetScopedPermission retrieves a scoped permission by ID.

func (*RBAC) GetSubordinateIDs

func (r *RBAC) GetSubordinateIDs(empID uint) ([]uint, error)

GetSubordinateIDs fetches IDs of employees whose roles are descendants of the caller's roles.

func (*RBAC) InvalidateBulkCache

func (r *RBAC) InvalidateBulkCache(employeeIDs []uint) error

InvalidateBulkCache invalidates cache for multiple employees

func (*RBAC) ListAuditLogs

func (r *RBAC) ListAuditLogs(actorEmpID, targetID *uint) ([]AuditLog, error)

ListAuditLogs retrieves audit logs, optionally filtered by actor or target.

func (*RBAC) ListDepartments

func (r *RBAC) ListDepartments() ([]Department, error)

ListDepartments retrieves all departments.

func (*RBAC) ListEmployeeRoles

func (r *RBAC) ListEmployeeRoles(empID uint) ([]EmployeeRole, error)

ListEmployeeRoles retrieves all roles for an employee.

func (*RBAC) ListPermissions

func (r *RBAC) ListPermissions() ([]Permission, error)

ListPermissions retrieves all permissions.

func (*RBAC) ListRoles

func (r *RBAC) ListRoles(deptID *uint) ([]Role, error)

ListRoles retrieves all roles, optionally filtered by department.

func (*RBAC) ListScopedPermissions

func (r *RBAC) ListScopedPermissions(roleID *uint) ([]ScopedPermission, error)

ListScopedPermissions retrieves all scoped permissions, optionally filtered by role.

func (*RBAC) SetContext

func (r *RBAC) SetContext(ctx context.Context)

SetContext allows setting a custom context

func (*RBAC) UpdateDepartment

func (r *RBAC) UpdateDepartment(id uint, name string) (*Department, error)

UpdateDepartment updates a department's name.

func (*RBAC) UpdateEmployeeRole

func (r *RBAC) UpdateEmployeeRole(empID, oldRoleID, newRoleID uint) error

UpdateEmployeeRole updates an employee-role mapping (reassigns role).

func (*RBAC) UpdatePermission

func (r *RBAC) UpdatePermission(id uint, name string, isGlobal bool) (*Permission, error)

UpdatePermission updates a permission's details.

func (*RBAC) UpdateRole

func (r *RBAC) UpdateRole(id uint, name string, deptID uint, parentRoleID *uint, isGlobal bool) (*Role, error)

UpdateRole updates a role's details.

func (*RBAC) UpdateScopedPermission

func (r *RBAC) UpdateScopedPermission(id, roleID, permID uint, deptID, targetEmpID *uint) error

UpdateScopedPermission updates a scoped permission's details.

func (*RBAC) WarmCache

func (r *RBAC) WarmCache() error

WarmCache preloads frequently accessed data into cache

type Role

type Role struct {
	ID           uint   `gorm:"primaryKey"`
	Name         string `gorm:"not null"`
	DepartmentID uint   `gorm:"not null;index"`
	ParentRoleID *uint  `gorm:"index"` // For role inheritance
	IsGlobal     bool   `gorm:"default:false"`
	CreatedAt    time.Time
	UpdatedAt    time.Time
	DeletedAt    gorm.DeletedAt `gorm:"index"`
}

Role represents a hierarchical position within a department.

type ScopedPermission

type ScopedPermission struct {
	ID           uint  `gorm:"primaryKey"`
	RoleID       uint  `gorm:"index;not null"`
	PermissionID uint  `gorm:"index;not null"`
	DepartmentID *uint `gorm:"index"` // Optional department scope
	EmployeeID   *uint `gorm:"index"` // Optional employee scope
	CreatedAt    time.Time
	UpdatedAt    time.Time
	DeletedAt    gorm.DeletedAt `gorm:"index"`
}

ScopedPermission grants a permission to a role with optional scoping.

Jump to

Keyboard shortcuts

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