sudo_rails 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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