From 4d3971113fc0b667da06676d2a5b5d65b4185095 Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Thu, 1 Aug 2024 21:41:42 -0400 Subject: [PATCH] Setup user login/logout (#21) Reviewed-on: https://git.atomaka.com/atomaka/budget/pulls/21 --- .../stylesheets/application.tailwind.css | 6 +++ app/controllers/sessions_controller.rb | 40 +++++++++++++++++++ app/helpers/sessions_helper.rb | 2 + app/models/session.rb | 22 ++++++++++ app/views/layouts/application.html.erb | 9 +++++ app/views/sessions/_form.html.erb | 27 +++++++++++++ app/views/sessions/_session.html.erb | 2 + app/views/sessions/_session.json.jbuilder | 2 + app/views/sessions/new.html.erb | 7 ++++ config/routes.rb | 2 + test/controllers/sessions_controller_test.rb | 27 +++++++++++++ test/models/session_test.rb | 25 ++++++++++++ test/system/sessions_test.rb | 25 ++++++++++++ 13 files changed, 196 insertions(+) create mode 100644 app/controllers/sessions_controller.rb create mode 100644 app/helpers/sessions_helper.rb create mode 100644 app/models/session.rb create mode 100644 app/views/sessions/_form.html.erb create mode 100644 app/views/sessions/_session.html.erb create mode 100644 app/views/sessions/_session.json.jbuilder create mode 100644 app/views/sessions/new.html.erb create mode 100644 test/controllers/sessions_controller_test.rb create mode 100644 test/models/session_test.rb create mode 100644 test/system/sessions_test.rb diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css index 8666d2f..13dc3ef 100644 --- a/app/assets/stylesheets/application.tailwind.css +++ b/app/assets/stylesheets/application.tailwind.css @@ -2,6 +2,12 @@ @tailwind components; @tailwind utilities; +.msg-notice { + @apply bg-green-300 text-green-900; +} +.msg-alert { + @apply bg-red-300 text-red-900; +} /* @layer components { diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000..f6fd1fe --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,40 @@ +class SessionsController < ApplicationController + # GET /sessions/new + def new + @session = Session.new + end + + # POST /sessions or /sessions.json + def create + @session = Session.new(session_params) + + respond_to do |format| + if @session.save + session[:current_user_id] = @session.user_id + Rails.logger.info("ID: #{@session.user_id}") + + format.html { redirect_to root_url, notice: "Session was successfully created." } + format.json { render :show, status: :created, location: @session } + else + format.html { render :new, status: :unprocessable_entity, alert: @session.errors } + format.json { render json: @session.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /sessions/1 or /sessions/1.json + def destroy + session[:current_user_id] = nil + + respond_to do |format| + format.html { redirect_to root_url, notice: "Session was successfully destroyed." } + format.json { head :no_content } + end + end + + private + # Only allow a list of trusted parameters through. + def session_params + params.require(:session).permit(:email, :password) + 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/models/session.rb b/app/models/session.rb new file mode 100644 index 0000000..c82ce7b --- /dev/null +++ b/app/models/session.rb @@ -0,0 +1,22 @@ +class Session + include ActiveModel::Model + + include ActiveModel::Attributes + include ActiveModel::Validations + + attr_accessor :user_id + + attribute :email, :string + attribute :password, :string + + validates :email, presence: true + validates :password, presence: true + + def save + user = User.authenticate_by(email: email, password: password) + + @user_id = user && user.id + + user.present? && self || nil + end +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index c90e132..fbc9c63 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -19,9 +19,18 @@
  • <%= link_to "Credit Card Bills", credit_card_bills_path, class: "text-white" %>
  • <%= link_to "Incomes", incomes_path, class: "text-white" %>
  • <%= link_to "Members", members_path, class: "text-white" %>
  • +
  • <%= link_to "Log out", session_path, data: {turbo_method: :delete}, class: "text-white" %>
  • + <% if flash.any? %> + <% flash.each do |type, msg| %> +
    + <%= msg %> +
    + <% end %> + <% end %> +
    <%= yield %>
    diff --git a/app/views/sessions/_form.html.erb b/app/views/sessions/_form.html.erb new file mode 100644 index 0000000..2f59bf6 --- /dev/null +++ b/app/views/sessions/_form.html.erb @@ -0,0 +1,27 @@ +<%= form_with(model: session, class: "contents") do |form| %> + <% if session.errors.any? %> +
    +

    <%= pluralize(session.errors.count, "error") %> prohibited this session from being saved:

    + + +
    + <% end %> + +
    + <%= form.label :email %> + <%= form.text_field :email, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %> +
    + +
    + <%= form.label :password %> + <%= form.password_field :password, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %> +
    + +
    + <%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %> +
    +<% end %> diff --git a/app/views/sessions/_session.html.erb b/app/views/sessions/_session.html.erb new file mode 100644 index 0000000..0a68161 --- /dev/null +++ b/app/views/sessions/_session.html.erb @@ -0,0 +1,2 @@ +
    +
    diff --git a/app/views/sessions/_session.json.jbuilder b/app/views/sessions/_session.json.jbuilder new file mode 100644 index 0000000..07f4f9f --- /dev/null +++ b/app/views/sessions/_session.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! session, :id, :created_at, :updated_at +json.url session_url(session, format: :json) diff --git a/app/views/sessions/new.html.erb b/app/views/sessions/new.html.erb new file mode 100644 index 0000000..e4f34d8 --- /dev/null +++ b/app/views/sessions/new.html.erb @@ -0,0 +1,7 @@ +
    +

    New session

    + + <%= render "form", session: @session %> + + <%= link_to "Back to sessions", sessions_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %> +
    diff --git a/config/routes.rb b/config/routes.rb index 74d76c3..d7e63ff 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,6 @@ Rails.application.routes.draw do + resources :sessions, only: %i[new create] + resource :session, only: :destroy resources :users resources :credit_card_bills resource :dashboard, only: :show diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 0000000..bdd5045 --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,27 @@ +require "test_helper" + +class SessionsControllerTest < ActionDispatch::IntegrationTest + test "should get new" do + get new_session_url + assert_response :success + end + + test "should create session" do + user = users(:one) + params = { + session: { + email: user.email, + password: "secret" + } + } + post sessions_url, params: params + + assert_redirected_to root_url + end + + test "should destroy session" do + delete session_url(@session) + + assert_redirected_to root_url + end +end diff --git a/test/models/session_test.rb b/test/models/session_test.rb new file mode 100644 index 0000000..e20618a --- /dev/null +++ b/test/models/session_test.rb @@ -0,0 +1,25 @@ +require "test_helper" + +class SessionTest < ActiveSupport::TestCase + def test_save_when_exists + user = users(:one) + + session = Session.new(email: user.email, password: "secret") + + assert session.save + end + + def test_save_when_not_exists + session = Session.new(email: "fake@example.org", password: "secret") + + assert_not session.save + end + + def test_save_when_password_incorrect + user = users(:one) + + session = Session.new(email: user.email, password: "bad_password") + + assert_not session.save + end +end diff --git a/test/system/sessions_test.rb b/test/system/sessions_test.rb new file mode 100644 index 0000000..7715288 --- /dev/null +++ b/test/system/sessions_test.rb @@ -0,0 +1,25 @@ +require "application_system_test_case" + +class SessionsTest < ApplicationSystemTestCase + setup do + @user = users(:one) + end + + test "should create session" do + visit new_session_url + + fill_in "Email", with: @user.email + fill_in "Password", with: "secret" + + click_on "Create Session" + + assert_text "Session was successfully created" + end + + test "should destroy Session" do + visit root_url + click_on "Log out", match: :first + + assert_text "Session was successfully destroyed" + end +end