...
 
Commits (3)
......@@ -5,4 +5,4 @@ You are allowed to:
2. Remove generators
3. Add installed generators
To add new installed generators automatically delete this file and reload the project.
--><GeneratorsGroup><Generator name="assets" /><Generator name="channel" /><Generator name="coffee:assets" /><Generator name="controller" /><Generator name="generator" /><Generator name="helper" /><Generator name="integration_test" /><Generator name="jbuilder" /><Generator name="job" /><Generator name="js:assets" /><Generator name="mailer" /><Generator name="migration" /><Generator name="model" /><Generator name="resource" /><Generator name="scaffold" /><Generator name="scaffold_controller" /><Generator name="system_test" /><Generator name="task" /><Generator name="test_unit:generator" /><Generator name="test_unit:plugin" /></GeneratorsGroup></Settings>
--><GeneratorsGroup><Generator name="active_record:migration" /><Generator name="active_record:model" /><Generator name="active_record:observer" /><Generator name="active_record:session_migration" /><Generator name="controller" /><Generator name="erb:controller" /><Generator name="erb:mailer" /><Generator name="erb:scaffold" /><Generator name="generator" /><Generator name="helper" /><Generator name="integration_test" /><Generator name="mailer" /><Generator name="metal" /><Generator name="migration" /><Generator name="model" /><Generator name="model_subclass" /><Generator name="observer" /><Generator name="performance_test" /><Generator name="plugin" /><Generator name="resource" /><Generator name="scaffold" /><Generator name="scaffold_controller" /><Generator name="session_migration" /><Generator name="stylesheets" /><Generator name="test_unit:controller" /><Generator name="test_unit:helper" /><Generator name="test_unit:integration" /><Generator name="test_unit:mailer" /><Generator name="test_unit:model" /><Generator name="test_unit:observer" /><Generator name="test_unit:performance" /><Generator name="test_unit:plugin" /><Generator name="test_unit:scaffold" /></GeneratorsGroup></Settings>
# Default ignored files
/workspace.xml
\ No newline at end of file
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
\ No newline at end of file
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="Rails sample_app: test" uuid="05ad187b-a4ec-4600-967e-4cd58a672ee0">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/config/database.yml</remarks>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db/test.sqlite3</jdbc-url>
<driver-properties>
<property name="enable_load_extension" value="true" />
</driver-properties>
</data-source>
<data-source source="LOCAL" name="Rails sample_app: development" uuid="9d763f9c-935d-4c89-8367-499ead553ee3">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/config/database.yml</remarks>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/db/development.sqlite3</jdbc-url>
<driver-properties>
<property name="enable_load_extension" value="true" />
</driver-properties>
</data-source>
</component>
</project>
\ No newline at end of file
This diff is collapsed.
......@@ -131,7 +131,7 @@ aside {
section {
padding: 10px 0;
margin-top: 20pix;
margin-top: 20px;
&:first-child {
border: 0;
......@@ -194,4 +194,18 @@ input {
.form-control {
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
......@@ -4,10 +4,11 @@ class SessionsController < ApplicationController
def new; end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user&.authenticate(params[:session][:password])
log_in user
redirect_to user
@user = User.find_by(email: params[:session][:email].downcase)
if @user&.authenticate(params[:session][:password])
log_in @user
params[:session][:remember_me] == "1" ? remember(@user):forget(@user)
redirect_to @user
else
flash.now[:danger] = 'Invalid email/password combination'
......@@ -16,7 +17,7 @@ class SessionsController < ApplicationController
end
def destroy
log_out
log_out if logged_in?
redirect_to root_url
end
end
# frozen_string_literal: true
class UsersController < ApplicationController
before_action :logged_in_user, only:[:edit, :update]
def show
@user = User.find(params[:id])
end
......@@ -10,7 +11,7 @@ class UsersController < ApplicationController
end
def create
@user = User.new user_params
@user = User.new(user_params)
if @user.save
log_in @user
flash[:success] = 'Welcome to the Sample App!'
......@@ -20,10 +21,31 @@ class UsersController < ApplicationController
end
end
def edit
@user = User.find(params[:id])
end
def update
@user = User.find params[:id]
if @user.update_attributes user_params
flash[:success] = "Profile updated"
redirect_to @user
else
render "edit"
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
def logged_in_user
unless logged_in?
flash[:danger] = "Please log in."
redirect_to login_url
end
end
end
......@@ -6,7 +6,21 @@ module SessionsHelper
end
def current_user
@current_user ||= User.find_by(id: session[:user_id]) if 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
def remember(user)
user.remember
cookies.permanent.signed[:user_id] = user.id
cookies.permanent[:remember_token] = user.remember_token
end
def logged_in?
......@@ -14,7 +28,14 @@ module SessionsHelper
end
def log_out
forget(current_user)
session.delete(:user_id)
@current_user = nil
end
def forget(user)
user.forget
cookies.delete(:user_id)
cookies.delete(:remember_token)
end
end
# frozen_string_literal: true
class User < ApplicationRecord
attr_accessor :remember_token
before_save { email.downcase! }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.][email protected][a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i.freeze
......@@ -8,10 +9,28 @@ class User < ApplicationRecord
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
def self.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
def User.new_token
SecureRandom.urlsafe_base64
end
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end
def forget
update_attribute(:remember_digest,nil)
end
end
......@@ -13,7 +13,7 @@
</a>
<ul class="dropdown-menu">
<li> <%= link_to 'Profile', current_user %></li>
<li><%= link_to 'Settings', "#" %></li>
<li><%= link_to "Settings", edit_user_path(current_user) %></li>
<li class="divider"></li>
<li>
<%= link_to 'Log out', logout_path, method: :delete %>
......
<%provide(:title, "Log in")%>
<% provide(:title, "Log in") %>
<h1>Log in</h1>
<div class="row">
<div class="col-md-6 cod-md-offset-3">
<%= form_for :session, url: login_path do |f| %>
<%= f.label :email%>
<%= f.email_field :email, class: "form-control"%>
<%= f.label :password%>
<%= f.password_field :password, class:"form-control"%>
<div class="col-md-6 cod-md-offset-3">
<%= form_for :session, url: login_path 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>
<%= f.label :remember_me, class: "checkboc inline" do %>
<%= f.check_box :remember_me %>
<span>Remember me on this computer</span>
<% end %>
<%= 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
<%= form_for(@user, url: yield(:url)) do |f| %>
<%= render "shared/error_messages", object: @user %>
<%= f.label :name %>
<%= f.text_field :name, class: "form-control" %>
<%= f.label :email %>
<%= f.text_field :email, class: "form-control" %>
<%= f.label :password %>
<%= f.password_field :password, class: "form-control" %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: "form-control" %>
<%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>
\ No newline at end of file
<% provide(:title, "Edit user")%>
<% provide(:button_text, "update") %>
<% provide(:url, user_path(@user)) %>
<h1>Update your profile</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= render "form" %>
<div class="gravatar_edit">
<%= gravatar_for @user %>
<a href="http://gravatar.com/emails" target="_blank" rel="noopener">change</a>
</div>
</div>
</div>
\ No newline at end of file
<% provide(:title,"Sign up")%>
<% provide(:button_text, "Create my account") %>
<% provide(:url, signup_path) %>
<h1>Sign up</h1>
<div class="row">
<div>
<%=form_for(@user, url: signup_path) do |f|%>
<%= render "shared/error_messages" %>
<%= f.label :name%>
<%= f.text_field :name, class: "form-control"%>
<%= f.label :email%>
<%= f.email_field :email, class:"form-control"%>
<%= f.label :password%>
<%= f.password_field :password, class:"form-control"%>
<%= f.label :password_confirmation, "Confirmation"%>
<%= f.password_field :password_confirmation,class:"form-control"%>
<%= f.submit "Create my account", class:"btn btn-primary"%>
<%end%>
</div>
<div class="col-md-6 col-md-offset-3">
<%=render "form" %>
</div>
</div>
\ No newline at end of file
class AddRememberDigestToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :remember_digest, :string
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20190812113144) do
ActiveRecord::Schema.define(version: 20190820003030) do
create_table "users", force: :cascade do |t|
t.string "name"
......@@ -18,6 +18,7 @@ ActiveRecord::Schema.define(version: 20190812113144) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "password_digest"
t.string "remember_digest"
t.index ["email"], name: "index_users_on_email", unique: true
end
......
require "test_helper"
class SessionsHelperTest < ActionView::TestCase
def setup
@user = users(:michael)
remember(@user)
end
test "current_user return 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
# frozen_string_literal: true
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test 'unsuccessful edit' do
log_in_as(@user)
get edit_user_path @user
assert_template 'users/edit'
patch user_path @user, params: { user: {
name: '',
email: '[email protected]',
password: 'foo',
password_confirmation: 'bar'
} }
assert_template "users/edit"
end
test "successful edit" do
log_in_as(@user)
get edit_user_path(@user)
assert_template "users/edit"
name = "Foo Bar"
email = "[email protected]"
patch user_path(@user),params:{
user:{
name: name,
email: email,
password: "",
password_confirmation:""
}
}
assert_not flash.empty?
assert_redirected_to @user
@user.reload
assert_equal name, @user.name
assert_equal email, @user.email
end
end
......@@ -46,9 +46,27 @@ class UsersLoginTest < ActionDispatch::IntegrationTest
delete logout_path
assert_not is_logged_in?
assert_redirected_to root_url
#2番めのウィンドウでログアウトをクリックするユーザーをシミュレートする。
delete logout_path
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
test "authenticated? should return false for user with nil digest" do
assert_not @user.authenticated?("")
end
test "login with remembering" do
log_in_as(@user, remember_me:"1")
assert_equal cookies["remember_token"], assigns(:user).remember_token
end
test "login without remembering" do
log_in_as(@user, remember_me:"1")
delete logout_path
log_in_as(@user, remember_me:"0")
assert_empty cookies["remember_token"]
end
end
......@@ -12,4 +12,20 @@ class ActiveSupport::TestCase
def is_logged_in?
!session[:user_id].nil?
end
def log_in_as(user)
session[:user_id] = user.id
end
end
class ActionDispatch::IntegrationTest
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