From 53819e683957c3c69873c4c22d4d21f512b3491e Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sat, 20 Mar 2021 14:23:06 +0100 Subject: [PATCH 01/23] user and session generated --- app/assets/stylesheets/sessions.scss | 3 +++ app/assets/stylesheets/users.scss | 3 +++ app/controllers/sessions_controller.rb | 10 ++++++++++ app/controllers/users_controller.rb | 10 ++++++++++ app/helpers/sessions_helper.rb | 2 ++ app/helpers/users_helper.rb | 2 ++ app/models/user.rb | 3 +++ app/views/sessions/create.html.erb | 2 ++ app/views/sessions/new.html.erb | 2 ++ app/views/sessions/welcome.html.erb | 3 +++ app/views/users/create.html.erb | 2 ++ app/views/users/new.html.erb | 8 ++++++++ config/routes.rb | 4 ++++ db/migrate/20210320130542_create_users.rb | 10 ++++++++++ test/controllers/sessions_controller_test.rb | 18 ++++++++++++++++++ test/controllers/users_controller_test.rb | 13 +++++++++++++ test/fixtures/users.yml | 9 +++++++++ test/models/user_test.rb | 7 +++++++ 18 files changed, 111 insertions(+) create mode 100644 app/assets/stylesheets/sessions.scss create mode 100644 app/assets/stylesheets/users.scss create mode 100644 app/controllers/sessions_controller.rb create mode 100644 app/controllers/users_controller.rb create mode 100644 app/helpers/sessions_helper.rb create mode 100644 app/helpers/users_helper.rb create mode 100644 app/models/user.rb create mode 100644 app/views/sessions/create.html.erb create mode 100644 app/views/sessions/new.html.erb create mode 100644 app/views/sessions/welcome.html.erb create mode 100644 app/views/users/create.html.erb create mode 100644 app/views/users/new.html.erb create mode 100644 db/migrate/20210320130542_create_users.rb create mode 100644 test/controllers/sessions_controller_test.rb create mode 100644 test/controllers/users_controller_test.rb create mode 100644 test/fixtures/users.yml create mode 100644 test/models/user_test.rb diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000..f986bd4 --- /dev/null +++ b/app/assets/stylesheets/sessions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sessions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: https://sass-lang.com/ diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss new file mode 100644 index 0000000..aaf17f7 --- /dev/null +++ b/app/assets/stylesheets/users.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the users controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: https://sass-lang.com/ diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000..710db28 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,10 @@ +class SessionsController < ApplicationController + def new + end + + def create + end + + def welcome + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000..0d7fd54 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,10 @@ +class UsersController < ApplicationController + def new + end + + def create + @user = User.create(params.require(:user).permit(:username, :password)) + session[:user_id] = @user.id + redirect_to '/welcome' + end +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb new file mode 100644 index 0000000..309f8b2 --- /dev/null +++ b/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb new file mode 100644 index 0000000..2310a24 --- /dev/null +++ b/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..d67da20 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,3 @@ +class User < ApplicationRecord + has_secure_password +end diff --git a/app/views/sessions/create.html.erb b/app/views/sessions/create.html.erb new file mode 100644 index 0000000..c251174 --- /dev/null +++ b/app/views/sessions/create.html.erb @@ -0,0 +1,2 @@ +

Sessions#create

+

Find me in app/views/sessions/create.html.erb

diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb new file mode 100644 index 0000000..b39a3bc --- /dev/null +++ b/app/views/sessions/new.html.erb @@ -0,0 +1,2 @@ +

Sessions#new

+

Find me in app/views/sessions/new.html.erb

diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb new file mode 100644 index 0000000..c63e0c1 --- /dev/null +++ b/app/views/sessions/welcome.html.erb @@ -0,0 +1,3 @@ +

Welcome

+<%= button_to "Login", '/login', method: :get%> +<%= button_to "Sign Up", '/users/new', method: :get%> \ No newline at end of file diff --git a/app/views/users/create.html.erb b/app/views/users/create.html.erb new file mode 100644 index 0000000..48ea02e --- /dev/null +++ b/app/views/users/create.html.erb @@ -0,0 +1,2 @@ +

Users#create

+

Find me in app/views/users/create.html.erb

diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb new file mode 100644 index 0000000..ac34536 --- /dev/null +++ b/app/views/users/new.html.erb @@ -0,0 +1,8 @@ +

Sign Up

+<%= form_for @user do |f|%> + <%= f.label :username%>
+ <%= f.text_field :username%>
+ <%= f.label :password%>
+ <%= f.password_field :password%>
+ <%= f.submit %> +<%end%> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index af3f220..4e90759 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,7 @@ Rails.application.routes.draw do + resources :users, only: [:new, :create] + get 'login', to: 'sessions#new' + post 'login', to: 'sessions#create' + get 'welcome', to: 'sessions#welcome' resources :books end diff --git a/db/migrate/20210320130542_create_users.rb b/db/migrate/20210320130542_create_users.rb new file mode 100644 index 0000000..1fe81e6 --- /dev/null +++ b/db/migrate/20210320130542_create_users.rb @@ -0,0 +1,10 @@ +class CreateUsers < ActiveRecord::Migration[6.1] + def change + create_table :users do |t| + t.string :username + t.string :password_digest + + t.timestamps + end + end +end diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 0000000..d8e9bf6 --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,18 @@ +require "test_helper" + +class SessionsControllerTest < ActionDispatch::IntegrationTest + test "should get new" do + get sessions_new_url + assert_response :success + end + + test "should get create" do + get sessions_create_url + assert_response :success + end + + test "should get welcome" do + get sessions_welcome_url + assert_response :success + end +end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb new file mode 100644 index 0000000..c6a205d --- /dev/null +++ b/test/controllers/users_controller_test.rb @@ -0,0 +1,13 @@ +require "test_helper" + +class UsersControllerTest < ActionDispatch::IntegrationTest + test "should get new" do + get users_new_url + assert_response :success + end + + test "should get create" do + get users_create_url + assert_response :success + end +end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000..d34cad0 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,9 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + username: MyString + password_digest: MyString + +two: + username: MyString + password_digest: MyString diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 0000000..5c07f49 --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 0b2bd70f16d2a18aedbd8f98a2e0904cf33eded1 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sat, 20 Mar 2021 17:08:11 +0100 Subject: [PATCH 02/23] rspec installed, first tests --- .rspec | 1 + Gemfile | 5 +- Gemfile.lock | 31 ++++++ db/schema.rb | 9 +- spec/controllers/sessions_controller_spec.rb | 18 ++++ spec/controllers/users_controller_spec.rb | 12 +++ spec/rails_helper.rb | 64 +++++++++++++ spec/spec_helper.rb | 96 +++++++++++++++++++ test/application_system_test_case.rb | 5 - .../application_cable/connection_test.rb | 11 --- test/controllers/.keep | 0 test/controllers/books_controller_test.rb | 7 -- test/controllers/sessions_controller_test.rb | 18 ---- test/controllers/users_controller_test.rb | 13 --- test/fixtures/authors.yml | 11 --- test/fixtures/book_authors.yml | 11 --- test/fixtures/books.yml | 11 --- test/fixtures/files/.keep | 0 test/fixtures/users.yml | 9 -- test/helpers/.keep | 0 test/integration/.keep | 0 test/mailers/.keep | 0 test/models/.keep | 0 test/models/author_test.rb | 7 -- test/models/book_author_test.rb | 7 -- test/models/book_test.rb | 7 -- test/models/user_test.rb | 7 -- test/system/.keep | 0 test/test_helper.rb | 13 --- 29 files changed, 234 insertions(+), 139 deletions(-) create mode 100644 .rspec create mode 100644 spec/controllers/sessions_controller_spec.rb create mode 100644 spec/controllers/users_controller_spec.rb create mode 100644 spec/rails_helper.rb create mode 100644 spec/spec_helper.rb delete mode 100644 test/application_system_test_case.rb delete mode 100644 test/channels/application_cable/connection_test.rb delete mode 100644 test/controllers/.keep delete mode 100644 test/controllers/books_controller_test.rb delete mode 100644 test/controllers/sessions_controller_test.rb delete mode 100644 test/controllers/users_controller_test.rb delete mode 100644 test/fixtures/authors.yml delete mode 100644 test/fixtures/book_authors.yml delete mode 100644 test/fixtures/books.yml delete mode 100644 test/fixtures/files/.keep delete mode 100644 test/fixtures/users.yml delete mode 100644 test/helpers/.keep delete mode 100644 test/integration/.keep delete mode 100644 test/mailers/.keep delete mode 100644 test/models/.keep delete mode 100644 test/models/author_test.rb delete mode 100644 test/models/book_author_test.rb delete mode 100644 test/models/book_test.rb delete mode 100644 test/models/user_test.rb delete mode 100644 test/system/.keep delete mode 100644 test/test_helper.rb diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/Gemfile b/Gemfile index 8947f2e..3d49e52 100644 --- a/Gemfile +++ b/Gemfile @@ -20,7 +20,7 @@ gem 'jbuilder', '~> 2.7' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use Active Model has_secure_password -# gem 'bcrypt', '~> 3.1.7' +gem 'bcrypt', '~> 3.1.7' gem 'materialize-sass', '~> 1.0.0' @@ -33,6 +33,9 @@ gem 'bootsnap', '>= 1.4.4', require: false group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] + gem 'rspec' + gem 'rspec-rails', ">= 2.0.0.beta" + gem 'rails-controller-testing' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 2ada529..671f766 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -64,6 +64,7 @@ GEM public_suffix (>= 2.0.2, < 5.0) autoprefixer-rails (10.2.4.0) execjs + bcrypt (3.1.16) bindex (0.8.1) bootsnap (1.7.2) msgpack (~> 1.0) @@ -80,6 +81,7 @@ GEM childprocess (3.0.0) concurrent-ruby (1.1.8) crass (1.0.6) + diff-lcs (1.4.4) erubi (1.10.0) execjs (2.7.0) ffi (1.15.0) @@ -137,6 +139,10 @@ GEM bundler (>= 1.15.0) railties (= 6.1.3) sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) @@ -153,6 +159,27 @@ GEM rb-inotify (0.10.1) ffi (~> 1.0) regexp_parser (2.1.1) + rspec (3.10.0) + rspec-core (~> 3.10.0) + rspec-expectations (~> 3.10.0) + rspec-mocks (~> 3.10.0) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.2) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.10.0) + rspec-rails (5.0.1) + actionpack (>= 5.2) + activesupport (>= 5.2) + railties (>= 5.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.10.2) rubyzip (2.3.0) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) @@ -209,6 +236,7 @@ PLATFORMS ruby DEPENDENCIES + bcrypt (~> 3.1.7) bootsnap (>= 1.4.4) byebug capybara (>= 3.26) @@ -218,6 +246,9 @@ DEPENDENCIES puma (~> 5.0) rack-mini-profiler (~> 2.0) rails (~> 6.1.3) + rails-controller-testing + rspec + rspec-rails (>= 2.0.0.beta) sass-rails (>= 6) selenium-webdriver spring diff --git a/db/schema.rb b/db/schema.rb index f539461..f541248 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: 2021_03_19_142059) do +ActiveRecord::Schema.define(version: 2021_03_20_130542) do create_table "authors", force: :cascade do |t| t.string "first_name" @@ -38,4 +38,11 @@ ActiveRecord::Schema.define(version: 2021_03_19_142059) do t.index ["published"], name: "index_books_on_published" end + create_table "users", force: :cascade do |t| + t.string "username" + t.string "password_digest" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb new file mode 100644 index 0000000..3a5b173 --- /dev/null +++ b/spec/controllers/sessions_controller_spec.rb @@ -0,0 +1,18 @@ +require 'rails_helper' + +RSpec.describe SessionsController do + describe 'get new' do + subject { get 'new' } + it 'renders the sessions/new template' do + expect(subject).to render_template('sessions/new') + end + end + describe 'get create' do + end + describe 'get welcome' do + subject { get 'welcome' } + it 'renders the sessions/welcome template' do + expect(subject).to render_template('sessions/welcome') + end + end +end \ No newline at end of file diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb new file mode 100644 index 0000000..56f7616 --- /dev/null +++ b/spec/controllers/users_controller_spec.rb @@ -0,0 +1,12 @@ +require 'rails_helper' + +RSpec.describe UsersController do + describe 'get new' do + subject { get 'new' } + it 'renders the users/new template' do + expect(subject).to render_template('users/new') + end + end + describe 'get create' do + end +end \ No newline at end of file diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb new file mode 100644 index 0000000..00345af --- /dev/null +++ b/spec/rails_helper.rb @@ -0,0 +1,64 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +require 'spec_helper' +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../config/environment', __dir__) +# Prevent database truncation if the environment is production +abort("The Rails environment is running in production mode!") if Rails.env.production? +require 'rspec/rails' +# Add additional requires below this line. Rails is not loaded until this point! + +# Requires supporting ruby files with custom matchers and macros, etc, in +# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are +# run as spec files by default. This means that files in spec/support that end +# in _spec.rb will both be required and run as specs, causing the specs to be +# run twice. It is recommended that you do not name files matching this glob to +# end with _spec.rb. You can configure this pattern with the --pattern +# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. +# +# The following line is provided for convenience purposes. It has the downside +# of increasing the boot-up time by auto-requiring all files in the support +# directory. Alternatively, in the individual `*_spec.rb` files, manually +# require only the support files necessary. +# +# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } + +# Checks for pending migrations and applies them before tests are run. +# If you are not using ActiveRecord, you can remove these lines. +begin + ActiveRecord::Migration.maintain_test_schema! +rescue ActiveRecord::PendingMigrationError => e + puts e.to_s.strip + exit 1 +end +RSpec.configure do |config| + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # You can uncomment this line to turn off ActiveRecord support entirely. + # config.use_active_record = false + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, type: :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! + + # Filter lines from Rails gems in backtraces. + config.filter_rails_from_backtrace! + # arbitrary gems may also be filtered via: + # config.filter_gems_from_backtrace("gem name") +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..ce33d66 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,96 @@ +# This file was generated by the `rails generate rspec:install` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + config.disable_monkey_patching! + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb deleted file mode 100644 index d19212a..0000000 --- a/test/application_system_test_case.rb +++ /dev/null @@ -1,5 +0,0 @@ -require "test_helper" - -class ApplicationSystemTestCase < ActionDispatch::SystemTestCase - driven_by :selenium, using: :chrome, screen_size: [1400, 1400] -end diff --git a/test/channels/application_cable/connection_test.rb b/test/channels/application_cable/connection_test.rb deleted file mode 100644 index 800405f..0000000 --- a/test/channels/application_cable/connection_test.rb +++ /dev/null @@ -1,11 +0,0 @@ -require "test_helper" - -class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase - # test "connects with cookies" do - # cookies.signed[:user_id] = 42 - # - # connect - # - # assert_equal connection.user_id, "42" - # end -end diff --git a/test/controllers/.keep b/test/controllers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/controllers/books_controller_test.rb b/test/controllers/books_controller_test.rb deleted file mode 100644 index 3927d43..0000000 --- a/test/controllers/books_controller_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -class BooksControllerTest < ActionDispatch::IntegrationTest - # test "the truth" do - # assert true - # end -end diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb deleted file mode 100644 index d8e9bf6..0000000 --- a/test/controllers/sessions_controller_test.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "test_helper" - -class SessionsControllerTest < ActionDispatch::IntegrationTest - test "should get new" do - get sessions_new_url - assert_response :success - end - - test "should get create" do - get sessions_create_url - assert_response :success - end - - test "should get welcome" do - get sessions_welcome_url - assert_response :success - end -end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb deleted file mode 100644 index c6a205d..0000000 --- a/test/controllers/users_controller_test.rb +++ /dev/null @@ -1,13 +0,0 @@ -require "test_helper" - -class UsersControllerTest < ActionDispatch::IntegrationTest - test "should get new" do - get users_new_url - assert_response :success - end - - test "should get create" do - get users_create_url - assert_response :success - end -end diff --git a/test/fixtures/authors.yml b/test/fixtures/authors.yml deleted file mode 100644 index 5181636..0000000 --- a/test/fixtures/authors.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -# This model initially had no columns defined. If you add columns to the -# model remove the '{}' from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value diff --git a/test/fixtures/book_authors.yml b/test/fixtures/book_authors.yml deleted file mode 100644 index 5181636..0000000 --- a/test/fixtures/book_authors.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -# This model initially had no columns defined. If you add columns to the -# model remove the '{}' from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value diff --git a/test/fixtures/books.yml b/test/fixtures/books.yml deleted file mode 100644 index 5181636..0000000 --- a/test/fixtures/books.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -# This model initially had no columns defined. If you add columns to the -# model remove the '{}' from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml deleted file mode 100644 index d34cad0..0000000 --- a/test/fixtures/users.yml +++ /dev/null @@ -1,9 +0,0 @@ -# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -one: - username: MyString - password_digest: MyString - -two: - username: MyString - password_digest: MyString diff --git a/test/helpers/.keep b/test/helpers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/integration/.keep b/test/integration/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/mailers/.keep b/test/mailers/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/models/.keep b/test/models/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/models/author_test.rb b/test/models/author_test.rb deleted file mode 100644 index b2d7df1..0000000 --- a/test/models/author_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -class AuthorTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/test/models/book_author_test.rb b/test/models/book_author_test.rb deleted file mode 100644 index b308c05..0000000 --- a/test/models/book_author_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -class BookAuthorTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/test/models/book_test.rb b/test/models/book_test.rb deleted file mode 100644 index 69ab9de..0000000 --- a/test/models/book_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -class BookTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/test/models/user_test.rb b/test/models/user_test.rb deleted file mode 100644 index 5c07f49..0000000 --- a/test/models/user_test.rb +++ /dev/null @@ -1,7 +0,0 @@ -require "test_helper" - -class UserTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end -end diff --git a/test/system/.keep b/test/system/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/test/test_helper.rb b/test/test_helper.rb deleted file mode 100644 index 47b598d..0000000 --- a/test/test_helper.rb +++ /dev/null @@ -1,13 +0,0 @@ -ENV['RAILS_ENV'] ||= 'test' -require_relative "../config/environment" -require "rails/test_help" - -class ActiveSupport::TestCase - # Run tests in parallel with specified workers - parallelize(workers: :number_of_processors) - - # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. - fixtures :all - - # Add more helper methods to be used by all tests here... -end From f8093d2c09a1c15d4706855d07c224f2d488c50c Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sat, 20 Mar 2021 20:02:37 +0100 Subject: [PATCH 03/23] session creation --- app/controllers/application_controller.rb | 8 ++++++++ app/controllers/sessions_controller.rb | 5 +++++ app/controllers/users_controller.rb | 1 + app/views/sessions/new.html.erb | 10 ++++++++-- app/views/sessions/welcome.html.erb | 3 +++ .../controllers/application_controller_spec.rb | 18 ++++++++++++++++++ spec/controllers/sessions_controller_spec.rb | 5 +++++ spec/controllers/users_controller_spec.rb | 14 ++++++++++++++ spec/spec_helper.rb | 2 +- 9 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 spec/controllers/application_controller_spec.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d1..1f1890d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,10 @@ class ApplicationController < ActionController::Base + helper_method :current_user + helper_method :logged_in? + def current_user + User.find_by(id: session[:user_id]) + end + def logged_in? + !current_user.nil? + end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 710db28..835e049 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -3,6 +3,11 @@ class SessionsController < ApplicationController end def create + @user = User.find_by(username: params[:username]) + if @user && @user.authenticate(params[:password]) + sessions[:user_id] = @user.id + end + redirect_to '/welcome' end def welcome diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 0d7fd54..4698680 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,6 @@ class UsersController < ApplicationController def new + @user = User.new end def create diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index b39a3bc..c22d0c3 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,2 +1,8 @@ -

