revise_auth 0.3.0 → 0.4.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: f5d5afd1201c6a751a50e0c153589fa552e949c45cad6da9f3147670e6aaf274
4
- data.tar.gz: 9d546d451af57bbc97d4e6dbae0dc83b00b6818fa14210f1a32735f79295686e
3
+ metadata.gz: 4877361ed28001b736c2e6387f0c65fa402229e47b08d34af1feb05ac3d6e8f8
4
+ data.tar.gz: 166a23ca4f1d792fa7af671bfcbc73bbb88cec68b611f1c1d9c17e84acd65940
5
5
  SHA512:
6
- metadata.gz: 39331cdedcd79bc56c9237436bbf844ea5b1b863242b3cf4b5935a48bc492e2ebfdc8d5e5bc987f92b22556f58558876e418e94c2850d1eb0be659e54067ec1e
7
- data.tar.gz: d1a39f4b6f81989be85657b540fcad3f0fbcb0a52ea3b184ea86263391ea204e192adf7038e164da190c03d6837da4c2ce8f3157779b6489cad65981e78f877f
6
+ metadata.gz: 891ca6da76f4a09caf6e169412a0c9a9cdc27ba6e641564a365bd8d2a623cf57cba9068fad9b4332424258f1cc95712139e7b9af242916718334782f4b8d5ae2
7
+ data.tar.gz: 81400af06d8b1845487acd05a293b1bf101eee6b21b1e1b6908befda918982c18a01df63c70ab96aabc9eebd24514471841741001bcb834445d9d8b9c56242e0
data/README.md CHANGED
@@ -41,6 +41,20 @@ $ rails g revise_auth:views
41
41
 
42
42
  This will copy the views into `app/views/revise_auth` in your application.
43
43
 
44
+ ### After Login Path
45
+
46
+ After a user logs in they will be redirected to the stashed location or the root path, by default. When a GET request hits `authenticate_user!`, it will stash the request path in the session and redirect back after login.
47
+
48
+ To override this, define `after_login_path` in your ApplicationController. You can also override `ReviseAuthController` and define it there.
49
+
50
+ ```ruby
51
+ class ApplicationController < ActionController::Base
52
+ def after_login_path
53
+ root_path
54
+ end
55
+ end
56
+ ```
57
+
44
58
  ## Contributing
45
59
 
46
60
  If you have an issue you'd like to submit, please do so using the issue tracker in GitHub. In order for us to help you in the best way possible, please be as detailed as you can.
@@ -1,24 +1,22 @@
1
1
  class ReviseAuth::PasswordController < ReviseAuthController
2
- before_action :validate_current_password, only: [:update]
2
+ before_action :authenticate_user!
3
3
 
4
4
  def update
5
5
  if current_user.update(password_params)
6
- flash[:notice] = I18n.t("revise_auth.password_changed")
6
+ redirect_to profile_path, notice: I18n.t("revise_auth.password_changed")
7
+ else
8
+ flash[:alert] = I18n.t("revise_auth.incorrect_password")
9
+ render "revise_auth/registrations/edit", status: :unprocessable_entity
7
10
  end
8
-
9
- redirect_to profile_path
10
11
  end
11
12
 
12
13
  private
13
14
 
14
15
  def password_params
15
- params.require(:user).permit(:password, :password_confirmation)
16
- end
17
-
18
- def validate_current_password
19
- unless current_user.authenticate(params[:current_password])
20
- flash[:alert] = I18n.t("revise_auth.incorrect_password")
21
- render "revise_auth/registrations/edit", status: :unprocessable_entity
22
- end
16
+ params.require(:user).permit(
17
+ :password,
18
+ :password_confirmation,
19
+ :password_challenge
20
+ ).with_defaults(password_challenge: "")
23
21
  end
24
22
  end
@@ -0,0 +1,48 @@
1
+ class ReviseAuth::PasswordResetsController < ReviseAuthController
2
+ before_action :set_user, only: [:edit, :update]
3
+
4
+ def new
5
+ @user = User.new
6
+ end
7
+
8
+ def create
9
+ if (user = User.find_by(email: user_params[:email]))
10
+ token = user.generate_token_for(:password_reset)
11
+ ReviseAuth::Mailer.with(user: user, token: token).password_reset.deliver_later
12
+ end
13
+
14
+ flash[:notice] = I18n.t("revise_auth.password_reset_sent")
15
+ redirect_to login_path
16
+ end
17
+
18
+ def edit
19
+ end
20
+
21
+ def update
22
+ if @user.update(password_params)
23
+ flash[:notice] = I18n.t("revise_auth.password_changed")
24
+ redirect_to login_path
25
+ else
26
+ render :edit, status: :unprocessable_entity
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def set_user
33
+ @user = User.find_by_token_for(:password_reset, params[:token])
34
+
35
+ return if @user.present?
36
+
37
+ flash[:alert] = I18n.t("revise_auth.password_link_invalid")
38
+ redirect_to new_password_reset_path
39
+ end
40
+
41
+ def user_params
42
+ params.require(:user).permit(:email)
43
+ end
44
+
45
+ def password_params
46
+ params.require(:user).permit(:password, :password_confirmation)
47
+ end
48
+ end
@@ -5,7 +5,7 @@ class ReviseAuth::SessionsController < ReviseAuthController
5
5
  def create
6
6
  if (user = User.authenticate_by(email: params[:email], password: params[:password]))
7
7
  login(user)
8
- redirect_to root_path
8
+ redirect_to resolve_after_login_path
9
9
  else
10
10
  flash[:alert] = I18n.t("revise_auth.invalid_email_or_password")
11
11
  render :new, status: :unprocessable_entity
@@ -16,4 +16,14 @@ class ReviseAuth::SessionsController < ReviseAuthController
16
16
  logout
17
17
  redirect_to root_path
18
18
  end
19
+
20
+ private
21
+
22
+ def resolve_after_login_path
23
+ try(:after_login_path) || return_to_location || root_path
24
+ end
25
+
26
+ def return_to_location
27
+ session.delete(:user_return_to)
28
+ end
19
29
  end
@@ -1,10 +1,2 @@
1
1
  class ReviseAuthController < ApplicationController
2
- # Return true if it's a revise_auth_controller. false to all controllers unless
3
- # the controllers defined inside revise_auth. Useful if you want to apply a before
4
- # filter to all controllers, except the ones in revise_auth:
5
- #
6
- # before_action :authenticate_user!, except: :revise_auth_controller?
7
- def revise_auth_controller?
8
- is_a?(::ReviseAuthController)
9
- end
10
2
  end
@@ -5,4 +5,11 @@ class ReviseAuth::Mailer < ApplicationMailer
5
5
 
6
6
  mail to: @user.unconfirmed_email
7
7
  end
8
+
9
+ def password_reset
10
+ @user = params[:user]
11
+ @token = params[:token]
12
+
13
+ mail to: @user.email
14
+ end
8
15
  end
@@ -0,0 +1,6 @@
1
+ <p>We've received a password reset request for your login. If this was you just visit the
2
+ the link below to finish up. If it wasn't you, you can simply ignore this email.</p>
3
+
4
+ <p><%= link_to "Reset my password", edit_password_reset_url(token: @token) %></p>
5
+
6
+ <p>This link will expire in 1 hour.</p>
@@ -0,0 +1,25 @@
1
+ <h1>Reset Your Password</h1>
2
+
3
+ <%= form_with model: @user, url: sign_up_path do |form| %>
4
+ <% if form.object.errors.any? %>
5
+ <ul>
6
+ <% form.object.errors.full_messages.each do |message| %>
7
+ <li><%= message %></li>
8
+ <% end %>
9
+ </ul>
10
+ <% end %>
11
+
12
+ <div>
13
+ <%= form.label :password %>
14
+ <%= form.password_field :password, required: true %>
15
+ </div>
16
+
17
+ <div>
18
+ <%= form.label :password_confirmation %>
19
+ <%= form.password_field :password_confirmation, required: true %>
20
+ </div>
21
+
22
+ <div>
23
+ <%= form.button "Reset password" %>
24
+ </div>
25
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <h1>Send Password Reset Instructions</h1>
2
+
3
+ <%= form_with model: @user, url: password_resets_path do |form| %>
4
+ <% if form.object.errors.any? %>
5
+ <ul>
6
+ <% form.object.errors.full_messages.each do |message| %>
7
+ <li><%= message %></li>
8
+ <% end %>
9
+ </ul>
10
+ <% end %>
11
+
12
+ <div>
13
+ <%= form.label :email %>
14
+ <%= form.email_field :email, required: true, autofocus: true %>
15
+ </div>
16
+
17
+ <div>
18
+ <%= form.button "Send Reset Instructions" %>
19
+ </div>
20
+ <% end %>
@@ -16,7 +16,7 @@
16
16
  </ul>
