diff --git a/app/controllers/api_keys_controller.rb b/app/controllers/api_keys_controller.rb index a9ca5a382..d00bff79c 100644 --- a/app/controllers/api_keys_controller.rb +++ b/app/controllers/api_keys_controller.rb @@ -1,4 +1,5 @@ class ApiKeysController < ApplicationController + before_action :requires_reauthentication respond_to :html, :json, :xml def new diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b3f45259c..5b36a3175 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -189,6 +189,15 @@ class ApplicationController < ActionController::Base params.fetch(PolicyFinder.new(record).param_key, {}) end + def requires_reauthentication + return if CurrentUser.user.is_anonymous? + + last_authenticated_at = session[:last_authenticated_at] + if last_authenticated_at.blank? || Time.parse(last_authenticated_at) < 60.minutes.ago + redirect_to confirm_password_session_path(url: request.fullpath) + end + end + # Remove blank `search` params from the url. # # /tags?search[name]=touhou&search[category]=&search[order]= diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index e95e76e2b..56d17a4e1 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -6,6 +6,9 @@ class SessionsController < ApplicationController @user = User.new end + def confirm_password + end + def create name, password, url = params.fetch(:session, params).slice(:name, :password, :url).values user = SessionLoader.new(request).login(name, password) diff --git a/app/logical/session_loader.rb b/app/logical/session_loader.rb index 57b27dcdc..8dd7eccdf 100644 --- a/app/logical/session_loader.rb +++ b/app/logical/session_loader.rb @@ -14,6 +14,7 @@ class SessionLoader if user.present? && user.authenticate_password(password) session[:user_id] = user.id + session[:last_authenticated_at] = Time.now.utc.to_s UserEvent.build_from_request(user, :login, request) user.last_logged_in_at = Time.now @@ -31,6 +32,7 @@ class SessionLoader def logout session.delete(:user_id) + session.delete(:last_authenticated_at) return if CurrentUser.user.is_anonymous? UserEvent.create_from_request!(CurrentUser.user, :logout, request) end diff --git a/app/views/sessions/confirm_password.html.erb b/app/views/sessions/confirm_password.html.erb new file mode 100644 index 000000000..afe67da10 --- /dev/null +++ b/app/views/sessions/confirm_password.html.erb @@ -0,0 +1,17 @@ +<% page_title "Confirm password" %> +<%= render "secondary_links" %> + +
You must re-enter your password to continue.
+ + <%= simple_form_for(:session, url: session_path) do |f| %> + <%= f.input :url, as: :hidden, input_html: { value: params[:url] } %> + <%= f.input :name, as: :hidden, input_html: { value: CurrentUser.user.name } %> + <%= f.input :password, hint: link_to("Forgot password?", password_reset_path), input_html: { autocomplete: "password" } %> + <%= f.submit "Continue" %> + <% end %> +