Sessions#new

-

Find me in app/views/sessions/new.html.erb

+

Login

+ <%= form_tag '/login' do %> + <%= label_tag :username%> + <%= text_field_tag :username %> + <%= label_tag :password%> + <%= password_field_tag :password%> + <%= submit_tag "Login"%> +<%end%> \ No newline at end of file diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index c63e0c1..71e1369 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,3 +1,6 @@

Welcome

+<% if logged_in? %> +

You are Logged In, <%= current_user.username %>

+<%end%> <%= button_to "Login", '/login', method: :get%> <%= button_to "Sign Up", '/users/new', method: :get%> \ No newline at end of file diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb new file mode 100644 index 0000000..cd64b2f --- /dev/null +++ b/spec/controllers/application_controller_spec.rb @@ -0,0 +1,18 @@ +require 'rails_helper' + +RSpec.describe ApplicationController do + describe 'current_user' do + before(:all) do + User.create(username: 'karol.selak@gmail.com', password: 'abcde') + end + context 'when a user is logged in' do + it 'returns the user' do + # TODO + # expect(current_user.username).to eql('karol.selak@gmail.com') + end + end + end + describe 'logged_in?' do + # TODO + end +end \ No newline at end of file diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 3a5b173..c959bc7 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -8,6 +8,11 @@ RSpec.describe SessionsController do end end describe 'get create' do + # TODO test session status + subject { get 'create' } + it 'redirects to /welcome' do + expect(subject).to redirect_to('/welcome') + end end describe 'get welcome' do subject { get 'welcome' } diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 56f7616..bf36687 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -8,5 +8,19 @@ RSpec.describe UsersController do end end describe 'get create' do + before(:all) do # TODO change it to cleanup after each test + User.destroy_all + end + subject { + get :create, params: {user: {username: 'karol.selak@gmail.com', password: 'abcde'}} + } + it 'creates a user' do + subject + expect(User.where(username: 'karol.selak@gmail.com').size).to eql(1) + end + it 'redirects to /welcome' do + subject + expect(subject).to redirect_to('/welcome') + end end end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ce33d66..383bef3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -93,4 +93,4 @@ RSpec.configure do |config| # as the one that triggered the failure. Kernel.srand config.seed =end -end +end \ No newline at end of file From 7412853a3e0d36c34ddc7d8001ce9a71399e0814 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sat, 20 Mar 2021 22:23:32 +0100 Subject: [PATCH 04/23] logout --- app/controllers/sessions_controller.rb | 7 ++++++- app/views/sessions/welcome.html.erb | 6 ++++-- config/routes.rb | 1 + spec/controllers/sessions_controller_spec.rb | 7 +++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 835e049..30ac1c4 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -5,11 +5,16 @@ class SessionsController < ApplicationController def create @user = User.find_by(username: params[:username]) if @user && @user.authenticate(params[:password]) - sessions[:user_id] = @user.id + session[:user_id] = @user.id end redirect_to '/welcome' end + def delete + session.delete(:user_id) + redirect_to '/welcome' + end + def welcome end end diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index 71e1369..640f008 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,6 +1,8 @@

Welcome

<% if logged_in? %>

You are Logged In, <%= current_user.username %>

+ <%= button_to "Logout", '/logout', method: :get%> +<%else%> + <%= button_to "Login", '/login', method: :get%> + <%= button_to "Sign Up", '/users/new', method: :get%> <%end%> -<%= button_to "Login", '/login', method: :get%> -<%= button_to "Sign Up", '/users/new', method: :get%> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 4e90759..4c00a41 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,7 @@ Rails.application.routes.draw do resources :users, only: [:new, :create] get 'login', to: 'sessions#new' + get 'logout', to: 'sessions#delete' post 'login', to: 'sessions#create' get 'welcome', to: 'sessions#welcome' resources :books diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index c959bc7..5a7a4f2 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -14,6 +14,13 @@ RSpec.describe SessionsController do expect(subject).to redirect_to('/welcome') end end + describe 'get delete' do + # TODO test session status + subject { get 'delete' } + it 'redirects to /welcome' do + expect(subject).to redirect_to('/welcome') + end + end describe 'get welcome' do subject { get 'welcome' } it 'renders the sessions/welcome template' do From cd40ef66c66fc2ae29bf9cf7b985920b1857e9d9 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sat, 20 Mar 2021 22:37:38 +0100 Subject: [PATCH 05/23] rename username to email --- app/controllers/sessions_controller.rb | 2 +- app/controllers/users_controller.rb | 2 +- app/views/sessions/new.html.erb | 4 ++-- app/views/sessions/welcome.html.erb | 2 +- app/views/users/new.html.erb | 4 ++-- db/migrate/20210320212922_change_username_to_email.rb | 5 +++++ db/schema.rb | 4 ++-- spec/controllers/application_controller_spec.rb | 4 ++-- spec/controllers/users_controller_spec.rb | 4 ++-- 9 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 db/migrate/20210320212922_change_username_to_email.rb diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 30ac1c4..b2ff728 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -3,7 +3,7 @@ class SessionsController < ApplicationController end def create - @user = User.find_by(username: params[:username]) + @user = User.find_by(email: params[:email]) if @user && @user.authenticate(params[:password]) session[:user_id] = @user.id end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 4698680..9392fc5 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -4,7 +4,7 @@ class UsersController < ApplicationController end def create - @user = User.create(params.require(:user).permit(:username, :password)) + @user = User.create(params.require(:user).permit(:email, :password)) session[:user_id] = @user.id redirect_to '/welcome' end diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index c22d0c3..67db6f9 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,7 +1,7 @@

Login

<%= form_tag '/login' do %> - <%= label_tag :username%> - <%= text_field_tag :username %> + <%= label_tag :email%> + <%= text_field_tag :email %> <%= label_tag :password%> <%= password_field_tag :password%> <%= submit_tag "Login"%> diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index 640f008..b97e9cf 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,6 +1,6 @@

Welcome

<% if logged_in? %> -

You are Logged In, <%= current_user.username %>

+

You are Logged In, <%= current_user.email %>

<%= button_to "Logout", '/logout', method: :get%> <%else%> <%= button_to "Login", '/login', method: :get%> diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index ac34536..51a2e32 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,7 +1,7 @@

Sign Up

<%= form_for @user do |f|%> - <%= f.label :username%>
- <%= f.text_field :username%>
+ <%= f.label :email%>
+ <%= f.text_field :email%>
<%= f.label :password%>
<%= f.password_field :password%>
<%= f.submit %> diff --git a/db/migrate/20210320212922_change_username_to_email.rb b/db/migrate/20210320212922_change_username_to_email.rb new file mode 100644 index 0000000..7ee7a5a --- /dev/null +++ b/db/migrate/20210320212922_change_username_to_email.rb @@ -0,0 +1,5 @@ +class ChangeUsernameToEmail < ActiveRecord::Migration[6.1] + def change + rename_column :users, :username, :email + end +end diff --git a/db/schema.rb b/db/schema.rb index f541248..7240eeb 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: 2021_03_20_130542) do +ActiveRecord::Schema.define(version: 2021_03_20_212922) do create_table "authors", force: :cascade do |t| t.string "first_name" @@ -39,7 +39,7 @@ ActiveRecord::Schema.define(version: 2021_03_20_130542) do end create_table "users", force: :cascade do |t| - t.string "username" + t.string "email" t.string "password_digest" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index cd64b2f..90e5974 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -3,12 +3,12 @@ require 'rails_helper' RSpec.describe ApplicationController do describe 'current_user' do before(:all) do - User.create(username: 'karol.selak@gmail.com', password: 'abcde') + User.create(email: 'karol.selak@gmail.com', password: 'abcde') end context 'when a user is logged in' do it 'returns the user' do # TODO - # expect(current_user.username).to eql('karol.selak@gmail.com') + # expect(current_user.email).to eql('karol.selak@gmail.com') end end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index bf36687..8253db7 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -12,11 +12,11 @@ RSpec.describe UsersController do User.destroy_all end subject { - get :create, params: {user: {username: 'karol.selak@gmail.com', password: 'abcde'}} + get :create, params: {user: {email: 'karol.selak@gmail.com', password: 'abcde'}} } it 'creates a user' do subject - expect(User.where(username: 'karol.selak@gmail.com').size).to eql(1) + expect(User.where(email: 'karol.selak@gmail.com').size).to eql(1) end it 'redirects to /welcome' do subject From 49998ee5b78a2bad0922875e280147caf488f04f Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 10:36:09 +0100 Subject: [PATCH 06/23] password recovery wip --- app/controllers/users_controller.rb | 25 +++++++++++++++++++ app/mailers/user_mailer.rb | 9 +++++++ app/views/sessions/welcome.html.erb | 1 + .../user_mailer/password_recovery.html.erb | 1 + app/views/users/password_recovery.html.erb | 9 +++++++ .../users/password_recovery_email.html.erb | 4 +++ .../send_password_recovery_email.html.erb | 1 + config/routes.rb | 4 +++ ...401_add_password_recovery_code_to_users.rb | 5 ++++ db/schema.rb | 3 ++- spec/mailers/previews/user_mailer_preview.rb | 4 +++ spec/mailers/user_mailer_spec.rb | 5 ++++ 12 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 app/mailers/user_mailer.rb create mode 100644 app/views/user_mailer/password_recovery.html.erb create mode 100644 app/views/users/password_recovery.html.erb create mode 100644 app/views/users/password_recovery_email.html.erb create mode 100644 app/views/users/send_password_recovery_email.html.erb create mode 100644 db/migrate/20210320233401_add_password_recovery_code_to_users.rb create mode 100644 spec/mailers/previews/user_mailer_preview.rb create mode 100644 spec/mailers/user_mailer_spec.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9392fc5..1e36920 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -8,4 +8,29 @@ class UsersController < ApplicationController session[:user_id] = @user.id redirect_to '/welcome' end + + def send_password_recovery_email + @user = User.where(email: params['email']).first + UserMailer.with(user: @user).password_recovery.deliver_now + end + + def password_recovery_email + end + + def password_recovery + @recovery_code = params[:recovery_code] + @user_id = params[:id] + end + + def recover_password + user = User.find(params[:user_id]) + if user.password_recovery_code == params[:recovery_code] + user.password = params[:password] + user.password_confirmation = params[:repeated_password] + user.password_recovery_code = nil + if user.save + redirect_to '/welcome' + end + end + end end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb new file mode 100644 index 0000000..a72456e --- /dev/null +++ b/app/mailers/user_mailer.rb @@ -0,0 +1,9 @@ +class UserMailer < ApplicationMailer + def password_recovery + @user = params[:user] + recovery_code = ('a'..'z').to_a.shuffle[0,8].join + @user.update(password_recovery_code: recovery_code) + @url = "http://localhost:18210/password_recovery/#{@user.id}/#{recovery_code}" + mail(to: @user.email, subject: 'Password recovery') + end +end diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index b97e9cf..a7e9d6e 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -5,4 +5,5 @@ <%else%> <%= button_to "Login", '/login', method: :get%> <%= button_to "Sign Up", '/users/new', method: :get%> + <%= button_to "Password recovery", '/password_recovery', method: :get%> <%end%> diff --git a/app/views/user_mailer/password_recovery.html.erb b/app/views/user_mailer/password_recovery.html.erb new file mode 100644 index 0000000..b89c984 --- /dev/null +++ b/app/views/user_mailer/password_recovery.html.erb @@ -0,0 +1 @@ +Please click the link to recover your password: <%= @url %> \ No newline at end of file diff --git a/app/views/users/password_recovery.html.erb b/app/views/users/password_recovery.html.erb new file mode 100644 index 0000000..7cc567b --- /dev/null +++ b/app/views/users/password_recovery.html.erb @@ -0,0 +1,9 @@ +Recover password + +<%= form_with url: "/recover_password", method: :post do |form| %> + <%= form.text_field :password %> + <%= form.text_field :repeated_password %> + <%= form.hidden_field :recovery_code, :value => @recovery_code %> + <%= form.hidden_field :user_id, :value => @user_id %> + <%= form.submit "Change password" %> +<% end %> \ No newline at end of file diff --git a/app/views/users/password_recovery_email.html.erb b/app/views/users/password_recovery_email.html.erb new file mode 100644 index 0000000..60b2904 --- /dev/null +++ b/app/views/users/password_recovery_email.html.erb @@ -0,0 +1,4 @@ +<%= form_with url: "/password_recovery", method: :post do |form| %> + <%= form.text_field :email %> + <%= form.submit "Send email" %> +<% end %> \ No newline at end of file diff --git a/app/views/users/send_password_recovery_email.html.erb b/app/views/users/send_password_recovery_email.html.erb new file mode 100644 index 0000000..18e5a7b --- /dev/null +++ b/app/views/users/send_password_recovery_email.html.erb @@ -0,0 +1 @@ +Recovery email sent. \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 4c00a41..e9dfcbe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,5 +4,9 @@ Rails.application.routes.draw do get 'logout', to: 'sessions#delete' post 'login', to: 'sessions#create' get 'welcome', to: 'sessions#welcome' + get 'password_recovery/:id/:recovery_code', to: 'users#password_recovery' + get 'password_recovery', to: 'users#password_recovery_email' + post 'password_recovery', to: 'users#send_password_recovery_email' + post 'recover_password', to: 'users#recover_password' resources :books end diff --git a/db/migrate/20210320233401_add_password_recovery_code_to_users.rb b/db/migrate/20210320233401_add_password_recovery_code_to_users.rb new file mode 100644 index 0000000..157cd56 --- /dev/null +++ b/db/migrate/20210320233401_add_password_recovery_code_to_users.rb @@ -0,0 +1,5 @@ +class AddPasswordRecoveryCodeToUsers < ActiveRecord::Migration[6.1] + def change + add_column :users, :password_recovery_code, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 7240eeb..4bcc3dc 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: 2021_03_20_212922) do +ActiveRecord::Schema.define(version: 2021_03_20_233401) do create_table "authors", force: :cascade do |t| t.string "first_name" @@ -43,6 +43,7 @@ ActiveRecord::Schema.define(version: 2021_03_20_212922) do t.string "password_digest" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.string "password_recovery_code" end end diff --git a/spec/mailers/previews/user_mailer_preview.rb b/spec/mailers/previews/user_mailer_preview.rb new file mode 100644 index 0000000..56c816a --- /dev/null +++ b/spec/mailers/previews/user_mailer_preview.rb @@ -0,0 +1,4 @@ +# Preview all emails at http://localhost:3000/rails/mailers/user +class UserMailerPreview < ActionMailer::Preview + +end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb new file mode 100644 index 0000000..4a78b85 --- /dev/null +++ b/spec/mailers/user_mailer_spec.rb @@ -0,0 +1,5 @@ +require "rails_helper" + +RSpec.describe UserMailer, type: :mailer do + pending "add some examples to (or delete) #{__FILE__}" +end From 639eb2ba04ca5d26ef47c573e1811c00a0493015 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 11:12:14 +0100 Subject: [PATCH 07/23] has_secure_password :recovery_password --- app/controllers/users_controller.rb | 4 ++-- app/mailers/user_mailer.rb | 7 ++++--- app/models/user.rb | 1 + ...e_password_recovery_code_to_recovery_password_digest.rb | 5 +++++ db/schema.rb | 4 ++-- 5 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1e36920..af59336 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -24,10 +24,10 @@ class UsersController < ApplicationController def recover_password user = User.find(params[:user_id]) - if user.password_recovery_code == params[:recovery_code] + if user.authenticate_recovery_password(params[:recovery_code]) user.password = params[:password] user.password_confirmation = params[:repeated_password] - user.password_recovery_code = nil + user.recovery_password_digest = nil if user.save redirect_to '/welcome' end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index a72456e..54cc9a9 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,9 +1,10 @@ class UserMailer < ApplicationMailer def password_recovery @user = params[:user] - recovery_code = ('a'..'z').to_a.shuffle[0,8].join - @user.update(password_recovery_code: recovery_code) - @url = "http://localhost:18210/password_recovery/#{@user.id}/#{recovery_code}" + recovery_password = ('a'..'z').to_a.shuffle[0,8].join + @user.recovery_password = recovery_password + @user.save + @url = "http://localhost:18210/password_recovery/#{@user.id}/#{recovery_password}" mail(to: @user.email, subject: 'Password recovery') end end diff --git a/app/models/user.rb b/app/models/user.rb index d67da20..36e30d8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,3 +1,4 @@ class User < ApplicationRecord has_secure_password + has_secure_password :recovery_password, validations: false end diff --git a/db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb b/db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb new file mode 100644 index 0000000..25603a4 --- /dev/null +++ b/db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb @@ -0,0 +1,5 @@ +class ChangePasswordRecoveryCodeToRecoveryPasswordDigest < ActiveRecord::Migration[6.1] + def change + rename_column :users, :password_recovery_code, :recovery_password_digest + end +end diff --git a/db/schema.rb b/db/schema.rb index 4bcc3dc..25f3a5f 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: 2021_03_20_233401) do +ActiveRecord::Schema.define(version: 2021_03_21_093857) do create_table "authors", force: :cascade do |t| t.string "first_name" @@ -43,7 +43,7 @@ ActiveRecord::Schema.define(version: 2021_03_20_233401) do t.string "password_digest" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false - t.string "password_recovery_code" + t.string "recovery_password_digest" end end From a5e7fef642617dbd4780c7c5a6c488e2734397c0 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 11:26:08 +0100 Subject: [PATCH 08/23] password recovery renaming --- app/controllers/users_controller.rb | 6 +++--- app/mailers/user_mailer.rb | 2 +- app/views/sessions/welcome.html.erb | 2 +- app/views/users/password_recovery_email.html.erb | 4 ---- ...ecovery_email.html.erb => password_recovery_request.erb} | 0 app/views/users/password_recovery_request_form.erb | 4 ++++ ...ord_recovery.html.erb => recover_password_form.html.erb} | 0 config/routes.rb | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) delete mode 100644 app/views/users/password_recovery_email.html.erb rename app/views/users/{send_password_recovery_email.html.erb => password_recovery_request.erb} (100%) create mode 100644 app/views/users/password_recovery_request_form.erb rename app/views/users/{password_recovery.html.erb => recover_password_form.html.erb} (100%) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index af59336..f37956e 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -9,15 +9,15 @@ class UsersController < ApplicationController redirect_to '/welcome' end - def send_password_recovery_email + def password_recovery_request @user = User.where(email: params['email']).first UserMailer.with(user: @user).password_recovery.deliver_now end - def password_recovery_email + def password_recovery_request_form end - def password_recovery + def recover_password_form @recovery_code = params[:recovery_code] @user_id = params[:id] end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 54cc9a9..6c23998 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -4,7 +4,7 @@ class UserMailer < ApplicationMailer recovery_password = ('a'..'z').to_a.shuffle[0,8].join @user.recovery_password = recovery_password @user.save - @url = "http://localhost:18210/password_recovery/#{@user.id}/#{recovery_password}" + @url = "http://localhost:18210/recover_password/#{@user.id}/#{recovery_password}" mail(to: @user.email, subject: 'Password recovery') end end diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index a7e9d6e..57e6dd2 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -5,5 +5,5 @@ <%else%> <%= button_to "Login", '/login', method: :get%> <%= button_to "Sign Up", '/users/new', method: :get%> - <%= button_to "Password recovery", '/password_recovery', method: :get%> + <%= button_to "Password recovery", '/password_recovery_request', method: :get%> <%end%> diff --git a/app/views/users/password_recovery_email.html.erb b/app/views/users/password_recovery_email.html.erb deleted file mode 100644 index 60b2904..0000000 --- a/app/views/users/password_recovery_email.html.erb +++ /dev/null @@ -1,4 +0,0 @@ -<%= form_with url: "/password_recovery", method: :post do |form| %> - <%= form.text_field :email %> - <%= form.submit "Send email" %> -<% end %> \ No newline at end of file diff --git a/app/views/users/send_password_recovery_email.html.erb b/app/views/users/password_recovery_request.erb similarity index 100% rename from app/views/users/send_password_recovery_email.html.erb rename to app/views/users/password_recovery_request.erb diff --git a/app/views/users/password_recovery_request_form.erb b/app/views/users/password_recovery_request_form.erb new file mode 100644 index 0000000..2e22108 --- /dev/null +++ b/app/views/users/password_recovery_request_form.erb @@ -0,0 +1,4 @@ +<%= form_with url: "/password_recovery_request", method: :post do |form| %> + <%= form.text_field :email %> + <%= form.submit "Send email" %> +<% end %> \ No newline at end of file diff --git a/app/views/users/password_recovery.html.erb b/app/views/users/recover_password_form.html.erb similarity index 100% rename from app/views/users/password_recovery.html.erb rename to app/views/users/recover_password_form.html.erb diff --git a/config/routes.rb b/config/routes.rb index e9dfcbe..b0a6324 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,9 +4,9 @@ Rails.application.routes.draw do get 'logout', to: 'sessions#delete' post 'login', to: 'sessions#create' get 'welcome', to: 'sessions#welcome' - get 'password_recovery/:id/:recovery_code', to: 'users#password_recovery' - get 'password_recovery', to: 'users#password_recovery_email' - post 'password_recovery', to: 'users#send_password_recovery_email' + get 'password_recovery_request', to: 'users#password_recovery_request_form' + post 'password_recovery_request', to: 'users#password_recovery_request' + get 'recover_password/:id/:recovery_code', to: 'users#recover_password_form' post 'recover_password', to: 'users#recover_password' resources :books end From dace874f4f75218b6ebc4644dd4afa9e6b897e49 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 11:40:53 +0100 Subject: [PATCH 09/23] UI and naming changes --- app/assets/stylesheets/application.scss | 4 ++++ app/controllers/users_controller.rb | 6 +++--- app/views/sessions/create.html.erb | 2 +- app/views/sessions/new.html.erb | 5 +++-- app/views/sessions/welcome.html.erb | 5 ++--- app/views/users/create.html.erb | 2 +- app/views/users/new.html.erb | 2 +- app/views/users/recover_password_form.html.erb | 6 +++--- config/routes.rb | 2 +- public/404.html | 2 +- public/422.html | 2 +- public/500.html | 2 +- 12 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index e1a69d8..e1ecc73 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1,2 +1,6 @@ @import "materialize"; @import "https://fonts.googleapis.com/icon?family=Material+Icons"; + +body { + margin: 100px; +} \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index f37956e..386c43b 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -18,15 +18,15 @@ class UsersController < ApplicationController end def recover_password_form - @recovery_code = params[:recovery_code] + @recovery_password = params[:recovery_password] @user_id = params[:id] end def recover_password user = User.find(params[:user_id]) - if user.authenticate_recovery_password(params[:recovery_code]) + if user.authenticate_recovery_password(params[:recovery_password]) user.password = params[:password] - user.password_confirmation = params[:repeated_password] + user.password_confirmation = params[:password_confirmation] user.recovery_password_digest = nil if user.save redirect_to '/welcome' diff --git a/app/views/sessions/create.html.erb b/app/views/sessions/create.html.erb index c251174..a7ac851 100644 --- a/app/views/sessions/create.html.erb +++ b/app/views/sessions/create.html.erb @@ -1,2 +1,2 @@ -

