decidim-core 0.25.2 → 0.26.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of decidim-core might be problematic. Click here for more details.

Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/app/cells/decidim/activity_cell.rb +2 -1
  3. data/app/cells/decidim/author/flag_user.erb +1 -1
  4. data/app/cells/decidim/author/profile_inline.erb +1 -1
  5. data/app/cells/decidim/author/withdraw.erb +2 -2
  6. data/app/cells/decidim/author_cell.rb +32 -0
  7. data/app/cells/decidim/card_m_cell.rb +1 -1
  8. data/app/cells/decidim/content_blocks/cta_cell.rb +1 -1
  9. data/app/cells/decidim/content_blocks/hero_cell.rb +1 -1
  10. data/app/cells/decidim/content_blocks/highlighted_content_banner/show.erb +1 -1
  11. data/app/cells/decidim/content_blocks/last_activity_cell.rb +1 -1
  12. data/app/cells/decidim/content_blocks/stats_cell.rb +12 -0
  13. data/app/cells/decidim/endorsers_list_cell.rb +3 -1
  14. data/app/cells/decidim/flag_modal/flag_user.erb +2 -2
  15. data/app/cells/decidim/flag_modal/show.erb +2 -2
  16. data/app/cells/decidim/flag_modal_cell.rb +10 -0
  17. data/app/cells/decidim/notification/show.erb +31 -0
  18. data/app/cells/decidim/notification_cell.rb +20 -0
  19. data/app/cells/decidim/notifications/show.erb +1 -24
  20. data/app/cells/decidim/notifications_cell.rb +0 -1
  21. data/app/cells/decidim/user_conversation/conversation_header.erb +1 -1
  22. data/app/cells/decidim/user_conversation/show.erb +4 -2
  23. data/app/cells/decidim/user_conversations/conversation_item.erb +1 -1
  24. data/app/commands/decidim/create_editor_image.rb +41 -0
  25. data/app/controllers/decidim/cookie_policy_controller.rb +2 -0
  26. data/app/controllers/decidim/editor_images_controller.rb +47 -0
  27. data/app/controllers/decidim/user_activities_controller.rb +2 -1
  28. data/app/forms/decidim/editor_image_form.rb +16 -0
  29. data/app/helpers/decidim/amendments_helper.rb +1 -1
  30. data/app/helpers/decidim/application_helper.rb +2 -2
  31. data/app/helpers/decidim/messaging/conversation_helper.rb +32 -3
  32. data/app/helpers/decidim/resource_versions_helper.rb +1 -1
  33. data/app/helpers/decidim/sanitize_helper.rb +65 -0
  34. data/app/models/decidim/editor_image.rb +14 -0
  35. data/app/models/decidim/messaging/conversation.rb +9 -0
  36. data/app/models/decidim/participatory_space_private_user.rb +16 -0
  37. data/app/models/decidim/user.rb +3 -3
  38. data/app/models/decidim/user_group.rb +40 -0
  39. data/app/packs/entrypoints/decidim_core.js +1 -0
  40. data/app/packs/src/decidim/dialog_mode.js +143 -0
  41. data/app/packs/src/decidim/dialog_mode.test.js +168 -0
  42. data/app/packs/src/decidim/editor.js +56 -14
  43. data/app/packs/src/decidim/form_attachments.js +5 -0
  44. data/app/packs/src/decidim/index.js +4 -0
  45. data/app/packs/src/decidim/vendor/image-resize.min.js +3 -0
  46. data/app/packs/src/decidim/vendor/image-upload.min.js +8 -0
  47. data/app/packs/stylesheets/decidim/extras/_extras.scss +0 -1
  48. data/app/packs/stylesheets/decidim/extras/_quill.scss +7 -0
  49. data/app/packs/stylesheets/decidim/modules/_buttons.scss +11 -4
  50. data/app/packs/stylesheets/decidim/modules/_cards.scss +4 -0
  51. data/app/packs/stylesheets/decidim/modules/_layout.scss +1 -1
  52. data/app/presenters/decidim/nil_presenter.rb +2 -2
  53. data/app/presenters/decidim/notification_presenter.rb +25 -0
  54. data/app/presenters/decidim/official_author_presenter.rb +1 -1
  55. data/app/presenters/decidim/validation_errors_presenter.rb +27 -0
  56. data/app/queries/decidim/similar_emendations.rb +1 -1
  57. data/app/resolvers/decidim/core/metric_resolver.rb +1 -1
  58. data/app/services/decidim/activity_search.rb +2 -2
  59. data/app/services/decidim/email_notification_generator.rb +4 -1
  60. data/app/services/decidim/html_truncation.rb +130 -0
  61. data/app/services/decidim/open_data_exporter.rb +29 -5
  62. data/app/services/decidim/resource_search.rb +1 -1
  63. data/app/uploaders/decidim/editor_image_uploader.rb +6 -0
  64. data/app/validators/password_validator.rb +123 -0
  65. data/app/views/decidim/account/_password_fields.html.erb +1 -1
  66. data/app/views/decidim/devise/passwords/edit.html.erb +1 -1
  67. data/app/views/decidim/devise/registrations/new.html.erb +1 -1
  68. data/app/views/decidim/devise/shared/_omniauth_buttons_mini.html.erb +6 -4
  69. data/app/views/decidim/messaging/conversations/_conversation.html.erb +3 -3
  70. data/app/views/decidim/messaging/conversations/_messages.html.erb +8 -2
  71. data/app/views/decidim/messaging/conversations/_show.html.erb +10 -12
  72. data/app/views/decidim/messaging/conversations/show.html.erb +4 -2
  73. data/app/views/decidim/newsletters/show.html.erb +1 -1
  74. data/app/views/decidim/notification_mailer/event_received.html.erb +17 -0
  75. data/app/views/decidim/pages/_tabbed.html.erb +1 -1
  76. data/app/views/decidim/searches/_filters_small_view.html.erb +3 -3
  77. data/app/views/decidim/shared/_login_modal.html.erb +5 -5
  78. data/app/views/decidim/shared/_orders.html.erb +1 -1
  79. data/app/views/decidim/shared/_results_per_page.html.erb +1 -1
  80. data/app/views/decidim/shared/participatory_space_filters/_filters_small_view.html.erb +3 -3
  81. data/app/views/layouts/decidim/_application.html.erb +1 -12
  82. data/app/views/layouts/decidim/_head.html.erb +4 -0
  83. data/app/views/layouts/decidim/_language_chooser.html.erb +1 -1
  84. data/app/views/layouts/decidim/_meta_tags_config.html.erb +11 -0
  85. data/app/views/layouts/decidim/_wrapper.html.erb +1 -1
  86. data/config/brakeman.ignore +149 -0
  87. data/config/initializers/devise.rb +1 -1
  88. data/config/initializers/rack_attack.rb +23 -21
  89. data/config/locales/ca.yml +2 -0
  90. data/config/locales/cs.yml +60 -0
  91. data/config/locales/en.yml +45 -0
  92. data/config/locales/es.yml +45 -0
  93. data/config/locales/eu.yml +5 -0
  94. data/config/locales/fi-plain.yml +6 -0
  95. data/config/locales/fi.yml +45 -0
  96. data/config/locales/fr-CA.yml +38 -0
  97. data/config/locales/fr.yml +44 -6
  98. data/config/locales/gl.yml +5 -0
  99. data/config/locales/it.yml +11 -0
  100. data/config/locales/ja.yml +72 -36
  101. data/config/locales/lb-LU.yml +1354 -0
  102. data/config/locales/lb.yml +1 -1
  103. data/config/locales/nl.yml +54 -0
  104. data/config/locales/pl.yml +5 -5
  105. data/config/locales/pt-BR.yml +1 -1
  106. data/config/locales/ro-RO.yml +8 -0
  107. data/config/locales/sv.yml +5 -0
  108. data/config/locales/val-ES.yml +1 -0
  109. data/config/routes.rb +2 -0
  110. data/db/migrate/20210730112319_create_decidim_editor_images.rb +12 -0
  111. data/db/migrate/20211126183540_add_timestamps_to_content_blocks.rb +14 -0
  112. data/db/seeds.rb +16 -14
  113. data/lib/decidim/api/functions/user_entity_list.rb +1 -0
  114. data/lib/decidim/api/input_sorts/component_input_sort.rb +1 -1
  115. data/lib/decidim/common_passwords.rb +56 -0
  116. data/lib/decidim/content_parsers/inline_images_parser.rb +68 -0
  117. data/lib/decidim/content_parsers.rb +1 -0
  118. data/lib/decidim/content_renderers/link_renderer.rb +85 -1
  119. data/lib/decidim/content_renderers/user_group_renderer.rb +1 -1
  120. data/lib/decidim/content_renderers/user_renderer.rb +1 -1
  121. data/lib/decidim/core/engine.rb +3 -12
  122. data/lib/decidim/core/test/factories.rb +7 -1
  123. data/lib/decidim/core/test/shared_examples/translated_event_examples.rb +131 -0
  124. data/lib/decidim/core/test.rb +1 -0
  125. data/lib/decidim/core/version.rb +1 -1
  126. data/lib/decidim/core.rb +22 -5
  127. data/lib/decidim/db/common-passwords.txt +128420 -0
  128. data/lib/decidim/etherpad/pad.rb +48 -0
  129. data/lib/decidim/etherpad.rb +7 -0
  130. data/lib/decidim/events/base_event.rb +18 -0
  131. data/lib/decidim/events/machine_translated_event.rb +36 -0
  132. data/lib/decidim/events/user_group_event.rb +1 -3
  133. data/lib/decidim/events.rb +1 -0
  134. data/lib/decidim/exporters/csv.rb +7 -7
  135. data/lib/decidim/faker/localized.rb +15 -6
  136. data/lib/decidim/form_builder.rb +14 -4
  137. data/lib/decidim/has_attachments.rb +11 -4
  138. data/lib/decidim/importers/import_manifest.rb +103 -3
  139. data/lib/decidim/paddable.rb +1 -9
  140. data/lib/decidim/searchable.rb +2 -2
  141. data/lib/decidim/settings_manifest.rb +2 -0
  142. data/lib/decidim/translatable_attributes.rb +6 -6
  143. data/lib/decidim/view_model.rb +10 -0
  144. data/lib/tasks/decidim_active_storage_migration_tasks.rake +68 -0
  145. metadata +56 -65
  146. data/app/packs/stylesheets/decidim/extras/_social_icons_mini.scss +0 -11
@@ -1283,7 +1283,7 @@ lb:
1283
1283
  share: Deelen
1284
1284
  share_link: Link deelen
1285
1285
  statistics:
1286
- comments_count: Kommentare
1286
+ comments_count: Kommentarer
1287
1287
  endorsements_count: Ënnerstëtzungen
1288
1288
  followers_count: Follower
1289
1289
  headline: Statistiken
@@ -75,6 +75,33 @@ nl:
75
75
  decidim_with_day_and_month_name: "%A %d %b %Y"
76
76
  decidim_with_month_name: "%d %B %Y"
77
77
  decidim_with_month_name_short: "%d %b"
78
+ datetime:
79
+ distance_in_words:
80
+ about_x_hours:
81
+ one: ongeveer 1 uur
82
+ other: ongeveer %{count} uren
83
+ about_x_months:
84
+ one: ongeveer 1 maand
85
+ other: ongeveer %{count} maanden
86
+ half_a_minute: een halve minuut
87
+ less_than_x_minutes:
88
+ one: minder dan een minuut
89
+ other: minder dan %{count} minuten
90
+ less_than_x_seconds:
91
+ one: nu meteen
92
+ other: minder dan %{count} seconden
93
+ x_days:
94
+ one: 1 dag geleden
95
+ other: "%{count} dagen geleden"
96
+ x_hours:
97
+ one: 1 uur geleden
98
+ other: "%{count} uren geleden"
99
+ x_minutes:
100
+ one: 1 minuut geleden
101
+ other: "%{count} minuten geleden"
102
+ x_seconds:
103
+ one: 1 seconde geleden
104
+ other: "%{count} seconden geleden"
78
105
  decidim:
79
106
  accessibility:
80
107
  external_link: Externe link
@@ -495,6 +522,11 @@ nl:
495
522
  this_application_will_not_be_able_to: 'Deze applicatie krijgt geen toegang tot:'
496
523
  update_profile: update je profiel
497
524
  wants_to_use_your_account_html: "<strong>%{application_name}</strong> wil toegang tot je account"
525
+ editor_images:
526
+ create:
527
+ error: Fout bij het uploaden van een afbeelding
528
+ success: Afbeelding met succes geüploaded
529
+ drag_and_drop_help: Voeg afbeeldingen toe door ze te slepen of te plakken.
498
530
  endorsable:
499
531
  endorsements: Aanbevelingen
500
532
  endorsements_count: Aantal suggesties
@@ -677,6 +709,7 @@ nl:
677
709
  no_followers: Nog geen volgers.
678
710
  following:
679
711
  no_followings: Volgt nog niets of niemand.
712
+ non_public_followings: Sommige van de gevolgde bronnen zijn niet openbaar.
680
713
  follows:
681
714
  create:
682
715
  button: Volgen
@@ -837,6 +870,15 @@ nl:
837
870
  index:
838
871
  last_activity: Laatste Activiteit
839
872
  resource_type: Type
873
+ links:
874
+ invalid_url: Ongeldige URL
875
+ warning:
876
+ body_1: Je staat op het punt om een externe link te bezoeken, wees voorzichtig met de inhoud van de externe site.
877
+ body_2: Controleer de link, zorg ervoor dat je deze herkent als een veilige site voor je verdergaat.
878
+ cancel: Annuleer
879
+ close_modal: Sluit venster
880
+ proceed: Doorgaan
881
+ title: Externe link openen
840
882
  log:
841
883
  base_presenter:
842
884
  create: "%{user_name} gemaakt %{resource_name}"
@@ -939,6 +981,7 @@ nl:
939
981
  show:
940
982
  back: Terug naar alle gesprekken
941
983
  chat_with: Gesprek met
984
+ deleted_accounts: Je kunt geen gesprek voeren met verwijderde accounts.
942
985
  not_allowed: Deze deelnemer aanvaardt geen rechtstreekse berichten.
943
986
  title: Gesprek met %{usernames}
944
987
  start:
@@ -1006,6 +1049,12 @@ nl:
1006
1049
  greetings: Groeten,<br/>%{organization_name}<br/><a href="%{organization_url}">%{organization_url}</a>
1007
1050
  hello: Hallo,
1008
1051
  subject: Wilt u relevante informatie over %{organization_name}blijven ontvangen?
1052
+ notification_mailer:
1053
+ event_received:
1054
+ no_translation_available: Sorry, de geautomatiseerde vertaling kon niet worden opgehaald toen de e-mail is verzonden. Je kan de vertaling van de oorspronkelijke tekst controleren via de volgende link %{link}.
1055
+ original_text: 'Originele tekst:'
1056
+ same_language: De inhoud werd in je voorkeurstaal (%{language}) geplaatst. Dit is de reden waarom er geen automatische vertaling wordt weergegeven in deze e-mail.
1057
+ translated_text: 'Automatisch vertaalde tekst:'
1009
1058
  notifications:
1010
1059
  no_notifications: Nog geen meldingen.
1011
1060
  notifications_settings:
@@ -1289,6 +1338,7 @@ nl:
1289
1338
  title_reply: Beantwoorden
1290
1339
  show:
1291
1340
  back: Toon alle gesprekken
1341
+ deleted_accounts: Je kunt geen gesprek voeren met verwijderde accounts.
1292
1342
  not_allowed: Deze gebruiker accepteert geen directe berichten meer.
1293
1343
  title: Gesprek met %{usernames}
1294
1344
  update:
@@ -1573,10 +1623,12 @@ nl:
1573
1623
  name: Nederlands
1574
1624
  name_with_error: Engels (fout!)
1575
1625
  password_validator:
1626
+ blacklisted: staat op de zwarte lijst
1576
1627
  domain_included_in_password: lijkt te veel op deze domeinnaam
1577
1628
  email_included_in_password: lijkt te veel op uw e-mail
1578
1629
  fallback: is niet geldig
1579
1630
  name_included_in_password: lijkt te veel op uw naam
1631
+ nickname_included_in_password: lijkt te veel op jouw bijnaam
1580
1632
  not_enough_unique_characters: heeft niet genoeg unieke tekens
1581
1633
  password_not_allowed: is niet toegestaan
1582
1634
  password_too_common: te algemeen
@@ -1611,6 +1663,8 @@ nl:
1611
1663
  day_of_week: "%a"
1612
1664
  day_of_week_long: "%a %e"
1613
1665
  day_of_year: "%d.%m.%y"
1666
+ ddmm: "%d.%m"
1667
+ ddmmyyyy: "%d.%m.%Y"
1614
1668
  decidim_day_of_year: "%d %B %Y"
1615
1669
  decidim_short: "%d/%m/%Y %H:%M"
1616
1670
  default: "%a, %d %b %Y %H:%M:%S %z"
@@ -412,7 +412,7 @@ pl:
412
412
  button_url: Adres url przycisku CTA
413
413
  description: Opis
414
414
  footer_sub_hero:
415
- name: Banner podrzędny stopki
415
+ name: Baner podrzędny stopki
416
416
  hero:
417
417
  name: Obraz główny
418
418
  hero_settings_form:
@@ -439,7 +439,7 @@ pl:
439
439
  stats:
440
440
  name: Statystyki organizacji
441
441
  sub_hero:
442
- name: Banner podrzędny
442
+ name: Baner podrzędny
443
443
  core:
444
444
  actions:
445
445
  login_before_access: Zaloguj się na swoje konto, żeby mieć dostęp
@@ -469,7 +469,7 @@ pl:
469
469
  newsletter: Chcę otrzymywać okazjonalne newslettery z istotnymi informacjami
470
470
  newsletter_title: Zgoda na subskrybcję
471
471
  nickname_help: Twój pseudonim w %{organization}. Może zawierać tylko litery, cyfry, '-' i '_'.
472
- password_help: "Minimalna liczba znaków: %{minimun_characters}; nie może być zbyt powszechny (np. 123456) i musi różnić się od Twojego pseudonimu i adresu e-mail."
472
+ password_help: "Minimalna liczba znaków: %{minimun_characters}; nie może być zbyt powszechne (np. 123456) i musi różnić się od Twojego pseudonimu i adresu e-mail."
473
473
  sign_in: Zaloguj się
474
474
  sign_up: Zarejestruj się
475
475
  sign_up_as:
@@ -682,7 +682,7 @@ pl:
682
682
  click_button: 'Kliknij poniższy przycisk, aby pobrać swoje dane. <br/>Plik będzie dostępny do %{date}. <br/>Będziesz potrzebował <a href=''''https://www.7-zip.org/''''>7-Zip</a> (Windows), <a href="https://www.keka.io/en/">Keka</a> (MacOS) lub <a href="https://peazip.github.io">PeaZip</a> (Linux) do otwarcia pliku. Hasło: %{password}'
683
683
  download: Pobieranie
684
684
  export:
