Class: Rhino::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/rhino/configuration.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rhino/configuration.rb', line 9

def initialize
  @models = {}
  @route_groups = {}
  @multi_tenant = {
    organization_identifier_column: "id"
  }
  @invitations = {
    expires_days: 7,
    allowed_roles: nil
  }
  @nested = {
    path: "nested",
    max_operations: 50,
    allowed_models: nil
  }
  @auth = {
    enforce_group_membership: false
  }
  @test_framework = "rspec"
  @client_path = nil
  @mobile_path = nil
end

Instance Attribute Details

#authObject

Returns the value of attribute auth.



7
8
9
# File 'lib/rhino/configuration.rb', line 7

def auth
  @auth
end

#client_pathObject

Returns the value of attribute client_path.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def client_path
  @client_path
end

#invitationsObject

Returns the value of attribute invitations.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def invitations
  @invitations
end

#mobile_pathObject

Returns the value of attribute mobile_path.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def mobile_path
  @mobile_path
end

#modelsObject

Returns the value of attribute models.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def models
  @models
end

#multi_tenantObject

Returns the value of attribute multi_tenant.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def multi_tenant
  @multi_tenant
end

#nestedObject

Returns the value of attribute nested.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def nested
  @nested
end

#route_groupsObject

Returns the value of attribute route_groups.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def route_groups
  @route_groups
end

#test_frameworkObject

Returns the value of attribute test_framework.



5
6
7
# File 'lib/rhino/configuration.rb', line 5

def test_framework
  @test_framework
end

Instance Method Details

#auth_enabled_groupsObject

Names of all groups (except :public) that opted into per-group auth.



144
145
146
147
# File 'lib/rhino/configuration.rb', line 144

def auth_enabled_groups
  @route_groups.keys.reject { |name| name.to_s == "public" }
               .select { |name| group_auth_enabled?(name) }
end

#auth_enabled_legacy_groupsObject

