mirror of
https://github.com/astuto/astuto.git
synced 2025-12-16 03:37:56 +01:00
Add default OAuths (#259)
This commit is contained in:
committed by
GitHub
parent
0828c9c879
commit
653e139a9e
@@ -49,7 +49,8 @@ class ApplicationController < ActionController::Base
|
||||
end
|
||||
|
||||
def load_oauths
|
||||
@o_auths = Current.tenant_or_raise!.o_auths
|
||||
@o_auths = OAuth
|
||||
.include_defaults
|
||||
.where(is_enabled: true)
|
||||
.order(created_at: :asc)
|
||||
end
|
||||
|
||||
@@ -7,15 +7,17 @@ class OAuthsController < ApplicationController
|
||||
|
||||
TOKEN_STATE_SEPARATOR = '-'
|
||||
|
||||
# [subdomain.]base_url/o_auths/:id/start?reason=user|test
|
||||
# [subdomain.]base_url/o_auths/:id/start?reason=login|test|tenantsignup
|
||||
# Generates authorize url with required parameters and redirects to provider
|
||||
def start
|
||||
@o_auth = OAuth.find(params[:id])
|
||||
return if params[:reason] == 'user' and not @o_auth.is_enabled?
|
||||
@o_auth = OAuth.unscoped.include_defaults.find(params[:id])
|
||||
|
||||
return if params[:reason] != 'test' and not @o_auth.is_enabled?
|
||||
|
||||
# Generate random state + other query params
|
||||
token_state = "#{params[:reason]}#{TOKEN_STATE_SEPARATOR}#{Devise.friendly_token(30)}"
|
||||
session[:token_state] = token_state
|
||||
tenant_domain = Current.tenant ? Current.tenant_or_raise!.subdomain : "null"
|
||||
token_state = "#{params[:reason]}#{TOKEN_STATE_SEPARATOR}#{tenant_domain}#{TOKEN_STATE_SEPARATOR}#{Devise.friendly_token(30)}"
|
||||
cookies[:token_state] = { value: token_state, domain: ".#{request.domain}", httponly: true }
|
||||
@o_auth.state = token_state
|
||||
|
||||
redirect_to @o_auth.authorize_url_with_query_params
|
||||
@@ -24,32 +26,42 @@ class OAuthsController < ApplicationController
|
||||
# [subdomain.]base_url/o_auths/:id/callback
|
||||
# Exchange authorization code for access token, fetch user info and sign in/up
|
||||
def callback
|
||||
reason, token_state = params[:state].split(TOKEN_STATE_SEPARATOR, 2)
|
||||
reason, tenant_domain, token_state = params[:state].split(TOKEN_STATE_SEPARATOR, 3)
|
||||
|
||||
return unless session[:token_state] == params[:state]
|
||||
return unless cookies[:token_state] == params[:state]
|
||||
cookies.delete(:token_state, domain: ".#{request.domain}")
|
||||
|
||||
@o_auth = OAuth.find(params[:id])
|
||||
@o_auth = OAuth.unscoped.include_defaults.find(params[:id])
|
||||
|
||||
return if reason != 'test' and not @o_auth.is_enabled?
|
||||
|
||||
# If it is a default OAuth we need to set the tenant
|
||||
if @o_auth.is_default?
|
||||
Current.tenant = Tenant.find_by(subdomain: tenant_domain)
|
||||
end
|
||||
|
||||
user_profile = OAuthExchangeAuthCodeForProfile.new(
|
||||
authorization_code: params[:code],
|
||||
o_auth: @o_auth
|
||||
).run
|
||||
|
||||
if reason == 'user'
|
||||
if reason == 'login'
|
||||
|
||||
user = OAuthSignInUser.new(
|
||||
user_profile: user_profile,
|
||||
o_auth: @o_auth
|
||||
).run
|
||||
|
||||
if user
|
||||
sign_in user
|
||||
flash[:notice] = I18n.t('devise.sessions.signed_in')
|
||||
redirect_to root_path
|
||||
oauth_token = user.generate_oauth_token
|
||||
redirect_to add_subdomain_to(method(:o_auth_sign_in_from_oauth_token_url), nil, {user_id: user.id, token: oauth_token})
|
||||
else
|
||||
flash[:alert] = I18n.t('errors.o_auth_login_error', name: @o_auth.name)
|
||||
redirect_to new_user_session_path
|
||||
redirect_to add_subdomain_to(method(:new_user_session_url))
|
||||
end
|
||||
|
||||
elsif reason == 'test'
|
||||
|
||||
unless user_signed_in? and current_user.admin?
|
||||
flash[:alert] = I18n.t('errors.unauthorized')
|
||||
redirect_to root_url
|
||||
@@ -57,15 +69,53 @@ class OAuthsController < ApplicationController
|
||||
end
|
||||
|
||||
@user_profile = user_profile
|
||||
@user_email = query_path_from_hash(user_profile, @o_auth.json_user_email_path)
|
||||
@user_email = query_path_from_object(user_profile, @o_auth.json_user_email_path)
|
||||
@email_valid = URI::MailTo::EMAIL_REGEXP.match?(@user_email)
|
||||
@user_name = query_path_from_hash(user_profile, @o_auth.json_user_name_path)
|
||||
@name_valid = !@user_name.nil?
|
||||
if not @o_auth.json_user_name_path.blank?
|
||||
@user_name = query_path_from_object(user_profile, @o_auth.json_user_name_path)
|
||||
@name_valid = !@user_name.nil?
|
||||
end
|
||||
|
||||
render 'o_auths/test', layout: false
|
||||
|
||||
elsif reason == 'tenantsignup'
|
||||
|
||||
@o_auths = []
|
||||
@user_email = query_path_from_object(user_profile, @o_auth.json_user_email_path)
|
||||
if not @o_auth.json_user_name_path.blank?
|
||||
@user_name = query_path_from_object(user_profile, @o_auth.json_user_name_path)
|
||||
end
|
||||
@o_auth_login_completed = true
|
||||
|
||||
session[:o_auth_sign_up] = "#{@user_email},#{@user_name}"
|
||||
|
||||
render 'tenants/new'
|
||||
|
||||
else
|
||||
|
||||
flash[:alert] = I18n.t('errors.unknown')
|
||||
redirect_to root_url
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# [subdomain.]base_url/o_auths/sign_in_from_oauth_token?user_id=<id>&token=<token>
|
||||
# Used for OAuth with reason 'login'
|
||||
# It has been introduced because of default OAuth providers,
|
||||
# since they must redirect to a common domain for all tenants.
|
||||
def sign_in_from_oauth_token
|
||||
return unless params[:user_id] and params[:token]
|
||||
|
||||
user = User.find(params[:user_id])
|
||||
|
||||
if user.oauth_token == params[:token]
|
||||
sign_in user
|
||||
user.invalidate_oauth_token
|
||||
flash[:notice] = I18n.t('devise.sessions.signed_in')
|
||||
redirect_to root_path
|
||||
else
|
||||
flash[:alert] = I18n.t('errors.o_auth_login_error', name: @o_auth.name)
|
||||
redirect_to new_user_session_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -74,7 +124,7 @@ class OAuthsController < ApplicationController
|
||||
def index
|
||||
authorize OAuth
|
||||
|
||||
@o_auths = OAuth.order(created_at: :asc)
|
||||
@o_auths = OAuth.include_defaults.order(created_at: :asc)
|
||||
|
||||
render json: to_json_custom(@o_auths)
|
||||
end
|
||||
|
||||
@@ -5,6 +5,7 @@ class TenantsController < ApplicationController
|
||||
|
||||
def new
|
||||
@page_title = t('signup.page_title')
|
||||
@o_auths = OAuth.unscoped.where(tenant_id: nil)
|
||||
end
|
||||
|
||||
def show
|
||||
@@ -16,17 +17,34 @@ class TenantsController < ApplicationController
|
||||
@tenant.assign_attributes(tenant_create_params)
|
||||
authorize @tenant
|
||||
|
||||
is_o_auth_login = params[:settings][:is_o_auth_login]
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
if is_o_auth_login
|
||||
# Check if OAuth email and username coincide with submitted ones
|
||||
# (session[:o_auth_sign_up] set in oauth#callback)
|
||||
email, username = session[:o_auth_sign_up].split(",", 2)
|
||||
raise "Mismatching email in OAuth login" unless email == params[:user][:email]
|
||||
|
||||
@tenant.status = "active" # no need to verify email address if logged in with oauth
|
||||
end
|
||||
|
||||
@tenant.save!
|
||||
Current.tenant = @tenant
|
||||
|
||||
@user = User.create!(
|
||||
full_name: params[:user][:full_name],
|
||||
|
||||
@user = User.new(
|
||||
full_name: params[:user][:full_name] || I18n.t('defaults.user_full_name'),
|
||||
email: params[:user][:email],
|
||||
password: params[:user][:password],
|
||||
password: is_o_auth_login ? Devise.friendly_token : params[:user][:password],
|
||||
role: "owner"
|
||||
)
|
||||
|
||||
|
||||
if is_o_auth_login
|
||||
@user.skip_confirmation
|
||||
end
|
||||
|
||||
@user.save!
|
||||
|
||||
render json: @tenant, status: :created
|
||||
|
||||
rescue ActiveRecord::RecordInvalid => exception
|
||||
|
||||
Reference in New Issue
Block a user