17
17
  <% end %>
18
18
 
19
- <p>Your email address is: <%= current_user.email %>
19
+ <p>Your email address is: <%= current_user.email %></p>
20
20
  <p>To change your email, we will send a confirmation email to your new address to complete the change.</p>
21
21
 
22
22
  <div>
@@ -43,8 +43,8 @@
43
43
  <% end %>
44
44
 
45
45
  <div>
46
- <%= label_tag :current_password %>
47
- <%= password_field_tag :current_password, nil, required: true %>
46
+ <%= form.label :password_challenge, "Current password" %>
47
+ <%= form.password_field :password_challenge, required: true %>
48
48
  </div>
49
49
 
50
50
  <div>
@@ -14,4 +14,8 @@
14
14
  <div>
15
15
  <%= form.button "Login" %>
16
16
  </div>
17
+
18
+ <div>
19
+ <%= link_to "Reset your password", new_password_reset_path %>
20
+ </div>
17
21
  <% end %>
@@ -9,6 +9,8 @@ en:
9
9
  # Password changes
10
10
  password_changed: "Your password has been changed successfully."
11
11
  incorrect_password: "Your current password is incorrect. Please try again."
12
+ password_link_invalid: "The provided password reset link is invalid."
13
+ password_reset_sent: "An email with password reset instructions has been sent if that account exists."
12
14
 
13
15
  # Email confirmations
14
16
  email_confirmed: "Your email address has been successfully confirmed."
@@ -0,0 +1,16 @@
1
+ pt:
2
+ revise_auth:
3
+ account_deleted: "A sua conta foi removida."
4
+ account_updated: "Conta atualizada com sucesso."
5
+
6
+ invalid_email_or_password: "Email ou password inválidos."
7
+ sign_up_or_login: "Registe-se ou clique em entrar para continuar."
8
+
9
+ # Password changes
10
+ password_changed: "A sua password foi alterada com sucesso."
11
+ incorrect_password: "A sua password atual está incorreta. Por favor tente de novo."
12
+
13
+ # Email confirmations
14
+ email_confirmed: "O seu endereço de email foi modificado com sucesso."
15
+ email_confirm_failed: "Não foi possível confirmar o endereço de email."
16
+ confirmation_email_sent: "Um email de confirmação foi enviado para %{email}"
@@ -22,7 +22,7 @@ module ReviseAuth
22
22
 
23
23
  # Authenticates a user or redirects to the login page
24
24
  def authenticate_user!
25
- redirect_to login_path, alert: I18n.t("revise_auth.sign_up_or_login") unless user_signed_in?
25
+ redirect_to_login_with_stashed_location unless user_signed_in?
26
26
  end
27
27
 
28
28
  # Authenticates the current user
@@ -40,17 +40,39 @@ module ReviseAuth
40
40
  end
41
41
 
42
42
  # Logs in the user
43
+ # - Reset the session to prevent session fixation
44
+ # See: https://guides.rubyonrails.org/security.html#session-fixation-countermeasures
43
45
  # - Set Current.user for the current request
44
46
  # - Save a session cookie so the next request is authenticated
45
47
  def login(user)
46
- Current.user = user
48
+ user_return_to = session[:user_return_to]
47
49
  reset_session
50
+ Current.user = user
48
51
  session[:user_id] = user.id
52
+ session[:user_return_to] = user_return_to
49
53
  end
50
54
 
51
55
  def logout
52
- Current.user = nil
53
56
  reset_session