Names of auth-enabled groups that have an empty prefix AND no domain, i.e. groups whose auth routes would be byte-for-byte identical to the legacy unprefixed /api/auth/* set (GROUP_AUTH_DESIGN.md §11.1). Such a group IS the default/legacy auth: the legacy routes adopt its route_group/hooks instead of registering a colliding second set. Two or more is a conflict (raised by the route-group validator).



155
156
157
158
159
160
161
162
# File 'lib/rhino/configuration.rb', line 155

def auth_enabled_legacy_groups
  auth_enabled_groups.select do |name|
    group = @route_groups[name.to_sym]
    prefix = group[:prefix].to_s
    domain = group[:domain]
    prefix.empty? && (domain.nil? || domain.to_s.strip.empty?)
  end
end

#enforce_group_membership?Boolean

Master flag (default off). When off, behavior is byte-for-byte today’s: no group-membership enforcement.

Returns:

  • (Boolean)


40
41
42
# File 'lib/rhino/configuration.rb', line 40

def enforce_group_membership?
  !!@auth[:enforce_group_membership]
end

#group_auth_enabled?(group_name) ⇒ Boolean

Whether a group has per-group auth routes enabled (‘auth: true`). The `public` group is never auth-enabled.

Returns:

  • (Boolean)


136
137
138
139
140
141
# File 'lib/rhino/configuration.rb', line 136

def group_auth_enabled?(group_name)
  return false if group_name.to_s == "public"

  group = @route_groups[group_name.to_sym]
  !!(group && group[:auth])
end

#group_is_tenant?(group_name) ⇒ Boolean

Whether a group is a tenant group (organization-scoped). Only the reserved ‘:tenant` group is treated as a tenant group, matching has_tenant_group?.

Returns:

  • (Boolean)


190
191
192
# File 'lib/rhino/configuration.rb', line 190

def group_is_tenant?(group_name)
  group_name.to_s == "tenant"
end

#has_public_group?Boolean

Whether a ‘public’ route group is configured

Returns:

  • (Boolean)


101
102
103
# File 'lib/rhino/configuration.rb', line 101

def has_public_group?
  @route_groups.key?(:public)
end

#has_tenant_group?Boolean

Whether a ‘tenant’ route group is configured

Returns:

  • (Boolean)


96
97
98
# File 'lib/rhino/configuration.rb', line 96

def has_tenant_group?
  @route_groups.key?(:tenant)
end

#hooks_for_group(group_name) ⇒ Object

Resolve the configured lifecycle-hooks class for a group, instantiated. Returns nil when the group has no hooks configured. Accepts a class, a class name string, or an instance.



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/rhino/configuration.rb', line 167

def hooks_for_group(group_name)
  return nil if group_name.nil?

  group = @route_groups[group_name.to_sym]
  return nil unless group

  hooks = group[:hooks]
  return nil if hooks.nil?

  case hooks
  when String
    klass = hooks.safe_constantize
    klass&.new
  when Class
    hooks.new
  else
    hooks
  end
end

#model(slug, klass_name) ⇒ Object

Register a model with its slug Usage: config.model :posts, ‘Post’



46
47
48
# File 'lib/rhino/configuration.rb', line 46

def model(slug, klass_name)
  @models[slug.to_sym] = klass_name.to_s
end

#model_in_group?(slug, group_name) ⇒ Boolean

Check if a specific slug belongs to a specific group

Returns:

  • (Boolean)


126
127
128
# File 'lib/rhino/configuration.rb', line 126

def model_in_group?(slug, group_name)
  models_for_group(group_name).include?(slug.to_sym)
end

#models_for_group(group_name) ⇒ Object

Resolve the model slugs for a given route group



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/rhino/configuration.rb', line 106

def models_for_group(group_name)
  group = @route_groups[group_name.to_sym]
  return [] unless group

  group_models = group[:models]
  if group_models == :all || group_models == "*"
    @models.keys
  else
    Array(group_models).map(&:to_sym) & @models.keys
  end
end

#public_model?(slug) ⇒ Boolean

Check if a model belongs to the ‘public’ route group

Returns:

  • (Boolean)


119
120
121
122
123
# File 'lib/rhino/configuration.rb', line 119

def public_model?(slug)
  return false unless has_public_group?

  models_for_group(:public).include?(slug.to_sym)
end

#resolve_model(slug) ⇒ Object

Resolve a model class from its slug



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rhino/configuration.rb', line 74

def resolve_model(slug)
  klass_name = @models[slug.to_sym]
  raise ActiveRecord::RecordNotFound, "The #{slug} model does not exist" unless klass_name

  klass = klass_name.constantize
  raise ActiveRecord::RecordNotFound, "The #{slug} model does not exist" unless klass

  klass
rescue NameError
  raise ActiveRecord::RecordNotFound, "The #{slug} model does not exist"
end

#route_group(name, prefix: "", domain: nil, middleware: [], models: :all, auth: false, hooks: nil) ⇒ Object

Register a route group with its configuration Usage: config.route_group :tenant, prefix: ‘:organization’, middleware: [Rhino::Middleware::ResolveOrganizationFromRoute], models: :all

The optional ‘domain:` keyword constrains the group’s routes to a specific host. Two groups can then share the same ‘prefix:` but live on different domains. A parameterized domain such as “organization.example.com” captures the subdomain and feeds organization resolution exactly like the path-prefix “:organization” does. Groups without a domain (nil/blank) match any host (default, fully backward compatible).



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rhino/configuration.rb', line 59

def route_group(name, prefix: "", domain: nil, middleware: [], models: :all, auth: false, hooks: nil)
  normalized_domain = domain.to_s.strip
  normalized_domain = nil if normalized_domain.empty?

  @route_groups[name.to_sym] = {
    prefix: prefix.to_s,
    domain: normalized_domain,
    middleware: Array(middleware),
    models: models,
    auth: !!auth,
    hooks: hooks
  }
end

#slug_for(model_class) ⇒ Object

Find the slug for a given model class



87
88
89
90
91
92
93
# File 'lib/rhino/configuration.rb', line 87

def slug_for(model_class)
  class_name = model_class.is_a?(Class) ? model_class.name : model_class.class.name
  @models.each do |slug, klass_name|
    return slug if klass_name == class_name
  end
  nil
end