standard_id 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 956fc621df693ec184f7d65482d96c4f25d99ae55274b68681c9c6b892bde095
4
- data.tar.gz: 0d5c39a196c8c9e8c99adb24fa61552698672f3df4a5bcf3d06d03b2b61e6a46
3
+ metadata.gz: b1c16f53717e8c9b0d2bcf1095f2387c99b9bfeb9b1327d1b101e2ea140d3eaf
4
+ data.tar.gz: 59d779aa3fe5a74f639f826505f9d21a845964b6edaedd085397d435241d5fa4
5
5
  SHA512:
6
- metadata.gz: 584c37aa6aa46abe4a576297d6d754e5632c4b710c59dd1bd2b6f8d7c5c17ac86a8aef109df15fe3de720a7d1be405af31441f833a914b3bc8bfea264b296da5
7
- data.tar.gz: 1733a94c80aba6290cc5eabbe7df67f4ff145c5af18e8cb9202cd3d598b5e5569039fc729cdfed3eacfee55908fe36bf4801e706da7c0e8b544666383b7b6863
6
+ metadata.gz: 4cef892853b6d5d87fe83919582b122e41d525cd20a938cd40444252a6cbf3470bca8aba08b8a6e7a04ed5b5eadc237410a2f03a475ad8b10941531dd7cbde8f
7
+ data.tar.gz: 7d1c980a1be28688515573053cd91c28afd03119a8d8db41d72be8859d4472f8a3ccf50c5d005376ba8f5a91a2f5bb9f0fd27fd3ed75611682c68a8600db94fa
@@ -28,7 +28,9 @@ module StandardId
28
28
  return unless respond_to?(:current_account, true) && current_account.present?
29
29
 
30
30
  context = { id: current_account.id }
31
- context[:session_id] = current_session.id if respond_to?(:current_session, true) && current_session.present?
31
+ if respond_to?(:current_session, true) && current_session.present? && current_session.respond_to?(:id)
32
+ context[:session_id] = current_session.id
33
+ end
32
34
 
33
35
  Sentry.set_user(context)
34
36
  end
@@ -6,6 +6,19 @@ module StandardId
6
6
  cancancan: :check_authorization
7
7
  }.freeze
8
8
 
9
+ # Frameworks where the skip falls through to skip_after_action.
10
+ # ActionPolicy is NOT listed here because it is handled first via
11
+ # CLASS_METHOD_SKIP. Only :pundit reaches this branch.
12
+ AFTER_ACTION_FRAMEWORKS = %i[pundit].freeze
13
+
14
+ # ActionPolicy provides a dedicated class method to undo
15
+ # verify_authorized. Using skip_before_action or skip_after_action
16
+ # would silently do nothing for ActionPolicy because it manages the
17
+ # callback through its own DSL.
18
+ CLASS_METHOD_SKIP = {
19
+ action_policy: :skip_verify_authorized
20
+ }.freeze
21
+
9
22
  MUTEX = Mutex.new
10
23
  private_constant :MUTEX
11
24
 
@@ -30,11 +43,12 @@ module StandardId
30
43
 
31
44
  MUTEX.synchronize do
32
45
  # Guard against duplicate to_prepare registrations if called more than
33
- # once (e.g. in tests or misconfigured initializers). skip_before_action
34
- # is idempotent so duplicates are harmless, but this keeps things tidy.
46
+ # once (e.g. in tests or misconfigured initializers). The skip methods
47
+ # are idempotent so duplicates are harmless, but this keeps things tidy.
35
48
  return if @callback_name
36
49
 
37
50
  @callback_name = resolve_callback(framework, callback)
51
+ @framework = framework&.to_sym
38
52
  # @prepared is intentionally NOT cleared by reset!. This ensures
39
53
  # at most one to_prepare block is registered per process lifetime.
40
54
  # Trade-off: after reset! + apply (e.g. in tests switching
@@ -64,7 +78,7 @@ module StandardId
64
78
  end
65
79
 
66
80
  # Whether apply has been called. Used by ControllerPolicy.register to
67
- # decide if newly loaded controllers need immediate skip_before_action.
81
+ # decide if newly loaded controllers need an immediate authorization skip.
68
82
  def applied?
69
83
  MUTEX.synchronize { !@callback_name.nil? }
70
84
  end
@@ -72,10 +86,11 @@ module StandardId
72
86
  # Apply skips to a single controller. Called by ControllerPolicy.register
73
87
  # when a controller is lazily loaded after apply has already been called.
74
88
  def apply_to_controller(controller, policy)
75
- callback = MUTEX.synchronize { @callback_name }
89
+ callback, framework = MUTEX.synchronize { [@callback_name, @framework] }
76
90
  return unless callback
77
91
 
78
- controller.skip_before_action callback, raise: false
92
+ skip_authorization_callback(controller, callback, framework)
93
+
79
94
  if policy == :public
80
95
  # authenticate_account! is defined in WebAuthentication, not on API
81
96
  # controllers. raise: false ensures this is a safe no-op for API
@@ -94,11 +109,15 @@ module StandardId
94
109
  end
95
110
 
96
111
  # @api private — intended for test isolation only.
97
- # NOTE: This clears @callback_name (so applied? returns false and apply
98
- # can be called again with a different framework) but intentionally does
99
- # NOT clear @prepared, so no additional to_prepare block is registered.
112
+ # NOTE: This clears @callback_name and @framework (so applied? returns
113
+ # false and apply can be called again with a different framework) but
114
+ # intentionally does NOT clear @prepared, so no additional to_prepare
115
+ # block is registered.
100
116
  def reset!
101
- MUTEX.synchronize { @callback_name = nil }
117
+ MUTEX.synchronize do
118
+ @callback_name = nil
119
+ @framework = nil
120
+ end
102
121
  end
103
122
 
104
123
  private
@@ -116,6 +135,29 @@ module StandardId
116
135
  raise ArgumentError, "Provide either framework: or callback:"
117
136
  end
118
137
  end
138
+
139
+ # Picks the right skip mechanism based on how the framework registers
140
+ # its authorization check:
141
+ #
142
+ # - ActionPolicy: provides `skip_verify_authorized` class method
143
+ # - Pundit: uses after_action, so `skip_after_action` is needed
144
+ # - CanCanCan: uses before_action, so `skip_before_action` works
145
+ # - Custom callback: assumed to be a before_action (caller can use
146
+ # framework: for known frameworks)
147
+ def skip_authorization_callback(controller, callback, framework)
148
+ if (class_method = CLASS_METHOD_SKIP[framework])
149
+ # Engine API controllers inherit from ActionController::API, not the
150
+ # host app's ApplicationController, so they won't include ActionPolicy.
151
+ # A controller without ActionPolicy can never have verify_authorized in
152
+ # its callback chain, so skipping the call is safe — not a silent failure.
153
+ # This mirrors the `raise: false` intent of the other branches.
154
+ controller.public_send(class_method) if controller.respond_to?(class_method)
155
+ elsif AFTER_ACTION_FRAMEWORKS.include?(framework)
156
+ controller.skip_after_action callback, raise: false
157
+ else
158
+ controller.skip_before_action callback, raise: false
159
+ end
160
+ end
119
161
  end
120
162
  end
121
163
  end
@@ -1,3 +1,3 @@
1
1
  module StandardId
2
- VERSION = "0.5.0"
2
+ VERSION = "0.5.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: standard_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaryl Sim