diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index e6f2912c9..b8b357820 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -1047,4 +1047,12 @@ td.day .calendar-text { top: 0; } } -} \ No newline at end of file +} + +.btn-oidc-only { + font-size: 36px; + padding: 4px; + margin: 12px 10px; + display: flex; + justify-content: center; +} diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a7ca517b2..13ea4950b 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -698,4 +698,14 @@ def unverified_notice(resource) def theme_path "themes/#{params[:theme_preview] || current_space&.theme || TeSS::Config.site['default_theme'] || 'default'}" end + + def omniauth_login_link(provider, config) + link_to( + t('authentication.omniauth.log_in_with', + provider: config.options[:label] || + t("authentication.omniauth.providers.#{provider}", default: provider.to_s.titleize)), + omniauth_authorize_path('user', provider), + method: :post + ) + end end diff --git a/app/models/user.rb b/app/models/user.rb index d113186c5..44b713043 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -62,7 +62,9 @@ class User < ApplicationRecord before_save :set_username_for_invitee # Include default devise modules. Others available are: :lockable, :timeoutable - if TeSS::Config.feature['registration'] + if TeSS::Config.feature['login_through_oidc_only'] + devise :database_authenticatable, :confirmable, :trackable, :validatable, :omniauthable, :authentication_keys => [:login] + elsif TeSS::Config.feature['registration'] devise :database_authenticatable, :confirmable, :registerable, :invitable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :authentication_keys => [:login] elsif TeSS::Config.feature['invitation'] diff --git a/app/views/devise/sessions/_omniauth_options.html.erb b/app/views/devise/sessions/_omniauth_options.html.erb index 8fa2bd23a..68745c4c7 100644 --- a/app/views/devise/sessions/_omniauth_options.html.erb +++ b/app/views/devise/sessions/_omniauth_options.html.erb @@ -1,7 +1,8 @@ <% if devise_mapping.omniauthable? -%> <% Devise.omniauth_configs.each do |provider, config| -%> <%= link_to(omniauth_authorize_path(resource_name, provider), method: :post, - class: config.options[:logo] ? '' : 'btn btn-default') do %> + class: config.options[:logo] ? '' : + TeSS::Config.feature["login_through_oidc_only"] ? 'btn btn-default btn-lg btn-oidc-only' : 'btn btn-default') do %> <% if config.options[:logo].present? %> <%= image_tag(config.options[:logo], class: "omniauth-logo omniauth-#{provider}") -%> <% else %> diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 61728b088..a8518c381 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,6 +1,8 @@
<% if resource_class.omniauth_providers.any? && devise_mapping.omniauthable? %> @@ -10,12 +12,20 @@
<% end %> + <% if TeSS::Config.feature["login_through_oidc_only"] %> +
+
+
+

+
<%= t('authentication.omniauth.admin') %>

+
+
+ <% end %> <%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<%= t('authentication.password.title') %>

<%= t('authentication.password.description') %>

<%= f.input :login, label: t('authentication.password.email_or_username'), autofocus: true %> <%= f.input :password, label: t('authentication.password.password'), - input_html: { autocomplete: 'off' } %> + input_html: { autocomplete: 'off' } %> <% if devise_mapping.rememberable? -%> <%= f.input :remember_me, label: t('authentication.password.remember_me'), as: :boolean %> <% end -%> @@ -23,6 +33,12 @@ <%= f.submit t('authentication.password.log_in'), :class => 'btn btn-primary' %>
<% end %> + <% if !TeSS::Config.feature["login_through_oidc_only"] %> <%= render "devise/shared/links" %> + <% else %> + +
+ + <% end %>
diff --git a/app/views/layouts/_login_menu.html.erb b/app/views/layouts/_login_menu.html.erb index ca404040b..f857983a5 100644 --- a/app/views/layouts/_login_menu.html.erb +++ b/app/views/layouts/_login_menu.html.erb @@ -1,14 +1,16 @@ +<% if TeSS::Config.feature["login_through_oidc_only"] && Devise.omniauth_configs.size == 1 %> +
  • + <% provider, config = Devise.omniauth_configs.first %> + <%= omniauth_login_link(provider, config) %> +
  • +<% else %> +<% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 2075e30ee..e85ca8e92 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -743,6 +743,7 @@ en: oidc: OpenID Connect oidc2: Alternative OpenID Connect log_in_with: 'Log in with %{provider}' + admin: Admin ingestion: categories: events: 'Events' diff --git a/config/tess.example.yml b/config/tess.example.yml index 103916215..fb40dd153 100644 --- a/config/tess.example.yml +++ b/config/tess.example.yml @@ -147,13 +147,11 @@ default: &default feature: elearning_materials: false events: true - invitation: false materials: true nodes: false collections: true content_providers: true subscription: true - registration: true trainers: false workflows: true sources: false @@ -171,6 +169,9 @@ default: &default learning_paths: false collection_curation: true spaces: false + invitation: false + registration: true + login_through_oidc_only: false # when true, only the first oidc authentication will be available in TeSS, useful when you have your org SSO. Be careful! invitation and registration must be false when using this feature. restrict_content_provider_selection: false user_ingestion_methods: ['bioschemas'] placeholder: diff --git a/test/controllers/static_controller_test.rb b/test/controllers/static_controller_test.rb index f4c93039d..13b254422 100644 --- a/test/controllers/static_controller_test.rb +++ b/test/controllers/static_controller_test.rb @@ -493,4 +493,25 @@ class StaticControllerTest < ActionController::TestCase end end end + + test 'should find log in drop down when login_through_oidc_only is disabled' do + with_settings({ feature: { login_through_oidc_only: false } }) do + get :home + assert_select 'ul.user-options.nav.navbar-nav.navbar-right' do + assert_select 'a.dropdown-toggle', count: 1 + end + end + end + + test 'should find log in button when login_through_oidc_only is enabled' do + Devise.stub( :omniauth_configs, { oidc: OpenStruct.new(options: { label: "OIDC" }) } + ) do + with_settings({ feature: { login_through_oidc_only: true } }) do + get :home + assert_select 'ul.user-options.nav.navbar-nav.navbar-right' do + assert_select 'a[href="/users/auth/oidc"]', count: 1 + end + end + end + end end diff --git a/test/integration/login_test.rb b/test/integration/login_test.rb index 58b02aaa1..6d65ce1da 100644 --- a/test/integration/login_test.rb +++ b/test/integration/login_test.rb @@ -29,6 +29,24 @@ class LoginTest < ActionDispatch::IntegrationTest logout_user end + test 'should not see big login button and admin login when login_through_oidc_only is disabled' do + with_settings({ feature: { login_through_oidc_only: false } }) do + get '/users/sign_in' + assert_response :success + assert_select 'div.form-middle a.btn-oidc-only', false + assert_select 'dl.faq', false + end + end + + test 'should see big login button and admin login when login_through_oidc_only is enabled' do + with_settings({ feature: { login_through_oidc_only: true } }) do + get '/users/sign_in' + assert_response :success + assert_select 'div.form-middle a.btn-oidc-only' + assert_select 'dl.faq' + end + end + private def login_user(username, identifier, password)