decidim-system 0.28.3 → 0.29.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/app/cells/decidim/system/system_checks/show.erb +13 -0
  4. data/app/cells/decidim/system/system_checks_cell.rb +48 -0
  5. data/app/commands/decidim/system/create_default_content_blocks.rb +0 -3
  6. data/app/commands/decidim/system/{populate_help.rb → create_default_help_pages.rb} +14 -7
  7. data/app/commands/decidim/system/create_default_pages.rb +0 -1
  8. data/app/commands/decidim/system/{register_organization.rb → create_organization.rb} +5 -7
  9. data/app/controllers/decidim/system/application_controller.rb +0 -1
  10. data/app/controllers/decidim/system/dashboard_controller.rb +2 -0
  11. data/app/controllers/decidim/system/organizations_controller.rb +2 -1
  12. data/app/forms/decidim/system/base_organization_form.rb +127 -0
  13. data/app/forms/decidim/system/register_organization_form.rb +23 -3
  14. data/app/forms/decidim/system/update_organization_form.rb +18 -103
  15. data/app/models/decidim/system/admin.rb +2 -2
  16. data/app/packs/stylesheets/decidim/system/application.scss +57 -0
  17. data/app/views/decidim/system/dashboard/show.html.erb +4 -0
  18. data/app/views/decidim/system/oauth_applications/_form.html.erb +1 -1
  19. data/app/views/decidim/system/oauth_applications/index.html.erb +3 -3
  20. data/app/views/decidim/system/organizations/edit.html.erb +4 -2
  21. data/app/views/decidim/system/shared/_admins_list.html.erb +2 -2
  22. data/app/views/decidim/system/shared/_organizations_list.html.erb +3 -3
  23. data/app/views/layouts/decidim/system/_js_configuration.html.erb +1 -1
  24. data/app/views/layouts/decidim/system/login.html.erb +1 -1
  25. data/config/locales/ar.yml +0 -1
  26. data/config/locales/bg.yml +9 -3
  27. data/config/locales/ca.yml +12 -3
  28. data/config/locales/cs.yml +5 -3
  29. data/config/locales/de.yml +10 -3
  30. data/config/locales/el.yml +0 -2
  31. data/config/locales/en.yml +12 -3
  32. data/config/locales/es-MX.yml +12 -3
  33. data/config/locales/es-PY.yml +12 -3
  34. data/config/locales/es.yml +12 -3
  35. data/config/locales/eu.yml +12 -3
  36. data/config/locales/fi-plain.yml +16 -7
  37. data/config/locales/fi.yml +16 -7
  38. data/config/locales/fr-CA.yml +12 -3
  39. data/config/locales/fr.yml +12 -3
  40. data/config/locales/gl.yml +0 -1
  41. data/config/locales/hu.yml +0 -2
  42. data/config/locales/id-ID.yml +0 -1
  43. data/config/locales/it.yml +0 -1
  44. data/config/locales/ja.yml +12 -3
  45. data/config/locales/lt.yml +0 -2
  46. data/config/locales/lv.yml +0 -1
  47. data/config/locales/nl.yml +0 -1
  48. data/config/locales/no.yml +0 -1
  49. data/config/locales/pl.yml +11 -2
  50. data/config/locales/pt-BR.yml +0 -3
  51. data/config/locales/pt.yml +0 -1
  52. data/config/locales/ro-RO.yml +0 -1
  53. data/config/locales/ru.yml +0 -1
  54. data/config/locales/sk.yml +0 -1
  55. data/config/locales/sv.yml +0 -2
  56. data/config/locales/tr-TR.yml +0 -1
  57. data/config/locales/zh-CN.yml +0 -1
  58. data/config/locales/zh-TW.yml +0 -2
  59. data/db/seeds.rb +1 -1
  60. data/decidim-system.gemspec +1 -1
  61. data/lib/decidim/system/engine.rb +4 -0
  62. data/lib/decidim/system/version.rb +1 -1
  63. data/lib/tasks/decidim_system.rake +1 -1
  64. metadata +15 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3ac2dea5f86dc764f509e37d465197718cb7db29d89e9bf98c71adeb30ad347
