diff --git a/.rubocop.yml b/.rubocop.yml index 1e18afd8358..729f32526c7 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -45,6 +45,10 @@ Naming/FileName: Naming/MethodParameterName: Enabled: false +# Not compatible with strong_migrations +Rails/BulkChangeTable: + Enabled: false + Rails/CreateTableWithTimestamps: Enabled: false diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index 87d25df6803..4f345c2b022 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,4 +1,4 @@ -class PasswordsController < ApplicationController +class PasswordsController < Devise::PasswordsController include SessionMethods layout "site" @@ -13,6 +13,8 @@ class PasswordsController < ApplicationController def new @title = t ".title" + + super end def edit @@ -32,26 +34,6 @@ def edit end end - def create - user = User.visible.find_by(:email => params[:email]) - - if user.nil? - users = User.visible.where("LOWER(email) = LOWER(?)", params[:email]) - - user = users.first if users.count == 1 - end - - if user - token = user.tokens.create - UserMailer.lost_password(user, token).deliver_later - flash[:notice] = t ".notice email on way" - redirect_to login_path - else - flash.now[:error] = t ".notice email cannot find" - render :new - end - end - def update if params[:token] token = UserToken.find_by(:token => params[:token]) @@ -82,4 +64,8 @@ def update head :bad_request end end + + def new_session_path(_) + new_user_session_path + end end diff --git a/app/models/user.rb b/app/models/user.rb index 7faf748cd8a..0bf827b7ee4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,50 +2,55 @@ # # Table name: users # -# email :string not null -# id :bigint(8) not null, primary key -# pass_crypt :string not null -# creation_time :datetime not null -# display_name :string default(""), not null -# data_public :boolean default(FALSE), not null -# description :text default(""), not null -# home_lat :float -# home_lon :float -# home_zoom :integer default(3) -# pass_salt :string -# email_valid :boolean default(FALSE), not null -# new_email :string -# creation_ip :string -# languages :string -# status :enum default("pending"), not null -# terms_agreed :datetime -# consider_pd :boolean default(FALSE), not null -# auth_uid :string -# preferred_editor :string -# terms_seen :boolean default(FALSE), not null -# description_format :enum default("markdown"), not null -# changesets_count :integer default(0), not null -# traces_count :integer default(0), not null -# diary_entries_count :integer default(0), not null -# image_use_gravatar :boolean default(FALSE), not null -# auth_provider :string -# home_tile :bigint(8) -# tou_agreed :datetime +# email :string not null +# id :bigint(8) not null, primary key +# pass_crypt :string not null +# creation_time :datetime not null +# display_name :string default(""), not null +# data_public :boolean default(FALSE), not null +# description :text default(""), not null +# home_lat :float +# home_lon :float +# home_zoom :integer default(3) +# pass_salt :string +# email_valid :boolean default(FALSE), not null +# new_email :string +# creation_ip :string +# languages :string +# status :enum default("pending"), not null +# terms_agreed :datetime +# consider_pd :boolean default(FALSE), not null +# auth_uid :string +# preferred_editor :string +# terms_seen :boolean default(FALSE), not null +# description_format :enum default("markdown"), not null +# changesets_count :integer default(0), not null +# traces_count :integer default(0), not null +# diary_entries_count :integer default(0), not null +# image_use_gravatar :boolean default(FALSE), not null +# auth_provider :string +# home_tile :bigint(8) +# tou_agreed :datetime +# reset_password_token :string +# reset_password_sent_at :datetime # # Indexes # -# users_auth_idx (auth_provider,auth_uid) UNIQUE -# users_display_name_canonical_idx (lower(NORMALIZE(display_name, NFKC))) -# users_display_name_idx (display_name) UNIQUE -# users_email_idx (email) UNIQUE -# users_email_lower_idx (lower((email)::text)) -# users_home_idx (home_tile) +# index_users_on_reset_password_token (reset_password_token) UNIQUE +# users_auth_idx (auth_provider,auth_uid) UNIQUE +# users_display_name_canonical_idx (lower(NORMALIZE(display_name, NFKC))) +# users_display_name_idx (display_name) UNIQUE +# users_email_idx (email) UNIQUE +# users_email_lower_idx (lower((email)::text)) +# users_home_idx (home_tile) # class User < ApplicationRecord require "digest" include AASM + devise :recoverable + has_many :traces, -> { where(:visible => true) } has_many :diary_entries, -> { order(:created_at => :desc) }, :inverse_of => :user has_many :diary_comments, -> { order(:created_at => :desc) }, :inverse_of => :user diff --git a/app/views/passwords/new.html.erb b/app/views/passwords/new.html.erb index dfcaf32bef6..829f3d814bc 100644 --- a/app/views/passwords/new.html.erb +++ b/app/views/passwords/new.html.erb @@ -4,7 +4,8 @@
<%= t ".help_text" %>
-<%= bootstrap_form_tag do |f| %> +<%= bootstrap_form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %> + <%= render "devise/shared/error_messages", :resource => resource %> <%= f.text_field :email, :label => t(".email address") %> <%= f.primary t(".new password button") %> <% end %> diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index f15430efa55..80832141e59 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -13,7 +13,7 @@ <%= hidden_field_tag("referer", h(params[:referer]), :autocomplete => "off") %> <%= f.text_field :username, :label => t(".email or username"), :tabindex => 1, :value => params[:username] %> - <%= f.password_field :password, :label => t(".password"), :tabindex => 2, :value => "", :help => link_to(t(".lost password link"), user_forgot_password_path) %> + <%= f.password_field :password, :label => t(".password"), :tabindex => 2, :value => "", :help => link_to(t(".lost password link"), new_user_password_path) %> <%= f.form_group do %> <%= f.check_box :remember_me, { :label => t(".remember"), :tabindex => 3, :checked => (params[:remember_me] == "yes") }, "yes" %> <% end %> diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index d199d332231..4eaaead1304 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -30,7 +30,7 @@ # config.mailer = 'Devise::Mailer' # Configure the parent class responsible to send e-mails. - # config.parent_mailer = 'ActionMailer::Base' + config.parent_mailer = "ApplicationMailer" # ==> ORM configuration # Load and configure the ORM. Supports :active_record (default) and diff --git a/config/routes.rb b/config/routes.rb index 09afe8fd928..165abb6eb0e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -159,7 +159,7 @@ get "/history/feed" => "changesets#feed", :defaults => { :format => :atom } get "/history/comments/feed" => "changeset_comments#index", :as => :changesets_comments_feed, :defaults => { :format => "rss" } get "/export" => "site#export" - get "/login" => "sessions#new" + get "/login" => "sessions#new", :as => :new_user_session post "/login" => "sessions#create" match "/logout" => "sessions#destroy", :via => [:get, :post] get "/offline" => "site#offline" @@ -175,12 +175,9 @@ match "/user/confirm" => "confirmations#confirm", :via => [:get, :post] match "/user/confirm-email" => "confirmations#confirm_email", :via => [:get, :post] post "/user/go_public" => "users#go_public" - scope :user, :as => "user" do - get "forgot-password" => "passwords#new" - post "forgot-password" => "passwords#create" - get "reset-password" => "passwords#edit" - post "reset-password" => "passwords#update" - end + + devise_for :users, :only => :passwords, :controllers => { :passwords => "passwords" } + get "/user/suspended" => "users#suspended" get "/index.html", :to => redirect(:path => "/") diff --git a/db/migrate/20231213113946_add_devise_passwords_to_users.rb b/db/migrate/20231213113946_add_devise_passwords_to_users.rb new file mode 100644 index 00000000000..84564cbc6fc --- /dev/null +++ b/db/migrate/20231213113946_add_devise_passwords_to_users.rb @@ -0,0 +1,6 @@ +class AddDevisePasswordsToUsers < ActiveRecord::Migration[7.1] + def change + add_column :users, :reset_password_token, :string + add_column :users, :reset_password_sent_at, :datetime + end +end diff --git a/db/migrate/20231213135917_add_index_to_users_reset_password_token.rb b/db/migrate/20231213135917_add_index_to_users_reset_password_token.rb new file mode 100644 index 00000000000..af5cacaa370 --- /dev/null +++ b/db/migrate/20231213135917_add_index_to_users_reset_password_token.rb @@ -0,0 +1,7 @@ +class AddIndexToUsersResetPasswordToken < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + + def change + add_index :users, :reset_password_token, :unique => true, :algorithm => :concurrently + end +end diff --git a/db/structure.sql b/db/structure.sql index 4998bc694a1..e20c8dcc289 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1597,7 +1597,9 @@ CREATE TABLE public.users ( image_use_gravatar boolean DEFAULT false NOT NULL, auth_provider character varying, home_tile bigint, - tou_agreed timestamp without time zone + tou_agreed timestamp without time zone, + reset_password_token character varying, + reset_password_sent_at timestamp(6) without time zone ); @@ -3583,6 +3585,8 @@ INSERT INTO "schema_migrations" (version) VALUES ('21'), ('20240117185445'), ('20231213182102'), +('20231213135917'), +('20231213113946'), ('20231206141457'), ('20231117170422'), ('20231101222146'),