decidim-trusted_ids 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE-AGPLv3.txt +661 -0
  3. data/README.md +344 -0
  4. data/Rakefile +40 -0
  5. data/app/commands/concerns/decidim/trusted_ids/system/create_organization_override.rb +22 -0
  6. data/app/commands/concerns/decidim/trusted_ids/system/needs_census_config.rb +29 -0
  7. data/app/commands/concerns/decidim/trusted_ids/system/update_organization_override.rb +21 -0
  8. data/app/controllers/concerns/decidim/trusted_ids/admin/impersonations_controller_override.rb +31 -0
  9. data/app/controllers/concerns/decidim/trusted_ids/check_existing_authorizations.rb +40 -0
  10. data/app/controllers/concerns/decidim/trusted_ids/check_omniauth_email_on_login.rb +25 -0
  11. data/app/controllers/concerns/decidim/trusted_ids/needs_trusted_ids_snippets.rb +26 -0
  12. data/app/events/decidim/trusted_ids/verifications/invalid_notification.rb +10 -0
  13. data/app/events/decidim/trusted_ids/verifications/success_notification.rb +33 -0
  14. data/app/forms/concerns/decidim/trusted_ids/system/organization_form_override.rb +93 -0
  15. data/app/forms/decidim/trusted_ids/verifications/trusted_ids_handler.rb +65 -0
  16. data/app/forms/decidim/via_oberta/verifications/via_oberta_handler.rb +103 -0
  17. data/app/jobs/decidim/trusted_ids/application_job.rb +8 -0
  18. data/app/jobs/decidim/trusted_ids/omniauth_verification_job.rb +76 -0
  19. data/app/jobs/decidim/trusted_ids/system/propagate_census_config_job.rb +29 -0
  20. data/app/jobs/decidim/trusted_ids/system/propagate_census_settings_job.rb +29 -0
  21. data/app/models/concerns/decidim/trusted_ids/authorization_override.rb +21 -0
  22. data/app/models/concerns/decidim/trusted_ids/organization_override.rb +17 -0
  23. data/app/models/decidim/trusted_ids/organization_config.rb +20 -0
  24. data/app/overrides/decidim/devise/sessions/new/add_trusted_id_buttons.html.erb.deface +3 -0
  25. data/app/overrides/decidim/devise/sessions/new/wrap_default_login_form.html.erb.deface +4 -0
  26. data/app/overrides/decidim/devise/shared/_omniauth_buttons/replace_button_content.html.erb.deface +17 -0
  27. data/app/overrides/decidim/devise/shared/_omniauth_buttons/skip_trusted_ids_provider.html.erb.deface +3 -0
  28. data/app/overrides/decidim/system/organizations/_advanced_settings/settings_form.html.erb.deface +3 -0
  29. data/app/overrides/decidim/system/organizations/_omniauth_provider/add_icon_placeholder.html.erb.deface +3 -0
  30. data/app/overrides/layouts/decidim/_head/add_trusted_ids_tags.html.erb.deface +11 -0
  31. data/app/packs/entrypoints/decidim_trusted_ids.js +3 -0
  32. data/app/packs/images/idcat_mobil-icon.svg +8 -0
  33. data/app/packs/images/valid-icon.png +0 -0
  34. data/app/packs/stylesheets/decidim/trusted_ids/oauth_icons.scss +75 -0
  35. data/app/services/decidim/via_oberta/api/request.rb +156 -0
  36. data/app/services/decidim/via_oberta/api/response.rb +67 -0
  37. data/app/views/decidim/trusted_ids/devise/sessions/_login_box.html.erb +30 -0
  38. data/app/views/decidim/trusted_ids/system/organizations/_icon_path_placeholder.html.erb +10 -0
  39. data/app/views/decidim/trusted_ids/system/organizations/_settings_form.html.erb +25 -0
  40. data/app/views/decidim/trusted_ids/verifications/_form.html.erb +39 -0
  41. data/app/views/decidim/via_oberta/verifications/_form.html.erb +56 -0
  42. data/config/assets.rb +16 -0
  43. data/config/i18n-tasks.yml +12 -0
  44. data/config/locales/ca.yml +132 -0
  45. data/config/locales/de.yml +168 -0
  46. data/config/locales/en.yml +169 -0
  47. data/config/locales/es.yml +132 -0
  48. data/config/locales/fr.yml +168 -0
  49. data/config/locales/it.yml +168 -0
  50. data/config/locales/oc.yml +132 -0
  51. data/config/locales/zz_fallbacks.rb +45 -0
  52. data/db/migrate/20230718082548_create_organization_trusted_ids_config.rb +14 -0
  53. data/lib/decidim/trusted_ids/engine.rb +181 -0
  54. data/lib/decidim/trusted_ids/test/factories.rb +21 -0
  55. data/lib/decidim/trusted_ids/verifications.rb +10 -0
  56. data/lib/decidim/trusted_ids/version.rb +10 -0
  57. data/lib/decidim/trusted_ids.rb +69 -0
  58. data/lib/omniauth/strategies/valid.rb +134 -0
  59. data/lib/omniauth/strategies.rb +7 -0
  60. data/lib/tasks/decidim_trusted_ids_upgrade_tasks.rake +5 -0
  61. data/package-lock.json +29154 -0
  62. data/package.json +43 -0
  63. metadata +200 -0
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ module System
6
+ module OrganizationFormOverride
7
+ extend ActiveSupport::Concern
8
+ include Decidim::AttributeObject::TypeMap
9
+
10
+ # Prepended into the form class so that super() correctly resolves to
11
+ # the core's encrypted_omniauth_settings. When icon_path is blank, sets the
12
+ # default path via the jsonb sub-attribute setter BEFORE calling super, so
13
+ # the core picks it up and encrypts it correctly. Empty string would be truthy
14
+ # in omniauth_settings and cause oauth_icon → external_icon("") to crash.
15
+ module EncryptedOmniauthSettingsOverride
16
+ def encrypted_omniauth_settings
17
+ provider = Decidim::TrustedIds.omniauth_provider
18
+ icon_attr = :"omniauth_settings_#{provider}_icon_path"
19
+ enabled_attr = :"omniauth_settings_#{provider}_enabled"
20
+
21
+ # Only normalize blank icon_path when the provider is being enabled.
22
+ # If not enabled, we leave all settings blank so the core can return nil
23
+ # (preserving ENV-var-based configuration).
24
+ if public_send(enabled_attr) && public_send(icon_attr).blank?
25
+ default = Decidim::TrustedIds.omniauth[:icon_path].presence ||
26
+ "media/images/#{provider.downcase}-icon.png"
27
+ public_send(:"#{icon_attr}=", default)
28
+ end
29
+
30
+ super
31
+ end
32
+ end
33
+
34
+ included do
35
+ prepend EncryptedOmniauthSettingsOverride
36
+
37
+ jsonb_attribute :trusted_ids_census_settings, TrustedIds.census_config_attributes
38
+ attribute :trusted_ids_census_expiration_days, Integer
39
+ translatable_attribute :trusted_ids_census_tos, String
40
+ attribute :census_expiration_apply_all_tenants, Boolean
41
+ attribute :census_tos_apply_all_tenants, Boolean
42
+
43
+ validate :validate_icon_path
44
+
45
+ def map_model(model)
46
+ self.secondary_hosts = model.secondary_hosts.join("\n")
47
+ self.omniauth_settings = (model.omniauth_settings || {}).transform_values do |v|
48
+ Decidim::OmniauthProvider.value_defined?(v) ? Decidim::AttributeEncryptor.decrypt(v) : v
49
+ end
50
+ self.file_upload_settings = Decidim::System::FileUploadSettingsForm.from_model(model.file_upload_settings)
51
+
52
+ self.trusted_ids_census_settings = model.trusted_ids_census_config&.settings || {}
53
+ self.trusted_ids_census_expiration_days = model.trusted_ids_census_config&.expiration_days
54
+ self.trusted_ids_census_tos = model.trusted_ids_census_config&.tos || {}
55
+ end
56
+
57
+ def default_expiration_days
58
+ @default_expiration_days ||= Decidim::TrustedIds.verification_expiration_time.to_i / 86_400
59
+ end
60
+
61
+ def default_icon_path
62
+ Decidim::TrustedIds.omniauth[:icon_path].presence ||
63
+ "media/images/#{Decidim::TrustedIds.omniauth_provider.downcase}-icon.png"
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def validate_icon_path
70
+ # jsonb_attribute generates a getter method for each sub-field that handles
71
+ # both string and symbol hash keys. Use it instead of direct hash access.
72
+ icon_key = :"omniauth_settings_#{Decidim::TrustedIds.omniauth_provider}_icon_path"
73
+ path = public_send(icon_key)
74
+ return if path.blank? # blank = will use default on save, always valid
75
+
76
+ # Must follow the media/images/ format expected by Shakapacker
77
+ unless path.start_with?("media/images/")
78
+ errors.add(icon_key, :invalid_icon_path_format)
79
+ return
80
+ end
81
+
82
+ # File must exist in the module's registered assets images directory.
83
+ # This is future-proof: any new icon added to app/packs/images/ will
84
+ # automatically pass this validation without needing code changes.
85
+ filename = path.delete_prefix("media/images/")
86
+ file_exists = Decidim::TrustedIds::Engine.root.join("app/packs/images", filename).exist?
87
+
88
+ errors.add(icon_key, :icon_path_not_found) unless file_exists
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ module Verifications
6
+ class TrustedIdsHandler < AuthorizationHandler
7
+ attribute :provider, String
8
+ attribute :uid, String
9
+ attribute :raw_data
10
+
11
+ validates :uid, presence: true
12
+ validate :trusted_ids_provider?
13
+ validate :exising_trusted_ids_identity?
14
+
15
+ def metadata
16
+ super.merge(
17
+ uid: uid,
18
+ provider: provider,
19
+ extra: extra_attributes
20
+ )
21
+ end
22
+
23
+ def unique_id
24
+ Digest::SHA512.hexdigest(
25
+ "#{uid}-#{user&.decidim_organization_id}-#{Rails.application.secret_key_base}"
26
+ )
27
+ end
28
+
29
+ # no public attributes
30
+ def form_attributes
31
+ attributes.except(:id, :user, :provider, :uid, :extra).keys
32
+ end
33
+
34
+ def to_partial_path
35
+ "decidim/trusted_ids/verifications/form"
36
+ end
37
+
38
+ private
39
+
40
+ def extra_attributes
41
+ return {} unless TrustedIds.authorization_metadata.respond_to? :map
42
+
43
+ TrustedIds.authorization_metadata.to_h do |key, parts|
44
+ parts = [parts] unless parts.is_a? Array
45
+ [key, raw_data.dig(*parts)]
46
+ end
47
+ end
48
+
49
+ def trusted_ids_provider?
50
+ return false if errors.any?
51
+ return false if provider == TrustedIds.omniauth_provider.to_s
52
+
53
+ errors.add(:base, I18n.t("decidim.verifications.trusted_ids.errors.invalid_method"))
54
+ end
55
+
56
+ def exising_trusted_ids_identity?
57
+ return false if errors.any?
58
+ return false if user&.identities&.exists?(provider: TrustedIds.omniauth_provider)
59
+
60
+ errors.add(:base, I18n.t("decidim.verifications.trusted_ids.errors.no_identity"))
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ViaOberta
5
+ module Verifications
6
+ class ViaObertaHandler < AuthorizationHandler
7
+ # VALID: 1=NIF, 2=NIE, 3=Passaport, 4=Altres
8
+ # VIAOBERTA: 1=NIF, 2=passaport, 3=permís residència, 4=NIE
9
+ DOCUMENT_TYPE = {
10
+ 1 => :nif,
11
+ 2 => :nie,
12
+ 3 => :passport,
13
+ 4 => :others
14
+ }.freeze
15
+
16
+ attribute :document_id, String
17
+ attribute :document_type, Integer
18
+ attribute :tos_agreement, Boolean
19
+ validates :document_id, :document_type, presence: true
20
+ validates :tos_agreement, allow_nil: false, acceptance: true
21
+
22
+ validate :existing_via_oberta_identity
23
+
24
+ attr_reader :response_error, :response_code
25
+
26
+ def unique_id
27
+ return unless organization
28
+ return unless census_response.success?
29
+
30
+ Digest::SHA256.hexdigest(
31
+ "#{document_id}-#{user&.decidim_organization_id}-#{Rails.application.secret_key_base}"
32
+ )
33
+ end
34
+
35
+ # use from previous authorization metadata. We don't allow user input here to prevent spoofing
36
+ # not memoized because @document_id would be defined if sent via form
37
+ def document_id
38
+ trusted_authorization&.metadata&.dig("uid") || impersonated_document_id
39
+ end
40
+
41
+ # use from previous authorization metadata or use the one from the form as a fallback
42
+ # not memoized because @document_id would be defined if sent via form
43
+ def document_type
44
+ document_type_from_metadata || DOCUMENT_TYPE[attributes[:document_type]]
45
+ end
46
+
47
+ def document_type_from_metadata
48
+ @document_type_from_metadata ||= DOCUMENT_TYPE[trusted_authorization&.metadata&.dig("extra", "identifier_type").to_i]
49
+ end
50
+
51
+ def document_types
52
+ @document_types ||= DOCUMENT_TYPE.map { |k, v| [I18n.t("decidim.via_oberta.verifications.document_type.#{v}", default: v.to_s), k] }
53
+ end
54
+
55
+ def document_type_string
56
+ return "" unless document_type
57
+
58
+ I18n.t("decidim.via_oberta.verifications.document_type.#{document_type}", default: document_type.to_s)
59
+ end
60
+
61
+ def census_response
62
+ @census_response ||= ViaOberta::Api::Request.new(document_id: document_id, document_type: document_type, organization: organization).response
63
+ end
64
+
65
+ def existing_via_oberta_identity
66
+ return unless tos_agreement
67
+
68
+ return errors.add(:base, I18n.t("decidim.verifications.trusted_ids.errors.invalid_id")) if document_id.blank?
69
+ return errors.add(:base, I18n.t("decidim.verifications.trusted_ids.errors.invalid_type")) if document_type.blank?
70
+
71
+ return if census_response.found?
72
+
73
+ errors.add(:base, I18n.t("decidim.verifications.trusted_ids.errors.invalid_census"))
74
+ @response_error = census_response.error
75
+ @response_code = census_response.code
76
+ end
77
+
78
+ # # no public attributes
79
+ def form_attributes
80
+ attributes.except(:id, :user, :document_id, :document_type).keys
81
+ end
82
+
83
+ def to_partial_path
84
+ "decidim/via_oberta/verifications/form"
85
+ end
86
+
87
+ private
88
+
89
+ def impersonated_document_id
90
+ attributes[:document_id] if user&.managed?
91
+ end
92
+
93
+ def trusted_authorization
94
+ @trusted_authorization ||= Decidim::Authorization.find_by(name: "trusted_ids_handler", user: user)
95
+ end
96
+
97
+ def organization
98
+ user&.organization
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ class ApplicationJob < ActiveJob::Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ class OmniauthVerificationJob < ApplicationJob
6
+ queue_as :default
7
+
8
+ def perform(data)
9
+ @data = data
10
+
11
+ unless data[:provider].to_s == Decidim::TrustedIds.omniauth_provider.to_s
12
+ Rails.logger.debug { "OmniauthVerificationJob: Omniauth [#{data[:provider]}] is not a valid trusted_ids provider (#{Decidim::TrustedIds.omniauth_provider})" }
13
+ return
14
+ end
15
+
16
+ unless trusted_ids_identity?
17
+ Rails.logger.error "OmniauthVerificationJob: User #{user.id} does not have a trusted_ids (#{Decidim::TrustedIds.omniauth_provider}) identity"
18
+ return
19
+ end
20
+
21
+ authorize_user!
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :data
27
+
28
+ def user
29
+ @user ||= Decidim::User.find(data[:user_id])
30
+ end
31
+
32
+ def trusted_ids_identity?
33
+ @trusted_ids_identity ||= user&.identities&.exists?(provider: Decidim::TrustedIds.omniauth_provider)
34
+ end
35
+
36
+ def handler
37
+ @handler ||= Decidim::AuthorizationHandler.handler_for("trusted_ids_handler", user: user, uid: data[:uid], provider: data[:provider], raw_data: data[:raw_data])
38
+ end
39
+
40
+ def authorization
41
+ @authorization ||= Decidim::Authorization.find_by(unique_id: handler.unique_id)
42
+ end
43
+
44
+ def authorize_user!
45
+ already_granted = authorization&.granted?
46
+ Decidim::Verifications::AuthorizeUser.call(handler, user.organization) do
47
+ on(:ok) do
48
+ notify_user(user, :ok) unless already_granted
49
+ end
50
+
51
+ on(:invalid) do
52
+ Rails.logger.error "OmniauthVerificationJob: User #{user.id} could not be authorized with #{handler.provider}. Errors: #{handler.errors.full_messages}"
53
+ notify_user(user, :invalid)
54
+ end
55
+ end
56
+ end
57
+
58
+ def notify_user(user, status)
59
+ return unless Decidim::TrustedIds.send_verification_notifications
60
+
61
+ notification_class = status == :ok ? Decidim::TrustedIds::Verifications::SuccessNotification : Decidim::TrustedIds::Verifications::InvalidNotification
62
+ Decidim::EventsManager.publish(
63
+ event: "decidim.events.trusted_ids.verifications.#{status}",
64
+ event_class: notification_class,
65
+ resource: authorization,
66
+ affected_users: [user],
67
+ extra: {
68
+ status: status.to_s,
69
+ errors: handler.errors.full_messages,
70
+ force_email: true
71
+ }
72
+ )
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ module System
6
+ class PropagateCensusConfigJob < ApplicationJob
7
+ queue_as :default
8
+
9
+ def perform(config_id, keys)
10
+ @config = Decidim::TrustedIds::OrganizationConfig.find_by(id: config_id)
11
+ return unless @config
12
+ return if keys.blank?
13
+
14
+ propagate_config!(@config.organization, keys)
15
+ end
16
+
17
+ def propagate_config!(organization, keys)
18
+ Decidim::Organization.where.not(id: organization).find_each do |tenant|
19
+ config = Decidim::TrustedIds::OrganizationConfig.find_or_create_by(organization: tenant)
20
+ config.expiration_days = @config.expiration_days if keys.include?(:expiration_days)
21
+ config.tos = @config.tos if keys.include?(:tos)
22
+
23
+ config.save!
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ module System
6
+ class PropagateCensusSettingsJob < ApplicationJob
7
+ queue_as :default
8
+
9
+ def perform(config_id, keys)
10
+ @config = Decidim::TrustedIds::OrganizationConfig.find_by(id: config_id)
11
+ return unless @config
12
+
13
+ propagate_settings!(@config.organization, keys)
14
+ end
15
+
16
+ def propagate_settings!(organization, keys)
17
+ Decidim::Organization.where.not(id: organization).find_each do |tenant|
18
+ conf = Decidim::TrustedIds::OrganizationConfig.find_or_create_by(organization: tenant)
19
+ keys.each do |key|
20
+ conf.settings[key] = @config.settings[key]
21
+ end
22
+
23
+ conf.save!
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ module AuthorizationOverride
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # allows to configure the expiration time with the organization config properties
10
+ def expires_at
11
+ return unless workflow_manifest
12
+
13
+ expires_in = organization.trusted_ids_census_config&.expiration_days&.days&.to_i || workflow_manifest.expires_in # rubocop:disable Style/SafeNavigationChainLength
14
+ return if expires_in.zero?
15
+
16
+ (granted_at || created_at) + expires_in
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ module OrganizationOverride
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ has_one :trusted_ids_census_config,
10
+ foreign_key: "decidim_organization_id",
11
+ class_name: "Decidim::TrustedIds::OrganizationConfig",
12
+ inverse_of: :organization,
13
+ dependent: :destroy
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TrustedIds
5
+ class OrganizationConfig < ApplicationRecord
6
+ include Decidim::TranslatableResource
7
+ include Decidim::TranslatableAttributes
8
+ self.table_name = "organization_trusted_ids_configs"
9
+
10
+ belongs_to :organization,
11
+ foreign_key: "decidim_organization_id",
12
+ class_name: "Decidim::Organization"
13
+ translatable_fields :tos
14
+
15
+ def translated_tos
16
+ translated_attribute(tos, organization).presence || I18n.t("content_html", scope: "decidim.via_oberta.verifications.tos")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ <!-- replace "erb[loud]:contains('decidim/devise/shared/omniauth_buttons')" -->
2
+
3
+ <%= render "decidim/trusted_ids/devise/sessions/login_box" %>
@@ -0,0 +1,4 @@
1
+ <!-- replace "erb[loud]:contains('decidim_form_for')" -->
2
+
3
+ <% override_login = Decidim::TrustedIds.custom_login_screen? && Devise.mappings[:user].omniauthable? && current_organization.enabled_omniauth_providers&.include?(Decidim::TrustedIds.omniauth_provider&.to_sym) %>
4
+ <%= decidim_form_for(resource, namespace: "session", as: resource_name, url: session_path(resource_name), html: {class: "new_user decidim-login #{'hide' if override_login}"}) do |f| %>
@@ -0,0 +1,17 @@
1
+ <!-- replace "erb[loud]:contains('oauth_icon provider')" -->
2
+
3
+ <%= begin
4
+ if provider.to_s == Decidim::TrustedIds.omniauth_provider.to_s
5
+ # For the VÀLid provider, fall back to the default PNG icon when
6
+ # icon_path is not configured in the organization's omniauth settings or in the module's omniauth settings.
7
+ settings = current_organization.enabled_omniauth_providers[provider]
8
+ icon_path = settings&.dig(:icon_path).presence ||
9
+ Decidim::TrustedIds.omniauth[:icon_path].presence ||
10
+ "media/images/#{Decidim::TrustedIds.omniauth_provider.downcase}-icon.png"
11
+ external_icon(icon_path)
12
+ else
13
+ oauth_icon provider
14
+ end
15
+ rescue ::Shakapacker::Manifest::MissingEntryError
16
+ nil
17
+ end %>
@@ -0,0 +1,3 @@
1
+ <!-- insert_after "erb[silent]:contains('current_organization.enabled_omniauth_providers.keys.each')" -->
2
+
3
+ <% next if controller_name == "sessions" && action_name == "new" && provider == Decidim::TrustedIds.omniauth_provider&.to_sym && Decidim::TrustedIds.custom_login_screen? %>
@@ -0,0 +1,3 @@
1
+ <!-- insert_top "#advanced-settings-panel" -->
2
+
3
+ <%= render "decidim/trusted_ids/system/organizations/settings_form", f: f %>
@@ -0,0 +1,3 @@
1
+ <!-- replace "erb[loud]:contains(':icon_path')" -->
2
+
3
+ <%= render "decidim/trusted_ids/system/organizations/icon_path_placeholder", f: f, setting: setting, i18n_scope: i18n_scope, provider: provider %>
@@ -0,0 +1,11 @@
1
+
2
+ <!-- insert_after "erb[loud]:contains('append_stylesheet_pack_tag')" -->
3
+
4
+ <%#
5
+ The CSS must be added to the header because the CSS files are not loaded on all screens.
6
+ To avoid making a more complex override of the Devise view, it is added to the header as is done
7
+ in other modules like Decidim Awesome.
8
+ %>
9
+
10
+ <% append_stylesheet_pack_tag "decidim_trusted_ids", media: "all" %>
11
+
@@ -0,0 +1,3 @@
1
+ import "../stylesheets/decidim/trusted_ids/oauth_icons.scss";
2
+ // Images
3
+ require.context("../images", true)
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="44" height="56" viewBox="0 0 44 56">
2
+ <g id="valid-fill" fill="#FFF" fill-rule="evenodd">
3
+ <path fill-rule="nonzero" d="M11.53 6.73L2.07 6.73 2.07.09 11.53.09 11.53 6.73zM2.07 9.4L11.53 9.4 11.53 34.19 2.07 34.19 2.07 9.4zM42.71 34.19L33.59 34.19 33.59 31.47 33.5 31.47C32.3 33.04 30.87 34.81 26.24 34.81 19.24 34.81 15.82 27.89 15.82 21.68 15.82 15.85 18.07 8.78 26.38 8.78 29.05573 8.70308662 31.5954717 9.95797374 33.16 12.13L33.26 12.13 33.26.13 42.71.13 42.71 34.19zM29.44 15.66C26.04 15.66 25.28 18.86 25.28 21.77 25.28 24.68 26.04 27.93 29.44 27.93 32.84 27.93 33.59 24.73 33.59 21.77 33.59 18.81 32.83 15.66 29.44 15.66z"/>
4
+ <path d="M10.94,46.13 C10.8353818,44.8627645 9.77151075,43.8904562 8.5,43.9 C6.31,43.9 5.61,46.02 5.61,48.06 C5.61,50.1 6.31,52.22 8.5,52.22 C10.07,52.22 10.68,51.12 10.96,49.69 L15.55,49.69 C15.55,52.75 13.06,56 8.62,56 C3.72,56 0.94,52.54 0.94,48.06 C0.94,43.28 3.94,40.12 8.62,40.12 C12.79,40.12 15.08,42.32 15.48,46.12 L10.94,46.13 Z"/>
5
+ <path fill-rule="nonzero" d="M21.7,40.48 L26.27,40.48 L31.79,55.64 L27,55.64 L26.36,53.47 L21.49,53.47 L20.81,55.64 L16.12,55.64 L21.7,40.48 Z M25.38,50.22 L24,45.55 L22.53,50.22 L25.38,50.22 Z"/>
6
+ <polygon points="34.93 44.36 30.68 44.36 30.68 40.48 43.85 40.48 43.85 44.36 39.6 44.36 39.6 55.64 34.93 55.64"/>
7
+ </g>
8
+ </svg>
Binary file
@@ -0,0 +1,75 @@
1
+ /* Decidim has a bug when using external_icon method that automatically adds a display:none inline css */
2
+
3
+ .social-register,
4
+ .button--social,
5
+ .button--unverified-login {
6
+ display: flex;
7
+ padding: 0 1.5rem 0 0;
8
+ min-width: 250px;
9
+ color: #fff;
10
+ height: 50px;
11
+ text-decoration-line: none;
12
+ font-weight: normal;
13
+
14
+ .button--social__icon {
15
+ img.icon.external-icon {
16
+ display: inline-block !important;
17
+ }
18
+ }
19
+ }
20
+
21
+ .login__omniauth-button {
22
+ background-color: var(--secondary) !important;
23
+ border-color: var(--secondary) !important;
24
+
25
+ img.icon.external-icon {
26
+ display: inline-block !important;
27
+ }
28
+ }
29
+
30
+ .login__omniauth-button > span {
31
+ color: white !important;
32
+ }
33
+
34
+ .button--social,
35
+ .button--valid {
36
+ background-color: var(--secondary);
37
+ justify-content: center;
38
+ align-items: center;
39
+ gap: 0.5rem;
40
+ padding: 0 0.5rem;
41
+ }
42
+
43
+ .button--unverified-login {
44
+ border-color: var(--secondary);
45
+ background-color: var(--secondary);
46
+ color: white;
47
+ }
48
+
49
+ .trusted-ids-login-box {
50
+ background: #fff;
51
+ border: 1px solid #ccc;
52
+ border-radius: 15px;
53
+ padding: 2em !important;
54
+ margin-top: 2em;
55
+
56
+ h6 {
57
+ font-size: 1em;
58
+ font-weight: 600;
59
+ margin-top: 2em;
60
+ }
61
+
62
+ hr {
63
+ width: 80%;
64
+ margin: 2em auto;
65
+ }
66
+
67
+ ul {
68
+ margin-left: 1.25rem;
69
+ list-style-type: disc !important;
70
+ }
71
+ }
72
+
73
+ .hide {
74
+ display: none;
75
+ }