4
- data.tar.gz: 84305bf2255ec3b9e3520dbf88efa0c8059627b32edbaef4bfcb91ca03214414
3
+ metadata.gz: 947a58b195365e516146ac29a1b1ccf623416523defcc0fe31ae44e3fd697a36
4
+ data.tar.gz: 713c800019aebcf933159515236a8c5c4dd5c79543f2822e1ac75059b0ddf293
5
5
  SHA512:
6
- metadata.gz: 6027a04afb963a7c625ff69e4b41b6ac0cd4687778f744c35b6356f39943ecea4dc83b73ddf9fa4bf382cdccc6f6f2e08dbe440c59f336152e2fb8d4cb0d2075
7
- data.tar.gz: 95ffe0f9792ceae36683b224be9cac2b1e9bafac5de5805ff32105f9152239de2a30a921783f4e226a0ad940e1fe333a014e11eba79d790912cf62c75b283332
6
+ metadata.gz: f88a26f5fdd1527aafaaadf95c4a6e450e08846d2852277a17c4fac539cd55b5311d7d8d5d71b6399b225194d7668bd2cb6d1993df265e86aec9fc29ba2e19c1
7
+ data.tar.gz: 675c8a7bf6cd5eb07ef01aba70ba8423673c5c4e4a624d49bc3b6dbe6548444e3c690b27b4afc8f96fcb3e597334947d3f1e85432dd7f9503be4b5008063748f
data/README.md CHANGED
@@ -49,7 +49,7 @@ bin/rails decidim_system:create_admin
49
49
  You will be asked for an email and a password. For security, the password will not get displayed back at you and you will need to confirm it.
50
50
 
51
51
  Once you have created your first admin you can access the system dashboard at `/system`. For instance, if you have Decidim running at `https://example.org`, this URL would be `https://example.org/system`.
52
- You will be able to login with your newly created user.
52
+ You will be able to log in with your newly created user.
53
53
 
54
54
  From the system dashboard you can add new admins.
55
55
 
@@ -73,11 +73,11 @@ system_admin.save
73
73
 
74
74
  ## Managing organizations
75
75
 
76
- Once you have your system admin setup you can also start managing the organizations in your deploy. To do it, login at the system dashboard and create a new organization
76
+ Once you have your system admin setup you can also start managing the organizations in your deploy. To do it, log in at the system dashboard and create a new organization
77
77
  following the form instructions. After creating it, a new admin user will be created and invited to start managing it.
78
78
 
79
79
  Remember that System admins and regular Admins are completely different users (they do not even share the same database table), so you cannot use your
80
- system user to login in as an organization admin.
80
+ system user to log in in as an organization admin.
81
81
 
82
82
  ## Contributing
83
83
 
@@ -0,0 +1,13 @@
1
+ <ul>
2
+ <% checks.each do |key, check| %>
3
+ <li>
4
+ <% if check[:check_method] %>
5
+ <%= icon "checkbox-circle-line", class: "fill-success inline" %>
6
+ <%= t("#{key}.success", scope: "decidim.system.system_checks") %>
7
+ <% else %>
8
+ <%= icon "close-circle-line", class: "fill-alert inline" %>
9
+ <%= t("#{key}.error", scope: "decidim.system.system_checks", error_extra: check[:error_extra]) %>
10
+ <% end %>
11
+ </li>
12
+ <% end %>
13
+ </ul>
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module System
5
+ class SystemChecksCell < Decidim::ViewModel
6
+ def show
7
+ render
8
+ end
9
+
10
+ private
11
+
12
+ def checks
13
+ {
14
+ secret_key: {
15
+ check_method: correct_secret_key_base?,
16
+ error_extra: generated_secret_key
17
+ },
18
+ active_job_queue: {
19
+ check_method: correct_active_job_queue?,
20
+ error_extra: active_job_queue_link
21
+ }
22
+ }
23
+ end
24
+
25
+ def correct_secret_key_base?
26
+ Rails.application.secrets.secret_key_base&.length == 128
27
+ end
28
+
29
+ def generated_secret_key
30
+ SecureRandom.hex(64)
31
+ end
32
+
33
+ def correct_active_job_queue?
34
+ # The default ActiveJob queue is not recommended for production environments,
35
+ # as it can lose jobs when restarting
36
+ Rails.application.config.active_job.queue_adapter != :async
37
+ end
38
+
39
+ def active_job_queue_link
40
+ link_to(t("active_job_queue.decidim_documentation", scope: "decidim.system.system_checks"),
41
+ "https://docs.decidim.org/en/develop/services/activejob",
42
+ class: "underline text-primary",
43
+ target: "_blank",
44
+ rel: "nofollow noopener noreferrer")
45
+ end
46
+ end
47
+ end
48
+ end
@@ -5,9 +5,6 @@ module Decidim
5
5
  # A command with all the business logic to create the default content blocks
6
6
  # for a newly-created organization.
7
7
  class CreateDefaultContentBlocks < Decidim::Command
8
- DEFAULT_CONTENT_BLOCKS =
9
- [:hero, :sub_hero, :highlighted_content_banner, :how_to_participate, :stats, :metrics, :footer_sub_hero].freeze
10
-
11
8
  # Public: Initializes the command.
12
9
  #
13
10
  # form - A form object with the params.
@@ -3,7 +3,9 @@
3
3
  module Decidim
4
4
  module System
5
5
  # A command that will create default help pages for an organization.
6
- class PopulateHelp < Decidim::Command
6
+ class CreateDefaultHelpPages < Decidim::Command
7
+ include Decidim::TranslatableAttributes
8
+
7
9
  # Public: Initializes the command.
8
10
  #
9
11
  # organization - An organization
@@ -17,16 +19,17 @@ module Decidim
17
19
  def call
18
20
  ActiveRecord::Base.transaction do
19
21
  topic = Decidim::StaticPageTopic.create!(
20
- title: multi_translation("decidim.help.main_topic.title", organization: @organization.name),
21
- description: multi_translation("decidim.help.main_topic.description", organization: @organization.name),
22
+ title: multi_translation("decidim.help.main_topic.title", organization: organization_name),
23
+ description: multi_translation("decidim.help.main_topic.description", organization: organization_name),
22
24
  organization: @organization,
25
+ show_in_footer: true,
23
26
  weight: 0
24
27
  )
25
28
 
