Use sorcery for logins
This gives us more flexibility and allows us to use password authentication later. Also we don't need to build the login functionality ourself.
This commit is contained in:
@@ -37,4 +37,9 @@ $light: #fff;
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.button.google {
|
||||
background: rgb(225, 98, 89);
|
||||
color: white;
|
||||
}
|
||||
34
app/controllers/oauths_controller.rb
Normal file
34
app/controllers/oauths_controller.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
class OauthsController < ApplicationController
|
||||
|
||||
# Sends the user on a trip to the provider,
|
||||
# and after authorizing there back to the callback url.
|
||||
def oauth
|
||||
login_at(params[:provider])
|
||||
end
|
||||
|
||||
def callback
|
||||
provider = params[:provider]
|
||||
if @user = login_from(provider)
|
||||
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
|
||||
else
|
||||
begin
|
||||
@user = create_from(provider)
|
||||
if authentication = @user.authentications.find_by(provider: provider)
|
||||
authentication.update({
|
||||
access_token: @access_token.token,
|
||||
refresh_token: @access_token.refresh_token,
|
||||
expires_at: Time.at(@access_token.expires_at)
|
||||
})
|
||||
end
|
||||
|
||||
reset_session
|
||||
auto_login(@user)
|
||||
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
|
||||
rescue
|
||||
Rails.logger.error("Failed to login from #{provider}")
|
||||
redirect_to root_path, :alert => "Failed to login from #{provider.titleize}!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,29 +1,7 @@
|
||||
require 'google/apis/oauth2_v2'
|
||||
class SessionsController < ApplicationController
|
||||
|
||||
def new
|
||||
reset_session
|
||||
redirect_to auth_client.authorization_uri.to_s
|
||||
end
|
||||
|
||||
def auth
|
||||
reset_session
|
||||
if params[:error]
|
||||
flash[:error] = 'Login failed'
|
||||
redirect_to root_url
|
||||
else
|
||||
auth_client.code = params[:code]
|
||||
auth_client.fetch_access_token!
|
||||
|
||||
@user, @authentication = User.find_by_oauth_info(auth_client)
|
||||
if @user.persisted? && @authentication.persisted?
|
||||
session[:user_id] = @user.id.to_s
|
||||
redirect_to forms_url
|
||||
else
|
||||
flash[:error] = 'Login failed'
|
||||
redirect_to root_url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@@ -31,18 +9,4 @@ class SessionsController < ApplicationController
|
||||
redirect_to root_url
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def auth_client
|
||||
@auth_client ||= CLIENT_SECRETS.to_authorization.tap do |c|
|
||||
c.update!(
|
||||
scope: 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/spreadsheets',
|
||||
redirect_uri: auth_url,
|
||||
additional_parameters: {
|
||||
'access_type' => 'offline', # offline access
|
||||
'include_granted_scopes' => 'true' # incremental auth
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
class Authentication < ApplicationRecord
|
||||
belongs_to :user
|
||||
|
||||
scope :for, -> (provider) { where(provider: provider) }
|
||||
|
||||
encrypts :access_token
|
||||
encrypts :refresh_token
|
||||
|
||||
@@ -9,6 +11,7 @@ class Authentication < ApplicationRecord
|
||||
end
|
||||
|
||||
def google_authorization
|
||||
return nil unless provider == 'google'
|
||||
@google_authorization ||= CLIENT_SECRETS.to_authorization.tap do |c|
|
||||
c.access_token = self.access_token
|
||||
c.refresh_token = self.refresh_token
|
||||
|
||||
@@ -1,40 +1,18 @@
|
||||
class User < ApplicationRecord
|
||||
authenticates_with_sorcery!
|
||||
has_many :authentications, dependent: :destroy
|
||||
has_many :forms, dependent: :destroy
|
||||
|
||||
def self.find_by_oauth_info(auth_client)
|
||||
oauth = Google::Apis::Oauth2V2::Oauth2Service.new
|
||||
oauth.authorization = auth_client
|
||||
user_info = oauth.get_userinfo
|
||||
|
||||
if user = User.find_by(google_id: user_info.id)
|
||||
authentication = user.authentications.last
|
||||
authentication.access_token = auth_client.access_token if auth_client.access_token.present?
|
||||
authentication.refresh_token = auth_client.refresh_token if auth_client.refresh_token.present?
|
||||
authentication.expires_at = Time.at(auth_client.expires_at) if auth_client.expires_at.present?
|
||||
authentication.save
|
||||
return user, authentication
|
||||
else
|
||||
user = User.create(name: user_info.name, email: user_info.email, google_id: user_info.id)
|
||||
authentication = user.authentications.create(
|
||||
access_token: auth_client.access_token,
|
||||
refresh_token: auth_client.refresh_token,
|
||||
expires_at: Time.at(auth_client.expires_at)
|
||||
)
|
||||
return user, authentication
|
||||
end
|
||||
end
|
||||
|
||||
def deactivate!(reason = nil)
|
||||
# currently we only use deactivate if we get an authentication exception appending data to a spreadsheet
|
||||
authentications.last&.update(expires_at: Time.current)
|
||||
end
|
||||
|
||||
def active?
|
||||
authentications.last.present? && !authentications.last.expired?
|
||||
authentications.any? { |a| !a.expired? }
|
||||
end
|
||||
|
||||
def google_authorization
|
||||
authentications.last.google_authorization
|
||||
authentications.for(:google).last.google_authorization
|
||||
end
|
||||
end
|
||||
|
||||
22
app/views/sessions/new.html.erb
Normal file
22
app/views/sessions/new.html.erb
Normal file
@@ -0,0 +1,22 @@
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="container has-text-centered">
|
||||
<h1 class="title has-text-centered">
|
||||
Login
|
||||
</h1>
|
||||
<div class="button google">
|
||||
<svg viewBox="0 0 15 15" class="googleLogo" style="width: 14px; height: 14px; display: block; fill: currentcolor; flex-shrink: 0; backface-visibility: hidden; margin-right: 6px;"><path d="M 7.28571 6.4125L 7.28571 9L 11.3929 9C 11.2143 10.0875 10.1429 12.225 7.28571 12.225C 4.78571 12.225 2.78571 10.0875 2.78571 7.5C 2.78571 4.9125 4.82143 2.775 7.28571 2.775C 8.71429 2.775 9.64286 3.4125 10.1786 3.9375L 12.1429 1.9875C 10.8929 0.75 9.25 0 7.28571 0C 3.25 0 0 3.3375 0 7.5C 0 11.6625 3.25 15 7.28571 15C 11.5 15 14.25 11.9625 14.25 7.6875C 14.25 7.2 14.2143 6.825 14.1429 6.45L 7.28571 6.45L 7.28571 6.4125Z"></path></svg>
|
||||
Login with Google
|
||||
</div>
|
||||
<hr>
|
||||
<p>
|
||||
As tinyforms builds on Google Sheets.<br>
|
||||
Simply login with your Google account.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user