1
1
# frozen_string_literal: true
2
2
3
- require_relative 'patcher/authenticatable_patch'
4
- require_relative 'patcher/rememberable_patch'
5
- require_relative 'patcher/registration_controller_patch'
3
+ require_relative '../../../core/utils/only_once'
4
+
5
+ require_relative 'tracking_middleware'
6
+ require_relative 'patches/signup_tracking_patch'
7
+ require_relative 'patches/signin_tracking_patch'
8
+ require_relative 'patches/skip_signin_tracking_patch'
6
9
7
10
module Datadog
8
11
module AppSec
9
12
module Contrib
10
13
module Devise
11
- # Patcher for AppSec on Devise
14
+ # Devise patcher
12
15
module Patcher
16
+ GUARD_ONCE_PER_APP = Hash . new do |hash , key |
17
+ hash [ key ] = Datadog ::Core ::Utils ::OnlyOnce . new
18
+ end
19
+
13
20
module_function
14
21
15
22
def patched?
@@ -21,29 +28,35 @@ def target_version
21
28
end
22
29
23
30
def patch
24
- patch_authenticatable_strategy
25
- patch_rememberable_strategy
26
- patch_registration_controller
27
-
28
- Patcher . instance_variable_set ( :@patched , true )
29
- end
30
-
31
- def patch_authenticatable_strategy
32
- ::Devise ::Strategies ::Authenticatable . prepend ( AuthenticatablePatch )
33
- end
31
+ ::ActiveSupport . on_load ( :before_initialize ) do |app |
32
+ GUARD_ONCE_PER_APP [ app ] . run do
33
+ begin
34
+ app . middleware . insert_after ( Warden ::Manager , TrackingMiddleware )
35
+ rescue RuntimeError
36
+ AppSec . telemetry . error ( 'AppSec: unable to insert Devise TrackingMiddleware' )
37
+ end
38
+ end
39
+ end
34
40
35
- def patch_rememberable_strategy
36
- return unless ::Devise ::STRATEGIES . include? ( :rememberable )
41
+ ::ActiveSupport . on_load ( :after_initialize ) do
42
+ if ::Devise ::RegistrationsController . descendants . empty?
43
+ ::Devise ::RegistrationsController . prepend ( Patches ::SignupTrackingPatch )
44
+ else
45
+ ::Devise ::RegistrationsController . descendants . each do |controller |
46
+ controller . prepend ( Patches ::SignupTrackingPatch )
47
+ end
48
+ end
49
+ end
37
50
38
- # Rememberable strategy is required in autoloaded Rememberable model
39
- ::Devise ::Models ::Rememberable # rubocop:disable Lint/Void
40
- ::Devise ::Strategies ::Rememberable . prepend ( RememberablePatch )
41
- end
51
+ ::Devise ::Strategies ::Authenticatable . prepend ( Patches ::SigninTrackingPatch )
42
52
43
- def patch_registration_controller
44
- ::ActiveSupport . on_load ( :after_initialize ) do
45
- ::Devise ::RegistrationsController . prepend ( RegistrationControllerPatch )
53
+ if ::Devise ::STRATEGIES . include? ( :rememberable )
54
+ # Rememberable strategy is required in autoloaded Rememberable model
55
+ require 'devise/models/rememberable'
56
+ ::Devise ::Strategies ::Rememberable . prepend ( Patches ::SkipSigninTrackingPatch )
46
57
end
58
+
59
+ Patcher . instance_variable_set ( :@patched , true )
47
60
end
48
61
end
49
62
end
0 commit comments