sudo_rails 0.8.0 → 0.9.0

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: 13a5abdefd6191deed91535f4401bf0def14a6e502b6d4b191d7129e7fb2c754
4
- data.tar.gz: 1166792b0ff651665d8dba513e56af064decf4b97c6d68c5302eddc3a194ac04
3
+ metadata.gz: ef841eee5e065e49eef95c49c95313b4ca06085ad72a9d8823a57601a8d77dab
4
+ data.tar.gz: a63794f0c1285c3a90ce9241032c906543f5865656525f2f578c5a0931f948b3
5
5
  SHA512:
6
- metadata.gz: cb284469c871a0f3bd17213d2c316835b4a1c3ea2ed82d3fda416066e1a89128f0d2b0c4848b3068eb1298109993ece6fec8941b119ca8cb1cf591d32998d2c8
7
- data.tar.gz: 6154b8cdda0c06b4c6afc7d19d751131fb1cfe33d93e6e090afd8f8070c52197c62d0f65d0928001281f5f489d6965dd9c2f229232308ae1d297af378ab3821a
6
+ metadata.gz: f9468293ceac9777f6b7f79fc115e3822e6ebb2bb20a8b166f8f78f3c3fe719e3014333644a8e516697357c03d5694a2b0427f35b9b1db5b8b235ce9b764f309
7
+ data.tar.gz: 9eaed5ed8dc3674198512128b94e22cb9b5f9f7079ca384af2daca03de8aad7f13576a6f535626c106db5e67fed9a59570be3d392842caf722674236915f93f6
data/README.md CHANGED
@@ -70,6 +70,18 @@ SudoRails.setup do |config|
70
70
 
71
71
  # Reset password link
72
72
  config.reset_pass_link = '/users/password/new'
73
+
74
+ # Subscribe to different events
75
+ config.callbacks = {
76
+ invalid_sudo_session: -> (context) {
77
+ user = context.current_user
78
+ AuthService.send_code(user)
79
+ },
80
+ invalid_confirmation: -> (context) {
81
+ user = context.current_user
82
+ Rails.logger.warn("[SUDO_RAILS] invalid password for #{user.email}")
83
+ }
84
+ }
73
85
  end
74
86
  ```
75
87
 
@@ -114,14 +126,49 @@ config.confirm_strategy = -> (context, password) {
114
126
  user.authenticate(password)
115
127
  }
116
128
 
117
- # Other custom implementations
129
+ # Another example, using ENV vars
118
130
  config.confirm_strategy = -> (context, password) {
119
131
  user = context.current_user
120
132
  user.admin? && password == ENV['SUPER_SECRET_PASSWORD']
121
133
  }
134
+ ```
122
135
 