685
- ready: Znajdź załączoną wersję eksportowanego pliku.
685
+ ready: Mail zawiera załączony plik eksportu.
686
686
  subject: Twój eksport "%{name}" jest gotowy
687
687
  filters:
688
688
  linked_classes:
@@ -1487,7 +1487,7 @@ pl:
1487
1487
  change_your_password: Zmień swoje hasło
1488
1488
  confirm_new_password: Potwierdź nowe hasło
1489
1489
  new_password: Nowe hasło
1490
- password_help: "Minimalna liczba znaków: %{minimun_characters}; nie może być zbyt powszechny (np. 123456) i musi różnić się od Twojego pseudonimu i adresu e-mail."
1490
+ password_help: "Minimalna liczba znaków: %{minimun_characters}; nie może być zbyt powszechne (np. 123456) i musi różnić się od Twojego pseudonimu i adresu e-mail."
1491
1491
  new:
1492
1492
  forgot_your_password: Zapomniałeś hasła?
1493
1493
  send_me_reset_password_instructions: Wyślij mi instrukcje resetowania hasła
@@ -1,4 +1,4 @@
1
- pt:
1
+ pt-BR:
2
2
  activemodel:
3
3
  attributes:
4
4
  account:
@@ -80,6 +80,9 @@ ro:
80
80
  decidim_with_day_and_month_name: "%A %d %b %Y"
81
81
  decidim_with_month_name: "%d %B %Y"
82
82
  decidim_with_month_name_short: "%d %b"
83
+ datetime:
84
+ distance_in_words:
85
+ half_a_minute: jumătate de minut
83
86
  decidim:
84
87
  accessibility:
85
88
  external_link: Link extern
@@ -518,6 +521,11 @@ ro:
518
521
  this_application_will_not_be_able_to: 'Această aplicație nu va putea să:'
519
522
  update_profile: Actualizeză-ți profilul
520
523
  wants_to_use_your_account_html: "<strong>%{application_name}</strong> vrea să folosească contul tău"
524
+ editor_images:
525
+ create:
526
+ error: Eroare la încărcarea imaginii
527
+ success: Imaginea a fost încărcată cu succes
528
+ drag_and_drop_help: Adaugă imagini prin tragere & plasare sau lipirea lor.
521
529
  endorsable:
522
530
  endorsements: Susținători
523
531
  endorsements_count: Număr de susțineri
@@ -505,6 +505,11 @@ sv:
505
505
  this_application_will_not_be_able_to: 'Det här programmet kommer inte att kunna:'
506
506
  update_profile: Uppdatera din profil
507
507
  wants_to_use_your_account_html: "<strong>%{application_name}</strong> vill använda ditt konto"
508
+ editor_images:
509
+ create:
510
+ error: Fel vid uppladdning av bild
511
+ success: Bilden har laddats upp
512
+ drag_and_drop_help: Lägg till bilder genom att dra och släppa eller klistra in dem.
508
513
  endorsable:
509
514
  endorsements: Instämmanden
510
515
  endorsements_count: Antal Endorsements
@@ -0,0 +1 @@
1
+ val:
data/config/routes.rb CHANGED
@@ -156,6 +156,8 @@ Decidim::Core::Engine.routes.draw do
156
156
  end
157
157
  end
158
158
 
159
+ resources :editor_images, only: [:create]
160
+
159
161
  namespace :gamification do
160
162
  resources :badges, only: [:index]
161
163
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDecidimEditorImages < ActiveRecord::Migration[6.0]
4
+ def change
5
+ create_table :decidim_editor_images do |t|
6
+ t.references :decidim_author, null: false, foreign_key: { to_table: :decidim_users }, index: { name: "decidim_editor_images_author" }
7
+ t.references :decidim_organization, null: false, foreign_key: true, index: { name: "decidim_editor_images_constraint_organization" }
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddTimestampsToContentBlocks < ActiveRecord::Migration[6.0]
4
+ def up
5
+ add_timestamps :decidim_content_blocks, default: Time.zone.now
6
+ change_column_default :decidim_content_blocks, :created_at, nil
7
+ change_column_default :decidim_content_blocks, :updated_at, nil
8
+ end
9
+
10
+ def down
11
+ remove_column :decidim_content_blocks, :updated_at
12
+ remove_column :decidim_content_blocks, :created_at
13
+ end
14
+ end
data/db/seeds.rb CHANGED
@@ -132,21 +132,23 @@ if !Rails.env.production? || ENV["SEED"]
132
132
  admin_terms_accepted_at: Time.current
133
133
  )
134
134
 
135
- regular_user = Decidim::User.find_or_initialize_by(email: "user@example.org")
135
+ ["user@example.org", "user2@example.org"].each do |email|
136
+ Decidim::User.find_or_initialize_by(email: email).update!(
137
+ name: Faker::Name.name,
138
+ nickname: Faker::Twitter.unique.screen_name,
139
+ password: "decidim123456",
140
+ password_confirmation: "decidim123456",
141
+ confirmed_at: Time.current,
142
+ locale: I18n.default_locale,
143
+ organization: organization,
144
+ tos_agreement: true,
145
+ personal_url: Faker::Internet.url,
146
+ about: Faker::Lorem.paragraph(sentence_count: 2),
147
+ accepted_tos_version: organization.tos_version
148
+ )
149
+ end
136
150
 
