Commit d7709f9a by Nguyen Hoang Mai Phuong

Merge branch 'basic-login' into 'master'

basic login

See merge request !10
parents 952a378c f9e786b7
Pipeline #1279 failed with stages
in 0 seconds
......@@ -47,11 +47,19 @@ p {
}
}
.navbar li a{
.navbar ul {
list-style: none;
}
li a {
color: #fff;
font-size: 18px;
font-weight: bold;
padding: 4px 10px;
text-decoration: none;
&:hover {
color: #000;
text-decoration: none;
}
}
.jumbotron {
......@@ -88,12 +96,12 @@ aside {
&:first-child {
border: 0;
padding-top: 0;
}
}
span {
display: block;
margin-bottom: 3px;
line-height: 1;
}
}
h1 {
font-size: 1.4em;
text-align: left;
......
// 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/
class SessionsController < ApplicationController
include SessionsHelper
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
log_out
redirect_to root_url
end
end
class UsersController < ApplicationController
def show
@user = User.find(params[:id])
end
......@@ -11,6 +10,7 @@ class UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.save
helpers.log_in @user
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
# Handle a successful save.
......
module SessionsHelper
def log_in(user)
session[:user_id] = user.id
end
# Returns the current logged-in user (if any).
def current_user
if session[:user_id]
@current_user ||= User.find_by(id: session[:user_id])
end
end
def logged_in?
!current_user.nil?
end
# Logs out the current user.
def log_out
session.delete(:user_id)
@current_user = nil
end
end
......@@ -7,6 +7,8 @@ import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
require("jquery")
import "bootstrap"
Rails.start()
Turbolinks.start()
......
......@@ -7,4 +7,11 @@ class User < ApplicationRecord
uniqueness: true
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
# Returns the hash digest of the given string.
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
end
......@@ -4,13 +4,29 @@
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo02">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<nav>
<ul class="collapse navbar-collapse ms-auto mb-2 mb-lg-0" id="navbarSupportedContent">
<li><%= link_to "Home",root_path %></li>
<li><%= link_to "Help", help_path %></li>
<li><%= link_to "About", about_path %></li>
<li><%= link_to "Log in", '#' %></li>
<% if logged_in? %>
<li><%= link_to "Users", '#' %></li>
<li class="dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Account
</a>
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="navbarDropdown">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", '#' %></li>
<li><hr class="dropdown-divider"></li>
<li>
<%= link_to "Log out", logout_path, method: :delete %>
</li>
</ul>
</li>
<% else %>
<li><%= link_to "Log in", login_path %></li>
<% end %>
</ul>
</div>
<nav>
</div>
</header>
\ No newline at end of file
......@@ -2,6 +2,7 @@
<head>
<title><%= full_title(yield(:title)) %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all',
......
<% provide(:title, "Log in") %>
<h1>Log in</h1>
<div class="row">
<div class="col-md-6 offset-md-3">
<%= form_with(url: login_path, scope: :session, local: true) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
\ No newline at end of file
......@@ -76,5 +76,5 @@ Rails.application.configure do
# Force all access to the app over SSL, use Strict-Transport-Security,
# and use secure cookies.
config.force_ssl = true
end
......@@ -97,6 +97,8 @@ Rails.application.configure do
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
config.force_ssl = true
# Inserts middleware to perform automatic connection switching.
# The `database_selector` hash is used to pass options to the DatabaseSelector
# middleware. The `delay` is used to determine how long to wait after a write
......
Rails.application.routes.draw do
get 'sessions/new'
root 'static_pages#home'
get '/home', to: 'static_pages#home'
get '/help', to: 'static_pages#help'
get '/about', to: 'static_pages#about'
get '/contact', to: 'static_pages#contact'
get '/signup', to: 'users#new'
get '/signup', to: 'users#new'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
resources :users
end
end
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery'
})
)
module.exports = environment
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -2,11 +2,14 @@
"name": "sample-app",
"private": true,
"dependencies": {
"@popperjs/core": "^2.9.2",
"@rails/actioncable": "^6.0.0",
"@rails/activestorage": "^6.0.0",
"@rails/ujs": "^6.0.0",
"@rails/webpacker": "5.4.0",
"bootstrap": "^5.0.1",
"@types/popper.js": "^1.11.0",
"bootstrap": "5.0.1",
"jquery": "^3.6.0",
"turbolinks": "^5.2.0",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12"
......
require "test_helper"
class SessionsControllerTest < ActionDispatch::IntegrationTest
test "should get new" do
get login_path
get sessions_new_url
assert_response :success
end
end
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
michael:
name: Michael Example
email: michael@example.com
password_digest: <%= User.digest('password') %>
\ No newline at end of file
require "test_helper"
class UsersLoginTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "login with valid email/invalid password" do
get login_path
assert_template 'sessions/new'
post login_path, params: { session: { email:
@user.email,
password: "invalid" } }
assert_not is_logged_in?
assert_template 'sessions/new'
assert_not flash.empty?
get root_path
assert flash.empty?
end
test "login with valid information followed by logout" do
get login_path
post login_path, params: { session: { email:
@user.email,
password: 'password' } }
assert is_logged_in?
assert_redirected_to @user
follow_redirect!
assert_template 'users/show'
assert_select "a[href=?]", login_path, count: 0
assert_select "a[href=?]", logout_path
assert_select "a[href=?]", user_path(@user)
delete logout_path
assert_not is_logged_in?
assert_redirected_to root_url
follow_redirect!
assert_select "a[href=?]", login_path
assert_select "a[href=?]", logout_path,
count: 0
assert_select "a[href=?]", user_path(@user), count: 0
end
end
......@@ -9,4 +9,8 @@ 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...
# Returns true if a test user is logged in.
def is_logged_in?
!session[:user_id].nil?
end
end
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment