Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
sample_app
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Quang Vinh Nguyen
sample_app
Commits
7844c61c
Commit
7844c61c
authored
May 31, 2018
by
Quang Vinh Nguyen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement advanced login
parent
e789eda4
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
171 additions
and
18 deletions
+171
-18
app/assets/stylesheets/custom.scss
+15
-0
app/controllers/sessions_controller.rb
+22
-11
app/helpers/sessions_helper.rb
+32
-2
app/models/user.rb
+27
-3
app/views/sessions/new.html.erb
+5
-0
db/migrate/20180531022956_add_remember_digest_to_users.rb
+5
-0
db/schema.rb
+2
-1
test/fixtures/users.yml
+4
-0
test/helpers/sessions_helper_test.rb
+19
-0
test/integration/users_login_test.rb
+21
-1
test/models/user_test.rb
+4
-0
test/test_helper.rb
+15
-0
No files found.
app/assets/stylesheets/custom.scss
View file @
7844c61c
...
@@ -190,3 +190,17 @@ input {
...
@@ -190,3 +190,17 @@ input {
color
:
$state-danger-text
;
color
:
$state-danger-text
;
}
}
}
}
.checkbox
{
margin-top
:
-10px
;
margin-bottom
:
10px
;
span
{
margin-left
:
20px
;
font-weight
:
normal
;
}
}
#session_remember_me
{
width
:
auto
;
margin-left
:
0
;
}
\ No newline at end of file
app/controllers/sessions_controller.rb
View file @
7844c61c
...
@@ -2,12 +2,29 @@ class SessionsController < ApplicationController
...
@@ -2,12 +2,29 @@ class SessionsController < ApplicationController
def
new
def
new
end
end
# def create
# user = User.find_by(email: params[:session][:email].downcase)
# if user && user.authenticate(params[:session][:password])
# # Log the user in and redirect to the user's show page.
# log_in user
# # remember user # update: remember_digest attribute
# params[:session][:remember_me] == '1' ? remember(user) : forget(user)
# redirect_to user
# else
# # Create an error message.
# flash.now[:danger] = 'Invalid email/password combination'
# render 'new'
# end
# end
def
create
def
create
user
=
User
.
find_by
(
email:
params
[
:session
][
:email
].
downcase
)
@
user
=
User
.
find_by
(
email:
params
[
:session
][
:email
].
downcase
)
if
user
&&
user
.
authenticate
(
params
[
:session
][
:password
])
if
@user
&&
@
user
.
authenticate
(
params
[
:session
][
:password
])
# Log the user in and redirect to the user's show page.
# Log the user in and redirect to the user's show page.
log_in
user
log_in
@user
redirect_to
user
# remember user # update: remember_digest attribute
params
[
:session
][
:remember_me
]
==
'1'
?
remember
(
@user
)
:
forget
(
@user
)
redirect_to
@user
else
else
# Create an error message.
# Create an error message.
flash
.
now
[
:danger
]
=
'Invalid email/password combination'
flash
.
now
[
:danger
]
=
'Invalid email/password combination'
...
@@ -15,14 +32,8 @@ class SessionsController < ApplicationController
...
@@ -15,14 +32,8 @@ class SessionsController < ApplicationController
end
end
end
end
# Logs out the current user.
def
log_out
session
.
delete
(
:user_id
)
@current_user
=
nil
end
def
destroy
def
destroy
log_out
log_out
if
logged_in?
redirect_to
root_url
redirect_to
root_url
end
end
end
end
app/helpers/sessions_helper.rb
View file @
7844c61c
#
The
#
comment
module
SessionsHelper
module
SessionsHelper
# Logs in the given user.
# Logs in the given user.
def
log_in
(
user
)
def
log_in
(
user
)
session
[
:user_id
]
=
user
.
id
session
[
:user_id
]
=
user
.
id
end
end
# remembers a user in a persistent session.
def
remember
(
user
)
user
.
remember
cookies
.
permanent
.
signed
[
:user_id
]
=
user
.
id
cookies
.
permanent
[
:remember_token
]
=
user
.
remember_token
end
# Return the current logged-in user (if any).
# Return the current logged-in user (if any).
def
current_user
def
current_user
@current_user
||=
User
.
find_by
(
id:
session
[
:user_id
])
# @current_user ||= User.find_by(id: session[:user_id])
if
(
user_id
=
session
[
:user_id
])
@current_user
||=
User
.
find_by
(
id:
user_id
)
elsif
(
user_id
=
cookies
.
signed
[
:user_id
])
user
=
User
.
find_by
(
id:
user_id
)
if
user
&&
user
.
authenticated?
(
cookies
[
:remember_token
])
log_in
user
@current_user
=
user
end
end
end
end
# Returns true if the user is logged in, false otherwise.
# Returns true if the user is logged in, false otherwise.
def
logged_in?
def
logged_in?
!
current_user
.
nil?
!
current_user
.
nil?
end
end
# Forgets a persistent session.
def
forget
(
user
)
user
.
forget
cookies
.
delete
(
:user_id
)
cookies
.
delete
(
:remember_token
)
end
# Logs out the current user.
def
log_out
forget
(
current_user
)
session
.
delete
(
:user_id
)
@current_user
=
nil
end
end
end
app/models/user.rb
View file @
7844c61c
#
This
#
comment
class
User
<
ApplicationRecord
class
User
<
ApplicationRecord
attr_accessor
:remember_token
# we don't wan't to save this attribute to database
before_save
{
self
.
email
.
downcase!
}
before_save
{
self
.
email
.
downcase!
}
validates
:name
,
presence:
true
,
length:
{
maximum:
50
}
validates
:name
,
presence:
true
,
length:
{
maximum:
50
}
VALID_EMAIL_REGEX
=
/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
VALID_EMAIL_REGEX
=
/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
validates
:email
,
presence:
true
,
length:
{
maximum:
255
},
validates
:email
,
presence:
true
,
length:
{
maximum:
255
},
format:
{
with:
VALID_EMAIL_REGEX
},
format:
{
with:
VALID_EMAIL_REGEX
},
uniqueness:
{
case_sensitive:
false
}
uniqueness:
{
case_sensitive:
false
}
validates
:password
,
presence:
true
,
length:
{
minimum:
6
}
validates
:password
,
presence:
true
,
length:
{
minimum:
6
}
has_secure_password
has_secure_password
# Returns the hash digest of the given string.
# Returns the hash digest of the given string.
def
User
.
digest
(
string
)
def
self
.
digest
(
string
)
cost
=
ActiveModel
::
SecurePassword
.
min_cost
?
BCrypt
::
Engine
::
MIN_COST
:
cost
=
ActiveModel
::
SecurePassword
.
min_cost
?
BCrypt
::
Engine
::
MIN_COST
:
BCrypt
::
Engine
.
cost
BCrypt
::
Engine
.
cost
BCrypt
::
Password
.
create
(
string
,
cost:
cost
)
BCrypt
::
Password
.
create
(
string
,
cost:
cost
)
end
end
# Returns a random token.
# def User.new_token
def
self
.
new_token
SecureRandom
.
urlsafe_base64
end
# Remembers a user in the database for use in persistent session.
def
remember
self
.
remember_token
=
User
.
new_token
update_attribute
(
:remember_digest
,
User
.
digest
(
remember_token
))
end
# Returns true if the given token matches the digest.
def
authenticated?
(
remember_token
)
return
false
if
remember_digest
.
nil?
BCrypt
::
Password
.
new
(
remember_digest
).
is_password?
(
remember_token
)
end
# Forgets a user.
def
forget
update_attribute
(
:remember_digest
,
nil
)
end
end
end
app/views/sessions/new.html.erb
View file @
7844c61c
...
@@ -10,6 +10,11 @@
...
@@ -10,6 +10,11 @@
<%=
f
.
label
:password
%>
<%=
f
.
label
:password
%>
<%=
f
.
password_field
:password
,
class:
'form-control'
%>
<%=
f
.
password_field
:password
,
class:
'form-control'
%>
<%=
f
.
label
:remember_me
,
class:
'checkbox inline'
do
%>
<%=
f
.
check_box
:remember_me
%>
<span>
Remember me on this computer
</span>
<%
end
%>
<%=
f
.
submit
"Log in"
,
class:
"btn btn-primary"
%>
<%=
f
.
submit
"Log in"
,
class:
"btn btn-primary"
%>
<%
end
%>
<%
end
%>
...
...
db/migrate/20180531022956_add_remember_digest_to_users.rb
0 → 100644
View file @
7844c61c
class
AddRememberDigestToUsers
<
ActiveRecord
::
Migration
[
5.1
]
def
change
add_column
:users
,
:remember_digest
,
:string
end
end
db/schema.rb
View file @
7844c61c
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
#
#
# It's strongly recommended that you check this file into your version control system.
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
201805
29074848
)
do
ActiveRecord
::
Schema
.
define
(
version:
201805
31022956
)
do
create_table
"users"
,
force: :cascade
do
|
t
|
create_table
"users"
,
force: :cascade
do
|
t
|
t
.
string
"name"
t
.
string
"name"
...
@@ -18,6 +18,7 @@ ActiveRecord::Schema.define(version: 20180529074848) do
...
@@ -18,6 +18,7 @@ ActiveRecord::Schema.define(version: 20180529074848) do
t
.
datetime
"created_at"
,
null:
false
t
.
datetime
"created_at"
,
null:
false
t
.
datetime
"updated_at"
,
null:
false
t
.
datetime
"updated_at"
,
null:
false
t
.
string
"password_digest"
t
.
string
"password_digest"
t
.
string
"remember_digest"
t
.
index
[
"email"
],
name:
"index_users_on_email"
,
unique:
true
t
.
index
[
"email"
],
name:
"index_users_on_email"
,
unique:
true
end
end
...
...
test/fixtures/users.yml
View file @
7844c61c
...
@@ -3,3 +3,7 @@ foo:
...
@@ -3,3 +3,7 @@ foo:
name
:
foo
name
:
foo
email
:
foo@bar.com
email
:
foo@bar.com
password_digest
:
<%= User.digest('password') %>
password_digest
:
<%= User.digest('password') %>
michael
:
name
:
Michael Example
email
:
michael@example.com
password_digest
:
<%= User.digest('password') %>
test/helpers/sessions_helper_test.rb
0 → 100644
View file @
7844c61c
require
'test_helper'
class
SessionsHelperTest
<
ActionView
::
TestCase
def
setup
@user
=
users
(
:foo
)
remember
(
@user
)
end
test
'current_user returns right user when session is nil'
do
assert_equal
@user
,
current_user
assert
is_logged_in?
end
test
'current_user returns nil when remember digest is wrong'
do
@user
.
update_attribute
(
:remember_digest
,
User
.
digest
(
User
.
new_token
))
assert_nil
current_user
end
end
\ No newline at end of file
test/integration/users_login_test.rb
View file @
7844c61c
...
@@ -3,7 +3,7 @@ require 'test_helper'
...
@@ -3,7 +3,7 @@ require 'test_helper'
class
UsersLoginTest
<
ActionDispatch
::
IntegrationTest
class
UsersLoginTest
<
ActionDispatch
::
IntegrationTest
# comment
# comment
def
setup
def
setup
@user
=
users
(
:
foo
)
@user
=
users
(
:
michael
)
end
end
# comment
# comment
...
@@ -32,9 +32,29 @@ class UsersLoginTest < ActionDispatch::IntegrationTest
...
@@ -32,9 +32,29 @@ class UsersLoginTest < ActionDispatch::IntegrationTest
delete
logout_path
delete
logout_path
assert_not
is_logged_in?
assert_not
is_logged_in?
assert_redirected_to
root_url
assert_redirected_to
root_url
# Simulate a user clicking logout in a second window.
delete
logout_path
follow_redirect!
follow_redirect!
assert_select
'a[href=?]'
,
login_path
assert_select
'a[href=?]'
,
login_path
assert_select
'a[href=?]'
,
logout_path
,
count:
0
assert_select
'a[href=?]'
,
logout_path
,
count:
0
assert_select
'a[href=?]'
,
user_path
(
@user
),
count:
0
assert_select
'a[href=?]'
,
user_path
(
@user
),
count:
0
end
end
# test 'login with remembering' do
# log_in_as(@user, remember_me: '1')
# assert_not_empty cookies['remember_token']
# end
test
'login with remembering'
do
log_in_as
(
@user
,
remember_me:
'1'
)
# assert_not_empty cookies['remember_token']
assert_equal
cookies
[
'remember_token'
],
assigns
(
:user
).
remember_token
end
test
'login without remembering'
do
# Log in to set the cookie.
log_in_as
(
@user
,
remember_me:
'1'
)
# Log in again and verify that the cookie is deleted.
log_in_as
(
@user
,
remember_me:
'0'
)
assert_empty
cookies
[
'remember_token'
]
end
end
end
test/models/user_test.rb
View file @
7844c61c
...
@@ -62,4 +62,8 @@ class UserTest < ActiveSupport::TestCase
...
@@ -62,4 +62,8 @@ class UserTest < ActiveSupport::TestCase
@user
.
password
=
@user
.
password_confirmation
=
'a'
*
5
@user
.
password
=
@user
.
password_confirmation
=
'a'
*
5
assert_not
@user
.
valid?
assert_not
@user
.
valid?
end
end
test
'authenticated? should return false for a user with nil digest'
do
assert_not
@user
.
authenticated?
(
''
)
end
end
end
test/test_helper.rb
View file @
7844c61c
...
@@ -18,4 +18,18 @@ class ActiveSupport::TestCase
...
@@ -18,4 +18,18 @@ class ActiveSupport::TestCase
def
is_logged_in?
def
is_logged_in?
!
session
[
:user_id
].
nil?
!
session
[
:user_id
].
nil?
end
end
# Log in as a particular user.
def
log_in_as
(
user
)
session
[
:user_id
]
=
user
.
id
end
end
class
ActionDispatch
::
IntegrationTest
# Log in as a particular user.
def
log_in_as
(
user
,
password:
'password'
,
remember_me:
'1'
)
post
login_path
,
params:
{
session:
{
email:
user
.
email
,
password:
password
,
remember_me:
remember_me
}
}
end
end
end
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment