-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GitHubログイン機能を実装した #67
Changes from all commits
570cdcd
53cf64c
fccf352
eb22f45
2a5f3fb
f046971
2c9a3d6
ccecc2b
641d393
6d9384a
574a34d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,11 @@ | ||
# frozen_string_literal: true | ||
|
||
class ApplicationController < ActionController::Base | ||
helper_method :logged_in? | ||
|
||
private | ||
|
||
def logged_in? | ||
!!session[:user_id] | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# frozen_string_literal: true | ||
|
||
class UserSessionsController < ApplicationController | ||
def create | ||
user = User.find_or_create_from_auth_hash!(request.env['omniauth.auth']) | ||
session[:user_id] = user.id | ||
redirect_to new_group_path, notice: 'ログインしました' | ||
end | ||
|
||
def destroy | ||
reset_session | ||
redirect_to root_path, notice: 'ログアウトしました' | ||
end | ||
|
||
def failure | ||
redirect_to root_path, notice: 'ログインをキャンセルしました' | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# frozen_string_literal: true | ||
|
||
class User < ApplicationRecord | ||
validates :provider, presence: true | ||
validates :uid, presence: true, uniqueness: { scope: :provider } | ||
validates :name, presence: true, uniqueness: true | ||
validates :image_url, presence: true, uniqueness: true | ||
|
||
def self.find_or_create_from_auth_hash!(auth_hash) | ||
provider = auth_hash[:provider] | ||
uid = auth_hash[:uid] | ||
nickname = auth_hash[:info][:nickname] | ||
image_url = auth_hash[:info][:image] | ||
|
||
User.find_or_create_by!(provider:, uid:) do |user| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
user.name = nickname | ||
user.image_url = image_url | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,14 @@ p.mb-4 | |
.mb-4 | ||
= link_to '2次会グループを作成', new_group_path | ||
|
||
.mb-4 | ||
- if logged_in? | ||
= button_to 'ログアウト', logout_path, method: :delete | ||
- else | ||
= button_to 'サインアップ / ログインをして2次会グループを作成', '/auth/github', data: { turbo: false } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
span.text-xs | ||
| GitHubアカウントが必要です | ||
|
||
p.text-xl.font-bold.mb-4 | ||
| 2次会グループ一覧 | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
p style="color: green" = notice | ||
|
||
h1.text-2xl.font-bold.mb-4 | ||
| 2次会グループを作成 | ||
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
JiytSi4MiwjEUWC995pbQqk0uR3EezofyHGzZxyM3RhxiS2NkVSKx/B0ULh6XVYJM5mwVgZ7Gcxh09PxmX78QQOx1D9/aVJ5fMF6O/3XLhVZ7FPkLQ5g9BPIZqJipqhb3QIaDGv3YCap+HtEuFtu0xv8Eqelz6p/Reabwxr+ZfIvJQZMWRsqnDDgbwkSBgvzgga1rR7C7F47chloAZSNYaF0oyGuH5SoULZB2+cKzjc2GD4M23NVhA0y2CfN0pZRcXLzvka1vyHTdgtkYW2DTWOs60gEuVslovBOQAb2/RuSM6dkG4tIG6zXOfu9Nk1rLQzSvcZFj9J8h5a85PJF1jC/fmXf8w6Bsk9JZkqfadQNbFuOd/vap1oPfuXSe68Neq45rG/Wp9XP+xUXdSUWCgIAv+UT--osFtXK0CWL5Y0STB--DusPBnj2G7mby6v8SvTDgw== | ||
WrNv9PmTDANqa1e1FWXw17TafFTDdNV17QaORIVYhjUKQ2vOEPpD2KOiFVEat2tewzJhP9F5akrJS8IOuEOuteFRcP7XPfiwX8tG8mo49Z7WBtLYlRKLNxwFffhzi23NCH6Rk1BiYrr7deVfhmaSvMacp9OYGxsKymlSOxURwRaAfn0uSIL8PmqtEigVTSan1RRqwcdEyTJEcegCiLZItZdjJzDATOTIF5Zapgt1BnttB+b7ylI6xdu8lX0dQKyxFxo77+vLIIjcwWZp/jNKOou3vv7iTGm8gqQ6Mg82RFmPF+q5HnLxWJVDLv7PRUXrJCg1RfEk1Zid6aQz87LnK+K16Vj3xrgTkJf3prYSZX5FLOGSjkkFRdtFC0cMQRtfjawjLTtp9pEdQhCJGgqR+L/Vn59ENaT+DTuHkG5ZjvuwN9f/m/abMpYy7RBBr02q5RyIya6giisznvixdZ5EzYIklan02hRBaAzoQ6d82qTV5hIxUFIJSZDUrURrbMdq6UMm3j+12GX2ETi/jHAxrsIcrJwUwLQUkYiY3KA=--xU62kZ2t3TKIjDjl--szzWlOmAxIdcsh91yZYfYQ== |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Rails.application.config.middleware.use OmniAuth::Builder do | ||
provider :github, | ||
Rails.application.credentials.github[:client_id], | ||
Rails.application.credentials.github[:client_secret] | ||
|
||
OmniAuth.config.on_failure = Proc.new { |env| | ||
OmniAuth::FailureEndpoint.new(env).redirect_to_failure | ||
} | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
class CreateUsers < ActiveRecord::Migration[7.1] | ||
def change | ||
create_table :users do |t| | ||
t.string :provider, null: false | ||
t.string :uid, null: false | ||
t.string :name, null: false | ||
t.string :image_url, null: false | ||
|
||
t.timestamps | ||
end | ||
|
||
add_index :users, %i[provider uid], unique: true | ||
end | ||
end |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class AddIndexToUsers < ActiveRecord::Migration[7.1] | ||
def change | ||
add_index :users, :name, unique: true | ||
add_index :users, :image_url, unique: true | ||
end | ||
end |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# frozen_string_literal: true | ||
|
||
FactoryBot.define do | ||
factory :user do | ||
provider { 'github' } | ||
uid { '0001' } | ||
name { 'tester1' } | ||
image_url { 'example.com/1' } | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rails_helper' | ||
|
||
RSpec.describe User, type: :model do | ||
let(:user) { FactoryBot.create(:user) } | ||
|
||
it 'is valid with all attributes' do | ||
expect(user).to be_valid | ||
end | ||
|
||
describe 'validations' do | ||
it 'is invalid without a provider' do | ||
user.provider = nil | ||
user.valid? | ||
expect(user.errors[:provider]).to include('を入力してください') | ||
end | ||
|
||
it 'is invalid without a uid' do | ||
user.uid = nil | ||
user.valid? | ||
expect(user.errors[:uid]).to include('を入力してください') | ||
end | ||
|
||
it 'is invalid without a name' do | ||
user.name = nil | ||
user.valid? | ||
expect(user.errors[:name]).to include('を入力してください') | ||
end | ||
|
||
it 'is invalid without an image_url' do | ||
user.image_url = nil | ||
user.valid? | ||
expect(user.errors[:image_url]).to include('を入力してください') | ||
end | ||
|
||
it 'is invalid with a duplicate name' do | ||
FactoryBot.create(:user) | ||
user2 = FactoryBot.build(:user, image_url: 'example.com/2', provider: 'twitter', uid: '0002') | ||
user2.valid? | ||
expect(user2.errors[:name]).to include('はすでに存在します') | ||
end | ||
|
||
it 'is invalid with a duplicate image_url' do | ||
FactoryBot.create(:user) | ||
user2 = FactoryBot.build(:user, name: 'tester2', provider: 'twitter', uid: '0002') | ||
user2.valid? | ||
expect(user2.errors[:image_url]).to include('はすでに存在します') | ||
end | ||
|
||
it 'is invalid with a duplicate uid and provider pair' do | ||
FactoryBot.create(:user) | ||
user2 = FactoryBot.build(:user, name: 'tester2', image_url: 'example.com/2') | ||
user2.valid? | ||
expect(user2.errors[:uid]).to include('はすでに存在します') | ||
end | ||
|
||
it 'allows duplicate uid with different provider' do | ||
FactoryBot.create(:user) | ||
user2 = FactoryBot.build(:user, name: 'tester2', image_url: 'example.com/2', provider: 'twitter') | ||
expect(user2).to be_valid | ||
end | ||
end | ||
|
||
describe '.find_or_create_from_auth_hash!' do | ||
let(:auth_hash) do | ||
{ | ||
provider: 'github', | ||
uid: '0001', | ||
info: { | ||
nickname: 'testuser', | ||
image: 'https://example.com/testuser.png' | ||
} | ||
} | ||
end | ||
|
||
context 'when user does not exist' do | ||
it 'creates a new user' do | ||
expect do | ||
described_class.find_or_create_from_auth_hash!(auth_hash) | ||
end.to change(described_class, :count).by(1) | ||
end | ||
|
||
it 'returns the created user' do | ||
user = described_class.find_or_create_from_auth_hash!(auth_hash) | ||
expect(user).to have_attributes( | ||
provider: 'github', | ||
uid: '0001', | ||
name: 'testuser', | ||
image_url: 'https://example.com/testuser.png' | ||
) | ||
end | ||
end | ||
|
||
context 'when user already exists' do | ||
before { FactoryBot.create(:user) } | ||
|
||
it 'does not create a new user' do | ||
expect do | ||
described_class.find_or_create_from_auth_hash!(auth_hash) | ||
end.not_to change(described_class, :count) | ||
end | ||
|
||
it 'returns the existing user' do | ||
user = described_class.find_or_create_from_auth_hash!(auth_hash) | ||
expect(user).to have_attributes( | ||
provider: 'github', | ||
uid: '0001', | ||
name: 'tester1', | ||
image_url: 'example.com/1' | ||
) | ||
end | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
認証方法はGitHub認証だけの予定。そのため
name
とimage_url
にもユニーク制約を追加(GitHub認証だけなら
provider
もいらないかも)