From fc198a8b4ca6d22eaedee2cfb03e088432dc4b30 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 3 Oct 2016 16:38:22 +0200 Subject: [PATCH] Adding e-mail confirmations --- app/assets/stylesheets/application.scss | 8 ++++++ app/controllers/application_controller.rb | 2 +- .../auth/confirmations_controller.rb | 3 +++ app/controllers/auth/sessions_controller.rb | 8 +++++- app/models/user.rb | 2 +- app/views/auth/confirmations/new.html.haml | 9 +++++++ .../mailer/confirmation_instructions.html.erb | 5 ++++ app/views/auth/passwords/edit.html.erb | 25 ------------------- app/views/auth/passwords/edit.html.haml | 12 +++++++++ app/views/auth/shared/_links.html.haml | 4 --- app/views/layouts/auth.html.haml | 6 +++++ config/routes.rb | 3 ++- ...20161003142332_add_confirmable_to_users.rb | 9 +++++++ db/schema.rb | 7 +++++- spec/fabricators/user_fabricator.rb | 5 ++-- 15 files changed, 72 insertions(+), 36 deletions(-) create mode 100644 app/controllers/auth/confirmations_controller.rb create mode 100644 app/views/auth/confirmations/new.html.haml create mode 100644 app/views/auth/mailer/confirmation_instructions.html.erb delete mode 100644 app/views/auth/passwords/edit.html.erb create mode 100644 app/views/auth/passwords/edit.html.haml create mode 100644 db/migrate/20161003142332_add_confirmable_to_users.rb diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index e6ae1d915d..8c90eb065a 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -104,6 +104,7 @@ body { .logo-container { max-width: 400px; margin: 100px auto; + margin-bottom: 0; cursor: default; @media screen and (max-width: 360px) { @@ -276,6 +277,13 @@ body { } } + .flash-message { + text-align: center; + font-size: 14px; + margin-bottom: 30px; + font-weight: 500; + } + .form-footer { margin-top: 30px; text-align: center; diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 91904ecf07..cd4b686f71 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,7 +10,7 @@ class ApplicationController < ActionController::Base rescue_from ActionController::RoutingError, with: :not_found rescue_from ActiveRecord::RecordNotFound, with: :not_found - before_filter :store_current_location, :unless => :devise_controller? + before_action :store_current_location, :unless => :devise_controller? def raise_not_found raise ActionController::RoutingError, "No route matches #{params[:unmatched_route]}" diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb new file mode 100644 index 0000000000..b8e9316f10 --- /dev/null +++ b/app/controllers/auth/confirmations_controller.rb @@ -0,0 +1,3 @@ +class Auth::ConfirmationsController < Devise::ConfirmationsController + layout 'auth' +end diff --git a/app/controllers/auth/sessions_controller.rb b/app/controllers/auth/sessions_controller.rb index e50a9835c8..bd41ffd3d8 100644 --- a/app/controllers/auth/sessions_controller.rb +++ b/app/controllers/auth/sessions_controller.rb @@ -12,6 +12,12 @@ class Auth::SessionsController < Devise::SessionsController protected def after_sign_in_path_for(_resource) - stored_location_for(:user) || root_path + last_url = stored_location_for(:user) + + if [about_path].include?(last_url) + root_path + else + last_url || root_path + end end end diff --git a/app/models/user.rb b/app/models/user.rb index da096d6e9b..c1243e9acc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,5 @@ class User < ApplicationRecord - devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable + devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable belongs_to :account, inverse_of: :user accepts_nested_attributes_for :account diff --git a/app/views/auth/confirmations/new.html.haml b/app/views/auth/confirmations/new.html.haml new file mode 100644 index 0000000000..5c1cf5734f --- /dev/null +++ b/app/views/auth/confirmations/new.html.haml @@ -0,0 +1,9 @@ += form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| + = devise_error_messages! + + .field + = f.email_field :email, autofocus: true, required: true, placeholder: 'E-mail address' + .actions + = f.button "Resend confirmation instructions", type: 'submit' + +.form-footer= render "auth/shared/links" diff --git a/app/views/auth/mailer/confirmation_instructions.html.erb b/app/views/auth/mailer/confirmation_instructions.html.erb new file mode 100644 index 0000000000..ef17b288f9 --- /dev/null +++ b/app/views/auth/mailer/confirmation_instructions.html.erb @@ -0,0 +1,5 @@ +

Welcome <%= @resource.email %>!

+ +

You can confirm your account email through the link below:

+ +

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

diff --git a/app/views/auth/passwords/edit.html.erb b/app/views/auth/passwords/edit.html.erb deleted file mode 100644 index 6a796b050e..0000000000 --- a/app/views/auth/passwords/edit.html.erb +++ /dev/null @@ -1,25 +0,0 @@ -

Change your password

- -<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> - <%= devise_error_messages! %> - <%= f.hidden_field :reset_password_token %> - -
- <%= f.label :password, "New password" %>
- <% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum)
- <% end %> - <%= f.password_field :password, autofocus: true, autocomplete: "off" %> -
- -
- <%= f.label :password_confirmation, "Confirm new password" %>
- <%= f.password_field :password_confirmation, autocomplete: "off" %> -
- -
- <%= f.submit "Change my password" %> -
-<% end %> - -<%= render "devise/shared/links" %> diff --git a/app/views/auth/passwords/edit.html.haml b/app/views/auth/passwords/edit.html.haml new file mode 100644 index 0000000000..0d5f0fe10c --- /dev/null +++ b/app/views/auth/passwords/edit.html.haml @@ -0,0 +1,12 @@ += form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| + = devise_error_messages! + = f.hidden_field :reset_password_token + + .field + = f.password_field :password, autofocus: true, autocomplete: "off", placeholder: 'New password' + .field + = f.password_field :password_confirmation, autocomplete: "off", placeholder: 'Confirm new password' + .actions + = f.button "Change my password", type: :submit + += render "devise/shared/links" diff --git a/app/views/auth/shared/_links.html.haml b/app/views/auth/shared/_links.html.haml index 6f89eed759..d24c7d98fa 100644 --- a/app/views/auth/shared/_links.html.haml +++ b/app/views/auth/shared/_links.html.haml @@ -13,7 +13,3 @@ - if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %li= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) - - - if devise_mapping.omniauthable? - - resource_class.omniauth_providers.each do |provider| - %li= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) diff --git a/app/views/layouts/auth.html.haml b/app/views/layouts/auth.html.haml index 54aa07e2cd..52d567280b 100644 --- a/app/views/layouts/auth.html.haml +++ b/app/views/layouts/auth.html.haml @@ -7,6 +7,12 @@ %small= Rails.configuration.x.local_domain .form-container + - if flash[:notice] + .flash-message.notice= flash[:notice] + + - if flash[:alert] + .flash-message.alert= flash[:alert] + = yield = render template: "layouts/application" diff --git a/config/routes.rb b/config/routes.rb index 7712944532..ec151137ee 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,7 +15,8 @@ Rails.application.routes.draw do devise_for :users, path: 'auth', controllers: { sessions: 'auth/sessions', registrations: 'auth/registrations', - passwords: 'auth/passwords' + passwords: 'auth/passwords', + confirmations: 'auth/confirmations' } resources :accounts, path: 'users', only: [:show], param: :username do diff --git a/db/migrate/20161003142332_add_confirmable_to_users.rb b/db/migrate/20161003142332_add_confirmable_to_users.rb new file mode 100644 index 0000000000..cbef4c4df2 --- /dev/null +++ b/db/migrate/20161003142332_add_confirmable_to_users.rb @@ -0,0 +1,9 @@ +class AddConfirmableToUsers < ActiveRecord::Migration[5.0] + def change + add_column :users, :confirmation_token, :string + add_column :users, :confirmed_at, :datetime + add_column :users, :confirmation_sent_at, :datetime + add_column :users, :unconfirmed_email, :string + add_index :users, :confirmation_token, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index f0d7cf5d34..f835c21b8d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160926213048) do +ActiveRecord::Schema.define(version: 20161003142332) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -158,7 +158,12 @@ ActiveRecord::Schema.define(version: 20160926213048) do t.inet "current_sign_in_ip" t.inet "last_sign_in_ip" t.boolean "admin", default: false + t.string "confirmation_token" + t.datetime "confirmed_at" + t.datetime "confirmation_sent_at" + t.string "unconfirmed_email" t.index ["account_id"], name: "index_users_on_account_id", using: :btree + t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree t.index ["email"], name: "index_users_on_email", unique: true, using: :btree t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree end diff --git a/spec/fabricators/user_fabricator.rb b/spec/fabricators/user_fabricator.rb index 87d86b4285..c08559137f 100644 --- a/spec/fabricators/user_fabricator.rb +++ b/spec/fabricators/user_fabricator.rb @@ -1,5 +1,6 @@ Fabricator(:user) do account - email "alice@example.com" - password "123456789" + email "alice@example.com" + password "123456789" + confirmed_at { Time.now } end