Exception: Otto::Security::AuthorizationError

Inherits:
ForbiddenError show all
Defined in:
lib/otto/security/authorization_error.rb

Overview

Authorization error for resource-level access control failures

This exception is designed to be raised from Logic classes when a user attempts to access a resource they don’t have permission to access.

Otto automatically registers this as a 403 Forbidden error during initialization, so raising this exception will return a 403 response instead of a 500 error.

Two-Layer Authorization Pattern:

  • Layer 1 (Route-level): RouteAuthWrapper checks authentication/basic roles

  • Layer 2 (Resource-level): Logic classes raise AuthorizationError for ownership/permissions

Examples:

Ownership check in Logic class

class PostEditLogic
  def raise_concerns
    @post = Post.find(params[:id])

    unless @post.user_id == @context.user_id
      raise Otto::Security::AuthorizationError, "Cannot edit another user's post"
    end
  end
end

Multi-condition authorization

class OrganizationDeleteLogic
  def raise_concerns
    @org = Organization.find(params[:id])

    unless @context.user_roles.include?('admin') || @org.owner_id == @context.user_id
      raise Otto::Security::AuthorizationError,
        "Requires admin role or organization ownership"
    end
  end
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from ForbiddenError

default_log_level, default_status

Methods inherited from HTTPError

default_log_level, default_status

Constructor Details

#initialize(message = 'Access denied', resource: nil, action: nil, user_id: nil) ⇒ AuthorizationError

Initialize authorization error with optional context

Parameters:

  • message (String) (defaults to: 'Access denied')

    Human-readable error message

  • resource (String, nil) (defaults to: nil)

    Resource type being accessed (e.g., ‘Post’, ‘Organization’)

  • action (String, nil) (defaults to: nil)

    Action being attempted (e.g., ‘edit’, ‘delete’)

  • user_id (String, Integer, nil) (defaults to: nil)

    ID of user attempting access



53
54
55
56
57
58
# File 'lib/otto/security/authorization_error.rb', line 53

def initialize(message = 'Access denied', resource: nil, action: nil, user_id: nil)
  super(message)
  @resource = resource
  @action = action
  @user_id = user_id
end

Instance Attribute Details

#actionObject (readonly)

Optional additional context for logging/debugging



45
46
47
# File 'lib/otto/security/authorization_error.rb', line 45

def action
  @action
end

#resourceObject (readonly)

Optional additional context for logging/debugging



45
46
47
# File 'lib/otto/security/authorization_error.rb', line 45

def resource
  @resource
end

#user_idObject (readonly)

Optional additional context for logging/debugging



45
46
47
# File 'lib/otto/security/authorization_error.rb', line 45

def user_id
  @user_id
end

Instance Method Details

#to_log_dataHash

Generate structured log data for authorization failures

Returns:

  • (Hash)

    Hash suitable for structured logging



63
64
65
66
67
68
69
70
# File 'lib/otto/security/authorization_error.rb', line 63

def to_log_data
  {
    error: message,
    resource: resource,
    action: action,
    user_id: user_id,
  }.compact
end