Class: ReactOnRailsPro::LicenseValidator

Inherits:
Object
  • Object
show all
Defined in:
lib/react_on_rails_pro/license_validator.rb

Overview

Validates React on Rails Pro licenses. This class only determines license status - it does NOT log. All logging is handled by Engine.log_license_status for environment-aware messaging. rubocop:disable Metrics/ClassLength

Constant Summary collapse

VALID_PLANS =

Valid license plan types. Must match VALID_PLANS in packages/react-on-rails-pro-node-renderer/src/shared/licenseValidator.ts

  • paid: Standard commercial license

  • startup: Complimentary for qualifying startups

  • nonprofit: Complimentary for non-profits

  • education: For educational institutions

  • oss: For open source projects

  • partner: Strategic partners

%w[paid startup nonprofit education oss partner].freeze
ATTRIBUTION_REQUIRED_PLANS =

Plans that require attribution by default (complimentary licenses)

Attribution defaults by plan:

Plan       | Attribution Required?
-----------|----------------------
paid       | No
partner    | No
startup    | Yes
oss        | Yes
nonprofit  | No (default)
education  | No (default)

These defaults can be overridden by explicit “attribution” field in the license JWT.

%w[startup oss].freeze
LICENSE_MUTEX =

Mutex for thread-safe license status initialization. Using a constant eliminates the race condition that would exist with @mutex ||= Mutex.new See: bugs.ruby-lang.org/issues/20875

Mutex.new

Class Method Summary collapse

Class Method Details

.attribution_required?Boolean

Returns whether attribution is required for this license Checks explicit attribution field first, then infers from plan type:

  • paid, partner: No attribution required

  • startup, oss: Attribution required

  • nonprofit, education: Attribution optional (default: no)

Returns:

  • (Boolean)

    True if attribution is required



98
99
100
101
102
103
104
105
106
# File 'lib/react_on_rails_pro/license_validator.rb', line 98

def attribution_required?
  return @attribution_required if defined?(@attribution_required)

  LICENSE_MUTEX.synchronize do
    return @attribution_required if defined?(@attribution_required)

    @attribution_required = determine_attribution_required
  end
end

.license_expirationTime?

Returns the license expiration time if available

Returns:

  • (Time, nil)

    The expiration time or nil if not available



58
59
60
61
62
63
64
65
66
# File 'lib/react_on_rails_pro/license_validator.rb', line 58

def license_expiration
  return @license_expiration if defined?(@license_expiration)

  LICENSE_MUTEX.synchronize do
    return @license_expiration if defined?(@license_expiration)

    @license_expiration = determine_license_expiration
  end
end

.license_infoHash

Returns license information for use in helpers and components

Returns:

  • (Hash)

    License info including org, plan, status, and attribution_required



110
111
112
113
114
115
116
117
118
# File 'lib/react_on_rails_pro/license_validator.rb', line 110

def license_info
  {
    org: license_organization,
    plan: license_plan,
    status: license_status,
    attribution_required: attribution_required?,
    expiration: license_expiration
  }
end

.license_organizationString?

Returns the organization name from the license if available

Returns:

  • (String, nil)

    The organization name or nil if not available



70
71
72
73
74
75
76
77
78
# File 'lib/react_on_rails_pro/license_validator.rb', line 70

def license_organization
  return @license_organization if defined?(@license_organization)

  LICENSE_MUTEX.synchronize do
    return @license_organization if defined?(@license_organization)

    @license_organization = determine_license_organization
  end
end

.license_planString?

Returns the license plan type if available

Returns:

  • (String, nil)

    The plan type (e.g., “paid”, “startup”) or nil if not available



82
83
84
85
86
87
88
89
90
# File 'lib/react_on_rails_pro/license_validator.rb', line 82

def license_plan
  return @license_plan if defined?(@license_plan)

  LICENSE_MUTEX.synchronize do
    return @license_plan if defined?(@license_plan)

    @license_plan = determine_license_plan
  end
end

.license_statusSymbol

Returns the current license status (never raises, never logs) Thread-safe: uses Mutex to prevent race conditions during initialization

Returns:

  • (Symbol)

    One of :valid, :expired, :invalid, :missing



45
46
47
48
49
50
51
52
53
54
# File 'lib/react_on_rails_pro/license_validator.rb', line 45

def license_status
  return @license_status if defined?(@license_status)

  LICENSE_MUTEX.synchronize do
    # Double-check pattern: another thread may have set it while we waited
    return @license_status if defined?(@license_status)

    @license_status = determine_license_status
  end
end

.reset!Object

Resets all cached state (primarily for testing)



121
122
123
124
125
126
127
128
129
# File 'lib/react_on_rails_pro/license_validator.rb', line 121

def reset!
  LICENSE_MUTEX.synchronize do
    remove_instance_variable(:@license_status) if defined?(@license_status)
    remove_instance_variable(:@license_expiration) if defined?(@license_expiration)
    remove_instance_variable(:@license_organization) if defined?(@license_organization)
    remove_instance_variable(:@license_plan) if defined?(@license_plan)
    remove_instance_variable(:@attribution_required) if defined?(@attribution_required)
  end
end