Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d57fc51

Browse files
committedNov 19, 2024·
Initial version of Github login
1 parent 345bda1 commit d57fc51

20 files changed

+265
-3
lines changed
 

‎Gemfile

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ gem "kamal", "~> 2.3.0", require: false
88
gem "thruster", "~> 0.1.8", require: false
99
gem "mission_control-jobs", "~> 0.4.0"
1010
gem "litestream", "~> 0.12.0"
11+
gem "omniauth-github", github: "omniauth/omniauth-github", branch: "master"
12+
gem "omniauth-rails_csrf_protection"
1113
gem "propshaft", "~> 1.1.0"
1214
gem "solid_cache", "~> 1.0.6"
1315
gem "solid_queue", "~> 1.0.1"

‎Gemfile.lock

+49
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
GIT
2+
remote: https://github.com/omniauth/omniauth-github.git
3+
revision: f27bb4e018150d87e9444ad13955acfc9e76f4d7
4+
branch: master
5+
specs:
6+
omniauth-github (2.0.1)
7+
omniauth (~> 2.0)
8+
omniauth-oauth2 (~> 1.8)
9+
110
GEM
211
remote: https://rubygems.org/
312
specs:
@@ -132,13 +141,20 @@ GEM
132141
erubi (1.13.0)
133142
et-orbi (1.2.11)
134143
tzinfo
144+
faraday (2.12.1)
145+
faraday-net_http (>= 2.0, < 3.5)
146+
json
147+
logger
148+
faraday-net_http (3.4.0)
149+
net-http (>= 0.5.0)
135150
friendly_id (5.5.1)
136151
activerecord (>= 4.0.0)
137152
fugit (1.11.1)
138153
et-orbi (~> 1, >= 1.2.11)
139154
raabro (~> 1.4)
140155
globalid (1.2.1)
141156
activesupport (>= 6.1)
157+
hashie (5.0.0)
142158
i18n (1.14.6)
143159
concurrent-ruby (~> 1.0)
144160
importmap-rails (2.0.3)
@@ -151,6 +167,8 @@ GEM
151167
rdoc (>= 4.0.0)
152168
reline (>= 0.4.2)
153169
json (2.7.2)
170+
jwt (2.9.3)
171+
base64
154172
kamal (2.3.0)
155173
activesupport (>= 7.0)
156174
base64 (~> 0.2)
@@ -227,6 +245,10 @@ GEM
227245
mocha (2.5.0)
228246
ruby2_keywords (>= 0.0.5)
229247
msgpack (1.7.2)
248+
multi_xml (0.7.1)
249+
bigdecimal (~> 3.1)
250+
net-http (0.5.0)
251+
uri
230252
net-imap (0.5.0)
231253
date
232254
net-protocol
@@ -254,6 +276,23 @@ GEM
254276
racc (~> 1.4)
255277
nokogiri (1.16.7-x86_64-linux)
256278
racc (~> 1.4)
279+
oauth2 (2.0.9)
280+
faraday (>= 0.17.3, < 3.0)
281+
jwt (>= 1.0, < 3.0)
282+
multi_xml (~> 0.5)
283+
rack (>= 1.2, < 4)
284+
snaky_hash (~> 2.0)
285+
version_gem (~> 1.1)
286+
omniauth (2.1.2)
287+
hashie (>= 3.4.6)
288+
rack (>= 2.2.3)
289+
rack-protection
290+
omniauth-oauth2 (1.8.0)
291+
oauth2 (>= 1.4, < 3)
292+
omniauth (~> 2.0)
293+
omniauth-rails_csrf_protection (1.0.2)
294+
actionpack (>= 4.2)
295+
omniauth (~> 2.0)
257296
ostruct (0.6.0)
258297
overcommit (0.64.0)
259298
childprocess (>= 0.6.3, < 6)
@@ -280,6 +319,10 @@ GEM
280319
raabro (1.4.0)
281320
racc (1.8.1)
282321
rack (3.1.7)
322+
rack-protection (4.1.0)
323+
base64 (>= 0.1.0)
324+
logger (>= 1.6.0)
325+
rack (>= 3.0.0, < 4)
283326
rack-proxy (0.7.7)
284327
rack
285328
rack-session (2.0.0)
@@ -373,6 +416,9 @@ GEM
373416
simplecov (~> 0.16)
374417
simplecov_json_formatter (0.1.4)
375418
smart_properties (1.17.0)
419+
snaky_hash (2.0.1)
420+
hashie
421+
version_gem (~> 1.1, >= 1.1.1)
376422
solid_cache (1.0.6)
377423
activejob (>= 7.2)
378424
activerecord (>= 7.2)
@@ -418,6 +464,7 @@ GEM
418464
unicode-display_width (2.6.0)
419465
uri (0.13.1)
420466
useragent (0.16.10)
467+
version_gem (1.1.4)
421468
vite_rails (3.0.19)
422469
railties (>= 5.1, < 9)
423470
vite_ruby (~> 3.0, >= 3.2.2)
@@ -472,6 +519,8 @@ DEPENDENCIES
472519
minio (~> 0.4.0)
473520
mission_control-jobs (~> 0.4.0)
474521
mocha (~> 2.5.0)
522+
omniauth-github!
523+
omniauth-rails_csrf_protection
475524
overcommit
476525
phlex-rails (~> 1.2.1)
477526
propshaft (~> 1.1.0)
+16-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,19 @@
11
class ApplicationController < ActionController::Base
2-
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
32
allow_browser versions: :modern
3+
4+
protect_from_forgery with: :exception
5+
helper_method :current_user
6+
helper_method :user_signed_in?
7+
8+
def authenticate_user!
9+
redirect_to root_path, alert: "Requires authentication" unless user_signed_in?
10+
end
11+
12+
def current_user
13+
@current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
14+
end
15+
16+
def user_signed_in?
17+
!!current_user
18+
end
419
end
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class DashboardController < ApplicationController
2+
before_action :authenticate_user!
3+
4+
def show
5+
end
6+
end
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
class SessionsController < ApplicationController
2+
def create
3+
@user = User.create_from_omniauth(request.env["omniauth.auth"])
4+
5+
if @user.persisted?
6+
session[:user_id] = @user.id
7+
redirect_path = request.env["omniauth.origin"] || dashboard_path
8+
redirect_to redirect_path, notice: "Logged in as #{@user.name}"
9+
else
10+
redirect_to root_url, alert: "Failure"
11+
end
12+
end
13+
14+
def destroy
15+
session[:user_id] = nil
16+
redirect_to root_path, notice: "Logged out"
17+
end
18+
19+
def failure
20+
end
21+
end

‎app/helpers/dashboard_helper.rb

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
module DashboardHelper
2+
end

‎app/models/user.rb

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class User < ApplicationRecord
2+
validates :provider, presence: true
3+
validates :uid, presence: true, uniqueness: true
4+
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }, presence: true, uniqueness: true
5+
6+
def self.create_from_omniauth(omniauth_params)
7+
provider = omniauth_params.provider
8+
uid = omniauth_params.uid
9+
10+
user = User.find_or_initialize_by(provider:, uid:)
11+
user.email = omniauth_params.info.email
12+
user.name = omniauth_params.info.name
13+
user.image = omniauth_params.info.image
14+
user.save
15+
user
16+
end
17+
end

‎app/views/components/nav/main/component.rb

+50
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# frozen_string_literal: true
22

33
class Nav::Main::Component < ApplicationComponent
4+
include Phlex::Rails::Helpers::ButtonTo
5+
6+
delegate :current_user, to: :helpers
7+
48
def view_template
59
div(data_controller: "nav-mobile-menu") do
610
div(class: "max-w-screen-xl mx-auto px-4 sm:px-6 sm:mt-0 md:mt-3 bg-white") do
@@ -51,6 +55,52 @@ def view_template
5155
whitespace
5256
end
5357
end
58+
59+
# Add Get in button on the right
60+
div(class: "hidden md:absolute md:flex md:items-center md:justify-end md:inset-y-0 md:right-0") do
61+
if current_user
62+
button_to(
63+
"/sign_out",
64+
method: :delete,
65+
class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-gray-900 hover:bg-gray-700"
66+
) do
67+
svg(
68+
class: "w-5 h-5 mr-2",
69+
fill: "currentColor",
70+
viewbox: "0 0 24 24",
71+
aria_hidden: "true"
72+
) do |s|
73+
s.path(
74+
fill_rule: "evenodd",
75+
clip_rule: "evenodd",
76+
d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
77+
)
78+
end
79+
plain "Logout"
80+
end
81+
else
82+
button_to(
83+
"/auth/github",
84+
method: :post,
85+
data: { turbo: false },
86+
class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-gray-900 hover:bg-gray-700"
87+
) do
88+
svg(
89+
class: "w-5 h-5 mr-2",
90+
fill: "currentColor",
91+
viewbox: "0 0 24 24",
92+
aria_hidden: "true"
93+
) do |s|
94+
s.path(
95+
fill_rule: "evenodd",
96+
clip_rule: "evenodd",
97+
d: "M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
98+
)
99+
end
100+
plain "Get in"
101+
end
102+
end
103+
end
54104
whitespace
55105
end
56106
end