123
- config.confirm_strategy = -> (context, password) {
124
- Auth.call(context.current_user.email, password)
136
+ ### Callbacks
137
+
138
+ You can subscribe to different lifecycle events via the `callbacks` option. Each callback must be a `lambda`, which will receive 1 argument, the controller instance (`context`).
139
+
140
+ You can subscribe to the following events:
141
+
142
+ - `:invalid_sudo_session`: fired when the confirmation page is rendered, because there is no valid sudo session. Be careful! If the page is re-submitted or the password is invalid, the confirmation page will be rendered again and this event will be fired again too.
143
+ - `:new_sudo_session`: fired when a new sudo session is started.
144
+ - `:invalid_confirmation`: fired when an invalid password is submitted.
145
+
146
+ This can be really useful for example for instrumentation or logging:
147
+
148
+ ```ruby
149
+ config.callbacks = {
150
+ invalid_confirmation: -> (context) {
151
+ user = context.current_user
152
+ request = context.request
153
+
154
+ Rails.logger.warn("[SUDO_RAILS] Invalid verification: #{user.email} - #{request.remote_ip}")
155
+ }
156
+ }
157
+ ```
158
+
159
+ Or you can even implement custom workflows along with the `confirm_strategy` option. Like for example, using your 2FA system instead of the session password:
160
+
161
+ ```ruby
162
+ config.callbacks = {
163
+ invalid_sudo_session: -> (context) {
164
+ user = context.current_user
165
+ AuthService.send_code(user)
166
+ }
167
+ }
168
+
169
+ config.confirm_strategy = -> (context, code) {
170
+ user = context.current_user
171
+ AuthService.validate_code(user, code)
125
172
  }
126
173
  ```
127
174
 
@@ -4,7 +4,7 @@ module SudoRails
4
4
 
5
5
  def confirm
6
6
  if SudoRails.confirm?(self, params[:password])
7
- session[:sudo_session] = Time.zone.now.to_s
7
+ extend_sudo_session!
8
8
  else
9
9
  flash[:alert] = I18n.t('sudo_rails.invalid_pass', locale: params[:locale])
10
10
  end
@@ -22,6 +22,13 @@ class SudoRails::ConfigGenerator < Rails::Generators::Base
22
22
 
23
23
  ### Reset password link
24
24
  # config.reset_pass_link = '/users/password/new'
25
+
26
+ ### Subscribe to different events
27
+ # config.callbacks = {
28
+ # new_sudo_session: -> (context) { Rails.logger.warn("new sudo session created") },
29
+ # invalid_sudo_session: -> (context) { Rails.logger.warn("invalid sudo session") },
30
+ # invalid_confirmation: -> (context) { Rails.logger.warn("invalid password in sudo session") }
31
+ # }
25
32
  end
26
33
  RUBY
27
34
  end
@@ -8,6 +8,8 @@ module SudoRails
8
8
  next unless SudoRails.enabled
9
9
  next if SudoRails.valid_sudo_session?(session[:sudo_session])
10
10
 
11
+ SudoRails.run_callback(:invalid_sudo_session, self)
12
+
11
13
  render 'sudo_rails/confirm_form', layout: SudoRails.get_layout
12
14
  end
13
15
  end
@@ -1,3 +1,3 @@
1
1
  module SudoRails
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0"
3
3
  end
data/lib/sudo_rails.rb CHANGED
@@ -7,8 +7,15 @@ module SudoRails
7
7
  class << self
8
8
  include Styling
9
9
 
10
+ AVAILABLE_CALLBACKS = [
11
+ :invalid_sudo_session,
12
+ :new_sudo_session,
13
+ :invalid_confirmation
14
+ ]
15
+
10
16
  attr_accessor :enabled,
11
17
  :confirm_strategy,
18
+ :callbacks,
12
19
  :sudo_session_duration,
13
20
  :reset_pass_link,
14
21
  :layout,
@@ -24,7 +31,15 @@ module SudoRails
24
31
  strategy = confirm_strategy
25
32
  raise(ArgumentError, 'Please, provide an strategy via SudoRails.confirm_strategy') unless strategy
26
33
 
27
- strategy.call(context, password)
34
+ confirmed = strategy.call(context, password)
35
+
36
+ if confirmed
37
+ SudoRails.run_callback(:new_sudo_session, context)
38
+ else
39
+ SudoRails.run_callback(:invalid_confirmation, context)
40
+ end
41
+
42
+ confirmed
28
43
  end
29
44
 
30
45
  def valid_sudo_session?(started_at)
@@ -33,10 +48,23 @@ module SudoRails
33
48
 
34
49
  DateTime.parse(started_at) + sudo_session_duration > Time.zone.now
35
50
  end
51
+
52
+ def run_callback(type, context)
53
+ type = type.to_sym
54
+ if !AVAILABLE_CALLBACKS.include?(type)
55
+ raise(ArgumentError, "Please, provide a valid callback: #{AVAILABLE_CALLBACKS.to_sentence}")
56
+ end
57
+
58
+ callback = callbacks[type]
59
+ return unless callback
60
+
61
+ callback.call(context)
62
+ end
36
63
  end
37
64
 
38
65
  self.enabled = true
39
66
  self.sudo_session_duration = 30.minutes
67
+ self.callbacks = {}
40
68
  end
41
69
 
42
70
  require 'sudo_rails/integrations/devise' if defined?(Devise)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sudo_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - markets
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-04 00:00:00.000000000 Z
11
+ date: 2024-04-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails