Skip to content

Commit

Permalink
Merge branch 'login-with-github'
Browse files Browse the repository at this point in the history
  • Loading branch information
trinitytakei committed Nov 21, 2024
2 parents 26cc8c8 + a5157ba commit 58f3139
Show file tree
Hide file tree
Showing 23 changed files with 336 additions and 42 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ group :test do
gem "mocha", "~> 2.5.0"
gem "simplecov", require: false
gem "simplecov-tailwindcss", require: false
gem "faker"
end

group :development, :test do
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ GEM
erubi (1.13.0)
et-orbi (1.2.11)
tzinfo
faker (3.5.1)
i18n (>= 1.8.11, < 2)
faraday (2.12.1)
faraday-net_http (>= 2.0, < 3.5)
json
Expand Down Expand Up @@ -513,6 +515,7 @@ DEPENDENCIES
debug
dotenv-rails
erb_lint
faker
friendly_id (~> 5.5.1)
kamal (~> 2.3.0)
litestream (~> 0.12.0)
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class ApplicationController < ActionController::Base
helper_method :user_signed_in?

def authenticate_user!
redirect_to root_path, alert: "Requires authentication" unless user_signed_in?
redirect_to root_path, alert: "Please sign in first." unless user_signed_in?
end

def current_user
Expand Down
18 changes: 13 additions & 5 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
class SessionsController < ApplicationController
def create
Rails.logger.info "OmniAuth Auth Hash: #{request.env['omniauth.auth'].inspect}"
@user = User.create_from_omniauth(request.env["omniauth.auth"])

if @user.persisted?
session[:user_id] = @user.id
redirect_path = request.env["omniauth.origin"] || dashboard_path
redirect_to redirect_path, notice: "Logged in as #{@user.name}"
else
redirect_to root_url, alert: "Failure"
Expand All @@ -14,12 +12,22 @@ def create

def destroy
session[:user_id] = nil
redirect_to root_path, notice: "Logged out"
redirect_to root_path, notice: "Signed out"
end

def failure
Rails.logger.error "OmniAuth Failure: #{request.env['omniauth.error'].inspect}"
Rails.logger.error "OmniAuth Error Type: #{request.env['omniauth.error.type'].inspect}"
redirect_to root_path, alert: "Authentication failed"
end

private

def redirect_path
origin_path = URI(request.env["omniauth.origin"]).path rescue "/"

if origin_path.present? && origin_path != "/" && origin_path != root_path
request.env["omniauth.origin"]
else
dashboard_path
end
end
end
9 changes: 9 additions & 0 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class UsersController < ApplicationController
before_action :authenticate_user!

def show
@user = User.friendly.find(params[:id])
rescue ActiveRecord::RecordNotFound
redirect_to root_path, alert: "User not found"
end
end
2 changes: 2 additions & 0 deletions app/helpers/users_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module UsersHelper
end
4 changes: 4 additions & 0 deletions app/models/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
# Table name: elements
#
# id :integer not null, primary key
# description :text
# image_path :string
# label :string not null
# position :integer
# variant_type :string
# created_at :datetime not null
# updated_at :datetime not null
Expand All @@ -13,6 +16,7 @@
# Indexes
#
# index_elements_on_label (label)
# index_elements_on_position (position)
# index_elements_on_sub_group_id (sub_group_id)
# index_elements_on_variant_type_and_variant_id (variant_type,variant_id)
#
Expand Down
11 changes: 6 additions & 5 deletions app/models/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
#
# Table name: groups
#
# id :integer not null, primary key
# title :string not null
# created_at :datetime not null
# updated_at :datetime not null
# page_id :integer not null
# id :integer not null, primary key
# behavior_type :string
# title :string not null
# created_at :datetime not null
# updated_at :datetime not null
# page_id :integer not null
#
# Indexes
#
Expand Down
23 changes: 22 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string
# image :string
# name :string
# provider :string
# slug :string
# uid :string
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_users_on_slug (slug) UNIQUE
#
class User < ApplicationRecord
extend FriendlyId
friendly_id :name, use: :slugged

validates :provider, presence: true
validates :uid, presence: true, uniqueness: true
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }, presence: true, uniqueness: true
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }, allow_blank: true

def self.create_from_omniauth(omniauth_params)
provider = omniauth_params.provider
Expand Down
1 change: 1 addition & 0 deletions app/views/users/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Welcome <%= @user.name %>
2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
get "users/show"
get "up", to: "rails/health#show", as: :rails_health_check

mount MissionControl::Jobs::Engine, at: "/jobs"
Expand All @@ -19,6 +20,7 @@
get "auth/failure", to: "sessions#failure"
delete "sign_out", to: "sessions#destroy"

resources :users, only: [ :show ], path: ""

root to: "static#home"
end
6 changes: 6 additions & 0 deletions db/migrate/20241121182456_add_slug_to_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddSlugToUsers < ActiveRecord::Migration[8.0]
def change
add_column :users, :slug, :string
add_index :users, :slug, unique: true
end
end
4 changes: 3 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions test/controllers/dashboard_controller_test.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
require "test_helper"