‎app/views/dashboard/show.html.erb

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<h1>Dashboard#index</h1>
2+
<p>Find me in app/views/dashboard/index.html.erb</p>

‎app/views/layouts/application.html.erb

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
<%= vite_javascript_tag "application" %>
1818
</head>
1919
<body>
20+
<% if notice %>
21+
<p class="p-4 mb-4 text-sm text-green-800 bg-green-100 rounded-lg dark:bg-green-200 dark:text-green-800"><%= notice %></p>
22+
<% end %>
23+
<% if alert %>
24+
<p class="p-4 mb-4 text-sm text-red-800 bg-red-100 rounded-lg dark:bg-red-200 dark:text-red-800"><%= alert %></p>
25+
<% end %>
2026
<%= render Nav::Main::Component.new %>
2127
<%= yield %>
2228
<!-- 100% privacy-first analytics -->

‎app/views/session/failure.html.erb

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<h1>Session#failure</h1>
2+
<p>Find me in app/views/session/failure.html.erb</p>
+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Sg7Q2dwnWxjK2Mq2MmPPUYWUX2PKM+l4e4DuEcAqkY/y+2kQNbkx+1bzA+tnJLCEOCsGB4UnJZJZh/bKSx7KdddYrb86o91Nr3voqyiiAiaSvYTlzh8q6+Wijc/zyd9pT8gSWRi6RKPGQ1tnBID258eA7EQLRz3seHq6V8hk/lbVbfcq2IWpIRuGhzFlvz9PPQQpzxHL/jMmSPg=--swKpIerep+qrJ0Rh--1nh/oIprZkKKXuCFQrkPNQ==
1+
cqgblP/WZVUj7XLxx2aTg3eRDgL12lKyx4MD1KGp+0HiDOpcv9v4vYLQAMYntjDybrPbmyxnw2JUlB0Jzrih5djoiw0vNsCtPhkdtxTm6HjnuH/L2lu+M0JSFtg4CliACwXt+hSawlaZgWlQhDbXRI3cNnDIOFJ5Qgv5t5wtqto1LYWDdaaLSui1SP62bA6BplhyQM3OjJfJs2njKb3U3JOkJ4bokWbgA31IQSnFkgxUNVSO/WNA7nm7cjvIOEhjhCoVSpIPZTQTWF2b9aemgCXFapNwN5iIeNVlctROm7FO1VLWkPGu2r8xnGftbdCwOcCBihOX8HmZqHkKCwTw1a5hjM2TFdE=--escjTzyiTJRzv0Y3--cA8eAACAaxaVdCfmxm6aZQ==

‎config/initializers/omniauth.rb

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Rails.application.config.middleware.use OmniAuth::Builder do
2+
github_oauth_credentials = Rails.application.credentials.github_oauth
3+
4+
provider :github,
5+
github_oauth_credentials.client_id,
6+
github_oauth_credentials.client_secret,
7+
scope: "public_repo"
8+
end

‎config/routes.rb

+6
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,11 @@
1313
get :about
1414
end
1515

16+
get "dashboard", to: "dashboard#show"
17+
18+
get "auth/github/callback", to: "sessions#create"
19+
get "auth/failure", to: "sessions#failure"
20+
delete "sign_out", to: "sessions#destroy"
21+
1622
root to: "static#home"
1723
end
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
class CreateUsers < ActiveRecord::Migration[8.0]
2+
def change
3+
create_table :users do |t|
4+
t.string :provider
5+
t.string :uid
6+
t.string :name
7+
t.string :email
8+
t.string :image
9+
10+
t.timestamps
11+
end
12+
end
13+
end

‎db/schema.rb

+16-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require "test_helper"
2+
3+
class DashboardControllerTest < ActionDispatch::IntegrationTest
4+
test "should get index" do
5+
get dashboard_index_url
6+
assert_response :success
7+
end
8+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require "test_helper"
2+
3+
class SessionControllerTest < ActionDispatch::IntegrationTest
4+
test "should get create" do
5+
get session_create_url
6+
assert_response :success
7+
end
8+
9+
test "should get destroy" do
10+
get session_destroy_url
11+
assert_response :success
12+
end
13+
14+
test "should get failure" do
15+
get session_failure_url
16+
assert_response :success
17+
end
18+
end

0 commit comments

Comments
 (0)