137
- regular_user.update!(
138
- name: Faker::Name.name,
139
- nickname: Faker::Twitter.unique.screen_name,
140
- password: "decidim123456",
141
- password_confirmation: "decidim123456",
142
- confirmed_at: Time.current,
143
- locale: I18n.default_locale,
144
- organization: organization,
145
- tos_agreement: true,
146
- personal_url: Faker::Internet.url,
147
- about: Faker::Lorem.paragraph(sentence_count: 2),
148
- accepted_tos_version: organization.tos_version
149
- )
151
+ regular_user = Decidim::User.find_or_initialize_by(email: "user@example.org")
150
152
 
151
153
  locked_user = Decidim::User.find_or_initialize_by(email: "locked_user@example.org")
152
154
 
@@ -20,6 +20,7 @@ module Decidim
20
20
  @query = Decidim::UserBaseEntity
21
21
  .where(organization: ctx[:current_organization])
22
22
  .where.not(confirmed_at: nil)
23
+ .includes(avatar_attachment: :blob)
23
24
  add_filter_keys(args[:filter])
24
25
  add_order_keys(args[:order].to_h)
25
26
  @query
@@ -23,7 +23,7 @@ module Decidim
23
23
  prepare: lambda { |direction, ctx|
24
24
  lambda { |locale|
25
25
  locale = ctx[:current_organization].default_locale if locale.blank?
26
- [Arel.sql("name->? #{direction.upcase}"), locale]
26
+ [Arel.sql("name->? #{direction.upcase}").to_s, locale]
27
27
  }
28
28
  }
29
29
  end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ class CommonPasswords