26
29
  Decidim::StaticPage.create!(
27
30
  slug: "help",
28
- title: multi_translation("decidim.help.main_topic.default_page.title", organization: @organization.name),
29
- content: multi_translation("decidim.help.main_topic.default_page.content", organization: @organization.name),
31
+ title: multi_translation("decidim.help.main_topic.default_page.title", organization: organization_name),
32
+ content: multi_translation("decidim.help.main_topic.default_page.content", organization: organization_name),
30
33
  topic:,
31
34
  organization: @organization,
32
35
  weight: 0
@@ -49,8 +52,12 @@ module Decidim
49
52
  end
50
53
  end
51
54
 
52
- def multi_translation(key, **arguments)
53
- Decidim::TranslationsHelper.multi_translation(key, @organization.available_locales, **arguments)
55
+ def multi_translation(key, **)
56
+ Decidim::TranslationsHelper.multi_translation(key, @organization.available_locales, **)
57
+ end
58
+
59
+ def organization_name
60
+ translated_attribute(@organization.name)
54
61
  end
55
62
  end
56
63
  end
@@ -23,7 +23,6 @@ module Decidim
23
23
  translated_slug = I18n.t(slug, scope: "decidim.system.default_pages")
24
24
  page.title = localized_attribute(translated_slug, :title)
25
25
  page.content = localized_attribute(translated_slug, :content)
26
- page.show_in_footer = true
27
26
  page.allow_public_access = true if slug == "terms-of-service"
28
27
  end
29
28
 
@@ -8,7 +8,8 @@ module Decidim
8
8
  # A command with all the business logic when creating a new organization in
9
9
  # the system. It creates the organization and invites the admin to the
10
10
  # system.
11
- class RegisterOrganization < Decidim::Command
11
+
12
+ class CreateOrganization < Decidim::Command
12
13
  # Public: Initializes the command.
13
14
  #
14
15
  # form - A form object with the params.
@@ -31,7 +32,7 @@ module Decidim
31
32
  transaction do
32
33
  @organization = create_organization
33
34
  CreateDefaultPages.call(@organization)
34
- PopulateHelp.call(@organization)
35
+ CreateDefaultHelpPages.call(@organization)
35
36
  CreateDefaultContentBlocks.call(@organization)
36
37
  invite_form = invite_user_form(@organization)
37
38
  raise InvitationFailedError if invite_form.invalid?
@@ -52,13 +53,13 @@ module Decidim
52
53
 
53
54
  def create_organization
54
55
  Decidim::Organization.create!(
55
- name: form.name,
56
+ name: { form.default_locale => form.name },
56
57
  host: form.host,
57
58
  secondary_hosts: form.clean_secondary_hosts,
58
59
  reference_prefix: form.reference_prefix,
59
60
  available_locales: form.available_locales,
60
61
  available_authorizations: form.clean_available_authorizations,
61
- external_domain_whitelist: ["decidim.org", "github.com"],
62
+ external_domain_allowlist: ["decidim.org", "github.com"],
62
63
  users_registration_mode: form.users_registration_mode,
63
64
  force_users_to_authenticate_before_access_organization: form.force_users_to_authenticate_before_access_organization,
64
65
  badges_enabled: true,
@@ -75,10 +76,7 @@ module Decidim
75
76
 
76
77
  def default_colors
77
78
  {
78
- alert: "#ec5840",
79
79
  primary: "#53bf40",
80
- success: "#57d685",
81
- warning: "#ffae00",
82
80
  tertiary: "#bf4053",
83
81
  secondary: "#4053bf"
84
82
  }
@@ -8,7 +8,6 @@ module Decidim
8
8
  include PayloadInfo
9
9
  include Headers::HttpCachingDisabler
10
10
  include DisableRedirectionToExternalHost
11
- include ActiveStorage::SetCurrent
12
11
 
13
12
  protect_from_forgery with: :exception, prepend: true
14
13
 
@@ -10,6 +10,8 @@ module Decidim
10
10
  @admins = Admin.all
11
11
  end
12
12
 
13
+ private
14
+
13
15
  def check_organizations_presence
14
16
  return if Organization.exists?
15
17
 
@@ -16,7 +16,7 @@ module Decidim
16
16
  def create
17
17
  @form = form(RegisterOrganizationForm).from_params(params)
18
18
 
19
- RegisterOrganization.call(@form) do
19
+ CreateOrganization.call(@form) do
20
20
  on(:ok) do
21
21
  flash[:notice] = t("organizations.create.success_html", scope: "decidim.system", host: @form.host, email: @form.organization_admin_email)
22
22
  redirect_to organizations_path
@@ -44,6 +44,7 @@ module Decidim
44
44
  end
45
45
 
46
46
  def update
47
+ @organization = Organization.find(params[:id])
47
48
  @form = form(UpdateOrganizationForm).from_params(params)
48
49
 
49
50
  UpdateOrganization.call(params[:id], @form) do
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "decidim/translatable_attributes"
4
+
5
+ module Decidim
6
+ module System
7
+ # A form object to be inherited to create and update organizations from the system dashboard.
8
+ #
9
+ class BaseOrganizationForm < Form
10
+ include TranslatableAttributes
11
+ include JsonbAttributes
12
+
13
+ mimic :organization
14
+
15
+ attribute :host, String
16
+ attribute :secondary_hosts, String
17
+ attribute :force_users_to_authenticate_before_access_organization, Boolean
18
+ attribute :available_authorizations, Array[String]
19
+ attribute :users_registration_mode, String
20
+ attribute :default_locale, String
21
+
22
+ jsonb_attribute :smtp_settings, [
23
+ [:from, String],
24
+ [:from_email, String],
25
+ [:from_label, String],
26
+ [:user_name, String],
27
+ [:encrypted_password, String],
28
+ [:address, String],
29
+ [:port, Integer],
30
+ [:authentication, String],
31
+ [:enable_starttls_auto, Boolean]
32
+ ]
33
+
34
+ jsonb_attribute :content_security_policy, [
35
+ [:"default-src", String],
36
+ [:"img-src", String],
37
+ [:"media-src", String],
38
+ [:"script-src", String],
39
+ [:"style-src", String],
40
+ [:"frame-src", String],
41
+ [:"font-src", String],
42
+ [:"connect-src", String]
43
+ ]
44
+
45
+ attribute :password, String
46
+ attribute :file_upload_settings, FileUploadSettingsForm
47
+
48
+ OMNIATH_PROVIDERS_ATTRIBUTES = Decidim::OmniauthProvider.available.keys.map do |provider|
49
+ Rails.application.secrets.dig(:omniauth, provider).keys.map do |setting|
50
+ if setting == :enabled
51
+ ["omniauth_settings_#{provider}_enabled".to_sym, Boolean]
52
+ else
53
+ ["omniauth_settings_#{provider}_#{setting}".to_sym, String]
54
+ end
55
+ end
56
+ end.flatten(1)
57
+
58
+ jsonb_attribute :omniauth_settings, OMNIATH_PROVIDERS_ATTRIBUTES
59
+
60
+ validates :host, :users_registration_mode, presence: true
61
+ validate :validate_organization_uniqueness
62
+ validate :validate_secret_key_base_for_encryption
63
+ validates :users_registration_mode, inclusion: { in: Decidim::Organization.users_registration_modes }
64
+
65
+ def map_model(model)
66
+ self.default_locale = model.default_locale
67
+ self.secondary_hosts = model.secondary_hosts.join("\n")
68
+ self.omniauth_settings = (model.omniauth_settings || {}).transform_values do |v|
69
+ Decidim::OmniauthProvider.value_defined?(v) ? Decidim::AttributeEncryptor.decrypt(v) : v
70
+ end
71
+ self.file_upload_settings = FileUploadSettingsForm.from_model(model.file_upload_settings)
72
+ end
73
+
74
+ def clean_secondary_hosts
75
+ return unless secondary_hosts
76
+
77
+ secondary_hosts.split("\n").map(&:chomp).select(&:present?)
78
+ end
79
+
80
+ def clean_available_authorizations
81
+ return unless available_authorizations
82
+
83
+ available_authorizations.select(&:present?)
84
+ end
85
+
86
+ def password
87
+ encrypted_password.nil? ? super : Decidim::AttributeEncryptor.decrypt(encrypted_password)
88
+ end
89
+
90
+ def encrypted_smtp_settings
91
+ smtp_settings["from"] = set_from
92
+
93
+ encrypted = smtp_settings.merge(encrypted_password: Decidim::AttributeEncryptor.encrypt(password))
94
+ # if all are empty, nil is returned so it does not break ENV vars configuration
95
+ encrypted.values.all?(&:blank?) ? nil : encrypted
96
+ end
97
+
98
+ def set_from
99
+ return from_email if from_label.blank?
100
+
101
+ "#{from_label} <#{from_email}>"
102
+ end
103
+
104
+ def encrypted_omniauth_settings
105
+ encrypted = omniauth_settings.transform_values do |v|
106
+ Decidim::OmniauthProvider.value_defined?(v) ? Decidim::AttributeEncryptor.encrypt(v) : v
107
+ end
108
+ # if all are empty, nil is returned so it does not break ENV vars configuration
109
+ encrypted.values.all?(&:blank?) ? nil : encrypted
110
+ end
111
+
112
+ private
113
+
114
+ # We need a valid secret key base for encrypting the SMTP password with it
115
+ # It is also necessary for other things in Rails (like Cookies encryption)
116
+ def validate_secret_key_base_for_encryption
117
+ return if Rails.application.secrets.secret_key_base&.length == 128
118
+
119
+ errors.add(:password, I18n.t("activemodel.errors.models.organization.attributes.password.secret_key"))
120
+ end
121
+
122
+ def validate_organization_uniqueness
123
+ raise "#{self.class.name} is expected to implement #validate_organization_uniqueness"
124
+ end
125
+ end
126
+ end
127
+ end
@@ -6,10 +6,12 @@ module Decidim
6
6
  module System
7
7
  # A form object used to create organizations from the system dashboard.
8
8
  #
9
- class RegisterOrganizationForm < UpdateOrganizationForm
9
+ class RegisterOrganizationForm < BaseOrganizationForm
10
10
  include JsonbAttributes
11
11
  mimic :organization
12
12
 
13
+ attribute :name, String
14
+
13
15
  attribute :organization_admin_email, String
14
16
  attribute :organization_admin_name, String
15
17
  attribute :available_locales, Array
@@ -18,11 +20,29 @@ module Decidim
18
20
  attribute :users_registration_mode, String
19
21
  attribute :force_users_to_authenticate_before_access_organization, Boolean
20
22
 
21
- validates :organization_admin_email, :organization_admin_name, :name, :host, :reference_prefix, :users_registration_mode, presence: true
23
+ validates :organization_admin_email, :organization_admin_name, :name, :reference_prefix, presence: true
24
+ validates :name, presence: true
22
25
  validates :available_locales, presence: true
23
26
  validates :default_locale, presence: true
24
27
  validates :default_locale, inclusion: { in: :available_locales }
25
- validates :users_registration_mode, inclusion: { in: Decidim::Organization.users_registration_modes }
28
+
29
+ private
30
+
31
+ def validate_organization_uniqueness
32
+ base_query = Decidim::Organization.pluck(:name)
33
+
34
+ organization_names = []
35
+
36
+ base_query.each do |value|
37
+ organization_names += value.except("machine_translations").values
38
+ organization_names += value.fetch("machine_translations", {}).values
39
+ end
40
+
41
+ organization_names = organization_names.map(&:downcase)
42
+
43
+ errors.add(:name, :taken) if organization_names.include?(name&.downcase)
44
+ errors.add(:host, :taken) if Decidim::Organization.where(host:).where.not(id:).exists?
45
+ end
26
46
  end
27
47
  end
28
48
  end
@@ -6,123 +6,38 @@ module Decidim
6
6
  module System
7
7
  # A form object used to update organizations from the system dashboard.
8
8
  #
9
- class UpdateOrganizationForm < Form
10
- include TranslatableAttributes
11
- include JsonbAttributes
9
+ class UpdateOrganizationForm < BaseOrganizationForm
10
+ translatable_attribute :name, String
12
11
 
13
- mimic :organization
12
+ validate :validate_organization_name_presence
14
13
 
15
- attribute :name, String
16
- attribute :host, String
17
- attribute :secondary_hosts, String
18
- attribute :force_users_to_authenticate_before_access_organization, Boolean
19
- attribute :available_authorizations, Array[String]
20
- attribute :users_registration_mode, String
21
- jsonb_attribute :smtp_settings, [
22
- [:from, String],
23
- [:from_email, String],
24
- [:from_label, String],
25
- [:user_name, String],
26
- [:encrypted_password, String],
27
- [:address, String],
28
- [:port, Integer],
29
- [:authentication, String],
30
- [:enable_starttls_auto, Boolean]
31
- ]
32
-
33
- jsonb_attribute :content_security_policy, [
34
- [:"default-src", String],
35
- [:"img-src", String],
36
- [:"media-src", String],
37
- [:"script-src", String],
38
- [:"style-src", String],
39
- [:"frame-src", String],
40
- [:"font-src", String],
41
- [:"connect-src", String]
42
- ]
43
-
44
- attribute :password, String
45
- attribute :file_upload_settings, FileUploadSettingsForm
46
-
47
- OMNIATH_PROVIDERS_ATTRIBUTES = Decidim::OmniauthProvider.available.keys.map do |provider|
48
- Rails.application.secrets.dig(:omniauth, provider).keys.map do |setting|
49
- if setting == :enabled
50
- ["omniauth_settings_#{provider}_enabled".to_sym, Boolean]
51
- else
52
- ["omniauth_settings_#{provider}_#{setting}".to_sym, String]
53
- end
54
- end
55
- end.flatten(1)
56
-
57
- jsonb_attribute :omniauth_settings, OMNIATH_PROVIDERS_ATTRIBUTES
58
-
59
- validates :name, :host, :users_registration_mode, presence: true
60
- validate :validate_organization_uniqueness
61
- validate :validate_secret_key_base_for_encryption
62
- validates :users_registration_mode, inclusion: { in: Decidim::Organization.users_registration_modes }
63
-
64
- def map_model(model)
65
- self.secondary_hosts = model.secondary_hosts.join("\n")
66
- self.omniauth_settings = (model.omniauth_settings || {}).transform_values do |v|
67
- Decidim::OmniauthProvider.value_defined?(v) ? Decidim::AttributeEncryptor.decrypt(v) : v
68
- end
69
- self.file_upload_settings = FileUploadSettingsForm.from_model(model.file_upload_settings)
70
- end
71
-
72
- def clean_secondary_hosts
73
- return unless secondary_hosts
74
-
75
- secondary_hosts.split("\n").map(&:chomp).select(&:present?)
76
- end
77
-
78
- def clean_available_authorizations
79
- return unless available_authorizations
80
-
81
- available_authorizations.select(&:present?)
82
- end
14
+ private
83
15
 
84
- def password
85
- encrypted_password.nil? ? super : Decidim::AttributeEncryptor.decrypt(encrypted_password)
16
+ def validate_organization_name_presence
17
+ translated_attr = "name_#{current_organization.try(:default_locale) || Decidim.default_locale.to_s}".to_sym
18
+ errors.add(translated_attr, :blank) if send(translated_attr).blank?
86
19
  end
87
20
 
88
- def encrypted_smtp_settings
89
- smtp_settings["from"] = set_from
21
+ def validate_organization_uniqueness
22
+ base_query = persisted? ? Decidim::Organization.where.not(id:).all : Decidim::Organization.all
90
23
 
91
- encrypted = smtp_settings.merge(encrypted_password: Decidim::AttributeEncryptor.encrypt(password))
24
+ organization_names = []
92
25
 
93
- # if all are empty, nil is returned so it does not break ENV vars configuration
94
- encrypted.values.all?(&:blank?) ? nil : encrypted
95
- end
26
+ base_query.pluck(:name).each do |value|
27
+ organization_names += value.except("machine_translations").values
28
+ organization_names += value.fetch("machine_translations", {}).values
29
+ end
96
30
 
97
- def set_from
98
- return from_email if from_label.blank?
31
+ organization_names = organization_names.map(&:downcase).compact_blank
99
32
 
100
- "#{from_label} <#{from_email}>"
101
- end
33
+ name.each do |language, value|
34
+ next if value.is_a?(Hash)
102
35
 
103
- def encrypted_omniauth_settings
104
- encrypted = omniauth_settings.transform_values do |v|
105
- Decidim::OmniauthProvider.value_defined?(v) ? Decidim::AttributeEncryptor.encrypt(v) : v
36
+ errors.add("name_#{language}", :taken) if organization_names.include?(value.downcase)
106
37
  end
107
38
 
108
- # if all are empty, nil is returned so it does not break ENV vars configuration
109
- encrypted.values.all?(&:blank?) ? nil : encrypted
110
- end
111
-
112
- private
113
-
114
- def validate_organization_uniqueness
115
- errors.add(:name, :taken) if Decidim::Organization.where(name:).where.not(id:).exists?
116
39
  errors.add(:host, :taken) if Decidim::Organization.where(host:).where.not(id:).exists?
117
40
  end
118
-
119
- # We need a valid secret key base for encrypting the SMTP password with it
120
- # It is also necessary for other things in Rails (like Cookies encryption)
121
- def validate_secret_key_base_for_encryption
122
- return if Rails.application.secrets.secret_key_base&.length == 128
123
-
124
- errors.add(:password, I18n.t("activemodel.errors.models.organization.attributes.password.secret_key"))
125
- end
126
41
  end
127
42
  end
128
43
  end
@@ -13,8 +13,8 @@ module Decidim
13
13
  private
14
14
 
15
15
  # Changes default Devise behaviour to use ActiveJob to send async emails.
16
- def send_devise_notification(notification, *args)
17
- devise_mailer.send(notification, self, *args).deliver_later
16
+ def send_devise_notification(notification, *)
17
+ devise_mailer.send(notification, self, *).deliver_later
18
18
  end
19
19
  end
20
20
  end
@@ -107,3 +107,60 @@ dl {
107
107
  .ts-dropdown {
108
108
  margin: 0;
109
109
  }
110
+
111
+ .tabs--lang {
112
+ @apply bg-transparent flex items-center gap-x-1;
113
+
114
+ li {
115
+ @apply p-0.5 rounded-t-sm text-secondary text-xs;
116
+
117
+ background-color: rgba(243, 244, 247, 1);
118
+
119
+ &.is-active,
120
+ &:hover {
121
+ @apply border-b border-secondary;
122
+ }
123
+
124
+ &:hover {
125
+ background-color: rgba(243, 244, 247, 1);
126
+ }
127
+ }
128
+
129
+ a {
130
+ @apply text-xs p-0;
131
+
132
+ &::before {
133
+ @apply content-[''] w-2 h-2 inline-block bg-white rounded-full mr-2 border;
134
+
135
+ border-color: rgba(116, 129, 144, 1);
136
+ }
137
+ }
138
+
139
+ .tabs-title > a[aria-selected="true"] {
140
+ @apply font-bold text-secondary;
141
+
142
+ background-color: rgba(243, 244, 247, 1);
143
+
144
+ &::before {
145
+ @apply border-white;
146
+
147
+ background-color: rgba(40, 167, 69, 1);
148
+ }
149
+ }
150
+
151
+ a.is-tab-error {
152
+ color: red;
153
+ }
154
+ }
155
+
156
+ .label--tabs {
157
+ @apply flex justify-between items-end;
158
+
159
+ label {
160
+ @apply inline-block;
161
+ }
162
+ }
163
+
164
+ .tabs-panel[aria-hidden="true"] {
165
+ @apply hidden;
166
+ }
@@ -4,6 +4,10 @@
4
4
  <h1 class="h1"><%= t("decidim.system.titles.dashboard") %></h1>
5
5
  <% end %>
6
6
 
7
+ <h2 class="h3"><%= t ".system_checks" %></h2>
8
+
9
+ <%= cell "decidim/system/system_checks", nil %>
10
+
7
11
  <h2 class="h3"><%= t ".current_organizations" %></h2>
8
12
 
9
13
  <%= link_to t("actions.new_organization", scope: "decidim.system"), [:new, :organization], class: "button button__sm md:button__lg button__primary" %>
@@ -2,7 +2,7 @@
2
2
  <%= form.text_field :name %>
3
3
  <%= form.text_field :redirect_uri %>
4
4
  <%= form.select :decidim_organization_id,
5
- Decidim::Organization.pluck(:name, :id),
5
+ Decidim::Organization.all.map { |o| [organization_name(o), o.id] },
6
6
  { include_blank: t(".select_organization") },
7
7
  { multiple: false } %>
8
8
  <%= form.text_field :organization_name %>