Sessions#create

+

Sessions#create

Find me in app/views/sessions/create.html.erb

diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index 67db6f9..4556936 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,8 +1,9 @@ -

Login

+

Login

<%= form_tag '/login' do %> <%= label_tag :email%> <%= text_field_tag :email %> <%= label_tag :password%> <%= password_field_tag :password%> <%= submit_tag "Login"%> -<%end%> \ No newline at end of file +<%end%> +<%= button_to "Password recovery", '/password_recovery_request', method: :get%> \ No newline at end of file diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index 57e6dd2..e04edd2 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,9 +1,8 @@ -

Welcome

+

Welcome

<% if logged_in? %> -

You are Logged In, <%= current_user.email %>

+ You are Logged In, <%= current_user.email %> <%= button_to "Logout", '/logout', method: :get%> <%else%> <%= button_to "Login", '/login', method: :get%> <%= button_to "Sign Up", '/users/new', method: :get%> - <%= button_to "Password recovery", '/password_recovery_request', method: :get%> <%end%> diff --git a/app/views/users/create.html.erb b/app/views/users/create.html.erb index 48ea02e..a4a1b5f 100644 --- a/app/views/users/create.html.erb +++ b/app/views/users/create.html.erb @@ -1,2 +1,2 @@ -

Users#create

+

Users#create

Find me in app/views/users/create.html.erb

diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index 51a2e32..8413e2e 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,4 +1,4 @@ -

Sign Up

+

Sign Up

<%= form_for @user do |f|%> <%= f.label :email%>
<%= f.text_field :email%>
diff --git a/app/views/users/recover_password_form.html.erb b/app/views/users/recover_password_form.html.erb index 7cc567b..a0d833f 100644 --- a/app/views/users/recover_password_form.html.erb +++ b/app/views/users/recover_password_form.html.erb @@ -1,9 +1,9 @@ Recover password <%= form_with url: "/recover_password", method: :post do |form| %> - <%= form.text_field :password %> - <%= form.text_field :repeated_password %> - <%= form.hidden_field :recovery_code, :value => @recovery_code %> + <%= form.password_field :password %> + <%= form.password_field :password_confirmation %> + <%= form.hidden_field :recovery_password, :value => @recovery_password %> <%= form.hidden_field :user_id, :value => @user_id %> <%= form.submit "Change password" %> <% end %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index b0a6324..43ec56d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -6,7 +6,7 @@ Rails.application.routes.draw do get 'welcome', to: 'sessions#welcome' get 'password_recovery_request', to: 'users#password_recovery_request_form' post 'password_recovery_request', to: 'users#password_recovery_request' - get 'recover_password/:id/:recovery_code', to: 'users#recover_password_form' + get 'recover_password/:id/:recovery_password', to: 'users#recover_password_form' post 'recover_password', to: 'users#recover_password' resources :books end diff --git a/public/404.html b/public/404.html index 2be3af2..c0db723 100644 --- a/public/404.html +++ b/public/404.html @@ -58,7 +58,7 @@
-

The page you were looking for doesn't exist.

+

The page you were looking for doesn't exist.

You may have mistyped the address or the page may have moved.

If you are the application owner check the logs for more information.

diff --git a/public/422.html b/public/422.html index c08eac0..5c98efa 100644 --- a/public/422.html +++ b/public/422.html @@ -58,7 +58,7 @@
-

The change you wanted was rejected.

+

The change you wanted was rejected.

Maybe you tried to change something you didn't have access to.

If you are the application owner check the logs for more information.

diff --git a/public/500.html b/public/500.html index 78a030a..54da439 100644 --- a/public/500.html +++ b/public/500.html @@ -58,7 +58,7 @@
-

We're sorry, but something went wrong.

+

We're sorry, but something went wrong.

If you are the application owner check the logs for more information.

From a69df8e6588919a0a220b60eb214842c0b3feaf5 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 12:41:21 +0100 Subject: [PATCH 10/23] notices, password recovery corner cases and UI changes --- app/controllers/sessions_controller.rb | 2 +- app/controllers/users_controller.rb | 13 +++++++++---- app/views/layouts/application.html.erb | 8 +++++++- app/views/sessions/create.html.erb | 2 -- app/views/sessions/new.html.erb | 6 +++--- app/views/sessions/welcome.html.erb | 10 +++++----- app/views/users/create.html.erb | 2 -- app/views/users/new.html.erb | 12 ++++++------ app/views/users/password_recovery_request.erb | 1 - .../users/password_recovery_request_form.erb | 9 ++++++--- app/views/users/recover_password_form.html.erb | 16 +++++++++------- public/404.html | 2 +- public/422.html | 2 +- public/500.html | 2 +- 14 files changed, 49 insertions(+), 38 deletions(-) delete mode 100644 app/views/sessions/create.html.erb delete mode 100644 app/views/users/create.html.erb delete mode 100644 app/views/users/password_recovery_request.erb diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index b2ff728..ac1e0c8 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -12,7 +12,7 @@ class SessionsController < ApplicationController def delete session.delete(:user_id) - redirect_to '/welcome' + redirect_to '/welcome', notice: 'Logged out properly' end def welcome diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 386c43b..d0c62bf 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,12 +6,13 @@ class UsersController < ApplicationController def create @user = User.create(params.require(:user).permit(:email, :password)) session[:user_id] = @user.id - redirect_to '/welcome' + redirect_to '/welcome', notice: 'Account has been created' end def password_recovery_request @user = User.where(email: params['email']).first UserMailer.with(user: @user).password_recovery.deliver_now + redirect_to '/welcome', notice: "Recovery email sent to #{params['email']}" end def password_recovery_request_form @@ -24,13 +25,17 @@ class UsersController < ApplicationController def recover_password user = User.find(params[:user_id]) - if user.authenticate_recovery_password(params[:recovery_password]) + if user.recovery_password_digest && user.authenticate_recovery_password(params[:recovery_password]) user.password = params[:password] user.password_confirmation = params[:password_confirmation] - user.recovery_password_digest = nil if user.save - redirect_to '/welcome' + user.update(recovery_password: nil) + redirect_to '/welcome', notice: 'Password changed' + else + redirect_to '/welcome', notice: 'Passwords don\'t match' end + else + redirect_to '/welcome', notice: 'Recovery link expired or unvalid' end end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 7ca2457..e3cec58 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -2,7 +2,7 @@ Book store - + <%= csrf_meta_tags %> <%= csp_meta_tag %> @@ -11,6 +11,12 @@ + <%= link_to 'Home', '/welcome', method: :get%> + <% flash.each do |type, msg| %> +
+ <%= msg %> +
+ <% end %> <%= yield %> diff --git a/app/views/sessions/create.html.erb b/app/views/sessions/create.html.erb deleted file mode 100644 index a7ac851..0000000 --- a/app/views/sessions/create.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Sessions#create

-

Find me in app/views/sessions/create.html.erb

diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index 4556936..23315d8 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,9 +1,9 @@ -

Login

+

Login

<%= form_tag '/login' do %> <%= label_tag :email%> <%= text_field_tag :email %> <%= label_tag :password%> <%= password_field_tag :password%> - <%= submit_tag "Login"%> + <%= submit_tag "Login", class: 'btn' %> <%end%> -<%= button_to "Password recovery", '/password_recovery_request', method: :get%> \ No newline at end of file +<%= link_to "Password recovery", '/password_recovery_request', method: :get%> \ No newline at end of file diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index e04edd2..2f18736 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,8 +1,8 @@ -

Welcome

+

Welcome

<% if logged_in? %> You are Logged In, <%= current_user.email %> <%= button_to "Logout", '/logout', method: :get%> -<%else%> - <%= button_to "Login", '/login', method: :get%> - <%= button_to "Sign Up", '/users/new', method: :get%> -<%end%> +<% else %> + <%= button_to "Login", '/login', method: :get, class: 'btn'%> + <%= button_to "Sign Up", '/users/new', method: :get, class: 'btn'%> +<% end %> diff --git a/app/views/users/create.html.erb b/app/views/users/create.html.erb deleted file mode 100644 index a4a1b5f..0000000 --- a/app/views/users/create.html.erb +++ /dev/null @@ -1,2 +0,0 @@ -

Users#create

-

Find me in app/views/users/create.html.erb

diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index 8413e2e..d81b5bf 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,8 +1,8 @@ -

Sign Up

+

Sign Up

<%= form_for @user do |f|%> - <%= f.label :email%>
- <%= f.text_field :email%>
- <%= f.label :password%>
- <%= f.password_field :password%>
- <%= f.submit %> + <%= f.label :email%> + <%= f.text_field :email%> + <%= f.label :password%> + <%= f.password_field :password%> + <%= f.submit 'Sign up', class: 'btn' %> <%end%> \ No newline at end of file diff --git a/app/views/users/password_recovery_request.erb b/app/views/users/password_recovery_request.erb deleted file mode 100644 index 18e5a7b..0000000 --- a/app/views/users/password_recovery_request.erb +++ /dev/null @@ -1 +0,0 @@ -Recovery email sent. \ No newline at end of file diff --git a/app/views/users/password_recovery_request_form.erb b/app/views/users/password_recovery_request_form.erb index 2e22108..66a90a4 100644 --- a/app/views/users/password_recovery_request_form.erb +++ b/app/views/users/password_recovery_request_form.erb @@ -1,4 +1,7 @@ -<%= form_with url: "/password_recovery_request", method: :post do |form| %> - <%= form.text_field :email %> - <%= form.submit "Send email" %> +

Password recovery

+Provide an email to password recovery +<%= form_with url: "/password_recovery_request", method: :post do |f| %> + <%= f.label :email%>
+ <%= f.text_field :email %> + <%= f.submit 'Send email', class: 'btn' %> <% end %> \ No newline at end of file diff --git a/app/views/users/recover_password_form.html.erb b/app/views/users/recover_password_form.html.erb index a0d833f..91f0d43 100644 --- a/app/views/users/recover_password_form.html.erb +++ b/app/views/users/recover_password_form.html.erb @@ -1,9 +1,11 @@ -Recover password +

Provide new password

-<%= form_with url: "/recover_password", method: :post do |form| %> - <%= form.password_field :password %> - <%= form.password_field :password_confirmation %> - <%= form.hidden_field :recovery_password, :value => @recovery_password %> - <%= form.hidden_field :user_id, :value => @user_id %> - <%= form.submit "Change password" %> +<%= form_with url: '/recover_password', method: :post do |f| %> + <%= f.label :password%> + <%= f.password_field :password %> + <%= f.label :password_confirmation%> + <%= f.password_field :password_confirmation %> + <%= f.hidden_field :recovery_password, :value => @recovery_password %> + <%= f.hidden_field :user_id, :value => @user_id %> + <%= f.submit 'Change password', class: 'btn' %> <% end %> \ No newline at end of file diff --git a/public/404.html b/public/404.html index c0db723..3e2d224 100644 --- a/public/404.html +++ b/public/404.html @@ -58,7 +58,7 @@
-

The page you were looking for doesn't exist.

+

The page you were looking for doesn't exist.

You may have mistyped the address or the page may have moved.

If you are the application owner check the logs for more information.

diff --git a/public/422.html b/public/422.html index 5c98efa..badeeb8 100644 --- a/public/422.html +++ b/public/422.html @@ -58,7 +58,7 @@
-

The change you wanted was rejected.

+

The change you wanted was rejected.

Maybe you tried to change something you didn't have access to.

If you are the application owner check the logs for more information.

diff --git a/public/500.html b/public/500.html index 54da439..1fd70e3 100644 --- a/public/500.html +++ b/public/500.html @@ -58,7 +58,7 @@
-

We're sorry, but something went wrong.

+

We're sorry, but something went wrong.

If you are the application owner check the logs for more information.