57
+ Current.user = nil
58
+ end
59
+
60
+ def stash_return_to_location(path)
61
+ session[:user_return_to] = path
62
+ end
63
+
64
+ def redirect_to_login_with_stashed_location
65
+ stash_return_to_location(request.fullpath) if request.get?
66
+ redirect_to login_path, alert: I18n.t("revise_auth.sign_up_or_login")
67
+ end
68
+
69
+ # Return true if it's a revise_auth_controller. false to all controllers unless
70
+ # the controllers defined inside revise_auth. Useful if you want to apply a before
71
+ # filter to all controllers, except the ones in revise_auth:
72
+ #
73
+ # before_action :authenticate_user!, except: :revise_auth_controller?
74
+ def revise_auth_controller?
75
+ is_a?(::ReviseAuthController)
54
76
  end
55
77
  end
56
78
  end
@@ -4,22 +4,25 @@ module ReviseAuth
4
4
 
5
5
  included do |base|
6
6
  base.const_set :EMAIL_VERIFICATION_TOKEN_VALIDITY, 1.day
7
+ base.const_set :PASSWORD_RESET_TOKEN_VALIDITY, 1.hour
7
8
 
8
9
  has_secure_password
9
10
  has_secure_token :confirmation_token
10
11
 
12
+ generates_token_for :password_reset, expires_in: base.const_get(:PASSWORD_RESET_TOKEN_VALIDITY) do
13
+ BCrypt::Password.new(password_digest).salt[-10..]
14
+ end
15
+
11
16
  generates_token_for :email_verification, expires_in: base.const_get(:EMAIL_VERIFICATION_TOKEN_VALIDITY) do
12
17
  email
13
18
  end
14
19
 
20
+ normalizes :email, with: -> { _1.strip.downcase }
21
+ normalizes :unconfirmed_email, with: -> { _1.strip.downcase }
22
+
15
23
  validates :email, format: {with: URI::MailTo::EMAIL_REGEXP}, presence: true, uniqueness: true
16
24
  validates :unconfirmed_email, format: {with: URI::MailTo::EMAIL_REGEXP}, allow_blank: true
17
25
  validates_length_of :password, minimum: 12, allow_nil: true
18
-
19
- before_validation do
20
- email&.downcase!&.strip!
21
- unconfirmed_email&.downcase!
22
- end
23
26
  end
24
27
 
25
28
  # Generates a confirmation token and send email to the user
@@ -12,6 +12,8 @@ module ActionDispatch::Routing
12
12
  patch "profile/email", to: "email#update"
13
13
  patch "profile/password", to: "password#update"
14
14
 
15
+ resources :password_resets, param: :token, only: [:new, :create, :edit, :update]
16
+
15
17
  # Email confirmation
16
18
  get "profile/email", to: "email#show"
17
19
 
@@ -1,3 +1,3 @@
1
1
  module ReviseAuth
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: revise_auth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Oliver
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-13 00:00:00.000000000 Z
11
+ date: 2023-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -50,11 +50,15 @@ files:
50
50
  - Rakefile
51
51
  - app/controllers/revise_auth/email_controller.rb
52
52
  - app/controllers/revise_auth/password_controller.rb
53
+ - app/controllers/revise_auth/password_resets_controller.rb
53
54
  - app/controllers/revise_auth/registrations_controller.rb
54
55
  - app/controllers/revise_auth/sessions_controller.rb
55
56
  - app/controllers/revise_auth_controller.rb
56
57
  - app/mailers/revise_auth/mailer.rb
57
58
  - app/views/revise_auth/mailer/confirm_email.html.erb
59
+ - app/views/revise_auth/mailer/password_reset.html.erb
60
+ - app/views/revise_auth/password_resets/edit.html.erb
61
+ - app/views/revise_auth/password_resets/new.html.erb
58
62
  - app/views/revise_auth/registrations/edit.html.erb
59
63
  - app/views/revise_auth/registrations/new.html.erb
60
64
  - app/views/revise_auth/sessions/new.html.erb
@@ -63,6 +67,7 @@ files:
63
67
  - config/locales/en.yml
64
68
  - config/locales/fr.yml
65
69
  - config/locales/nl.yml
70
+ - config/locales/pt.yml
66
71
  - config/locales/tr.yml
67
72
  - config/locales/zh-TW.yml
68
73
  - lib/generators/revise_auth/model_generator.rb