mirror of
https://github.com/we-promise/sure.git
synced 2026-04-07 22:34:47 +00:00
* feat: add support for displaying and managing legacy SSO providers - Introduced UI section for environment/YAML-configured SSO providers. - Added warnings and guidance on migrating legacy providers to database-backed configuration. - Enhanced localization with new keys for legacy provider management. - Updated form and toggle components for improved usability. * Expand SSO documentation: add SAML 2.0 support, JIT provisioning settings, super-admin setup steps, audit logging, and user administration details. * Update JIT provisioning docs: clarify role mapping behavior and add examples; note new `logout_idp` audit log event. --------- Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>
164 lines
4.8 KiB
Ruby
164 lines
4.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Admin
|
|
class SsoProvidersController < Admin::BaseController
|
|
before_action :set_sso_provider, only: %i[show edit update destroy toggle test_connection]
|
|
|
|
def index
|
|
authorize SsoProvider
|
|
@sso_providers = policy_scope(SsoProvider).order(:name)
|
|
|
|
# Load runtime providers (from YAML/env) that might not be in the database
|
|
# This helps show users that legacy providers are active but not manageable via UI
|
|
@runtime_providers = Rails.configuration.x.auth.sso_providers || []
|
|
db_provider_names = @sso_providers.pluck(:name)
|
|
@legacy_providers = @runtime_providers.reject { |p| db_provider_names.include?(p[:name].to_s) }
|
|
end
|
|
|
|
def show
|
|
authorize @sso_provider
|
|
end
|
|
|
|
def new
|
|
@sso_provider = SsoProvider.new
|
|
authorize @sso_provider
|
|
end
|
|
|
|
def create
|
|
@sso_provider = SsoProvider.new(processed_params)
|
|
authorize @sso_provider
|
|
|
|
# Auto-generate redirect_uri if not provided
|
|
if @sso_provider.redirect_uri.blank? && @sso_provider.name.present?
|
|
@sso_provider.redirect_uri = "#{request.base_url}/auth/#{@sso_provider.name}/callback"
|
|
end
|
|
|
|
if @sso_provider.save
|
|
log_provider_change(:create, @sso_provider)
|
|
clear_provider_cache
|
|
redirect_to admin_sso_providers_path, notice: t(".success")
|
|
else
|
|
render :new, status: :unprocessable_entity
|
|
end
|
|
end
|
|
|
|
def edit
|
|
authorize @sso_provider
|
|
end
|
|
|
|
def update
|
|
authorize @sso_provider
|
|
|
|
# Auto-update redirect_uri if name changed
|
|
params_hash = processed_params.to_h
|
|
if params_hash[:name].present? && params_hash[:name] != @sso_provider.name
|
|
params_hash[:redirect_uri] = "#{request.base_url}/auth/#{params_hash[:name]}/callback"
|
|
end
|
|
|
|
if @sso_provider.update(params_hash)
|
|
log_provider_change(:update, @sso_provider)
|
|
clear_provider_cache
|
|
redirect_to admin_sso_providers_path, notice: t(".success")
|
|
else
|
|
render :edit, status: :unprocessable_entity
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
authorize @sso_provider
|
|
|
|
@sso_provider.destroy!
|
|
log_provider_change(:destroy, @sso_provider)
|
|
clear_provider_cache
|
|
|
|
redirect_to admin_sso_providers_path, notice: t(".success")
|
|
end
|
|
|
|
def toggle
|
|
authorize @sso_provider
|
|
|
|
@sso_provider.update!(enabled: !@sso_provider.enabled)
|
|
log_provider_change(:toggle, @sso_provider)
|
|
clear_provider_cache
|
|
|
|
notice = @sso_provider.enabled? ? t(".success_enabled") : t(".success_disabled")
|
|
redirect_to admin_sso_providers_path, notice: notice
|
|
end
|
|
|
|
def test_connection
|
|
authorize @sso_provider
|
|
|
|
tester = SsoProviderTester.new(@sso_provider)
|
|
result = tester.test!
|
|
|
|
render json: {
|
|
success: result.success?,
|
|
message: result.message,
|
|
details: result.details
|
|
}
|
|
end
|
|
|
|
private
|
|
def set_sso_provider
|
|
@sso_provider = SsoProvider.find(params[:id])
|
|
end
|
|
|
|
def sso_provider_params
|
|
params.require(:sso_provider).permit(
|
|
:strategy,
|
|
:name,
|
|
:label,
|
|
:icon,
|
|
:enabled,
|
|
:issuer,
|
|
:client_id,
|
|
:client_secret,
|
|
:redirect_uri,
|
|
:scopes,
|
|
:prompt,
|
|
settings: [
|
|
:default_role, :scopes, :prompt,
|
|
# SAML settings
|
|
:idp_metadata_url, :idp_sso_url, :idp_slo_url,
|
|
:idp_certificate, :idp_cert_fingerprint, :name_id_format,
|
|
role_mapping: {}
|
|
]
|
|
)
|
|
end
|
|
|
|
# Process params to convert role_mapping comma-separated strings to arrays
|
|
def processed_params
|
|
result = sso_provider_params.to_h
|
|
|
|
if result[:settings].present? && result[:settings][:role_mapping].present?
|
|
result[:settings][:role_mapping] = result[:settings][:role_mapping].transform_values do |v|
|
|
# Convert comma-separated string to array, removing empty values
|
|
v.to_s.split(",").map(&:strip).reject(&:blank?)
|
|
end
|
|
|
|
# Remove empty role mappings
|
|
result[:settings][:role_mapping] = result[:settings][:role_mapping].reject { |_, v| v.empty? }
|
|
result[:settings].delete(:role_mapping) if result[:settings][:role_mapping].empty?
|
|
end
|
|
|
|
result
|
|
end
|
|
|
|
def log_provider_change(action, provider)
|
|
Rails.logger.info(
|
|
"[Admin::SsoProviders] #{action.to_s.upcase} - " \
|
|
"user_id=#{Current.user.id} " \
|
|
"provider_id=#{provider.id} " \
|
|
"provider_name=#{provider.name} " \
|
|
"strategy=#{provider.strategy} " \
|
|
"enabled=#{provider.enabled}"
|
|
)
|
|
end
|
|
|
|
def clear_provider_cache
|
|
ProviderLoader.clear_cache
|
|
Rails.logger.info("[Admin::SsoProviders] Provider cache cleared by user_id=#{Current.user.id}")
|
|
end
|
|
end
|
|
end
|