From 77662ef03f69fe595d888d8c52ece20c359c4e5c Mon Sep 17 00:00:00 2001 From: pabois <pierreandre.boissinot@noesya.coop> Date: Mon, 2 May 2022 15:12:27 +0200 Subject: [PATCH] wip mapping --- app/models/user/with_omniauth.rb | 48 ++++++++++++++++++-- app/views/server/universities/_form.html.erb | 6 ++- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/app/models/user/with_omniauth.rb b/app/models/user/with_omniauth.rb index f0de9a849..5ce3c64a2 100644 --- a/app/models/user/with_omniauth.rb +++ b/app/models/user/with_omniauth.rb @@ -5,10 +5,9 @@ module User::WithOmniauth def self.from_omniauth(university, attributes) mapping = university.sso_mapping - email = 'pierreandre.boissinot@noesya.coop' - # email_sso_key = mapping.select { |elmt| elmt['internal_key'] == 'email' }&.first&.dig('sso_key') - email_sso_key = 'email' + # first step: we find the email (we are supposed to have an email mapping) + email_sso_key = mapping.select { |elmt| elmt['internal_key'] == 'email' }&.first&.dig('sso_key') email = attributes.dig(email_sso_key) return unless email email = email.first if email.is_a?(Array) @@ -17,6 +16,49 @@ module User::WithOmniauth user = User.where(university: university, email: email).first_or_create do |u| u.password = "#{Devise.friendly_token[0,20]}!" # meets password complexity requirements end + + # update user data according to mapping & infos provided by SSO + mapping.select { |elmt| elmt['internal_key'] != 'email' }.each do |mapping_element| + user = self.update_data_for_mapping_element(user, mapping_element, attributes) + end + + user.save + user + end + + protected + + def self.update_data_for_mapping_element(user, mapping_element, attributes) + sso_key = mapping_element['sso_key'] + return user if attributes[sso_key].nil? # if not provided by sso, just return + internal_key = mapping_element['internal_key'] + user = self.update_data_for_mapping_element_standard(user, mapping_element, self.get_provided_answer(attributes[sso_key])) + user + end + + def self.update_data_for_mapping_element_standard(user, mapping_element, sso_value) + case mapping_element['type'] + when 'text' + user[mapping_element['internal_key']] = sso_value.first + when 'select' + value = mapping_element['values'].select { |val| val['sso_value'] == sso_value.first } + user[mapping_element['internal_key']] = value.first&.dig('internal_value') + when 'newsletter' + user.optin_newsletter_basic = '1' if mapping_element['values'].first['sso_value'] == sso_value.first + when 'language' + user = self.set_best_id_for(user, mapping_element['type'], sso_value.first) + end + user + end + + def self.get_provided_answer(value) + # SAML send an array (even for a single value) where OAuth2 send a string for single values. We harmonize to always get an array + value.is_a?(Array) ? value : [value] + end + + def self.set_best_id_for(user, type, iso) + element_id = eval(type.classify).find_by(iso_code: iso)&.id + user["#{type}_id"] = element_id unless element_id.nil? user end diff --git a/app/views/server/universities/_form.html.erb b/app/views/server/universities/_form.html.erb index c3e2a4743..aafc0fcb5 100644 --- a/app/views/server/universities/_form.html.erb +++ b/app/views/server/universities/_form.html.erb @@ -36,8 +36,10 @@ <%= f.input :sso_target_url, required: true %> <%= f.input :sso_cert, required: true %> <%= f.input :sso_name_identifier_format, required: true %> - - <%#= render 'sso_mapping', brand: brand %> + </div> + </div> + <div class="col-md-6"> + <%= render 'sso_mapping', university: university %> </div> </div> -- GitLab