From 39a89ad564707c8332102b7c3a122c9915e045da Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 14:44:59 +0100 Subject: [PATCH 11/23] password recovery refactoring and tests --- app/controllers/users_controller.rb | 7 +- app/mailers/user_mailer.rb | 6 +- .../application_controller_spec.rb | 4 +- spec/controllers/users_controller_spec.rb | 95 +++++++++++++++++-- spec/mailers/user_mailer_spec.rb | 2 +- 5 files changed, 98 insertions(+), 16 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d0c62bf..fe97096 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -11,7 +11,10 @@ class UsersController < ApplicationController def password_recovery_request @user = User.where(email: params['email']).first - UserMailer.with(user: @user).password_recovery.deliver_now + recovery_password = ('a'..'z').to_a.shuffle[0,8].join + @user.recovery_password = recovery_password + @user.save + UserMailer.with(user: @user, recovery_password: recovery_password).password_recovery.deliver_now redirect_to '/welcome', notice: "Recovery email sent to #{params['email']}" end @@ -35,7 +38,7 @@ class UsersController < ApplicationController redirect_to '/welcome', notice: 'Passwords don\'t match' end else - redirect_to '/welcome', notice: 'Recovery link expired or unvalid' + redirect_to '/welcome', notice: 'Recovery link expired or invalid' end end end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 6c23998..7a5ef41 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,10 +1,8 @@ class UserMailer < ApplicationMailer def password_recovery @user = params[:user] - recovery_password = ('a'..'z').to_a.shuffle[0,8].join - @user.recovery_password = recovery_password - @user.save - @url = "http://localhost:18210/recover_password/#{@user.id}/#{recovery_password}" + @recovery_password = params[:recovery_password] + @url = "http://localhost:18210/recover_password/#{@user.id}/#{@recovery_password}" mail(to: @user.email, subject: 'Password recovery') end end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 90e5974..c6b1a80 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -3,12 +3,12 @@ require 'rails_helper' RSpec.describe ApplicationController do describe 'current_user' do before(:all) do - User.create(email: 'karol.selak@gmail.com', password: 'abcde') + User.create(email: 'test2@example.com', password: 'abcde') end context 'when a user is logged in' do it 'returns the user' do # TODO - # expect(current_user.email).to eql('karol.selak@gmail.com') + # expect(current_user.email).to eql('test2@example.com') end end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 8253db7..5a5c41d 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -1,26 +1,107 @@ require 'rails_helper' RSpec.describe UsersController do + before(:all) do # TODO change it to cleanup after each test + User.destroy_all + end + let(:user1) do + User.create(email: 'test1@example.com', password: 'abcde', recovery_password: 'recovery password') + end describe 'get new' do - subject { get 'new' } + subject { get :new } it 'renders the users/new template' do expect(subject).to render_template('users/new') end end describe 'get create' do - before(:all) do # TODO change it to cleanup after each test - User.destroy_all + subject do + get :create, params: {user: {email: 'test2@example.com', password: 'abcde'}} end - subject { - get :create, params: {user: {email: 'karol.selak@gmail.com', password: 'abcde'}} - } it 'creates a user' do subject - expect(User.where(email: 'karol.selak@gmail.com').size).to eql(1) + expect(User.where(email: 'test2@example.com').size).to eql(1) end it 'redirects to /welcome' do subject expect(subject).to redirect_to('/welcome') end end + describe 'get password_recovery_request_form' do + subject { get :password_recovery_request_form } + it 'renders the users/password_recovery_request_form template' do + expect(subject).to render_template('users/password_recovery_request_form') + end + end + describe 'post password_recovery_request' do + subject do + get :password_recovery_request, params: {email: user1.email} + end + it 'sends the proper recovery email' do + srand(10) + subject + email_text = ActionMailer::Base.deliveries.last.body.raw_source + expect(email_text).to match("recover_password/#{user1.id}/tfohbclx") + end + it 'sends a recovery email to the proper email' do + subject + expect(ActionMailer::Base.deliveries.last.to).to eql([user1.email]) + end + it 'flashes a notice' do + subject + expect(subject.request.flash[:notice]).to match("Recovery email sent to #{user1.email}") + end + end + describe 'get recover_password_form' do + subject do + get :recover_password_form, params: {id: user1.id, recovery_password: 'recovery password'} + end + it 'renders proper form' do + subject + expect(subject).to render_template('users/recover_password_form') + end + end + describe 'post recover_password' do + context 'when passwords match and recovery password is proper' do + subject do + post :recover_password, params: { + user_id: user1.id, + recovery_password: 'recovery password', + password: 'new password', + password_confirmation: 'new password' + } + end + it 'flashes a notice about success' do + subject + expect(subject.request.flash[:notice]).to match('Password changed') + end + end + context 'when recovery password is inproper' do + subject do + post :recover_password, params: { + user_id: user1.id, + recovery_password: 'improper recovery password', + password: 'new password', + password_confirmation: 'new password' + } + end + it 'flashes a notice about failure' do + subject + expect(subject.request.flash[:notice]).to match('Recovery link expired or invalid') + end + end + context 'when passwords match and recovery password is improper' do + subject do + post :recover_password, params: { + user_id: user1.id, + recovery_password: 'recovery password', + password: 'new password', + password_confirmation: 'bad password' + } + end + it 'flashes a notice about failure' do + subject + expect(subject.request.flash[:notice]).to match('Passwords don\'t match') + end + end + end end \ No newline at end of file diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 4a78b85..6ebbdf6 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -1,5 +1,5 @@ require "rails_helper" RSpec.describe UserMailer, type: :mailer do - pending "add some examples to (or delete) #{__FILE__}" + # TODO end From ed6a5d69f606f2493c2c98c3036884e1fad5c72e Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 17:02:04 +0100 Subject: [PATCH 12/23] user validation --- app/controllers/application_controller.rb | 9 +++++++++ app/controllers/users_controller.rb | 8 ++++++-- app/models/user.rb | 5 +++++ app/views/layouts/application.html.erb | 10 ++++++++-- app/views/sessions/welcome.html.erb | 6 +++--- db/migrate/20210321135711_add_role_to_users.rb | 5 +++++ db/schema.rb | 3 ++- 7 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 db/migrate/20210321135711_add_role_to_users.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1f1890d..90af2ed 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,10 +1,19 @@ class ApplicationController < ActionController::Base helper_method :current_user helper_method :logged_in? + def current_user User.find_by(id: session[:user_id]) end + def logged_in? !current_user.nil? end + + def notices_from_errors(record) + messages = record.errors.messages.map do |attribute, messages| + messages.map { |message| "#{attribute} #{message}".capitalize } + end + messages.flatten + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index fe97096..e25d5f1 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -5,8 +5,12 @@ class UsersController < ApplicationController def create @user = User.create(params.require(:user).permit(:email, :password)) - session[:user_id] = @user.id - redirect_to '/welcome', notice: 'Account has been created' + if @user.invalid? + redirect_to '/welcome', notice: notices_from_errors(@user) + else + session[:user_id] = @user.id + redirect_to '/welcome', notice: 'Account has been created' + end end def password_recovery_request diff --git a/app/models/user.rb b/app/models/user.rb index 36e30d8..174b4bc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,9 @@ class User < ApplicationRecord has_secure_password has_secure_password :recovery_password, validations: false + enum role: [:customer, :admin], _default: :customer + + validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP } + validates :role, presence: true + validates :password, presence: true, length: { minimum: 8 } end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index e3cec58..2a12733 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,9 +12,15 @@ <%= link_to 'Home', '/welcome', method: :get%> - <% flash.each do |type, msg| %> + <% flash.each do |type, notice| %>
- <%= msg %> + <% if notice.is_a? String %> + <%= notice %> + <% else %> + <% notice.each do |msg| %> +
<%= msg %>
+ <% end %> + <% end %>
<% end %> <%= yield %> diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index 2f18736..dc85f35 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,8 +1,8 @@

Welcome

<% if logged_in? %> You are Logged In, <%= current_user.email %> - <%= button_to "Logout", '/logout', method: :get%> + <%= button_to "Logout", '/logout', method: :get, class: 'btn' %> <% else %> - <%= button_to "Login", '/login', method: :get, class: 'btn'%> - <%= button_to "Sign Up", '/users/new', method: :get, class: 'btn'%> + <%= button_to "Login", '/login', method: :get, class: 'btn' %> + <%= button_to "Sign Up", '/users/new', method: :get, class: 'btn' %> <% end %> diff --git a/db/migrate/20210321135711_add_role_to_users.rb b/db/migrate/20210321135711_add_role_to_users.rb new file mode 100644 index 0000000..a7a966f --- /dev/null +++ b/db/migrate/20210321135711_add_role_to_users.rb @@ -0,0 +1,5 @@ +class AddRoleToUsers < ActiveRecord::Migration[6.1] + def change + add_column :users, :role, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 25f3a5f..fb945c3 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: 2021_03_21_093857) do +ActiveRecord::Schema.define(version: 2021_03_21_135711) do create_table "authors", force: :cascade do |t| t.string "first_name" @@ -44,6 +44,7 @@ ActiveRecord::Schema.define(version: 2021_03_21_093857) do t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.string "recovery_password_digest" + t.integer "role" end end From 5095f63fd72e978d2b6a883e85bff928cb55a7f4 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 17:06:54 +0100 Subject: [PATCH 13/23] book and author validation --- app/models/author.rb | 2 ++ app/models/book.rb | 3 +++ 2 files changed, 5 insertions(+) diff --git a/app/models/author.rb b/app/models/author.rb index e399202..9f3a806 100644 --- a/app/models/author.rb +++ b/app/models/author.rb @@ -1,2 +1,4 @@ class Author < ApplicationRecord + validates :first_name, presence: true + validates :last_name, presence: true end diff --git a/app/models/book.rb b/app/models/book.rb index 1b16bc8..860c5d5 100644 --- a/app/models/book.rb +++ b/app/models/book.rb @@ -2,4 +2,7 @@ class Book < ApplicationRecord has_and_belongs_to_many :authors scope :published, -> { where(published: true) } + validates :title, presence: true + validates :price, presence: true + validates :published, presence: true end From e36cc369477790ae627a9c2b7554fddb4d374662 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 20:30:25 +0100 Subject: [PATCH 14/23] books edition by admin --- app/controllers/authors_controller.rb | 5 ++++ app/controllers/books_controller.rb | 40 +++++++++++++++++++++++++- app/models/book.rb | 1 - app/models/user.rb | 6 +++- app/presenters/books_presenter.rb | 6 +++- app/views/books/edit.html.erb | 14 +++++++++ app/views/books/index.html.erb | 20 +++++++++---- app/views/books/show.html.erb | 20 +++++++++++++ app/views/layouts/application.html.erb | 1 + db/seeds.rb | 26 ++++++++++------- 10 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 app/controllers/authors_controller.rb create mode 100644 app/views/books/edit.html.erb create mode 100644 app/views/books/show.html.erb diff --git a/app/controllers/authors_controller.rb b/app/controllers/authors_controller.rb new file mode 100644 index 0000000..f96718c --- /dev/null +++ b/app/controllers/authors_controller.rb @@ -0,0 +1,5 @@ +class AuthorsController < ApplicationController + def index + @authors = Author.all + end +end diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb index bafab99..3ef6625 100644 --- a/app/controllers/books_controller.rb +++ b/app/controllers/books_controller.rb @@ -1,5 +1,43 @@ class BooksController < ApplicationController + before_action :set_book, only: [:show, :edit, :update] + before_action :ensure_admin, only: [:edit, :update] + def index - @books = Book.published.map { |book| BooksPresenter.new(book) } + if current_user.admin? + books = Book.all + else + books = Book.published + end + @books = books.map { |book| BooksPresenter.new(book) } + end + + def show + end + + def edit + end + + def update + if @book.update(book_params) + redirect_to '/books' + end + end + + private + + def ensure_admin + unless current_user&.admin? + redirect_to '/welcome', notice: 'You are not allowed to perform this action' + end + end + + def set_book + @book = BooksPresenter.new(Book.find(params[:id])) + end + + def book_params + result = params.require(:book).permit(:title, :price, :published) + result['price'] = result['price'].to_d * 100 + result end end diff --git a/app/models/book.rb b/app/models/book.rb index 860c5d5..e0b5624 100644 --- a/app/models/book.rb +++ b/app/models/book.rb @@ -4,5 +4,4 @@ class Book < ApplicationRecord scope :published, -> { where(published: true) } validates :title, presence: true validates :price, presence: true - validates :published, presence: true end diff --git a/app/models/user.rb b/app/models/user.rb index 174b4bc..9731bb0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,5 +5,9 @@ class User < ApplicationRecord validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP } validates :role, presence: true - validates :password, presence: true, length: { minimum: 8 } + validates :password, { + presence: true, + length: { minimum: 8 }, + if: lambda{ new_record? || !password.nil? } + } end diff --git a/app/presenters/books_presenter.rb b/app/presenters/books_presenter.rb index 49888bb..c6b3f40 100644 --- a/app/presenters/books_presenter.rb +++ b/app/presenters/books_presenter.rb @@ -2,7 +2,11 @@ class BooksPresenter < SimpleDelegator include ActiveSupport::NumberHelper def price - number_to_currency(super / 100) + super / 100 + end + + def price_with_currency + number_to_currency(price) end def authors diff --git a/app/views/books/edit.html.erb b/app/views/books/edit.html.erb new file mode 100644 index 0000000..d45ee1c --- /dev/null +++ b/app/views/books/edit.html.erb @@ -0,0 +1,14 @@ +

Edit book