5
+ include Singleton
6
+
7
+ attr_reader :passwords
8
+
9
+ URLS = %w(
10
+ https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/xato-net-10-million-passwords-1000000.txt
11
+ https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/darkweb2017-top10000.txt
12
+ https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt
13
+ ).freeze
14
+
15
+ def initialize
16
+ raise FileNotFoundError unless File.exist?(self.class.common_passwords_path)
17
+
18
+ File.open(self.class.common_passwords_path, "r") do |file|
19
+ @passwords = file.read.split
20
+ end
21
+ end
22
+
23
+ def self.update_passwords!
24
+ File.open(common_passwords_path, "w") do |file|
25
+ common_password_list.each { |item| file.puts(item) }
26
+ end
27
+ end
28
+
29
+ def self.common_password_list
30
+ @common_password_list ||= begin
31
+ list = []
32
+ URLS.each do |url|
33
+ URI.open(url) do |data|
34
+ data.read.split.each do |line|
35
+ list << line if line.length >= min_length
36
+ end
37
+ end
38
+ end
39
+
40
+ list.uniq
41
+ end
42
+ end
43
+
44
+ def self.min_length
45
+ return ::PasswordValidator::MINIMUM_LENGTH if defined?(::PasswordValidator)
46
+
47
+ 10
48
+ end
49
+
50
+ def self.common_passwords_path
51
+ File.join(__dir__, "db", "common-passwords.txt")
52
+ end
53
+
54
+ class FileNotFoundError < StandardError; end
55
+ end
56
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module ContentParsers
5
+ # A parser that searches for inline images in an html content and
6
+ # replaces them with EditorImage attachments. Note that rewrite method may
7
+ # create EditorImage instances
8
+ #
9
+ # @see BaseParser Examples of how to use a content parser
10
+ class InlineImagesParser < BaseParser
11
+ # @return [String] the content with the inline images replaced.
12
+ def rewrite
13
+ return content unless inline_images?
14
+
15
+ replace_inline_images
16
+ parsed_content.to_html
17
+ end
18
+
19
+ def inline_images?
20
+ parsed_content.search(:img).find do |image|
21
+ image.attr(:src).start_with?(%r{data:image/[a-z]{3,4};base64,})
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def parsed_content
28
+ @parsed_content ||= Nokogiri::HTML(content)
29
+ end
30
+
31
+ def replace_inline_images
32
+ parsed_content.search(:img).each do |image|
33
+ next unless image.attr(:src).start_with?(%r{data:image/[a-z]{3,4};base64,})
34
+
35
+ file = base64_tempfile(image.attr(:src))
36
+ editor_image = EditorImage.create!(
37
+ decidim_author_id: context[:user]&.id,
38
+ organization: context[:user].organization,
39
+ file: file
40
+ )
41
+
42
+ image.set_attribute(:src, editor_image.attached_uploader(:file).path)
43
+ end
44
+ end
45
+
46
+ def base64_tempfile(base64_data, filename = nil)
47
+ return base64_data unless base64_data.is_a? String
48
+
49
+ start_regex = %r{data:image/[a-z]{3,4};base64,}
50
+ filename ||= SecureRandom.hex
51
+
52
+ regex_result = start_regex.match(base64_data)
53
+
54
+ return unless base64_data && regex_result
55
+
56
+ start = regex_result.to_s
57
+ tempfile = Tempfile.new(filename)
58
+ tempfile.binmode
59
+ tempfile.write(Base64.decode64(base64_data[start.length..-1]))
60
+ ActionDispatch::Http::UploadedFile.new(
61
+ tempfile: tempfile,
62
+ filename: filename,
63
+ original_filename: filename
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
@@ -8,5 +8,6 @@ module Decidim
8
8
  autoload :HashtagParser, "decidim/content_parsers/hashtag_parser"
9
9
  autoload :NewlineParser, "decidim/content_parsers/newline_parser"
10
10
  autoload :LinkParser, "decidim/content_parsers/link_parser"
11
+ autoload :InlineImagesParser, "decidim/content_parsers/inline_images_parser"
11
12
  end
12
13
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Decidim
4
4
  module ContentRenderers
5
+ # Original: https://github.com/neighborland/anchored/
5
6
  # A renderer that converts URLs to links and strips attributes in anchors.
6
7
  #
7
8
  # Examples:
@@ -20,7 +21,90 @@ module Decidim
20
21
  return content unless content.is_a?(String)
21
22
 
22
23
  options = { target: "_blank", rel: "nofollow noopener" }.merge(options)
23
- Anchored::Linker.auto_link(content, options)
24
+ auto_link(content, options)
25
+ end
26
+
27
+ def auto_link(text, options = {}, &block)
28
+ return "" if text.to_s.empty?
29
+
30
+ auto_link_urls(text, options, &block)
31
+ end
32
+
33
+ # remove_target_if_local("http://same.com/x", "same.com", target: "_blank")
34
+ # => <a href="http://same.com/x">http://same.com/x</a>
35
+ #
36
+ # remove_target_if_local("http://same.com/x", "different.com", target: "_blank")
37
+ # => <a href="http://same.com/x" target="_blank">http://same.com/x</a>
38
+ #
39
+ # modifies options in place
40
+ def remove_target_if_local(href, domain, options)
41
+ return unless options[:target]
42
+
43
+ options.delete(:target) if href.include?("//#{domain}")
44
+ end
45
+
46
+ private
47
+
48
+ AUTO_LINK_RE = %r{(?: ((?:ftp|http|https):)// | www\. )[^\s<\u00A0"]+}ix.freeze
49
+
50
+ # # regexps for determining context, used high-volume
51
+ AUTO_LINK_CRE = [/<[^>]+$/, /^[^>]*>/, /<a\b.*?>/i, %r{</a>}i].freeze
52
+
53
+ PUNCTUATION_RE = %r{[^\p{Word}/=&]$}.freeze
54
+
55
+ BRACKETS = { "]" => "[", ")" => "(", "}" => "{" }.freeze
56
+
57
+ # Turns all urls into clickable links. If a block is given, each url
58
+ # is yielded and the result is used as the link text.
59
+ def auto_link_urls(text, options = {})
60
+ # to_str is for SafeBuffer objects (text marked html_safe)
61
+ text.to_str.gsub(AUTO_LINK_RE) do
62
+ match = Regexp.last_match
63
+ href = match[0]
64
+ scheme = match[1]
65
+ punctuation = []
66
+
67
+ if auto_linked?(match)
68
+ # do not change string; URL is already linked
69
+ href
70
+ else
71
+ # don't include trailing punctuation character as part of the URL
72
+ while href.sub!(PUNCTUATION_RE, "")
73
+ punctuation.push Regexp.last_match(0)
74
+ if (opening = BRACKETS[punctuation.last]) && href.scan(opening).size > href.scan(punctuation.last).size
75
+ href << punctuation.pop
76
+ break
77
+ end
78
+ end
79
+
80
+ link_text = block_given? ? yield(href) : href
81
+ href = "http://#{href}" unless scheme
82
+
83
+ # content_tag(:a, link_text, html.merge(href: href)) + punctuation.reverse.join('')
84
+ anchor_tag(href, link_text, options) + punctuation.reverse.join
85
+ end
86
+ end
87
+ end
88
+
89
+ # Detects already linked context or position in the middle of a tag
90
+ # Note: this changes the current Regexp
91
+ def auto_linked?(match)
92
+ left = match.pre_match
93
+ right = match.post_match
94
+ (left =~ AUTO_LINK_CRE[0] && right =~ AUTO_LINK_CRE[1]) ||
95
+ (left.rindex(AUTO_LINK_CRE[2]) && Regexp.last_match.post_match !~ AUTO_LINK_CRE[3])
96
+ end
97
+
98
+ def anchor_attrs(options)
99
+ options.map { |k, v| %(#{k}="#{v}") }.unshift("").join(" ")
100
+ end
101
+
102
+ def anchor_tag(href, text, options)
103
+ options = options.dup
104
+ if (domain = options.delete(:domain))
105
+ remove_target_if_local href, domain, options
106
+ end
107
+ %(<a href="#{href}"#{anchor_attrs(options)}>#{text}</a>)
24
108
  end
25
109
  end
26
110
  end
@@ -10,7 +10,7 @@ module Decidim
10
10
  # @see BaseRenderer Examples of how to use a content renderer
11
11
  class UserGroupRenderer < BaseRenderer
12
12
  # Matches a global id representing a Decidim::UserGroup
13
- GLOBAL_ID_REGEX = %r{gid://\S+/Decidim::UserGroup/\d+}.freeze
13
+ GLOBAL_ID_REGEX = %r{gid://[\w-]+/Decidim::UserGroup/\d+}.freeze
14
14
 
15
15
  # Replaces found Global IDs matching an existing user with
16
16
  # a link to their profile. The Global IDs representing an
@@ -10,7 +10,7 @@ module Decidim
10
10
  # @see BaseRenderer Examples of how to use a content renderer
11
11
  class UserRenderer < BaseRenderer
12
12
  # Matches a global id representing a Decidim::User
13
- GLOBAL_ID_REGEX = %r{gid://\S+/Decidim::User/\d+}.freeze
13
+ GLOBAL_ID_REGEX = %r{gid://[\w-]+/Decidim::User/\d+}.freeze
14
14
 
15
15
  # Replaces found Global IDs matching an existing user with
16
16
  # a link to their profile. The Global IDs representing an
@@ -17,7 +17,6 @@ require "rectify"
17
17
  require "carrierwave"
18
18
  require "rails-i18n"
19
19
  require "date_validator"
20
- require "truncato"
21
20
  require "file_validators"
22
21
  require "omniauth"
23
22
  require "omniauth-facebook"
@@ -34,11 +33,9 @@ require "cell/partial"
34
33
  require "kaminari"
35
34
  require "doorkeeper"
36
35
  require "doorkeeper-i18n"
37
- require "nobspw"
38
36
  require "batch-loader"
39
- require "etherpad-lite"
37
+ require "mime-types"
40
38
  require "diffy"
41
- require "anchored"
42
39
  require "social-share-button"
43
40
  require "ransack"
44
41
  require "searchlight"
@@ -85,8 +82,6 @@ module Decidim
85
82
  end
86
83
 
87
84
  initializer "decidim.graphql_api" do
88
- # Enable them method `!` everywhere for compatibility, this line will be removed when upgrading to GraphQL 2.0
89
- GraphQL::DeprecatedDSL.activate
90
85
  Decidim::Api::QueryType.include Decidim::QueryExtensions
91
86
 
92
87
  Decidim::Api.add_orphan_type Decidim::Core::UserType
@@ -304,7 +299,7 @@ module Decidim
304
299
 
305
300
  initializer "SSL and HSTS" do
306
301
  Rails.application.configure do
307
- config.force_ssl = Rails.env.production? && Decidim.config.force_ssl
302
+ config.force_ssl = Decidim.config.force_ssl
308
303
  end
309
304
  end
310
305
 
@@ -315,7 +310,7 @@ module Decidim
315
310
  end
316
311
 
317
312
  initializer "Expire sessions" do
318
- Rails.application.config.session_store :cookie_store, expire_after: Decidim.config.expire_session_after
313
+ Rails.application.config.session_store :cookie_store, secure: Decidim.config.force_ssl, expire_after: Decidim.config.expire_session_after
319
314
  end
320
315
 
321
316
  initializer "decidim.core.register_resources" do
@@ -542,10 +537,6 @@ module Decidim
542
537
  end
543
538
  end
544
539
 
545
- initializer "nbspw" do
546
- NOBSPW.configuration.use_ruby_grep = true
547
- end
548
-
549
540
  initializer "decidim.premailer" do
550
541
  Premailer::Adapter.use = :decidim
551
542
  end
@@ -248,7 +248,7 @@ FactoryBot.define do
248
248
  end
249
249
 
250
250
  factory :user_group_membership, class: "Decidim::UserGroupMembership" do
251
- user
251
+ user { create(:user, :confirmed, organization: user_group.organization) }
252
252
  role { :creator }
253
253
  user_group
254
254
  end
@@ -749,4 +749,10 @@ FactoryBot.define do
749
749
  last_used_at { 1.hour.ago }
750
750
  end
751
751
  end
752
+
753
+ factory :editor_image, class: "Decidim::EditorImage" do
754
+ organization
755
+ author { create(:user, :admin, :confirmed, organization: organization) }
756
+ file { Decidim::Dev.test_file("city.jpeg", "image/jpeg") }
757
+ end
752
758
  end