Module: AgentCode::HasPermissions

Extended by:
ActiveSupport::Concern
Defined in:
lib/agentcode/concerns/has_permissions.rb

Overview

Permission checking concern for the User model. Mirrors the Laravel HasPermissions trait.

Usage: class User < ApplicationRecord include AgentCode::HasPermissions

has_many :user_roles
end

Permission format: 'slug.action' (e.g., 'posts.index', 'blogs.store') Wildcard support:

  • '*' grants access to everything
  • 'posts.*' grants access to all actions on posts

Two permission sources:

  • users.permissions: used for non-tenant route groups (no organization context). Stored as a JSON array directly on the user model.
  • role.permissions (via user_roles): used for tenant route groups (organization context present). Resolved per-organization via the user_roles → role association.

Resolution:

  1. When an organization is provided (tenant route group) → checks role.permissions for that specific organization via user_roles.
  2. When no organization is provided (non-tenant route group) → checks users.permissions directly on the user model.

Instance Method Summary collapse

Instance Method Details

#has_permission?(permission, organization = nil) ⇒ Boolean

Check if the user has a specific permission.

Parameters:

  • permission (String)

    Permission string like 'posts.index'

  • organization (Object, nil) (defaults to: nil)

    Organization to check permissions for

Returns:

  • (Boolean)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/agentcode/concerns/has_permissions.rb', line 38

def has_permission?(permission, organization = nil)
  return false if permission.blank?

  if organization
    # Tenant route group: check permissions for this organization
    user_role = find_user_role(organization)

    if user_role
      # Check user_role.permissions first (per-user-org permissions on the pivot)
      ur_permissions = parse_permissions(user_role.respond_to?(:permissions) ? user_role.permissions : nil)
      if ur_permissions.present?
        return matches_permission?(permission, ur_permissions)
      end

      # Fallback to role.permissions (shared role-level permissions)
      role = user_role.respond_to?(:role) ? user_role.role : nil
      if role
        role_permissions = parse_permissions(role.respond_to?(:permissions) ? role.permissions : nil)
        return matches_permission?(permission, role_permissions) if role_permissions.present?
      end
    end

    return false
  end

  # Non-tenant route group: check users.permissions directly
  user_perms = parse_permissions(respond_to?(:permissions) ? self.permissions : nil)
  matches_permission?(permission, user_perms)
end

#role_slug_for_validation(organization = nil) ⇒ String?

Get the role slug for validation purposes.

Parameters:

  • organization (Object, nil) (defaults to: nil)

    Organization context

Returns:

  • (String, nil)

    Role slug or nil



72
73
74
75
76
77
78
79
80
# File 'lib/agentcode/concerns/has_permissions.rb', line 72

def role_slug_for_validation(organization = nil)
  user_role = find_user_role(organization)
  return nil unless user_role

  role = user_role.respond_to?(:role) ? user_role.role : nil
  return nil unless role

  role.respond_to?(:slug) ? role.slug : nil
end