+<%= form_for @book do |f|%> + <%= f.label :title %> + <%= f.text_field :title %> + <%= f.label :price %> + <%= f.number_field :price, step: 0.01 %> + + <%= f.submit 'Save changes', class: 'btn' %> +<%end%> \ No newline at end of file diff --git a/app/views/books/index.html.erb b/app/views/books/index.html.erb index 904091b..b1bb82a 100644 --- a/app/views/books/index.html.erb +++ b/app/views/books/index.html.erb @@ -1,17 +1,27 @@
<% @books.each do |book| %>
-
- Title: <%= book.title %> +
+ Title: <%= link_to book.title, book %>
-
- Price: <%= book.price %> +
+ Price: <%= book.price_with_currency %>
-
+
Authors: <%= book.authors %> +
+ + <% if current_user.admin? %> +
+ <%= book.published ? 'published' : 'unpublished' %> +
+
+ <%= link_to 'Edit', edit_book_path(book), class: "btn" %> +
+ <% end %>
<% end %>
diff --git a/app/views/books/show.html.erb b/app/views/books/show.html.erb new file mode 100644 index 0000000..5370cff --- /dev/null +++ b/app/views/books/show.html.erb @@ -0,0 +1,20 @@ +
+
+
+ Title: <%= link_to @book.title, @book %> +
+ +
+ Price: <%= @book.price_with_currency %> +
+ +
+ Authors: <%= @book.authors %> +
+
+ <% if current_user&.admin? %> +
+ <%= link_to 'Edit', edit_book_path(@book), class: "btn" %> +
+ <% end %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 2a12733..455b4e4 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -12,6 +12,7 @@ <%= link_to 'Home', '/welcome', method: :get%> + <%= link_to 'Books', '/books', method: :get%> <% flash.each do |type, notice| %>
<% if notice.is_a? String %> diff --git a/db/seeds.rb b/db/seeds.rb index 1f3af18..74e1732 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -31,21 +31,25 @@ authors = Author.create([ }, ]) -BookAuthor.create([ +books.first.authors << authors.first +books.second.authors << authors.first +books.third.authors << authors.second +books.third.authors << authors.third + +User.create([ { - book: books.first, - author: authors.first + email: 'abc@o2.pl', + password: 'aaaaaaaa', + role: :admin }, { - book: books[1], - author: authors.first + email: 'abcd@o2.pl', + password: 'aaaaaaaa', + role: :customer }, { - book: books[2], - author: authors[1] - }, - { - book: books[2], - author: authors[2] + email: 'abcde@o2.pl', + password: 'aaaaaaaa', + role: :customer }, ]) \ No newline at end of file From ccb6e23960d2f1207d776f966b89fefa30757d04 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 22:31:58 +0100 Subject: [PATCH 15/23] edit authors, delete users, UI changes --- Gemfile | 2 + Gemfile.lock | 5 +++ app/controllers/application_controller.rb | 8 ++++ app/controllers/authors_controller.rb | 23 +++++++++++ app/controllers/books_controller.rb | 6 --- app/controllers/users_controller.rb | 11 +++++ app/javascript/packs/application.js | 2 + app/views/authors/edit.html.erb | 10 +++++ app/views/authors/index.html.erb | 13 ++++++ app/views/books/edit.html.erb | 30 +++++++------- app/views/layouts/application.html.erb | 40 ++++++++++++++----- app/views/sessions/new.html.erb | 20 +++++----- app/views/sessions/welcome.html.erb | 18 +++++---- app/views/users/index.html.erb | 15 +++++++ app/views/users/new.html.erb | 18 +++++---- .../users/password_recovery_request_form.erb | 16 ++++---- .../users/recover_password_form.html.erb | 22 +++++----- config/environments/development.rb | 3 +- config/routes.rb | 3 +- 19 files changed, 190 insertions(+), 75 deletions(-) create mode 100644 app/views/authors/edit.html.erb create mode 100644 app/views/authors/index.html.erb create mode 100644 app/views/users/index.html.erb diff --git a/Gemfile b/Gemfile index 3d49e52..2b78fd1 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,8 @@ gem 'bcrypt', '~> 3.1.7' gem 'materialize-sass', '~> 1.0.0' +gem 'jquery-rails' + # Use Active Storage variant # gem 'image_processing', '~> 1.2' diff --git a/Gemfile.lock b/Gemfile.lock index 671f766..7c63543 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -91,6 +91,10 @@ GEM concurrent-ruby (~> 1.0) jbuilder (2.11.2) activesupport (>= 5.0.0) + jquery-rails (4.4.0) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) listen (3.4.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) @@ -241,6 +245,7 @@ DEPENDENCIES byebug capybara (>= 3.26) jbuilder (~> 2.7) + jquery-rails listen (~> 3.3) materialize-sass (~> 1.0.0) puma (~> 5.0) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 90af2ed..4e12a38 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,10 +10,18 @@ class ApplicationController < ActionController::Base !current_user.nil? end + protected + def notices_from_errors(record) messages = record.errors.messages.map do |attribute, messages| messages.map { |message| "#{attribute} #{message}".capitalize } end messages.flatten end + + def ensure_admin + unless current_user&.admin? + redirect_to '/welcome', notice: 'You are not allowed to perform this action' + end + end end diff --git a/app/controllers/authors_controller.rb b/app/controllers/authors_controller.rb index f96718c..abd8ecb 100644 --- a/app/controllers/authors_controller.rb +++ b/app/controllers/authors_controller.rb @@ -1,5 +1,28 @@ class AuthorsController < ApplicationController + before_action :ensure_admin + before_action :set_author, only: [:edit, :update] + def index @authors = Author.all end + + def edit + @author = Author.find(params[:id]) + end + + def update + if @author.update(author_params) + redirect_to '/authors' + end + end + + private + + def set_author + @author = Author.find(params[:id]) + end + + def author_params + params.require(:author).permit(:first_name, :last_name) + end end diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb index 3ef6625..499d455 100644 --- a/app/controllers/books_controller.rb +++ b/app/controllers/books_controller.rb @@ -25,12 +25,6 @@ class BooksController < ApplicationController private - def ensure_admin - unless current_user&.admin? - redirect_to '/welcome', notice: 'You are not allowed to perform this action' - end - end - def set_book @book = BooksPresenter.new(Book.find(params[:id])) end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index e25d5f1..ec02862 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,4 +1,10 @@ class UsersController < ApplicationController + before_action :ensure_admin, only: [:destroy] + + def index + @users = User.all + end + def new @user = User.new end @@ -45,4 +51,9 @@ class UsersController < ApplicationController redirect_to '/welcome', notice: 'Recovery link expired or invalid' end end + + def destroy + User.destroy(params[:id]) + redirect_to '/users' + end end diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index a5843e7..2d92af0 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -4,6 +4,8 @@ // that code so it'll be compiled. //= require materialize +//= require jquery +//= require jquery_ujs import Rails from "@rails/ujs" import Turbolinks from "turbolinks" diff --git a/app/views/authors/edit.html.erb b/app/views/authors/edit.html.erb new file mode 100644 index 0000000..57de572 --- /dev/null +++ b/app/views/authors/edit.html.erb @@ -0,0 +1,10 @@ +
+

Edit author

+ <%= form_for @author do |f|%> + <%= f.label :first_name %> + <%= f.text_field :first_name %> + <%= f.label :last_name %> + <%= f.text_field :last_name %> + <%= f.submit 'Save changes', class: 'btn' %> + <%end%> +
\ No newline at end of file diff --git a/app/views/authors/index.html.erb b/app/views/authors/index.html.erb new file mode 100644 index 0000000..f0509a1 --- /dev/null +++ b/app/views/authors/index.html.erb @@ -0,0 +1,13 @@ +
+ <% @authors.each do |author| %> +
+
+ <%= author.first_name %> <%= author.last_name %> +
+ +
+ <%= link_to 'Edit', edit_author_path(author), class: "btn" %> +
+
+ <% end %> +
diff --git a/app/views/books/edit.html.erb b/app/views/books/edit.html.erb index d45ee1c..78e654f 100644 --- a/app/views/books/edit.html.erb +++ b/app/views/books/edit.html.erb @@ -1,14 +1,16 @@ -

Edit book

-<%= form_for @book do |f|%> - <%= f.label :title %> - <%= f.text_field :title %> - <%= f.label :price %> - <%= f.number_field :price, step: 0.01 %> - - <%= f.submit 'Save changes', class: 'btn' %> -<%end%> \ No newline at end of file +
+

Edit book

+ <%= form_for @book do |f|%> + <%= f.label :title %> + <%= f.text_field :title %> + <%= f.label :price %> + <%= f.number_field :price, step: 0.01 %> + + <%= f.submit 'Save changes', class: 'btn' %> + <%end%> +
\ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 455b4e4..0bffcd9 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -8,22 +8,40 @@ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> + <%= javascript_include_tag 'rails-ujs' %> - <%= link_to 'Home', '/welcome', method: :get%> - <%= link_to 'Books', '/books', method: :get%> - <% flash.each do |type, notice| %> -
- <% if notice.is_a? String %> - <%= notice %> - <% else %> - <% notice.each do |msg| %> -
<%= msg %>
- <% end %> +
+
+
+ <%= link_to 'Home', '/welcome', method: :get%> +
+ +
+ <%= link_to 'Books', '/books', method: :get%> +
+ <% if current_user&.admin? %> +
+ <%= link_to 'Authors', '/authors', method: :get%> +
+
+ <%= link_to 'Users', '/users', method: :get%> +
<% end %>
- <% end %> + <% flash.each do |type, notice| %> +
+ <% if notice.is_a? String %> + <%= notice %> + <% else %> + <% notice.each do |msg| %> +
<%= msg %>
+ <% end %> + <% end %> +
+ <% end %> +
<%= yield %> diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb index 23315d8..9d3fca7 100644 --- a/app/views/sessions/new.html.erb +++ b/app/views/sessions/new.html.erb @@ -1,9 +1,11 @@ -

Login

- <%= form_tag '/login' do %> - <%= label_tag :email%> - <%= text_field_tag :email %> - <%= label_tag :password%> - <%= password_field_tag :password%> - <%= submit_tag "Login", class: 'btn' %> -<%end%> -<%= link_to "Password recovery", '/password_recovery_request', method: :get%> \ No newline at end of file +
+

Login

+ <%= form_tag '/login' do %> + <%= label_tag :email%> + <%= text_field_tag :email %> + <%= label_tag :password%> + <%= password_field_tag :password%> + <%= submit_tag "Login", class: 'btn' %> + <%end%> + <%= link_to "Password recovery", '/password_recovery_request', method: :get %> +
diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index dc85f35..5a3f277 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,8 +1,10 @@ -

Welcome

-<% if logged_in? %> - You are Logged In, <%= current_user.email %> - <%= button_to "Logout", '/logout', method: :get, class: 'btn' %> -<% else %> - <%= button_to "Login", '/login', method: :get, class: 'btn' %> - <%= button_to "Sign Up", '/users/new', method: :get, class: 'btn' %> -<% end %> +
+

Welcome

+ <% if logged_in? %> + You are Logged In, <%= current_user.email %> + <%= button_to "Logout", '/logout', method: :get, class: 'btn' %> + <% else %> + <%= button_to "Login", '/login', method: :get, class: 'btn' %> + <%= button_to "Sign Up", '/users/new', method: :get, class: 'btn' %> + <% end %> +
diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000..bd6b704 --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,15 @@ +
+ <% @users.each do |user| %> +
+
+ <%= user.email %> +
+
+ <%= user.role %> +
+
+ <%= link_to 'Delete', user, method: :delete, class: "btn" %> +
+
+ <% end %> +
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb index d81b5bf..a4ce410 100644 --- a/app/views/users/new.html.erb +++ b/app/views/users/new.html.erb @@ -1,8 +1,10 @@ -

Sign Up

-<%= form_for @user do |f|%> - <%= f.label :email%> - <%= f.text_field :email%> - <%= f.label :password%> - <%= f.password_field :password%> - <%= f.submit 'Sign up', class: 'btn' %> -<%end%> \ No newline at end of file +
+

Sign Up

+ <%= form_for @user do |f|%> + <%= f.label :email%> + <%= f.text_field :email%> + <%= f.label :password%> + <%= f.password_field :password%> + <%= f.submit 'Sign up', class: 'btn' %> + <%end%> +
diff --git a/app/views/users/password_recovery_request_form.erb b/app/views/users/password_recovery_request_form.erb index 66a90a4..b267001 100644 --- a/app/views/users/password_recovery_request_form.erb +++ b/app/views/users/password_recovery_request_form.erb @@ -1,7 +1,9 @@ -

Password recovery

-Provide an email to password recovery -<%= form_with url: "/password_recovery_request", method: :post do |f| %> - <%= f.label :email%>
- <%= f.text_field :email %> - <%= f.submit 'Send email', class: 'btn' %> -<% end %> \ No newline at end of file +
+

Password recovery

+ Provide an email to password recovery + <%= form_with url: "/password_recovery_request", method: :post do |f| %> + <%= f.label :email%>
+ <%= f.text_field :email %> + <%= f.submit 'Send email', class: 'btn' %> + <% end %> +
diff --git a/app/views/users/recover_password_form.html.erb b/app/views/users/recover_password_form.html.erb index 91f0d43..29e7b58 100644 --- a/app/views/users/recover_password_form.html.erb +++ b/app/views/users/recover_password_form.html.erb @@ -1,11 +1,13 @@ -

Provide new password

+
+

Provide new password

-<%= form_with url: '/recover_password', method: :post do |f| %> - <%= f.label :password%> - <%= f.password_field :password %> - <%= f.label :password_confirmation%> - <%= f.password_field :password_confirmation %> - <%= f.hidden_field :recovery_password, :value => @recovery_password %> - <%= f.hidden_field :user_id, :value => @user_id %> - <%= f.submit 'Change password', class: 'btn' %> -<% end %> \ No newline at end of file + <%= form_with url: '/recover_password', method: :post do |f| %> + <%= f.label :password%> + <%= f.password_field :password %> + <%= f.label :password_confirmation%> + <%= f.password_field :password_confirmation %> + <%= f.hidden_field :recovery_password, :value => @recovery_password %> + <%= f.hidden_field :user_id, :value => @user_id %> + <%= f.submit 'Change password', class: 'btn' %> + <% end %> +
diff --git a/config/environments/development.rb b/config/environments/development.rb index 7a9f6c3..93cd1a8 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -56,7 +56,8 @@ Rails.application.configure do # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. - config.assets.debug = true + config.assets.debug = false + config.assets.check_precompiled_asset = false # Suppress logger output for asset requests. config.assets.quiet = true diff --git a/config/routes.rb b/config/routes.rb index 43ec56d..6f791c6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,5 @@ Rails.application.routes.draw do - resources :users, only: [:new, :create] + resources :users get 'login', to: 'sessions#new' get 'logout', to: 'sessions#delete' post 'login', to: 'sessions#create' @@ -9,4 +9,5 @@ Rails.application.routes.draw do get 'recover_password/:id/:recovery_password', to: 'users#recover_password_form' post 'recover_password', to: 'users#recover_password' resources :books + resources :authors end From 2804c55fd92a750d52acf83ed5a9567ef23799b0 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Sun, 21 Mar 2021 23:43:09 +0100 Subject: [PATCH 16/23] user blocking --- app/controllers/sessions_controller.rb | 14 ++++++++++++-- app/controllers/users_controller.rb | 7 ++++++- app/models/user.rb | 2 ++ app/views/users/index.html.erb | 10 ++++++++-- config/routes.rb | 1 + db/migrate/20210321213901_add_status_to_users.rb | 5 +++++ db/schema.rb | 3 ++- db/seeds.rb | 9 ++++++--- spec/controllers/users_controller_spec.rb | 4 ++-- 9 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 db/migrate/20210321213901_add_status_to_users.rb diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index ac1e0c8..da232a7 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -4,9 +4,19 @@ class SessionsController < ApplicationController def create @user = User.find_by(email: params[:email]) - if @user && @user.authenticate(params[:password]) - session[:user_id] = @user.id + unless @user + redirect_to '/welcome', notice: 'Wrong email address' + return end + unless @user.authenticate(params[:password]) + redirect_to '/welcome', notice: 'Wrong password' + return + end + if @user.blocked? + redirect_to '/welcome', notice: 'You are blocked, please contact support' + return + end + session[:user_id] = @user.id redirect_to '/welcome' end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index ec02862..841daa0 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,5 @@ class UsersController < ApplicationController - before_action :ensure_admin, only: [:destroy] + before_action :ensure_admin, only: [:destroy, :block] def index @users = User.all @@ -56,4 +56,9 @@ class UsersController < ApplicationController User.destroy(params[:id]) redirect_to '/users' end + + def block + User.find(params[:id]).update(status: :blocked) + redirect_to '/users' + end end diff --git a/app/models/user.rb b/app/models/user.rb index 9731bb0..a4f75f3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -2,9 +2,11 @@ class User < ApplicationRecord has_secure_password has_secure_password :recovery_password, validations: false enum role: [:customer, :admin], _default: :customer + enum status: [:ready, :blocked], _default: :ready validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP } validates :role, presence: true + validates :status, presence: true validates :password, { presence: true, length: { minimum: 8 }, diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb index bd6b704..bc5ecb1 100644 --- a/app/views/users/index.html.erb +++ b/app/views/users/index.html.erb @@ -4,12 +4,18 @@
<%= user.email %>
-
+
<%= user.role %>
-
+
+ <%= user.status %> +
+
<%= link_to 'Delete', user, method: :delete, class: "btn" %>
+
+ <%= link_to 'Block', "/user/#{user.id}/block", method: :post, class: "btn" %> +
<% end %>
diff --git a/config/routes.rb b/config/routes.rb index 6f791c6..e9d2b49 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,7 @@ Rails.application.routes.draw do post 'password_recovery_request', to: 'users#password_recovery_request' get 'recover_password/:id/:recovery_password', to: 'users#recover_password_form' post 'recover_password', to: 'users#recover_password' + post 'user/:id/block', to: 'users#block' resources :books resources :authors end diff --git a/db/migrate/20210321213901_add_status_to_users.rb b/db/migrate/20210321213901_add_status_to_users.rb new file mode 100644 index 0000000..d0de06d --- /dev/null +++ b/db/migrate/20210321213901_add_status_to_users.rb @@ -0,0 +1,5 @@ +class AddStatusToUsers < ActiveRecord::Migration[6.1] + def change + add_column :users, :status, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index fb945c3..4a38152 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: 2021_03_21_135711) do +ActiveRecord::Schema.define(version: 2021_03_21_213901) do create_table "authors", force: :cascade do |t| t.string "first_name" @@ -45,6 +45,7 @@ ActiveRecord::Schema.define(version: 2021_03_21_135711) do t.datetime "updated_at", precision: 6, null: false t.string "recovery_password_digest" t.integer "role" + t.integer "status" end end diff --git a/db/seeds.rb b/db/seeds.rb index 74e1732..5f2ae2a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -40,16 +40,19 @@ User.create([ { email: 'abc@o2.pl', password: 'aaaaaaaa', - role: :admin + role: :admin, + status: :ready }, { email: 'abcd@o2.pl', password: 'aaaaaaaa', - role: :customer + role: :customer, + status: :ready }, { email: 'abcde@o2.pl', password: 'aaaaaaaa', - role: :customer + role: :customer, + status: :ready }, ]) \ No newline at end of file diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 5a5c41d..63d46bf 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -5,7 +5,7 @@ RSpec.describe UsersController do User.destroy_all end let(:user1) do - User.create(email: 'test1@example.com', password: 'abcde', recovery_password: 'recovery password') + User.create(email: 'test1@example.com', password: 'abcdefgh', recovery_password: 'recovery password') end describe 'get new' do subject { get :new } @@ -15,7 +15,7 @@ RSpec.describe UsersController do end describe 'get create' do subject do - get :create, params: {user: {email: 'test2@example.com', password: 'abcde'}} + get :create, params: {user: {email: 'test2@example.com', password: 'abcdefgh'}} end it 'creates a user' do subject From c2dfc1f04a63293d59325a9371c4e47582ec969e Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Mon, 22 Mar 2021 00:54:45 +0100 Subject: [PATCH 17/23] AuditRecord --- app/models/application_record.rb | 15 +++++++++++++++ app/models/audit_record.rb | 2 ++ db/migrate/20210321225317_create_audit_records.rb | 11 +++++++++++ db/schema.rb | 10 +++++++++- spec/models/audit_record_spec.rb | 5 +++++ 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 app/models/audit_record.rb create mode 100644 db/migrate/20210321225317_create_audit_records.rb create mode 100644 spec/models/audit_record_spec.rb diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 10a4cba..d894dc0 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,3 +1,18 @@ class ApplicationRecord < ActiveRecord::Base self.abstract_class = true + def update(*args) + result = super(*args) + AuditRecord.create(model: self.class, action: 'update', params: self.to_json) + result + end + def save(*args) + result = super(*args) + AuditRecord.create(model: self.class, action: 'save', params: self.to_json) + result + end + def self.create(*args) + result = super(*args) + AuditRecord.create(model: self.class, action: 'create', params: result.to_json) + result + end end diff --git a/app/models/audit_record.rb b/app/models/audit_record.rb new file mode 100644 index 0000000..f11cf2b --- /dev/null +++ b/app/models/audit_record.rb @@ -0,0 +1,2 @@ +class AuditRecord < ActiveRecord::Base +end diff --git a/db/migrate/20210321225317_create_audit_records.rb b/db/migrate/20210321225317_create_audit_records.rb new file mode 100644 index 0000000..e376865 --- /dev/null +++ b/db/migrate/20210321225317_create_audit_records.rb @@ -0,0 +1,11 @@ +class CreateAuditRecords < ActiveRecord::Migration[6.1] + def change + create_table :audit_records do |t| + t.string :model + t.string :action + t.string :params + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 4a38152..44467b1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,15 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_03_21_213901) do +ActiveRecord::Schema.define(version: 2021_03_21_225317) do + + create_table "audit_records", force: :cascade do |t| + t.string "model" + t.string "action" + t.string "params" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end create_table "authors", force: :cascade do |t| t.string "first_name" diff --git a/spec/models/audit_record_spec.rb b/spec/models/audit_record_spec.rb new file mode 100644 index 0000000..24cf532 --- /dev/null +++ b/spec/models/audit_record_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe AuditRecord, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end From 733870ce968d8589d2d7cb283e1fe1b40843b828 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Mon, 22 Mar 2021 01:24:13 +0100 Subject: [PATCH 18/23] books quantity --- app/assets/stylesheets/application.scss | 2 +- app/controllers/books_controller.rb | 2 +- app/views/books/index.html.erb | 29 +++++++++++---- app/views/layouts/application.html.erb | 35 +++++++++++-------- .../20210321235625_add_quantity_to_books.rb | 5 +++ db/schema.rb | 3 +- db/seeds.rb | 9 +++-- 7 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 db/migrate/20210321235625_add_quantity_to_books.rb diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index e1ecc73..64cc60f 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -2,5 +2,5 @@ @import "https://fonts.googleapis.com/icon?family=Material+Icons"; body { - margin: 100px; + margin: 10px; } \ No newline at end of file diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb index 499d455..4eb947d 100644 --- a/app/controllers/books_controller.rb +++ b/app/controllers/books_controller.rb @@ -3,7 +3,7 @@ class BooksController < ApplicationController before_action :ensure_admin, only: [:edit, :update] def index - if current_user.admin? + if current_user&.admin? books = Book.all else books = Book.published diff --git a/app/views/books/index.html.erb b/app/views/books/index.html.erb index b1bb82a..2359275 100644 --- a/app/views/books/index.html.erb +++ b/app/views/books/index.html.erb @@ -1,20 +1,35 @@
+
+
Title
+
Authors
+
Price
+
Quantity
+ +
<% @books.each do |book| %>
+
+ <%= link_to book.title, book %> +
+
- Title: <%= link_to book.title, book %> + <%= book.authors %>
-
- Price: <%= book.price_with_currency %> +
+ <%= book.price_with_currency %>
-
- Authors: <%= book.authors %> - +
+ <%= book.quantity %> +
+
+ <% if logged_in? && book.quantity.positive? %> + <%= link_to 'Add', edit_book_path(book), class: "btn" %> + <% end %>
- <% if current_user.admin? %> + <% if current_user&.admin? %>
<%= book.published ? 'published' : 'unpublished' %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 0bffcd9..af8d743 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -13,22 +13,29 @@
-
-
- <%= link_to 'Home', '/welcome', method: :get%> -
+
+
+
+ <%= link_to 'Home', '/welcome', method: :get%> +
-
- <%= link_to 'Books', '/books', method: :get%> +
+ <%= link_to 'Books', '/books', method: :get%> +
+ <% if current_user&.admin? %> +
+ <%= link_to 'Authors', '/authors', method: :get%> +
+
+ <%= link_to 'Users', '/users', method: :get%> +
+ <% end %> + <% if logged_in? %> +
+ <%= link_to 'Shopping cart', '/authors', method: :get%> +
+ <% end %>
- <% if current_user&.admin? %> -
- <%= link_to 'Authors', '/authors', method: :get%> -
-
- <%= link_to 'Users', '/users', method: :get%> -
- <% end %>
<% flash.each do |type, notice| %>
diff --git a/db/migrate/20210321235625_add_quantity_to_books.rb b/db/migrate/20210321235625_add_quantity_to_books.rb new file mode 100644 index 0000000..ee6dbc1 --- /dev/null +++ b/db/migrate/20210321235625_add_quantity_to_books.rb @@ -0,0 +1,5 @@ +class AddQuantityToBooks < ActiveRecord::Migration[6.1] + def change + add_column :books, :quantity, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 44467b1..27ba16b 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: 2021_03_21_225317) do +ActiveRecord::Schema.define(version: 2021_03_21_235625) do create_table "audit_records", force: :cascade do |t| t.string "model" @@ -43,6 +43,7 @@ ActiveRecord::Schema.define(version: 2021_03_21_225317) do t.boolean "published" t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.integer "quantity" t.index ["published"], name: "index_books_on_published" end diff --git a/db/seeds.rb b/db/seeds.rb index 5f2ae2a..f2c9c04 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -2,17 +2,20 @@ books = Book.create([ { title: 'Journey to the Center of the Earth', price: 10900, - published: true + published: true, + quantity: 100 }, { title: 'From the Earth to the Moon', price: 6300, - published: false + published: false, + quantity: 0 }, { title: 'Imaginary trip', price: 3600, - published: true + published: true, + quantity: 0 }, ]) From df7585c5e17294a73da20eddec000b401414bdf0 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Mon, 22 Mar 2021 02:25:17 +0100 Subject: [PATCH 19/23] shopping cart --- app/controllers/books_controller.rb | 13 ++++++++++- app/models/application_record.rb | 5 +++++ app/models/user.rb | 2 ++ app/views/books/index.html.erb | 4 ++-- app/views/books/shopping_cart.erb | 22 +++++++++++++++++++ app/views/layouts/application.html.erb | 2 +- config/routes.rb | 3 +++ .../20210322002803_create_books_users.rb | 10 +++++++++ db/schema.rb | 11 +++++++++- db/seeds.rb | 13 ++++++++++- spec/models/audit_record_spec.rb | 5 ----- 11 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 app/views/books/shopping_cart.erb create mode 100644 db/migrate/20210322002803_create_books_users.rb delete mode 100644 spec/models/audit_record_spec.rb diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb index 4eb947d..29b4e35 100644 --- a/app/controllers/books_controller.rb +++ b/app/controllers/books_controller.rb @@ -1,5 +1,5 @@ class BooksController < ApplicationController - before_action :set_book, only: [:show, :edit, :update] + before_action :set_book, only: [:show, :edit, :update, :add_to_cart] before_action :ensure_admin, only: [:edit, :update] def index @@ -23,6 +23,17 @@ class BooksController < ApplicationController end end + def add_to_cart + @book = Book.find(params[:id]) + current_user.books << @book + @book.decrement!(:quantity) + redirect_to '/books', notice: 'Book added to your cart' + end + + def shopping_cart + @books = current_user.books.map { |book| BooksPresenter.new(book) } + end + private def set_book diff --git a/app/models/application_record.rb b/app/models/application_record.rb index d894dc0..2b160a5 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -15,4 +15,9 @@ class ApplicationRecord < ActiveRecord::Base AuditRecord.create(model: self.class, action: 'create', params: result.to_json) result end + def decrement!(*args) + result = super(*args) + AuditRecord.create(model: self.class, action: 'decrement!', params: self.to_json) + result + end end diff --git a/app/models/user.rb b/app/models/user.rb index a4f75f3..fef0b53 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,6 @@ class User < ApplicationRecord + has_and_belongs_to_many :books + has_secure_password has_secure_password :recovery_password, validations: false enum role: [:customer, :admin], _default: :customer diff --git a/app/views/books/index.html.erb b/app/views/books/index.html.erb index 2359275..d13fc32 100644 --- a/app/views/books/index.html.erb +++ b/app/views/books/index.html.erb @@ -24,8 +24,8 @@ <%= book.quantity %>
- <% if logged_in? && book.quantity.positive? %> - <%= link_to 'Add', edit_book_path(book), class: "btn" %> + <% if logged_in? && book.quantity.positive? && !current_user.books.exists?(book.id) %> + <%= link_to 'Add', "book/#{book.id}/add_to_cart", method: :post, class: "btn" %> <% end %>
diff --git a/app/views/books/shopping_cart.erb b/app/views/books/shopping_cart.erb new file mode 100644 index 0000000..8b6ee48 --- /dev/null +++ b/app/views/books/shopping_cart.erb @@ -0,0 +1,22 @@ +
+
+
Title
+
Authors
+
Price
+
+ <% @books.each do |book| %> +
+
+ <%= link_to book.title, book %> +
+ +
+ <%= book.authors %> +
+ +
+ <%= book.price_with_currency %> +
+
+ <% end %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index af8d743..904da48 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -32,7 +32,7 @@ <% end %> <% if logged_in? %>
- <%= link_to 'Shopping cart', '/authors', method: :get%> + <%= link_to 'Shopping cart', '/shopping_cart', method: :get%>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb index e9d2b49..4c8765d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,9 @@ Rails.application.routes.draw do get 'recover_password/:id/:recovery_password', to: 'users#recover_password_form' post 'recover_password', to: 'users#recover_password' post 'user/:id/block', to: 'users#block' + post 'book/:id/add_to_cart', to: 'books#add_to_cart' + get 'shopping_cart', to: 'books#shopping_cart' + resources :books resources :authors end diff --git a/db/migrate/20210322002803_create_books_users.rb b/db/migrate/20210322002803_create_books_users.rb new file mode 100644 index 0000000..d852ec0 --- /dev/null +++ b/db/migrate/20210322002803_create_books_users.rb @@ -0,0 +1,10 @@ +class CreateBooksUsers < ActiveRecord::Migration[6.1] + def change + create_table :books_users do |t| + t.belongs_to :book + t.belongs_to :user + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 27ba16b..5580947 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: 2021_03_21_235625) do +ActiveRecord::Schema.define(version: 2021_03_22_002803) do create_table "audit_records", force: :cascade do |t| t.string "model" @@ -47,6 +47,15 @@ ActiveRecord::Schema.define(version: 2021_03_21_235625) do t.index ["published"], name: "index_books_on_published" end + create_table "books_users", force: :cascade do |t| + t.integer "book_id" + t.integer "user_id" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["book_id"], name: "index_books_users_on_book_id" + t.index ["user_id"], name: "index_books_users_on_user_id" + end + create_table "users", force: :cascade do |t| t.string "email" t.string "password_digest" diff --git a/db/seeds.rb b/db/seeds.rb index f2c9c04..1cdfbec 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -15,7 +15,13 @@ books = Book.create([ title: 'Imaginary trip', price: 3600, published: true, - quantity: 0 + quantity: 1 + }, + { + title: 'Winnie the Pooh', + price: 3700, + published: true, + quantity: 5 }, ]) @@ -32,12 +38,17 @@ authors = Author.create([ first_name: 'Rick', last_name: 'Pickle' }, + { + first_name: 'Alan', + last_name: 'Milne' + }, ]) books.first.authors << authors.first books.second.authors << authors.first books.third.authors << authors.second books.third.authors << authors.third +books.fourth.authors << authors.fourth User.create([ { diff --git a/spec/models/audit_record_spec.rb b/spec/models/audit_record_spec.rb deleted file mode 100644 index 24cf532..0000000 --- a/spec/models/audit_record_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe AuditRecord, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end From c63c6bc448b18b57e318848c5ae8fbb460852d45 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Mon, 22 Mar 2021 02:49:05 +0100 Subject: [PATCH 20/23] cart summary and refactoring --- app/controllers/books_controller.rb | 2 ++ app/helpers/books_helper.rb | 6 ++++++ app/views/books/index.html.erb | 10 +++++----- app/views/books/shopping_cart.erb | 10 +++++++--- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb index 29b4e35..190b6da 100644 --- a/app/controllers/books_controller.rb +++ b/app/controllers/books_controller.rb @@ -25,6 +25,8 @@ class BooksController < ApplicationController def add_to_cart @book = Book.find(params[:id]) + return unless @book.quantity.positive? + current_user.books << @book @book.decrement!(:quantity) redirect_to '/books', notice: 'Book added to your cart' diff --git a/app/helpers/books_helper.rb b/app/helpers/books_helper.rb index 4b9311e..00d4182 100644 --- a/app/helpers/books_helper.rb +++ b/app/helpers/books_helper.rb @@ -1,2 +1,8 @@ module BooksHelper + def cart_summary + number_to_currency(@books.map{ |b| b.price }.reduce(:+)) + end + def can_book_be_added?(book) + logged_in? && book.quantity.positive? && !current_user.books.exists?(book.id) + end end diff --git a/app/views/books/index.html.erb b/app/views/books/index.html.erb index d13fc32..412346b 100644 --- a/app/views/books/index.html.erb +++ b/app/views/books/index.html.erb @@ -1,9 +1,9 @@
-
Title
-
Authors
-
Price
-
Quantity
+
Title
+
Authors
+
Price
+
Quantity
<% @books.each do |book| %> @@ -24,7 +24,7 @@ <%= book.quantity %>
- <% if logged_in? && book.quantity.positive? && !current_user.books.exists?(book.id) %> + <% if can_book_be_added?(book) %> <%= link_to 'Add', "book/#{book.id}/add_to_cart", method: :post, class: "btn" %> <% end %>
diff --git a/app/views/books/shopping_cart.erb b/app/views/books/shopping_cart.erb index 8b6ee48..39f6cdf 100644 --- a/app/views/books/shopping_cart.erb +++ b/app/views/books/shopping_cart.erb @@ -1,8 +1,8 @@
-
Title
-
Authors
-
Price
+
Title
+
Authors
+
Price
<% @books.each do |book| %>
@@ -19,4 +19,8 @@
<% end %> +
+
Summary
+
<%= cart_summary %>
+
From de29815686eb4bbaec0b4770bb9cb66126d89396 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Mon, 22 Mar 2021 03:16:29 +0100 Subject: [PATCH 21/23] rubocop corrections --- Gemfile | 14 +- Gemfile.lock | 20 +++ Rakefile | 4 +- app/channels/application_cable/channel.rb | 2 + app/channels/application_cable/connection.rb | 2 + app/controllers/application_controller.rb | 13 +- app/controllers/authors_controller.rb | 9 +- app/controllers/books_controller.rb | 27 ++-- app/controllers/sessions_controller.rb | 38 +++--- app/controllers/users_controller.rb | 10 +- app/helpers/application_helper.rb | 2 + app/helpers/books_helper.rb | 5 +- app/helpers/sessions_helper.rb | 2 + app/helpers/users_helper.rb | 2 + app/jobs/application_job.rb | 2 + app/mailers/application_mailer.rb | 2 + app/mailers/user_mailer.rb | 2 + app/models/application_record.rb | 11 +- app/models/audit_record.rb | 2 + app/models/author.rb | 2 + app/models/book.rb | 2 + app/models/user.rb | 8 +- app/presenters/books_presenter.rb | 2 + bin/bundle | 46 ++++--- bin/rails | 8 +- bin/rake | 8 +- bin/setup | 4 +- bin/spring | 14 +- bin/webpack | 19 +-- bin/webpack-dev-server | 19 +-- bin/yarn | 16 ++- config.ru | 4 +- config/application.rb | 6 +- config/boot.rb | 6 +- config/environment.rb | 4 +- config/environments/development.rb | 4 +- config/environments/production.rb | 10 +- config/environments/test.rb | 4 +- .../application_controller_renderer.rb | 1 + config/initializers/assets.rb | 2 + config/initializers/backtrace_silencers.rb | 4 +- .../initializers/content_security_policy.rb | 1 + config/initializers/cookies_serializer.rb | 2 + .../initializers/filter_parameter_logging.rb | 6 +- config/initializers/inflections.rb | 1 + config/initializers/mime_types.rb | 1 + config/initializers/permissions_policy.rb | 1 + config/initializers/wrap_parameters.rb | 2 + config/puma.rb | 14 +- config/routes.rb | 2 + config/spring.rb | 10 +- db/migrate/20210319142051_create_authors.rb | 4 +- db/migrate/20210319142054_create_books.rb | 2 + .../20210319142059_create_authors_books.rb | 2 + db/migrate/20210320130542_create_users.rb | 2 + ...20210320212922_change_username_to_email.rb | 2 + ...401_add_password_recovery_code_to_users.rb | 2 + ...covery_code_to_recovery_password_digest.rb | 2 + .../20210321135711_add_role_to_users.rb | 2 + .../20210321213901_add_status_to_users.rb | 2 + .../20210321225317_create_audit_records.rb | 2 + .../20210321235625_add_quantity_to_books.rb | 2 + .../20210322002803_create_books_users.rb | 2 + db/schema.rb | 90 ++++++------- db/seeds.rb | 124 +++++++++--------- .../application_controller_spec.rb | 4 +- spec/controllers/sessions_controller_spec.rb | 8 +- spec/controllers/users_controller_spec.rb | 14 +- spec/mailers/previews/user_mailer_preview.rb | 3 +- spec/mailers/user_mailer_spec.rb | 4 +- spec/rails_helper.rb | 4 +- spec/spec_helper.rb | 100 +++++++------- 72 files changed, 468 insertions(+), 311 deletions(-) diff --git a/Gemfile b/Gemfile index 2b78fd1..a3cd5db 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } @@ -32,12 +34,14 @@ gem 'jquery-rails' # Reduces boot times through caching; required in config/boot.rb gem 'bootsnap', '>= 1.4.4', require: false +gem 'rubocop', require: false + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] - gem 'rspec' - gem 'rspec-rails', ">= 2.0.0.beta" + gem 'byebug', platforms: %i[mri mingw x64_mingw] gem 'rails-controller-testing' + gem 'rspec' + gem 'rspec-rails', '>= 2.0.0.beta' end group :development do @@ -45,8 +49,8 @@ group :development do gem 'web-console', '>= 4.1.0' # Display performance information such as SQL time and flame graphs for each request in your browser. # Can be configured to work on production as well see: https://github.com/MiniProfiler/rack-mini-profiler/blob/master/README.md - gem 'rack-mini-profiler', '~> 2.0' gem 'listen', '~> 3.3' + gem 'rack-mini-profiler', '~> 2.0' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' end @@ -60,4 +64,4 @@ group :test do end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem -gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] +gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby] diff --git a/Gemfile.lock b/Gemfile.lock index 7c63543..a2efec0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -62,6 +62,7 @@ GEM zeitwerk (~> 2.3) addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) + ast (2.4.2) autoprefixer-rails (10.2.4.0) execjs bcrypt (3.1.16) @@ -117,6 +118,9 @@ GEM nokogiri (1.11.2) mini_portile2 (~> 2.5.0) racc (~> 1.4) + parallel (1.20.1) + parser (3.0.0.0) + ast (~> 2.4.1) public_suffix (4.0.6) puma (5.2.2) nio4r (~> 2.0) @@ -158,11 +162,13 @@ GEM method_source rake (>= 0.8.7) thor (~> 1.0) + rainbow (3.0.0) rake (13.0.3) rb-fsevent (0.10.4) rb-inotify (0.10.1) ffi (~> 1.0) regexp_parser (2.1.1) + rexml (3.2.4) rspec (3.10.0) rspec-core (~> 3.10.0) rspec-expectations (~> 3.10.0) @@ -184,6 +190,18 @@ GEM rspec-mocks (~> 3.10) rspec-support (~> 3.10) rspec-support (3.10.2) + rubocop (1.11.0) + parallel (~> 1.10) + parser (>= 3.0.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.2.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.4.1) + parser (>= 2.7.1.5) + ruby-progressbar (1.11.0) rubyzip (2.3.0) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) @@ -215,6 +233,7 @@ GEM turbolinks-source (5.2.0) tzinfo (2.0.4) concurrent-ruby (~> 1.0) + unicode-display_width (2.0.0) web-console (4.1.0) actionview (>= 6.0.0) activemodel (>= 6.0.0) @@ -254,6 +273,7 @@ DEPENDENCIES rails-controller-testing rspec rspec-rails (>= 2.0.0.beta) + rubocop sass-rails (>= 6) selenium-webdriver spring diff --git a/Rakefile b/Rakefile index 9a5ea73..488c551 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. -require_relative "config/application" +require_relative 'config/application' Rails.application.load_tasks diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb index d672697..9aec230 100644 --- a/app/channels/application_cable/channel.rb +++ b/app/channels/application_cable/channel.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationCable class Channel < ActionCable::Channel::Base end diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index 0ff5442..8d6c2a1 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module ApplicationCable class Connection < ActionCable::Connection::Base end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4e12a38..97eed14 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,3 +1,6 @@ +# frozen_string_literal: true + +# Base for application controllers class ApplicationController < ActionController::Base helper_method :current_user helper_method :logged_in? @@ -5,7 +8,7 @@ class ApplicationController < ActionController::Base def current_user User.find_by(id: session[:user_id]) end - + def logged_in? !current_user.nil? end @@ -13,15 +16,13 @@ class ApplicationController < ActionController::Base protected def notices_from_errors(record) - messages = record.errors.messages.map do |attribute, messages| + errors = record.errors.messages.map do |attribute, messages| messages.map { |message| "#{attribute} #{message}".capitalize } end - messages.flatten + errors.flatten end def ensure_admin - unless current_user&.admin? - redirect_to '/welcome', notice: 'You are not allowed to perform this action' - end + redirect_to '/welcome', notice: 'You are not allowed to perform this action' unless current_user&.admin? end end diff --git a/app/controllers/authors_controller.rb b/app/controllers/authors_controller.rb index abd8ecb..47bfa01 100644 --- a/app/controllers/authors_controller.rb +++ b/app/controllers/authors_controller.rb @@ -1,6 +1,9 @@ +# frozen_string_literal: true + +# Authors controller class AuthorsController < ApplicationController before_action :ensure_admin - before_action :set_author, only: [:edit, :update] + before_action :set_author, only: %i[edit update] def index @authors = Author.all @@ -11,9 +14,7 @@ class AuthorsController < ApplicationController end def update - if @author.update(author_params) - redirect_to '/authors' - end + redirect_to '/authors' if @author.update(author_params) end private diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb index 190b6da..98071eb 100644 --- a/app/controllers/books_controller.rb +++ b/app/controllers/books_controller.rb @@ -1,26 +1,25 @@ +# frozen_string_literal: true + +# Books controller class BooksController < ApplicationController - before_action :set_book, only: [:show, :edit, :update, :add_to_cart] - before_action :ensure_admin, only: [:edit, :update] + before_action :set_book, only: %i[show edit update add_to_cart] + before_action :ensure_admin, only: %i[edit update] def index - if current_user&.admin? - books = Book.all - else - books = Book.published - end + books = if current_user&.admin? + Book.all + else + Book.published + end @books = books.map { |book| BooksPresenter.new(book) } end - def show - end + def show; end - def edit - end + def edit; end def update - if @book.update(book_params) - redirect_to '/books' - end + redirect_to '/books' if @book.update(book_params) end def add_to_cart diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index da232a7..d89d31d 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,23 +1,18 @@ +# frozen_string_literal: true + +# Sessions controller class SessionsController < ApplicationController - def new - end + def new; end def create @user = User.find_by(email: params[:email]) - unless @user - redirect_to '/welcome', notice: 'Wrong email address' - return + problem = problem_with_login + if problem + redirect_to '/welcome', notice: problem + else + session[:user_id] = @user.id + redirect_to '/welcome' end - unless @user.authenticate(params[:password]) - redirect_to '/welcome', notice: 'Wrong password' - return - end - if @user.blocked? - redirect_to '/welcome', notice: 'You are blocked, please contact support' - return - end - session[:user_id] = @user.id - redirect_to '/welcome' end def delete @@ -25,6 +20,17 @@ class SessionsController < ApplicationController redirect_to '/welcome', notice: 'Logged out properly' end - def welcome + def welcome; end + + private + + def problem_with_login + if !@user + 'Wrong email address' + elsif !@user.authenticate(params[:password]) + 'Wrong password' + elsif @user.blocked? + 'You are blocked, please contact support' + end end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 841daa0..8137d00 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,5 +1,8 @@ +# frozen_string_literal: true + +# Users controller class UsersController < ApplicationController - before_action :ensure_admin, only: [:destroy, :block] + before_action :ensure_admin, only: %i[destroy block] def index @users = User.all @@ -21,15 +24,14 @@ class UsersController < ApplicationController def password_recovery_request @user = User.where(email: params['email']).first - recovery_password = ('a'..'z').to_a.shuffle[0,8].join + recovery_password = ('a'..'z').to_a.sample(8).join @user.recovery_password = recovery_password @user.save UserMailer.with(user: @user, recovery_password: recovery_password).password_recovery.deliver_now redirect_to '/welcome', notice: "Recovery email sent to #{params['email']}" end - def password_recovery_request_form - end + def password_recovery_request_form; end def recover_password_form @recovery_password = params[:recovery_password] diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be79..15b06f0 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module ApplicationHelper end diff --git a/app/helpers/books_helper.rb b/app/helpers/books_helper.rb index 00d4182..0e4b37c 100644 --- a/app/helpers/books_helper.rb +++ b/app/helpers/books_helper.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + module BooksHelper def cart_summary - number_to_currency(@books.map{ |b| b.price }.reduce(:+)) + number_to_currency(@books.map(&:price).reduce(:+)) end + def can_book_be_added?(book) logged_in? && book.quantity.positive? && !current_user.books.exists?(book.id) end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 309f8b2..97aeb4c 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module SessionsHelper end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 2310a24..4dc909e 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + module UsersHelper end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb index d394c3d..bef3959 100644 --- a/app/jobs/application_job.rb +++ b/app/jobs/application_job.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ApplicationJob < ActiveJob::Base # Automatically retry jobs that encountered a deadlock # retry_on ActiveRecord::Deadlocked diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 286b223..d84cb6e 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ApplicationMailer < ActionMailer::Base default from: 'from@example.com' layout 'mailer' diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 7a5ef41..51d0f22 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class UserMailer < ApplicationMailer def password_recovery @user = params[:user] diff --git a/app/models/application_record.rb b/app/models/application_record.rb index 2b160a5..e2e8915 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,23 +1,28 @@ +# frozen_string_literal: true + class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def update(*args) result = super(*args) - AuditRecord.create(model: self.class, action: 'update', params: self.to_json) + AuditRecord.create(model: self.class, action: 'update', params: to_json) result end + def save(*args) result = super(*args) - AuditRecord.create(model: self.class, action: 'save', params: self.to_json) + AuditRecord.create(model: self.class, action: 'save', params: to_json) result end + def self.create(*args) result = super(*args) AuditRecord.create(model: self.class, action: 'create', params: result.to_json) result end + def decrement!(*args) result = super(*args) - AuditRecord.create(model: self.class, action: 'decrement!', params: self.to_json) + AuditRecord.create(model: self.class, action: 'decrement!', params: to_json) result end end diff --git a/app/models/audit_record.rb b/app/models/audit_record.rb index f11cf2b..48a1aab 100644 --- a/app/models/audit_record.rb +++ b/app/models/audit_record.rb @@ -1,2 +1,4 @@ +# frozen_string_literal: true + class AuditRecord < ActiveRecord::Base end diff --git a/app/models/author.rb b/app/models/author.rb index 9f3a806..e7a3204 100644 --- a/app/models/author.rb +++ b/app/models/author.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Author < ApplicationRecord validates :first_name, presence: true validates :last_name, presence: true diff --git a/app/models/book.rb b/app/models/book.rb index e0b5624..67cd8ec 100644 --- a/app/models/book.rb +++ b/app/models/book.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class Book < ApplicationRecord has_and_belongs_to_many :authors diff --git a/app/models/user.rb b/app/models/user.rb index fef0b53..9da6781 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,10 +1,12 @@ +# frozen_string_literal: true + class User < ApplicationRecord has_and_belongs_to_many :books has_secure_password has_secure_password :recovery_password, validations: false - enum role: [:customer, :admin], _default: :customer - enum status: [:ready, :blocked], _default: :ready + enum role: %i[customer admin], _default: :customer + enum status: %i[ready blocked], _default: :ready validates :email, presence: true, uniqueness: true, format: { with: URI::MailTo::EMAIL_REGEXP } validates :role, presence: true @@ -12,6 +14,6 @@ class User < ApplicationRecord validates :password, { presence: true, length: { minimum: 8 }, - if: lambda{ new_record? || !password.nil? } + if: -> { new_record? || !password.nil? } } end diff --git a/app/presenters/books_presenter.rb b/app/presenters/books_presenter.rb index c6b3f40..f382006 100644 --- a/app/presenters/books_presenter.rb +++ b/app/presenters/books_presenter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class BooksPresenter < SimpleDelegator include ActiveSupport::NumberHelper diff --git a/bin/bundle b/bin/bundle index a71368e..73ec947 100755 --- a/bin/bundle +++ b/bin/bundle @@ -8,46 +8,46 @@ # this file is here to facilitate running it. # -require "rubygems" +require 'rubygems' m = Module.new do module_function def invoked_as_script? - File.expand_path($0) == File.expand_path(__FILE__) + File.expand_path($PROGRAM_NAME) == File.expand_path(__FILE__) end def env_var_version - ENV["BUNDLER_VERSION"] + ENV['BUNDLER_VERSION'] end def cli_arg_version return unless invoked_as_script? # don't want to hijack other binstubs - return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + return unless 'update'.start_with?(ARGV.first || ' ') # must be running `bundle update` + bundler_version = nil update_index = nil ARGV.each_with_index do |a, i| - if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN - bundler_version = a - end + bundler_version = a if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ - bundler_version = $1 + + bundler_version = Regexp.last_match(1) update_index = i end bundler_version end def gemfile - gemfile = ENV["BUNDLE_GEMFILE"] + gemfile = ENV['BUNDLE_GEMFILE'] return gemfile if gemfile && !gemfile.empty? - File.expand_path("../../Gemfile", __FILE__) + File.expand_path('../Gemfile', __dir__) end def lockfile lockfile = case File.basename(gemfile) - when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) + when 'gems.rb' then gemfile.sub(/\.rb$/, gemfile) else "#{gemfile}.lock" end File.expand_path(lockfile) @@ -55,15 +55,17 @@ m = Module.new do def lockfile_version return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ + Regexp.last_match(1) end def bundler_version @bundler_version ||= env_var_version || cli_arg_version || - lockfile_version + lockfile_version end def bundler_requirement @@ -73,28 +75,32 @@ m = Module.new do requirement = bundler_gem_version.approximate_recommendation - return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") + return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new('2.7.0') - requirement += ".a" if bundler_gem_version.prerelease? + requirement += '.a' if bundler_gem_version.prerelease? requirement end def load_bundler! - ENV["BUNDLE_GEMFILE"] ||= gemfile + ENV['BUNDLE_GEMFILE'] ||= gemfile activate_bundler end def activate_bundler gem_error = activation_error_handling do - gem "bundler", bundler_requirement + gem 'bundler', bundler_requirement end return if gem_error.nil? + require_error = activation_error_handling do - require "bundler/version" + require 'bundler/version' end - return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + return + end + warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" exit 42 end @@ -109,6 +115,4 @@ end m.load_bundler! -if m.invoked_as_script? - load Gem.bin_path("bundler", "bundle") -end +load Gem.bin_path('bundler', 'bundle') if m.invoked_as_script? diff --git a/bin/rails b/bin/rails index 21d3e02..33ffd90 100755 --- a/bin/rails +++ b/bin/rails @@ -1,5 +1,7 @@ #!/usr/bin/env ruby -load File.expand_path("spring", __dir__) +# frozen_string_literal: true + +load File.expand_path('spring', __dir__) APP_PATH = File.expand_path('../config/application', __dir__) -require_relative "../config/boot" -require "rails/commands" +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake index 7327f47..05ee931 100755 --- a/bin/rake +++ b/bin/rake @@ -1,5 +1,7 @@ #!/usr/bin/env ruby -load File.expand_path("spring", __dir__) -require_relative "../config/boot" -require "rake" +# frozen_string_literal: true + +load File.expand_path('spring', __dir__) +require_relative '../config/boot' +require 'rake' Rake.application.run diff --git a/bin/setup b/bin/setup index 90700ac..0e38d30 100755 --- a/bin/setup +++ b/bin/setup @@ -1,5 +1,7 @@ #!/usr/bin/env ruby -require "fileutils" +# frozen_string_literal: true + +require 'fileutils' # path to your application root. APP_ROOT = File.expand_path('..', __dir__) diff --git a/bin/spring b/bin/spring index b4147e8..e52a4f8 100755 --- a/bin/spring +++ b/bin/spring @@ -1,13 +1,15 @@ #!/usr/bin/env ruby -if !defined?(Spring) && [nil, "development", "test"].include?(ENV["RAILS_ENV"]) - gem "bundler" - require "bundler" +# frozen_string_literal: true + +if !defined?(Spring) && [nil, 'development', 'test'].include?(ENV['RAILS_ENV']) + gem 'bundler' + require 'bundler' # Load Spring without loading other gems in the Gemfile, for speed. - Bundler.locked_gems&.specs&.find { |spec| spec.name == "spring" }&.tap do |spring| + Bundler.locked_gems&.specs&.find { |spec| spec.name == 'spring' }&.tap do |spring| Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path - gem "spring", spring.version - require "spring/binstub" + gem 'spring', spring.version + require 'spring/binstub' rescue Gem::LoadError # Ignore when Spring is not installed. end diff --git a/bin/webpack b/bin/webpack index 1031168..62114ba 100755 --- a/bin/webpack +++ b/bin/webpack @@ -1,18 +1,19 @@ #!/usr/bin/env ruby +# frozen_string_literal: true -ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= "development" +ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development' +ENV['NODE_ENV'] ||= 'development' -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', + Pathname.new(__FILE__).realpath) -require "bundler/setup" +require 'bundler/setup' -require "webpacker" -require "webpacker/webpack_runner" +require 'webpacker' +require 'webpacker/webpack_runner' -APP_ROOT = File.expand_path("..", __dir__) +APP_ROOT = File.expand_path('..', __dir__) Dir.chdir(APP_ROOT) do Webpacker::WebpackRunner.run(ARGV) end diff --git a/bin/webpack-dev-server b/bin/webpack-dev-server index dd96627..e4f41cc 100755 --- a/bin/webpack-dev-server +++ b/bin/webpack-dev-server @@ -1,18 +1,19 @@ #!/usr/bin/env ruby +# frozen_string_literal: true -ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" -ENV["NODE_ENV"] ||= "development" +ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development' +ENV['NODE_ENV'] ||= 'development' -require "pathname" -ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", - Pathname.new(__FILE__).realpath) +require 'pathname' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', + Pathname.new(__FILE__).realpath) -require "bundler/setup" +require 'bundler/setup' -require "webpacker" -require "webpacker/dev_server_runner" +require 'webpacker' +require 'webpacker/dev_server_runner' -APP_ROOT = File.expand_path("..", __dir__) +APP_ROOT = File.expand_path('..', __dir__) Dir.chdir(APP_ROOT) do Webpacker::DevServerRunner.run(ARGV) end diff --git a/bin/yarn b/bin/yarn index 9fab2c3..9da8e5c 100755 --- a/bin/yarn +++ b/bin/yarn @@ -1,17 +1,19 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + APP_ROOT = File.expand_path('..', __dir__) Dir.chdir(APP_ROOT) do - yarn = ENV["PATH"].split(File::PATH_SEPARATOR). - select { |dir| File.expand_path(dir) != __dir__ }. - product(["yarn", "yarn.cmd", "yarn.ps1"]). - map { |dir, file| File.expand_path(file, dir) }. - find { |file| File.executable?(file) } + yarn = ENV['PATH'].split(File::PATH_SEPARATOR) + .reject { |dir| File.expand_path(dir) == __dir__ } + .product(['yarn', 'yarn.cmd', 'yarn.ps1']) + .map { |dir, file| File.expand_path(file, dir) } + .find { |file| File.executable?(file) } if yarn exec yarn, *ARGV else - $stderr.puts "Yarn executable was not detected in the system." - $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + warn 'Yarn executable was not detected in the system.' + warn 'Download Yarn at https://yarnpkg.com/en/docs/install' exit 1 end end diff --git a/config.ru b/config.ru index 4a3c09a..6dc8321 100644 --- a/config.ru +++ b/config.ru @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # This file is used by Rack-based servers to start the application. -require_relative "config/environment" +require_relative 'config/environment' run Rails.application Rails.application.load_server diff --git a/config/application.rb b/config/application.rb index 1dba805..c526332 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,8 @@ -require_relative "boot" +# frozen_string_literal: true -require "rails/all" +require_relative 'boot' + +require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. diff --git a/config/boot.rb b/config/boot.rb index 3cda23b..c04863f 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,4 +1,6 @@ +# frozen_string_literal: true + ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -require "bundler/setup" # Set up gems listed in the Gemfile. -require "bootsnap/setup" # Speed up boot time by caching expensive operations. +require 'bundler/setup' # Set up gems listed in the Gemfile. +require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/environment.rb b/config/environment.rb index cac5315..d5abe55 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,7 @@ +# frozen_string_literal: true + # Load the Rails application. -require_relative "application" +require_relative 'application' # Initialize the Rails application. Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index 93cd1a8..7f56706 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,4 +1,6 @@ -require "active_support/core_ext/integer/time" +# frozen_string_literal: true + +require 'active_support/core_ext/integer/time' Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/config/environments/production.rb b/config/environments/production.rb index 36dd980..bceeda0 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,4 +1,6 @@ -require "active_support/core_ext/integer/time" +# frozen_string_literal: true + +require 'active_support/core_ext/integer/time' Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -53,7 +55,7 @@ Rails.application.configure do config.log_level = :info # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store @@ -88,8 +90,8 @@ Rails.application.configure do # require "syslog/logger" # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') - if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new(STDOUT) + if ENV['RAILS_LOG_TO_STDOUT'].present? + logger = ActiveSupport::Logger.new($stdout) logger.formatter = config.log_formatter config.logger = ActiveSupport::TaggedLogging.new(logger) end diff --git a/config/environments/test.rb b/config/environments/test.rb index 93ed4f1..74b1be2 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,4 +1,6 @@ -require "active_support/core_ext/integer/time" +# frozen_string_literal: true + +require 'active_support/core_ext/integer/time' # The test environment is used exclusively to run your application's # test suite. You never need to work with it otherwise. Remember that diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index 89d2efa..f4556db 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 4b828e8..a9b0d0f 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 33699c3..d43cc1d 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. @@ -5,4 +7,4 @@ # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". -Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] +Rails.backtrace_cleaner.remove_silencers! if ENV['BACKTRACE'] diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index 35d0f26..f3bcce5 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Define an application-wide content security policy diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 5a6a32d..ee8dff9 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb index 4b34a03..3babc73 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [ - :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +Rails.application.config.filter_parameters += %i[ + passw secret token _key crypt salt certificate otp ssn ] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index ac033bf..aa7435f 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index dc18996..6e1d16f 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb index 00f64d7..50bcf4e 100644 --- a/config/initializers/permissions_policy.rb +++ b/config/initializers/permissions_policy.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Define an application-wide HTTP permissions policy. For further # information see https://developers.google.com/web/updates/2018/06/feature-policy # diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index bbfc396..2f3c0db 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/config/puma.rb b/config/puma.rb index d9b3e83..8ae6a78 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,28 +1,30 @@ +# frozen_string_literal: true + # Puma can serve each request in a thread from an internal thread pool. # The `threads` method setting takes two numbers: a minimum and maximum. # Any libraries that use thread pools should be configured to match # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } -min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5) +min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count } threads min_threads_count, max_threads_count # Specifies the `worker_timeout` threshold that Puma will use to wait before # terminating a worker in development environments. # -worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" +worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development' # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 3000 } +port ENV.fetch('PORT', 3000) # Specifies the `environment` that Puma will run in. # -environment ENV.fetch("RAILS_ENV") { "development" } +environment ENV.fetch('RAILS_ENV', 'development') # Specifies the `pidfile` that Puma will use. -pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } +pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid') # Specifies the number of `workers` to boot in clustered mode. # Workers are forked web server processes. If using threads and workers together diff --git a/config/routes.rb b/config/routes.rb index 4c8765d..dfe1a61 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.routes.draw do resources :users get 'login', to: 'sessions#new' diff --git a/config/spring.rb b/config/spring.rb index db5bf13..93cd0ff 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + Spring.watch( - ".ruby-version", - ".rbenv-vars", - "tmp/restart.txt", - "tmp/caching-dev.txt" + '.ruby-version', + '.rbenv-vars', + 'tmp/restart.txt', + 'tmp/caching-dev.txt' ) diff --git a/db/migrate/20210319142051_create_authors.rb b/db/migrate/20210319142051_create_authors.rb index 1265628..d76d005 100644 --- a/db/migrate/20210319142051_create_authors.rb +++ b/db/migrate/20210319142051_create_authors.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateAuthors < ActiveRecord::Migration[6.1] def change create_table :authors do |t| @@ -7,6 +9,6 @@ class CreateAuthors < ActiveRecord::Migration[6.1] t.timestamps end - add_index :authors, [ :first_name, :last_name ] + add_index :authors, %i[first_name last_name] end end diff --git a/db/migrate/20210319142054_create_books.rb b/db/migrate/20210319142054_create_books.rb index 868e375..e819f45 100644 --- a/db/migrate/20210319142054_create_books.rb +++ b/db/migrate/20210319142054_create_books.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateBooks < ActiveRecord::Migration[6.1] def change create_table :books do |t| diff --git a/db/migrate/20210319142059_create_authors_books.rb b/db/migrate/20210319142059_create_authors_books.rb index f26bea6..3bbd6e7 100644 --- a/db/migrate/20210319142059_create_authors_books.rb +++ b/db/migrate/20210319142059_create_authors_books.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateAuthorsBooks < ActiveRecord::Migration[6.1] def change create_table :authors_books do |t| diff --git a/db/migrate/20210320130542_create_users.rb b/db/migrate/20210320130542_create_users.rb index 1fe81e6..c5b5a4d 100644 --- a/db/migrate/20210320130542_create_users.rb +++ b/db/migrate/20210320130542_create_users.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateUsers < ActiveRecord::Migration[6.1] def change create_table :users do |t| diff --git a/db/migrate/20210320212922_change_username_to_email.rb b/db/migrate/20210320212922_change_username_to_email.rb index 7ee7a5a..3f6cd5e 100644 --- a/db/migrate/20210320212922_change_username_to_email.rb +++ b/db/migrate/20210320212922_change_username_to_email.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ChangeUsernameToEmail < ActiveRecord::Migration[6.1] def change rename_column :users, :username, :email diff --git a/db/migrate/20210320233401_add_password_recovery_code_to_users.rb b/db/migrate/20210320233401_add_password_recovery_code_to_users.rb index 157cd56..a0afccc 100644 --- a/db/migrate/20210320233401_add_password_recovery_code_to_users.rb +++ b/db/migrate/20210320233401_add_password_recovery_code_to_users.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddPasswordRecoveryCodeToUsers < ActiveRecord::Migration[6.1] def change add_column :users, :password_recovery_code, :string diff --git a/db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb b/db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb index 25603a4..a88ab42 100644 --- a/db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb +++ b/db/migrate/20210321093857_change_password_recovery_code_to_recovery_password_digest.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class ChangePasswordRecoveryCodeToRecoveryPasswordDigest < ActiveRecord::Migration[6.1] def change rename_column :users, :password_recovery_code, :recovery_password_digest diff --git a/db/migrate/20210321135711_add_role_to_users.rb b/db/migrate/20210321135711_add_role_to_users.rb index a7a966f..c6d293e 100644 --- a/db/migrate/20210321135711_add_role_to_users.rb +++ b/db/migrate/20210321135711_add_role_to_users.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddRoleToUsers < ActiveRecord::Migration[6.1] def change add_column :users, :role, :integer diff --git a/db/migrate/20210321213901_add_status_to_users.rb b/db/migrate/20210321213901_add_status_to_users.rb index d0de06d..09e39e2 100644 --- a/db/migrate/20210321213901_add_status_to_users.rb +++ b/db/migrate/20210321213901_add_status_to_users.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddStatusToUsers < ActiveRecord::Migration[6.1] def change add_column :users, :status, :integer diff --git a/db/migrate/20210321225317_create_audit_records.rb b/db/migrate/20210321225317_create_audit_records.rb index e376865..3efe7bd 100644 --- a/db/migrate/20210321225317_create_audit_records.rb +++ b/db/migrate/20210321225317_create_audit_records.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateAuditRecords < ActiveRecord::Migration[6.1] def change create_table :audit_records do |t| diff --git a/db/migrate/20210321235625_add_quantity_to_books.rb b/db/migrate/20210321235625_add_quantity_to_books.rb index ee6dbc1..2cd1cb3 100644 --- a/db/migrate/20210321235625_add_quantity_to_books.rb +++ b/db/migrate/20210321235625_add_quantity_to_books.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddQuantityToBooks < ActiveRecord::Migration[6.1] def change add_column :books, :quantity, :integer diff --git a/db/migrate/20210322002803_create_books_users.rb b/db/migrate/20210322002803_create_books_users.rb index d852ec0..b870a0a 100644 --- a/db/migrate/20210322002803_create_books_users.rb +++ b/db/migrate/20210322002803_create_books_users.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class CreateBooksUsers < ActiveRecord::Migration[6.1] def change create_table :books_users do |t| diff --git a/db/schema.rb b/db/schema.rb index 5580947..ed53db2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -10,60 +12,58 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_03_22_002803) do - - create_table "audit_records", force: :cascade do |t| - t.string "model" - t.string "action" - t.string "params" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false +ActiveRecord::Schema.define(version: 20_210_322_002_803) do + create_table 'audit_records', force: :cascade do |t| + t.string 'model' + t.string 'action' + t.string 'params' + t.datetime 'created_at', precision: 6, null: false + t.datetime 'updated_at', precision: 6, null: false end - create_table "authors", force: :cascade do |t| - t.string "first_name" - t.string "last_name" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["first_name", "last_name"], name: "index_authors_on_first_name_and_last_name" + create_table 'authors', force: :cascade do |t| + t.string 'first_name' + t.string 'last_name' + t.datetime 'created_at', precision: 6, null: false + t.datetime 'updated_at', precision: 6, null: false + t.index %w[first_name last_name], name: 'index_authors_on_first_name_and_last_name' end - create_table "authors_books", force: :cascade do |t| - t.integer "book_id" - t.integer "author_id" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["author_id"], name: "index_authors_books_on_author_id" - t.index ["book_id"], name: "index_authors_books_on_book_id" + create_table 'authors_books', force: :cascade do |t| + t.integer 'book_id' + t.integer 'author_id' + t.datetime 'created_at', precision: 6, null: false + t.datetime 'updated_at', precision: 6, null: false + t.index ['author_id'], name: 'index_authors_books_on_author_id' + t.index ['book_id'], name: 'index_authors_books_on_book_id' end - create_table "books", force: :cascade do |t| - t.string "title" - t.decimal "price", precision: 10, scale: 2 - t.boolean "published" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.integer "quantity" - t.index ["published"], name: "index_books_on_published" + create_table 'books', force: :cascade do |t| + t.string 'title' + t.decimal 'price', precision: 10, scale: 2 + t.boolean 'published' + t.datetime 'created_at', precision: 6, null: false + t.datetime 'updated_at', precision: 6, null: false + t.integer 'quantity' + t.index ['published'], name: 'index_books_on_published' end - create_table "books_users", force: :cascade do |t| - t.integer "book_id" - t.integer "user_id" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.index ["book_id"], name: "index_books_users_on_book_id" - t.index ["user_id"], name: "index_books_users_on_user_id" + create_table 'books_users', force: :cascade do |t| + t.integer 'book_id' + t.integer 'user_id' + t.datetime 'created_at', precision: 6, null: false + t.datetime 'updated_at', precision: 6, null: false + t.index ['book_id'], name: 'index_books_users_on_book_id' + t.index ['user_id'], name: 'index_books_users_on_user_id' end - create_table "users", force: :cascade do |t| - t.string "email" - t.string "password_digest" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false - t.string "recovery_password_digest" - t.integer "role" - t.integer "status" + create_table 'users', force: :cascade do |t| + t.string 'email' + t.string 'password_digest' + t.datetime 'created_at', precision: 6, null: false + t.datetime 'updated_at', precision: 6, null: false + t.string 'recovery_password_digest' + t.integer 'role' + t.integer 'status' end - end diff --git a/db/seeds.rb b/db/seeds.rb index 1cdfbec..92b4b80 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,48 +1,50 @@ +# frozen_string_literal: true + books = Book.create([ - { - title: 'Journey to the Center of the Earth', - price: 10900, - published: true, - quantity: 100 - }, - { - title: 'From the Earth to the Moon', - price: 6300, - published: false, - quantity: 0 - }, - { - title: 'Imaginary trip', - price: 3600, - published: true, - quantity: 1 - }, - { - title: 'Winnie the Pooh', - price: 3700, - published: true, - quantity: 5 - }, -]) + { + title: 'Journey to the Center of the Earth', + price: 10_900, + published: true, + quantity: 100 + }, + { + title: 'From the Earth to the Moon', + price: 6300, + published: false, + quantity: 0 + }, + { + title: 'Imaginary trip', + price: 3600, + published: true, + quantity: 1 + }, + { + title: 'Winnie the Pooh', + price: 3700, + published: true, + quantity: 5 + } + ]) authors = Author.create([ - { - first_name: 'Jules', - last_name: 'Verne' - }, - { - first_name: 'Dick', - last_name: 'Pick', - }, - { - first_name: 'Rick', - last_name: 'Pickle' - }, - { - first_name: 'Alan', - last_name: 'Milne' - }, -]) + { + first_name: 'Jules', + last_name: 'Verne' + }, + { + first_name: 'Dick', + last_name: 'Pick' + }, + { + first_name: 'Rick', + last_name: 'Pickle' + }, + { + first_name: 'Alan', + last_name: 'Milne' + } + ]) books.first.authors << authors.first books.second.authors << authors.first @@ -51,22 +53,22 @@ books.third.authors << authors.third books.fourth.authors << authors.fourth User.create([ - { - email: 'abc@o2.pl', - password: 'aaaaaaaa', - role: :admin, - status: :ready - }, - { - email: 'abcd@o2.pl', - password: 'aaaaaaaa', - role: :customer, - status: :ready - }, - { - email: 'abcde@o2.pl', - password: 'aaaaaaaa', - role: :customer, - status: :ready - }, -]) \ No newline at end of file + { + email: 'abc@o2.pl', + password: 'aaaaaaaa', + role: :admin, + status: :ready + }, + { + email: 'abcd@o2.pl', + password: 'aaaaaaaa', + role: :customer, + status: :ready + }, + { + email: 'abcde@o2.pl', + password: 'aaaaaaaa', + role: :customer, + status: :ready + } + ]) diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index c6b1a80..7b028e7 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe ApplicationController do @@ -15,4 +17,4 @@ RSpec.describe ApplicationController do describe 'logged_in?' do # TODO end -end \ No newline at end of file +end diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb index 5a7a4f2..e34a98d 100644 --- a/spec/controllers/sessions_controller_spec.rb +++ b/spec/controllers/sessions_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe SessionsController do @@ -8,14 +10,14 @@ RSpec.describe SessionsController do end end describe 'get create' do - # TODO test session status + # TODO: test session status subject { get 'create' } it 'redirects to /welcome' do expect(subject).to redirect_to('/welcome') end end describe 'get delete' do - # TODO test session status + # TODO: test session status subject { get 'delete' } it 'redirects to /welcome' do expect(subject).to redirect_to('/welcome') @@ -27,4 +29,4 @@ RSpec.describe SessionsController do expect(subject).to render_template('sessions/welcome') end end -end \ No newline at end of file +end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index 63d46bf..db741e1 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -1,7 +1,9 @@ +# frozen_string_literal: true + require 'rails_helper' RSpec.describe UsersController do - before(:all) do # TODO change it to cleanup after each test + before(:all) do # TODO: change it to cleanup after each test User.destroy_all end let(:user1) do @@ -15,7 +17,7 @@ RSpec.describe UsersController do end describe 'get create' do subject do - get :create, params: {user: {email: 'test2@example.com', password: 'abcdefgh'}} + get :create, params: { user: { email: 'test2@example.com', password: 'abcdefgh' } } end it 'creates a user' do subject @@ -34,13 +36,13 @@ RSpec.describe UsersController do end describe 'post password_recovery_request' do subject do - get :password_recovery_request, params: {email: user1.email} + get :password_recovery_request, params: { email: user1.email } end it 'sends the proper recovery email' do srand(10) subject email_text = ActionMailer::Base.deliveries.last.body.raw_source - expect(email_text).to match("recover_password/#{user1.id}/tfohbclx") + expect(email_text).to match("recover_password/#{user1.id}/jeravuxl") end it 'sends a recovery email to the proper email' do subject @@ -53,7 +55,7 @@ RSpec.describe UsersController do end describe 'get recover_password_form' do subject do - get :recover_password_form, params: {id: user1.id, recovery_password: 'recovery password'} + get :recover_password_form, params: { id: user1.id, recovery_password: 'recovery password' } end it 'renders proper form' do subject @@ -104,4 +106,4 @@ RSpec.describe UsersController do end end end -end \ No newline at end of file +end diff --git a/spec/mailers/previews/user_mailer_preview.rb b/spec/mailers/previews/user_mailer_preview.rb index 56c816a..b8ce9ed 100644 --- a/spec/mailers/previews/user_mailer_preview.rb +++ b/spec/mailers/previews/user_mailer_preview.rb @@ -1,4 +1,5 @@ +# frozen_string_literal: true + # Preview all emails at http://localhost:3000/rails/mailers/user class UserMailerPreview < ActionMailer::Preview - end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 6ebbdf6..ca6cf07 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -1,4 +1,6 @@ -require "rails_helper" +# frozen_string_literal: true + +require 'rails_helper' RSpec.describe UserMailer, type: :mailer do # TODO diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 00345af..edf8b47 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,9 +1,11 @@ +# frozen_string_literal: true + # This file is copied to spec/ when you run 'rails generate rspec:install' require 'spec_helper' ENV['RAILS_ENV'] ||= 'test' require File.expand_path('../config/environment', __dir__) # Prevent database truncation if the environment is production -abort("The Rails environment is running in production mode!") if Rails.env.production? +abort('The Rails environment is running in production mode!') if Rails.env.production? require 'rspec/rails' # Add additional requires below this line. Rails is not loaded until this point! diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 383bef3..01f7c97 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # This file was generated by the `rails generate rspec:install` command. Conventionally, all # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. # The generated `.rspec` file contains `--require spec_helper` which will cause @@ -44,53 +46,51 @@ RSpec.configure do |config| # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = "doc" - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end -end \ No newline at end of file + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = "spec/examples.txt" + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = "doc" + # end + # + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed +end From f7ec73f85e838a3304faa16f5bf35ac1cc1fb433 Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Mon, 22 Mar 2021 04:19:37 +0100 Subject: [PATCH 22/23] tests and UI changes --- app/controllers/books_controller.rb | 2 -- app/views/books/index.html.erb | 2 +- app/views/books/shopping_cart.erb | 2 +- app/views/books/show.html.erb | 20 -------------------- app/views/sessions/welcome.html.erb | 17 ++++++++++------- spec/controllers/users_controller_spec.rb | 22 ++++++++++++++++++++-- 6 files changed, 32 insertions(+), 33 deletions(-) delete mode 100644 app/views/books/show.html.erb diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb index 98071eb..88479ed 100644 --- a/app/controllers/books_controller.rb +++ b/app/controllers/books_controller.rb @@ -14,8 +14,6 @@ class BooksController < ApplicationController @books = books.map { |book| BooksPresenter.new(book) } end - def show; end - def edit; end def update diff --git a/app/views/books/index.html.erb b/app/views/books/index.html.erb index 412346b..8dd3a2b 100644 --- a/app/views/books/index.html.erb +++ b/app/views/books/index.html.erb @@ -9,7 +9,7 @@ <% @books.each do |book| %>
- <%= link_to book.title, book %> + <%= book.title %>
diff --git a/app/views/books/shopping_cart.erb b/app/views/books/shopping_cart.erb index 39f6cdf..dc6121d 100644 --- a/app/views/books/shopping_cart.erb +++ b/app/views/books/shopping_cart.erb @@ -7,7 +7,7 @@ <% @books.each do |book| %>
- <%= link_to book.title, book %> + <%= book.title %>
diff --git a/app/views/books/show.html.erb b/app/views/books/show.html.erb deleted file mode 100644 index 5370cff..0000000 --- a/app/views/books/show.html.erb +++ /dev/null @@ -1,20 +0,0 @@ -
-
-
- Title: <%= link_to @book.title, @book %> -
- -
- Price: <%= @book.price_with_currency %> -
- -
- Authors: <%= @book.authors %> -
-
- <% if current_user&.admin? %> -
- <%= link_to 'Edit', edit_book_path(@book), class: "btn" %> -
- <% end %> -
diff --git a/app/views/sessions/welcome.html.erb b/app/views/sessions/welcome.html.erb index 5a3f277..f2a1bcd 100644 --- a/app/views/sessions/welcome.html.erb +++ b/app/views/sessions/welcome.html.erb @@ -1,10 +1,13 @@

Welcome

- <% if logged_in? %> - You are Logged In, <%= current_user.email %> - <%= button_to "Logout", '/logout', method: :get, class: 'btn' %> - <% else %> - <%= button_to "Login", '/login', method: :get, class: 'btn' %> - <%= button_to "Sign Up", '/users/new', method: :get, class: 'btn' %> - <% end %> +
+ <% if logged_in? %> +

You are logged in, <%= current_user.email %>

+ <%= link_to 'Logout', '/logout', method: :get, class: 'btn' %> + <% else %> +

You are not logged in

+ <%= link_to 'Login', '/login', method: :get, class: 'btn' %> + <%= link_to 'Sign Up', '/users/new', method: :get, class: 'btn' %> + <% end %> +
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index db741e1..8595b6c 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -3,11 +3,22 @@ require 'rails_helper' RSpec.describe UsersController do - before(:all) do # TODO: change it to cleanup after each test + before(:all) do # TODO: turn it into cleanup after each test User.destroy_all end let(:user1) do - User.create(email: 'test1@example.com', password: 'abcdefgh', recovery_password: 'recovery password') + User.create( + email: 'test1@example.com', + password: 'abcdefgh', + recovery_password: 'recovery password', + role: :admin + ) + end + describe 'get index' do + subject { get :index } + it 'renders the users/index template' do + expect(subject).to render_template('users/index') + end end describe 'get new' do subject { get :new } @@ -106,4 +117,11 @@ RSpec.describe UsersController do end end end + describe 'delete destroy' do + context 'when admin is logged in' do + it 'deletes the user' do + # TODO + end + end + end end From 54750866222c065e3d9fb8fee84d8bc82be341db Mon Sep 17 00:00:00 2001 From: Karol Selak Date: Mon, 22 Mar 2021 04:38:35 +0100 Subject: [PATCH 23/23] refactoring and rubocop changes --- app/controllers/users_controller.rb | 31 +++++++++++++------ app/helpers/application_helper.rb | 1 + app/helpers/books_helper.rb | 1 + app/helpers/sessions_helper.rb | 1 + app/helpers/users_helper.rb | 1 + app/mailers/user_mailer.rb | 1 + app/models/application_record.rb | 1 + app/presenters/books_presenter.rb | 1 + config/application.rb | 1 + db/migrate/20210319142051_create_authors.rb | 1 + db/migrate/20210319142054_create_books.rb | 1 + .../20210319142059_create_authors_books.rb | 1 + db/migrate/20210320130542_create_users.rb | 1 + 13 files changed, 33 insertions(+), 10 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 8137d00..fc77082 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -39,16 +39,9 @@ class UsersController < ApplicationController end def recover_password - user = User.find(params[:user_id]) - if user.recovery_password_digest && user.authenticate_recovery_password(params[:recovery_password]) - user.password = params[:password] - user.password_confirmation = params[:password_confirmation] - if user.save - user.update(recovery_password: nil) - redirect_to '/welcome', notice: 'Password changed' - else - redirect_to '/welcome', notice: 'Passwords don\'t match' - end + @user = User.find(params[:user_id]) + if recovery_password_proper? + set_new_password else redirect_to '/welcome', notice: 'Recovery link expired or invalid' end @@ -63,4 +56,22 @@ class UsersController < ApplicationController User.find(params[:id]).update(status: :blocked) redirect_to '/users' end + + private + + def recovery_password_proper? + @user.recovery_password_digest && + @user.authenticate_recovery_password(params[:recovery_password]) + end + + def set_new_password + @user.password = params[:password] + @user.password_confirmation = params[:password_confirmation] + if @user.save + @user.update(recovery_password: nil) + redirect_to '/welcome', notice: 'Password changed' + else + redirect_to '/welcome', notice: 'Passwords don\'t match' + end + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 15b06f0..292788a 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# Application helper module ApplicationHelper end diff --git a/app/helpers/books_helper.rb b/app/helpers/books_helper.rb index 0e4b37c..84f1d25 100644 --- a/app/helpers/books_helper.rb +++ b/app/helpers/books_helper.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Books helper module BooksHelper def cart_summary number_to_currency(@books.map(&:price).reduce(:+)) diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb index 97aeb4c..dc9b8a1 100644 --- a/app/helpers/sessions_helper.rb +++ b/app/helpers/sessions_helper.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# Sessions helper module SessionsHelper end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 4dc909e..f9820e4 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +# Users helper module UsersHelper end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 51d0f22..169ef04 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# User mailer class UserMailer < ApplicationMailer def password_recovery @user = params[:user] diff --git a/app/models/application_record.rb b/app/models/application_record.rb index e2e8915..536baf0 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Application record class ApplicationRecord < ActiveRecord::Base self.abstract_class = true def update(*args) diff --git a/app/presenters/books_presenter.rb b/app/presenters/books_presenter.rb index f382006..b5762ba 100644 --- a/app/presenters/books_presenter.rb +++ b/app/presenters/books_presenter.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Books presenter class BooksPresenter < SimpleDelegator include ActiveSupport::NumberHelper diff --git a/config/application.rb b/config/application.rb index c526332..a55fbe9 100644 --- a/config/application.rb +++ b/config/application.rb @@ -8,6 +8,7 @@ require 'rails/all' # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) +# App module App class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. diff --git a/db/migrate/20210319142051_create_authors.rb b/db/migrate/20210319142051_create_authors.rb index d76d005..100b87c 100644 --- a/db/migrate/20210319142051_create_authors.rb +++ b/db/migrate/20210319142051_create_authors.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Create authors class CreateAuthors < ActiveRecord::Migration[6.1] def change create_table :authors do |t| diff --git a/db/migrate/20210319142054_create_books.rb b/db/migrate/20210319142054_create_books.rb index e819f45..f87d7cc 100644 --- a/db/migrate/20210319142054_create_books.rb +++ b/db/migrate/20210319142054_create_books.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Create books class CreateBooks < ActiveRecord::Migration[6.1] def change create_table :books do |t| diff --git a/db/migrate/20210319142059_create_authors_books.rb b/db/migrate/20210319142059_create_authors_books.rb index 3bbd6e7..d0fe027 100644 --- a/db/migrate/20210319142059_create_authors_books.rb +++ b/db/migrate/20210319142059_create_authors_books.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Create association table between authors and books class CreateAuthorsBooks < ActiveRecord::Migration[6.1] def change create_table :authors_books do |t| diff --git a/db/migrate/20210320130542_create_users.rb b/db/migrate/20210320130542_create_users.rb index c5b5a4d..d264856 100644 --- a/db/migrate/20210320130542_create_users.rb +++ b/db/migrate/20210320130542_create_users.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# Create users class CreateUsers < ActiveRecord::Migration[6.1] def change create_table :users do |t|