class DashboardControllerTest < ActionDispatch::IntegrationTest
test "should get show" do
user = users(:john)
sign_in(user)
get dashboard_path
assert_response :success
end
end
120 changes: 120 additions & 0 deletions test/controllers/sessions_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
require "test_helper"

class SessionControllerTest < ActionDispatch::IntegrationTest
setup do
# without this omniauth.origin can be set to the one in previous test (tags_url) resulting in flaky tests
OmniAuth.config.before_callback_phase do |env|
env["omniauth.origin"] = nil
end
end

test "guest should not be able to access dashboard" do
get dashboard_path
assert_redirected_to root_path

get dashboard_url
assert_response :redirect
assert_redirected_to root_path
assert_equal "Please sign in first.", flash[:alert]
end

test "authenticated github user should get dashboard" do
login_with_github

get dashboard_url
assert_response :success

delete sign_out_path
assert_response :redirect
assert_redirected_to root_url
assert_equal "Signed out", flash[:notice]
end


test "successful github sign in" do
login_with_github

assert_response :redirect
assert_redirected_to dashboard_url
email = OmniAuth.config.mock_auth[:github][:info][:email]
name = OmniAuth.config.mock_auth[:github][:info][:name]
assert_equal "Logged in as #{name}", flash[:notice]
assert User.pluck(:email).include?(email)
assert_equal controller.current_user.email, email
end

test "github oauth failure" do
silence_omniauth_logger do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:github] = :invalid_credentials
Rails.application.env_config["omniauth.auth"] = OmniAuth.config.mock_auth[:github]
get "/auth/github/callback"
follow_redirect!

assert_response :redirect
assert_redirected_to root_path
assert_equal "Authentication failed", flash[:alert]
assert_nil controller.current_user
end
end

test "github auth with no email" do
silence_omniauth_logger do
auth_hash = OmniAuth::AuthHash.new({
provider: "github",
uid: "123545",
info: {
nickname: "test nickname",
name: "test name",
email: nil,
image: "https://avatars.githubusercontent.com/u/123545?v=3"
}
})

OmniAuth.config.mock_auth[:github] = auth_hash
Rails.application.env_config["omniauth.auth"] = auth_hash

get "/auth/github/callback"

assert_redirected_to dashboard_path
assert_match "test name", flash[:notice]
end
end

test "redirect to previous page after login" do
user = users(:john)


OmniAuth.config.before_callback_phase do |env|
env["omniauth.origin"] = user_path(user)
end

sign_in(user)
assert_response :redirect
assert_redirected_to user_path(user)
end

test "github auth fails when user cannot be persisted" do
silence_omniauth_logger do
auth_hash = OmniAuth::AuthHash.new({
provider: "github",
uid: "", # Invalid uid (blank) will cause persistence to fail
info: {
nickname: "test nickname",
name: "foo",
email: "[email protected]",
image: "https://avatars.githubusercontent.com/u/123545?v=3"
}
})

OmniAuth.config.mock_auth[:github] = auth_hash
Rails.application.env_config["omniauth.auth"] = auth_hash

get "/auth/github/callback"

assert_redirected_to root_url
assert_equal "Failure", flash[:alert]
assert_nil session[:user_id]
end
end
end
30 changes: 30 additions & 0 deletions test/controllers/users_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require "test_helper"

class UsersControllerTest < ActionDispatch::IntegrationTest
test "should redierect for unauthenticated user" do
user = users(:john)
get user_path(user)

assert_response :redirect
assert_redirected_to root_path
assert_equal "Please sign in first.", flash[:alert]
end

test "should get show for authenticated user" do
user = users(:john)
sign_in(user)
get user_path(user)

assert_response :success
end

test "should raise error for non-existent user" do
user = users(:john)
sign_in(user)
get user_path("non-existent-user")

assert_response :redirect
assert_redirected_to root_path
assert_equal "User not found", flash[:alert]
end
end
4 changes: 4 additions & 0 deletions test/fixtures/elements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
# Table name: elements
#
# id :integer not null, primary key
# description :text
# image_path :string
# label :string not null
# position :integer
# variant_type :string
# created_at :datetime not null
# updated_at :datetime not null
Expand All @@ -15,6 +18,7 @@
# Indexes
#
# index_elements_on_label (label)
# index_elements_on_position (position)
# index_elements_on_sub_group_id (sub_group_id)
# index_elements_on_variant_type_and_variant_id (variant_type,variant_id)
#
Expand Down
13 changes: 7 additions & 6 deletions test/fixtures/groups.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
#
# Table name: groups
#
# id :integer not null, primary key
# title :string not null
# created_at :datetime not null
# updated_at :datetime not null
# page_id :integer not null
# id :integer not null, primary key
# behavior_type :string
# title :string not null
# created_at :datetime not null
# updated_at :datetime not null
# page_id :integer not null
#
# Indexes
#
Expand All @@ -30,4 +31,4 @@ dev_env:

essentials:
title: Essentials
page: basic_setup
page: basic_setup
Loading

0 comments on commit 58f3139

Please sign in to comment.