decidim-cdtb 0.2.1 → 0.4.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +11 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -2
- data/README.md +105 -2
- data/config/initializers/rack_attack.rb +34 -11
- data/lib/decidim/cdtb/fixes/you_tube_embeds_fixer.rb +115 -0
- data/lib/decidim/cdtb/participatory_spaces/add_content_blocks.rb +84 -0
- data/lib/decidim/cdtb/participatory_spaces/manages_content_blocks.rb +56 -0
- data/lib/decidim/cdtb/participatory_spaces/move_images_to_content_block.rb +60 -0
- data/lib/decidim/cdtb/tasks.rb +3 -0
- data/lib/decidim/cdtb/users/remover.rb +26 -0
- data/lib/decidim/cdtb/version.rb +1 -1
- data/lib/tasks/fix_youtube_embeds.rake +22 -0
- data/lib/tasks/logs.rake +107 -5
- data/lib/tasks/participatory_spaces.rake +88 -0
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 153977aa97421818ceebb2f5bd934c01df29717da6b03cec2d3e596868cf482b
|
4
|
+
data.tar.gz: 4b0f14017084367cb8665ffcca4fe4ea9c6db70667cdf9d253366cd667819991
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7c0f4ec00c7d921a2182de07d3601f7c99027ebdcbda6550d7d19007d98051b5c0e1864da1aa45a377b0b5206146032fc42b19338ad5857c501ba2840451df1
|
7
|
+
data.tar.gz: ee1d931e38468fadd1cfbc0b0e1f1504358f37da6a99f8c46ba6666989cb0a59c644d8ac6c5d4a63e24cca812676ce8f418637332f2488aee774f4fa0e2f8ff7
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
## [0.
|
3
|
+
## [0.4.0] - 2025-02-10 (minor - Llefiscós però deliciós)
|
4
|
+
|
5
|
+
- Add task to move images to hero content block in participatory spaces
|
6
|
+
- Improve remove users task disabling and enabling email on moderations
|
7
|
+
|
8
|
+
## [0.3.0] - 2024-12-24 (minor - L'artista de la pista)
|
9
|
+
|
10
|
+
- Fix YouTube embeds to Decidim v0.28 format in different places. Only YouTube is supported right now.
|
11
|
+
- Add task to add new content blocks in participatory spaces
|
12
|
+
|
13
|
+
## [0.2.1] - 2024-09-25 (patch - Una idea sobre rodes)
|
4
14
|
|
5
15
|
- Fix validate_migrations CI which requires Postgres service
|
6
16
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
decidim-cdtb (0.
|
4
|
+
decidim-cdtb (0.4.0)
|
5
5
|
decidim (>= 0.27.0)
|
6
6
|
rails (>= 6)
|
7
7
|
ruby-progressbar
|
@@ -745,7 +745,7 @@ GEM
|
|
745
745
|
concurrent-ruby (~> 1.0)
|
746
746
|
uber (0.1.0)
|
747
747
|
unicode-display_width (2.5.0)
|
748
|
-
uri (0.13.
|
748
|
+
uri (0.13.1)
|
749
749
|
valid_email2 (2.3.1)
|
750
750
|
activemodel (>= 3.2)
|
751
751
|
mail (~> 2.5)
|
@@ -805,6 +805,7 @@ DEPENDENCIES
|
|
805
805
|
rspec (~> 3.0)
|
806
806
|
rubocop
|
807
807
|
sqlite3 (~> 1.4)
|
808
|
+
uri (>= 0.13.1)
|
808
809
|
|
809
810
|
BUNDLED WITH
|
810
811
|
2.3.6
|
data/README.md
CHANGED
@@ -51,6 +51,21 @@ Available rake tasks:
|
|
51
51
|
- `bin/rake cdtb:anonymize:system_admins` anonymizes system admins
|
52
52
|
- `bin/rake cdtb:anonymize:paper_trail` anonymizes paper trails
|
53
53
|
|
54
|
+
### Fix YouTube embeds for Decidim v0.28
|
55
|
+
|
56
|
+
Fixes YouTube embeds to Decidim v0.28 format in different places, which at the moment are:
|
57
|
+
|
58
|
+
- Decidim::Meetings::Meeting
|
59
|
+
- Decidim::Debates::Debate
|
60
|
+
- Decidim::Pages::Page
|
61
|
+
- Decidim::Assembly
|
62
|
+
- Decidim::ParticipatoryProcess
|
63
|
+
|
64
|
+
```
|
65
|
+
bin/rake cdtb:embeds:fix_youtube
|
66
|
+
```
|
67
|
+
|
68
|
+
|
54
69
|
### Migrate ActiveStorage service from S3 to local
|
55
70
|
|
56
71
|
To migrate from S3 to local storage, the identified steps will be:
|
@@ -127,12 +142,100 @@ You can delete users through a CSV with the user ID and a reporter user mailer.
|
|
127
142
|
|
128
143
|
This task reports and hide the user's comments, blocks the user, and finally deletes the user.
|
129
144
|
|
130
|
-
The CSV will have a header and one column with the user ID.
|
145
|
+
The CSV will have a header and one column with the user ID and must be separated by ",".
|
146
|
+
|
147
|
+
To execute the task run:
|
148
|
+
|
149
|
+
```
|
150
|
+
bundle exec rake cdtb:users:remove[spam_users.csv,reporter_user@example.org]
|
151
|
+
```
|
152
|
+
|
153
|
+
### Participatory Spaces
|
154
|
+
|
155
|
+
#### Add content blocks
|
156
|
+
|
157
|
+
You can add content blocks to a participatory spaces with the content block name (manifest_name).
|
158
|
+
This rake task affects spaces in all organizations.
|
159
|
+
|
160
|
+
Content block manifest names list:
|
161
|
+
|
162
|
+
```
|
163
|
+
basic_only_text
|
164
|
+
image_text_cta
|
165
|
+
metadata
|
166
|
+
hero
|
167
|
+
participatory_processes
|
168
|
+
html_2
|
169
|
+
main_data
|
170
|
+
title
|
171
|
+
cta
|
172
|
+
highlighted_proposals
|
173
|
+
how_to_participate
|
174
|
+
html_1
|
175
|
+
related_documents
|
176
|
+
stats
|
177
|
+
html
|
178
|
+
slider
|
179
|
+
footer_sub_hero
|
180
|
+
global_menu
|
181
|
+
sub_hero
|
182
|
+
highlighted_content_banner
|
183
|
+
highlighted_processes
|
184
|
+
highlighted_assemblies
|
185
|
+
highlighted_regulations
|
186
|
+
upcoming_meetings
|
187
|
+
extra_data
|
188
|
+
highlighted_meetings
|
189
|
+
highlighted_results
|
190
|
+
metrics
|
191
|
+
related_assemblies
|
192
|
+
announcement
|
193
|
+
social_networks_metadata
|
194
|
+
related_processes
|
195
|
+
highlighted_posts
|
196
|
+
last_activity
|
197
|
+
```
|
198
|
+
|
199
|
+
Spaces supported:
|
200
|
+
|
201
|
+
- Decidim::ParticipatoryProcess
|
202
|
+
- Decidim::Assembly
|
203
|
+
|
204
|
+
To execute the task run:
|
205
|
+
|
206
|
+
```
|
207
|
+
bundle exec rake cdtb:participatory_spaces:add_content_blocks[manifest_name]
|
208
|
+
```
|
209
|
+
|
210
|
+
You can add multiple manifest names with this format:
|
211
|
+
|
212
|
+
```
|
213
|
+
bundle exec rake cdtb:participatory_spaces:add_content_blocks[['manifest_name_one manifest_name_two']]
|
214
|
+
```
|
215
|
+
|
216
|
+
Some examples
|
217
|
+
```
|
218
|
+
bundle exec rake cdtb:participatory_spaces:add_content_blocks[extra_data]
|
219
|
+
|
220
|
+
bundle exec rake cdtb:participatory_spaces:add_content_blocks[['extra_data related_documents']]
|
221
|
+
|
222
|
+
```
|
223
|
+
|
224
|
+
#### Move banner images to hero content block
|
225
|
+
|
226
|
+
In previous versions of Decidim (0.27 and previous) banner images are in participatory space configuration. Now, this image is in a content block but for old spaces are in configuration yet.
|
227
|
+
|
228
|
+
This task move the banner image to a hero content block.
|
229
|
+
|
230
|
+
Spaces supported:
|
231
|
+
|
232
|
+
- Decidim::ParticipatoryProcess
|
233
|
+
- Decidim::Assembly
|
131
234
|
|
132
235
|
To execute the task run:
|
133
236
|
|
134
237
|
```
|
135
|
-
bundle exec rake cdtb:
|
238
|
+
bundle exec rake cdtb:participatory_spaces:move_images_to_content_block
|
136
239
|
```
|
137
240
|
|
138
241
|
### Upgrades:
|
@@ -3,26 +3,49 @@
|
|
3
3
|
unless ENV["CDTB_RACK_ATTACK_DISABLED"].to_i.positive? || %w[development test].include?(Rails.env)
|
4
4
|
require "rack/attack"
|
5
5
|
|
6
|
-
|
7
|
-
period= ENV.fetch("RACK_ATTACK_THROTTLE_PERIOD", 60)
|
8
|
-
Rails.logger.info("Configuring Rack::Attack.throttle with limit: #{limit}, period: #{period}")
|
9
|
-
Rack::Attack.throttle("requests by (forwarded) ip", limit: limit.to_i, period: period.to_i) do |request|
|
10
|
-
# ignore requests to assets
|
11
|
-
next if request.path.start_with?("/rails/active_storage")
|
12
|
-
|
6
|
+
def extract_ip(request)
|
13
7
|
x_forwarded_for= request.get_header("HTTP_X_FORWARDED_FOR")
|
14
8
|
Rails.logger.info { ">>>>>>>>>>>>>>>>>>>> X-Forwarded-For: #{x_forwarded_for}" }
|
15
9
|
if x_forwarded_for.present?
|
16
|
-
|
17
|
-
|
10
|
+
x_forwarded_for.split(":").first
|
11
|
+
|
18
12
|
else
|
19
13
|
request.ip
|
20
14
|
end
|
21
15
|
end
|
22
16
|
|
17
|
+
limit= ENV.fetch("RACK_ATTACK_THROTTLE_LIMIT", 30)
|
18
|
+
period= ENV.fetch("RACK_ATTACK_THROTTLE_PERIOD", 60)
|
19
|
+
Rails.logger.info("Configuring Rack::Attack.throttle with limit: #{limit}, period: #{period}")
|
20
|
+
Rack::Attack.throttle("requests by ip", limit: limit.to_i, period: period.to_i) do |request|
|
21
|
+
# ignore requests to assets
|
22
|
+
next if request.path.start_with?("/rails/active_storage")
|
23
|
+
|
24
|
+
extract_ip(request)
|
25
|
+
end
|
26
|
+
|
27
|
+
limit= ENV.fetch("RACK_ATTACK_THROTTLE_RANGE_LIMIT", 10)
|
28
|
+
period= ENV.fetch("RACK_ATTACK_THROTTLE_RANGE_PERIOD", 20)
|
29
|
+
Rails.logger.info("Configuring Rack::Attack.throttle with limits for IP Ranges: #{limit}, period: #{period}")
|
30
|
+
Rack::Attack.throttle("requests by ip range", limit: limit.to_i, period: period.to_i) do |request|
|
31
|
+
# ignore requests to assets
|
32
|
+
next if request.path.start_with?("/rails/active_storage")
|
33
|
+
|
34
|
+
ip= extract_ip(request)
|
35
|
+
# rubocop: disable Lint/UselessAssignment
|
36
|
+
range_32bit= ip.split(".")[0, 2]
|
37
|
+
# rubocop: enable Lint/UselessAssignment
|
38
|
+
end
|
39
|
+
|
40
|
+
Rack::Attack.blocklist("block all /.well-known/traffic-advice") do |request|
|
41
|
+
request.path.start_with?("/.well-known/traffic-advice")
|
42
|
+
end
|
43
|
+
|
23
44
|
if ENV["RACK_ATTACK_BLOCKED_IPS"].present?
|
24
|
-
ENV["RACK_ATTACK_BLOCKED_IPS"].split(",")
|
25
|
-
|
45
|
+
blocked_ips_and_subnets= ENV["RACK_ATTACK_BLOCKED_IPS"].split(",")
|
46
|
+
Rack::Attack.blocklist("block all unaccepted IPs") do |request|
|
47
|
+
ip= extract_ip(request)
|
48
|
+
blocked_ips_and_subnets.any? { |ip_or_subnet| ip.start_with?(ip_or_subnet) }
|
26
49
|
end
|
27
50
|
end
|
28
51
|
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# require "decidim"
|
4
|
+
# require "decidim/assembly"
|
5
|
+
# require "decidim/participatory_process"
|
6
|
+
# require "decidim/meetings/meeting"
|
7
|
+
# require "decidim/debates/debate"
|
8
|
+
# require "decidim/pages/page"
|
9
|
+
|
10
|
+
module Decidim
|
11
|
+
module Cdtb
|
12
|
+
module Fixes
|
13
|
+
# Fixes YouTube embeds to Decidim v0.28 format in PROCESSED_MODELS.
|
14
|
+
# Only YouTube is supported right now.
|
15
|
+
class YouTubeEmbedsFixer < ::Decidim::Cdtb::Task
|
16
|
+
PROCESSED_MODELS= {
|
17
|
+
"Decidim::Meetings::Meeting" => [:description],
|
18
|
+
"Decidim::Debates::Debate" => %i[description instructions],
|
19
|
+
"Decidim::Pages::Page" => [:body],
|
20
|
+
"Decidim::Assembly" => %i[short_description description],
|
21
|
+
"Decidim::ParticipatoryProcess" => %i[short_description description]
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
progress_bar= { title: self.class.name }
|
26
|
+
super("FIX YOUTUBE EMBEDS", progress_bar: progress_bar)
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :num_fixed
|
30
|
+
|
31
|
+
def prepare_execution(_ctx = nil)
|
32
|
+
@num_fixed= @num_items= 0
|
33
|
+
|
34
|
+
PROCESSED_MODELS.each_key do |model_class|
|
35
|
+
@num_items+= model_class.constantize.count
|
36
|
+
end
|
37
|
+
log_task_info("Checking #{@num_items} models...")
|
38
|
+
end
|
39
|
+
|
40
|
+
def total_items
|
41
|
+
@num_items
|
42
|
+
end
|
43
|
+
|
44
|
+
def do_execution(context)
|
45
|
+
progress_bar= context[:progress_bar]
|
46
|
+
|
47
|
+
PROCESSED_MODELS.each_pair do |model_class_name, attribs|
|
48
|
+
log_task_step("Processing #{model_class_name.pluralize}")
|
49
|
+
|
50
|
+
model_class= model_class_name.constantize
|
51
|
+
model_class.find_each do |model|
|
52
|
+
Rails.logger.debug("Processing #{model_class_name}[#{model.id}]")
|
53
|
+
|
54
|
+
attribs.each do |attribute|
|
55
|
+
fix_embed(model, attribute)
|
56
|
+
end
|
57
|
+
|
58
|
+
@num_fixed+= 1 if model.changed?
|
59
|
+
model.save!(validate: false)
|
60
|
+
progress_bar.increment
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def end_execution(_ctx)
|
66
|
+
log_task_step("#{@num_fixed} embeds fixed")
|
67
|
+
end
|
68
|
+
|
69
|
+
# --------------------------------------------------
|
70
|
+
private
|
71
|
+
|
72
|
+
# --------------------------------------------------
|
73
|
+
|
74
|
+
def fix_embed(model, attribute)
|
75
|
+
contents= model.send(attribute)
|
76
|
+
return if contents.blank?
|
77
|
+
|
78
|
+
contents.each_pair do |locale, content|
|
79
|
+
Rails.logger.debug "#{locale} => #{content}"
|
80
|
+
next if locale.to_s == "machine_translations"
|
81
|
+
next if content.blank?
|
82
|
+
|
83
|
+
fixes= fix_localized_embed(content)
|
84
|
+
contents[locale]= fixes.reverse.find { |fix| fix != false } if fixes.any?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# rubocop: disable Metrics/AbcSize
|
89
|
+
def fix_localized_embed(content)
|
90
|
+
parsed= Nokogiri::HTML(content)
|
91
|
+
divs_w_embed= parsed.css("div[class=editor-content-videoEmbed]")
|
92
|
+
Rails.logger.debug "=> #{divs_w_embed.size} => #{content}"
|
93
|
+
|
94
|
+
divs_w_embed.map do |div|
|
95
|
+
regexp_match= div["data-video-embed"].match(%r{https://www.youtube.com/embed/(?<yt_id>\w+)})
|
96
|
+
next unless regexp_match
|
97
|
+
|
98
|
+
Rails.logger.debug("EMBED:::: #{div.class} => #{div}")
|
99
|
+
|
100
|
+
yt_id= regexp_match["yt_id"]
|
101
|
+
div["data-video-embed"]= "https://www.youtube.com/watch?v=#{yt_id}"
|
102
|
+
iframe= div.css("iframe").first
|
103
|
+
iframe["src"]= "https://www.youtube-nocookie.com/embed/#{yt_id}?cc_load_policy=1&modestbranding=1"
|
104
|
+
fixed_div= div
|
105
|
+
Rails.logger.debug("FIXED TO: #{fixed_div.to_html}")
|
106
|
+
new_content= parsed.css("body").children.to_html
|
107
|
+
Rails.logger.debug("FIXED TO: #{new_content}")
|
108
|
+
new_content
|
109
|
+
end
|
110
|
+
end
|
111
|
+
# rubocop: enable Metrics/AbcSize
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/cdtb/participatory_spaces/manages_content_blocks"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Cdtb
|
7
|
+
module ParticipatorySpaces
|
8
|
+
# Add content blocks to participatory spaces
|
9
|
+
class AddContentBlocks < ::Decidim::Cdtb::Task
|
10
|
+
include ::Decidim::Cdtb::ParticipatorySpaces::ManagesContentBlocks
|
11
|
+
|
12
|
+
def initialize(processed_models, content_block_names)
|
13
|
+
progress_bar= { title: self.class.name }
|
14
|
+
@processed_models = processed_models
|
15
|
+
@content_block_names = content_block_names
|
16
|
+
super("ADD CONTENT BLOCKS", progress_bar: progress_bar)
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :num_added
|
20
|
+
|
21
|
+
def prepare_execution(_ctx = nil)
|
22
|
+
@num_added= @num_items= 0
|
23
|
+
|
24
|
+
@processed_models.each do |model_name|
|
25
|
+
@num_items+= model_name.count
|
26
|
+
end
|
27
|
+
log_task_info("Adding content blocks in #{@num_items} spaces...")
|
28
|
+
end
|
29
|
+
|
30
|
+
def total_items
|
31
|
+
@num_items
|
32
|
+
end
|
33
|
+
|
34
|
+
# rubocop:disable Metrics/AbcSize
|
35
|
+
def do_execution(context)
|
36
|
+
progress_bar= context[:progress_bar]
|
37
|
+
|
38
|
+
@processed_models.each do |processed_model|
|
39
|
+
log_task_step("Processing #{processed_model}")
|
40
|
+
|
41
|
+
spaces = processed_model
|
42
|
+
|
43
|
+
@content_block_names.each do |content_block_name|
|
44
|
+
log_task_step("Adding #{content_block_name} content block")
|
45
|
+
|
46
|
+
spaces.find_each do |space|
|
47
|
+
current_content_blocks = current_space_content_blocks(scope_name(space), space.organization, space.id)
|
48
|
+
|
49
|
+
new_content_block = find_or_create_content_block(space, content_block_name)
|
50
|
+
if content_block_name == "extra_data" && space.instance_of?(Decidim::ParticipatoryProcess)
|
51
|
+
next if new_content_block.weight == 20
|
52
|
+
|
53
|
+
force_extra_data_content_block_weight!(content_block_name, current_content_blocks)
|
54
|
+
end
|
55
|
+
|
56
|
+
@num_added += 1
|
57
|
+
progress_bar.increment
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
# rubocop:enable Metrics/AbcSize
|
63
|
+
|
64
|
+
def end_execution(_ctx)
|
65
|
+
log_task_step("#{@num_added} content blocks added")
|
66
|
+
end
|
67
|
+
|
68
|
+
# +extra_data+ content block usually be down of hero image, therefore, it's weight is 20 and all others content blocks
|
69
|
+
# go one position down added 10
|
70
|
+
def force_extra_data_content_block_weight!(content_block_name, current_content_blocks)
|
71
|
+
extra_data_content_block = current_content_blocks.find_by(manifest_name: content_block_name)
|
72
|
+
extra_data_content_block.update(weight: 20)
|
73
|
+
|
74
|
+
current_content_blocks.each do |content_block|
|
75
|
+
# hero is usually the first content block
|
76
|
+
next if content_block == extra_data_content_block || content_block.manifest_name == "hero"
|
77
|
+
|
78
|
+
content_block.update(weight: content_block.weight + 10)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Cdtb
|
5
|
+
module ParticipatorySpaces
|
6
|
+
# Methods for use in participatory spaces tasks
|
7
|
+
module ManagesContentBlocks
|
8
|
+
# rubocop:disable Metrics/AbcSize
|
9
|
+
def find_or_create_content_block(space, content_block_name)
|
10
|
+
current_content_blocks = current_space_content_blocks(scope_name(space), space.organization, space.id)
|
11
|
+
exists_content_block = Decidim::ContentBlock.find_by(decidim_organization_id: space.organization.id,
|
12
|
+
scope_name: scope_name(space), manifest_name: content_block_name,
|
13
|
+
scoped_resource_id: space.id)
|
14
|
+
|
15
|
+
return exists_content_block if exists_content_block.present?
|
16
|
+
|
17
|
+
weight = (current_content_blocks.last.weight + 1) * 10
|
18
|
+
log_task_step("Adding #{content_block_name} to #{space.slug}[#{space.id}]")
|
19
|
+
Decidim::ContentBlock.create(
|
20
|
+
decidim_organization_id: space.organization.id,
|
21
|
+
weight: weight,
|
22
|
+
scope_name: scope_name(space),
|
23
|
+
scoped_resource_id: space.id,
|
24
|
+
manifest_name: content_block_name,
|
25
|
+
published_at: Time.current
|
26
|
+
)
|
27
|
+
end
|
28
|
+
# rubocop:enable Metrics/AbcSize
|
29
|
+
|
30
|
+
def update_content_block_image(content_block, image)
|
31
|
+
content_block.manifest.images.each do |image_config|
|
32
|
+
image_name = image_config[:name]
|
33
|
+
|
34
|
+
next if content_block.images_container.send(image_name).present?
|
35
|
+
|
36
|
+
content_block.images_container.send("#{image_name}=", image.blob)
|
37
|
+
content_block.save
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def current_space_content_blocks(scope_name, organization, scoped_resource_id)
|
42
|
+
Decidim::ContentBlock.for_scope(scope_name, organization: organization).where(scoped_resource_id: scoped_resource_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
def manifest_for(resource)
|
46
|
+
return resource.manifest if resource.is_a? Decidim::Participable
|
47
|
+
return resource.resource_manifest if resource.is_a? Decidim::Resourceable
|
48
|
+
end
|
49
|
+
|
50
|
+
def scope_name(space)
|
51
|
+
manifest_for(space).content_blocks_scope_name
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/cdtb/participatory_spaces/manages_content_blocks"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module Cdtb
|
7
|
+
module ParticipatorySpaces
|
8
|
+
# Move images to content block for participatory spaces
|
9
|
+
class MoveImagesToContentBlock < ::Decidim::Cdtb::Task
|
10
|
+
include ::Decidim::Cdtb::ParticipatorySpaces::ManagesContentBlocks
|
11
|
+
|
12
|
+
def initialize(processed_models)
|
13
|
+
progress_bar= { title: self.class.name }
|
14
|
+
@processed_models = processed_models
|
15
|
+
super("MOVING IMAGES...", progress_bar: progress_bar)
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :num_added
|
19
|
+
|
20
|
+
def prepare_execution(_ctx = nil)
|
21
|
+
@num_added= @num_items= 0
|
22
|
+
|
23
|
+
@processed_models.each do |model_name|
|
24
|
+
@num_items+= model_name.count
|
25
|
+
end
|
26
|
+
log_task_info("Moving images to content block in #{@num_items} spaces...")
|
27
|
+
end
|
28
|
+
|
29
|
+
def total_items
|
30
|
+
@num_items
|
31
|
+
end
|
32
|
+
|
33
|
+
def do_execution(context)
|
34
|
+
progress_bar= context[:progress_bar]
|
35
|
+
|
36
|
+
@processed_models.each do |processed_model|
|
37
|
+
log_task_step("Processing #{processed_model}")
|
38
|
+
|
39
|
+
spaces = processed_model
|
40
|
+
|
41
|
+
spaces.find_each do |space|
|
42
|
+
image_content_block = find_or_create_content_block(space, "hero")
|
43
|
+
|
44
|
+
next if image_content_block.images.present?
|
45
|
+
|
46
|
+
update_content_block_image(image_content_block, space.banner_image)
|
47
|
+
|
48
|
+
@num_added += 1
|
49
|
+
progress_bar.increment
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def end_execution(_ctx)
|
55
|
+
log_task_step("#{@num_added} content blocks added")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/decidim/cdtb/tasks.rb
CHANGED
@@ -3,8 +3,11 @@
|
|
3
3
|
require "decidim/cdtb/tasks_utils"
|
4
4
|
require "decidim/cdtb/task"
|
5
5
|
require "decidim/cdtb/fixes/nickname_fixer"
|
6
|
+
require "decidim/cdtb/fixes/you_tube_embeds_fixer"
|
6
7
|
require "decidim/cdtb/users/remover"
|
7
8
|
require "decidim/cdtb/multitenants/org_by_host_like"
|
9
|
+
require "decidim/cdtb/participatory_spaces/add_content_blocks"
|
10
|
+
require "decidim/cdtb/participatory_spaces/move_images_to_content_block"
|
8
11
|
require "decidim/cdtb/spam/user_spam_detector"
|
9
12
|
require "decidim/cdtb/storage/local_sharding"
|
10
13
|
require "decidim/cdtb/storage/set_local_on_blobs"
|
@@ -20,9 +20,14 @@ module Decidim
|
|
20
20
|
File.open(@csv_path).readlines.size - 1
|
21
21
|
end
|
22
22
|
|
23
|
+
# rubocop:disable Metrics/AbcSize
|
23
24
|
def do_execution(context)
|
24
25
|
progress_bar = context[:progress_bar]
|
25
26
|
|
27
|
+
users_with_email_on_moderations = Decidim::User.where(email_on_moderations: true)
|
28
|
+
|
29
|
+
disable_email_moderations(users_with_email_on_moderations)
|
30
|
+
|
26
31
|
CSV.foreach(@csv_path, headers: true, col_sep: ",") do |row|
|
27
32
|
user = Decidim::User.find_by(id: row[0])
|
28
33
|
next unless user.present?
|
@@ -34,7 +39,10 @@ module Decidim
|
|
34
39
|
destroy_user(user) if block_user(user, reporter_user)
|
35
40
|
progress_bar.increment
|
36
41
|
end
|
42
|
+
ensure
|
43
|
+
enable_email_moderations(users_with_email_on_moderations)
|
37
44
|
end
|
45
|
+
# rubocop:enable Metrics/AbcSize
|
38
46
|
|
39
47
|
def end_execution(_ctx)
|
40
48
|
log_task_step("#{@num_applied} users removed")
|
@@ -42,6 +50,24 @@ module Decidim
|
|
42
50
|
|
43
51
|
private
|
44
52
|
|
53
|
+
def disable_email_moderations(users)
|
54
|
+
log_task_step("Disabling email on moderations...")
|
55
|
+
|
56
|
+
users.find_each do |user|
|
57
|
+
user.email_on_moderations = false
|
58
|
+
user.save(validate: false)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def enable_email_moderations(users)
|
63
|
+
log_task_step("Enabling email on moderations...")
|
64
|
+
|
65
|
+
users.find_each do |user|
|
66
|
+
user.email_on_moderations = true
|
67
|
+
user.save(validate: false)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
45
71
|
def manage_comments(comments, user, reporter_user)
|
46
72
|
comments.find_each do |comment|
|
47
73
|
report_comment(comment, user, reporter_user)
|
data/lib/decidim/cdtb/version.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/version"
|
4
|
+
require "decidim/cdtb/tasks"
|
5
|
+
|
6
|
+
namespace :cdtb do
|
7
|
+
namespace :embeds do
|
8
|
+
desc <<~EODESC
|
9
|
+
Fix YouTube embeds to Decidim v0.28 format.
|
10
|
+
Only youtube is supported right now.
|
11
|
+
EODESC
|
12
|
+
task fix_youtube: [:environment] do
|
13
|
+
unless Decidim.version >= "0.28"
|
14
|
+
puts "This command is only compatible with Decidim v0.28 or higher"
|
15
|
+
exit(-1)
|
16
|
+
end
|
17
|
+
|
18
|
+
fixer= ::Decidim::Cdtb::Fixes::YouTubeEmbedsFixer.new
|
19
|
+
fixer.execute!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/tasks/logs.rake
CHANGED
@@ -2,15 +2,117 @@
|
|
2
2
|
|
3
3
|
namespace :cdtb do
|
4
4
|
namespace :logs do
|
5
|
-
desc "Analize logs in Rails format. Counts the number of requests for each IP in the logs. Accepts a
|
5
|
+
desc "Analize logs in Rails format. Counts the number of requests for each IP in the logs. Accepts a log path param."
|
6
6
|
task :num_rq_per_ip, [:logfile] do |_task, args|
|
7
|
-
|
7
|
+
file_path= args.logfile || "log/production.log"
|
8
8
|
|
9
|
-
file_path= "log/#{logfile}"
|
10
9
|
first_cmd= "grep Started"
|
11
10
|
piped_cmds= [%(grep " for "), "cut -d ' ' -f13", "sort", "uniq -c", "sort"].join(" | ")
|
12
|
-
|
13
|
-
|
11
|
+
cmd= "#{first_cmd} #{file_path} | #{piped_cmds}"
|
12
|
+
|
13
|
+
puts "Running: `#{cmd}`"
|
14
|
+
puts `#{cmd}`
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Analize logs in Rails format. Counts the number of requests for each IP range in the logs. Accepts a log path param."
|
18
|
+
task :num_rq_per_ip_range, [:logfile] do |_task, args|
|
19
|
+
file_path= args.logfile || "log/production.log"
|
20
|
+
|
21
|
+
first_cmd= "grep Started"
|
22
|
+
piped_cmds= [
|
23
|
+
%(grep " for "),
|
24
|
+
# take the IP
|
25
|
+
"cut -d ' ' -f13",
|
26
|
+
# trim blank spaces
|
27
|
+
"awk '{$1=$1;print}'",
|
28
|
+
# range: only the first 2 blocks of the IP
|
29
|
+
"cut -d '.' -f1,2",
|
30
|
+
"sort",
|
31
|
+
"uniq -c",
|
32
|
+
"sort"
|
33
|
+
].join(" | ")
|
34
|
+
cmd= "#{first_cmd} #{file_path} | #{piped_cmds}"
|
35
|
+
|
36
|
+
puts "Running: `#{cmd}`"
|
37
|
+
puts `#{cmd}`
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'Returns the duration, the order in the logs, and the timestamp of each "Completed" trace.'
|
41
|
+
task :slow_rq, [:logfile] do |_task, args|
|
42
|
+
# Based on the follwoing example execution:
|
43
|
+
# grep -e "Completed 200 OK in" log/development.log | ruby logparser.rb | sort
|
44
|
+
|
45
|
+
file_path= args.logfile || "log/production.log"
|
46
|
+
|
47
|
+
idx= 0
|
48
|
+
File.open(file_path).each_line do |line|
|
49
|
+
idx += 1
|
50
|
+
next unless line.include?("Completed 200 OK in")
|
51
|
+
|
52
|
+
split= line.split("Completed 200 OK in")
|
53
|
+
second_part= split.last.strip
|
54
|
+
words= second_part.split
|
55
|
+
response_duration= words.first
|
56
|
+
puts "#{response_duration.rjust(7, "0")}, #{idx}, #{line[4, 22]}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Most requested paths. Accepts a log path param, and an only_path to ignore the query part of the URL."
|
61
|
+
task :most_rq_paths, [:logfile, :only_path] do |_task, args|
|
62
|
+
file_path= args.logfile || "log/production.log"
|
63
|
+
|
64
|
+
first_cmd= "grep Started"
|
65
|
+
piped_cmds= ["cut -d ' ' -f11"]
|
66
|
+
piped_cmds << "cut -d '?' -f 1" if args.only_path == "only_path"
|
67
|
+
piped_cmds+= ["sort", "uniq -c", "sort"]
|
68
|
+
cmd= "#{first_cmd} #{file_path} | #{piped_cmds.join(" | ")}"
|
69
|
+
|
70
|
+
puts "Running: `#{cmd}`"
|
71
|
+
puts `#{cmd}`
|
72
|
+
end
|
73
|
+
|
74
|
+
desc "Analizes output from num_rq_per_ip. Finds the country from each IP in the log file. Accepts a log path param."
|
75
|
+
task :geolocate_ips, [:logfile] do |_task, args|
|
76
|
+
file_path= args.logfile || "log/num_rq_per_ip.log"
|
77
|
+
|
78
|
+
cmd= [
|
79
|
+
# strip spaces
|
80
|
+
"awk '{$1=$1;print}' #{file_path}",
|
81
|
+
"cut -d ' ' -f2",
|
82
|
+
"sort"
|
83
|
+
].join(" | ")
|
84
|
+
|
85
|
+
cmd_out= `#{cmd}`
|
86
|
+
cmd_out.each_line do |ip|
|
87
|
+
ip= ip.strip
|
88
|
+
locations= Geocoder.search(ip)
|
89
|
+
location_rs= locations.first
|
90
|
+
country= parse_nominatim_result(location_rs) || parse_ipinfoio_result(location_rs) || "N/F"
|
91
|
+
puts "#{ip},#{country}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_nominatim_result(result)
|
96
|
+
result&.dig("address", "country")
|
97
|
+
end
|
98
|
+
|
99
|
+
def parse_ipinfoio_result(result)
|
100
|
+
result&.dig("country")
|
101
|
+
end
|
102
|
+
|
103
|
+
desc "Lists from the output of geolocated_ips. Finds the country from each IP in the csv file. Accepts a file path param."
|
104
|
+
task :bannable_ips, [:path, :countries] do |_task, args|
|
105
|
+
file_path= args.path || "tmp/geolocated_ips.csv"
|
106
|
+
countries= args.countries || %w[FR GB IT PT]
|
107
|
+
|
108
|
+
cmd= ["grep -v ES #{file_path}"]
|
109
|
+
countries.each do |country_iso|
|
110
|
+
cmd << "grep -v #{country_iso}"
|
111
|
+
end
|
112
|
+
cmd << "cut -d ',' -f1"
|
113
|
+
cmd << "sort"
|
114
|
+
|
115
|
+
puts `#{cmd.join(" | ")}`
|
14
116
|
end
|
15
117
|
end
|
16
118
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/version"
|
4
|
+
require "decidim/cdtb/tasks"
|
5
|
+
|
6
|
+
namespace :cdtb do
|
7
|
+
namespace :participatory_spaces do
|
8
|
+
desc <<~EODESC
|
9
|
+
Add content blocks to a participatory processes
|
10
|
+
EODESC
|
11
|
+
task :add_content_blocks, [:content_block_names] => :environment do |_task, args|
|
12
|
+
unless Decidim.version >= "0.28"
|
13
|
+
puts "This command is only compatible with Decidim v0.28 or higher"
|
14
|
+
exit(-1)
|
15
|
+
end
|
16
|
+
|
17
|
+
content_block_names = args[:content_block_names].split
|
18
|
+
|
19
|
+
puts "\n Select participatory spaces you want to add the content blocks: #{content_block_names}"
|
20
|
+
puts "\n 1. Decidim::ParticipatoryProcess"
|
21
|
+
puts "\n 2. Decidim::Assembly"
|
22
|
+
puts "\n 3. All"
|
23
|
+
|
24
|
+
selected_option = $stdin.gets.chomp
|
25
|
+
puts selected_option
|
26
|
+
|
27
|
+
case selected_option
|
28
|
+
when "1"
|
29
|
+
processed_models = [
|
30
|
+
Decidim::ParticipatoryProcess
|
31
|
+
].freeze
|
32
|
+
when "2"
|
33
|
+
processed_models = [
|
34
|
+
Decidim::Assembly
|
35
|
+
].freeze
|
36
|
+
when "3"
|
37
|
+
processed_models = [
|
38
|
+
Decidim::ParticipatoryProcess,
|
39
|
+
Decidim::Assembly
|
40
|
+
].freeze
|
41
|
+
else
|
42
|
+
return "Please, select an option"
|
43
|
+
end
|
44
|
+
|
45
|
+
adder = ::Decidim::Cdtb::ParticipatorySpaces::AddContentBlocks.new(processed_models, content_block_names)
|
46
|
+
adder.execute!
|
47
|
+
end
|
48
|
+
|
49
|
+
desc <<~EODESC
|
50
|
+
Move images to content block for the participatory spaces
|
51
|
+
EODESC
|
52
|
+
task move_images_to_content_block: :environment do
|
53
|
+
unless Decidim.version >= "0.28"
|
54
|
+
puts "This command is only compatible with Decidim v0.28 or higher"
|
55
|
+
exit(-1)
|
56
|
+
end
|
57
|
+
|
58
|
+
puts "\n Select participatory spaces you want to move the images"
|
59
|
+
puts "\n 1. Decidim::ParticipatoryProcess"
|
60
|
+
puts "\n 2. Decidim::Assembly"
|
61
|
+
puts "\n 3. All"
|
62
|
+
|
63
|
+
selected_option = $stdin.gets.chomp
|
64
|
+
puts selected_option
|
65
|
+
|
66
|
+
case selected_option
|
67
|
+
when "1"
|
68
|
+
processed_models = [
|
69
|
+
Decidim::ParticipatoryProcess
|
70
|
+
].freeze
|
71
|
+
when "2"
|
72
|
+
processed_models = [
|
73
|
+
Decidim::Assembly
|
74
|
+
].freeze
|
75
|
+
when "3"
|
76
|
+
processed_models = [
|
77
|
+
Decidim::ParticipatoryProcess,
|
78
|
+
Decidim::Assembly
|
79
|
+
].freeze
|
80
|
+
else
|
81
|
+
return "Please, select an option"
|
82
|
+
end
|
83
|
+
|
84
|
+
adder = ::Decidim::Cdtb::ParticipatorySpaces::MoveImagesToContentBlock.new(processed_models)
|
85
|
+
adder.execute!
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decidim-cdtb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oliver Valls
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: decidim
|
@@ -105,7 +105,11 @@ files:
|
|
105
105
|
- lib/decidim/cdtb.rb
|
106
106
|
- lib/decidim/cdtb/engine.rb
|
107
107
|
- lib/decidim/cdtb/fixes/nickname_fixer.rb
|
108
|
+
- lib/decidim/cdtb/fixes/you_tube_embeds_fixer.rb
|
108
109
|
- lib/decidim/cdtb/multitenants/org_by_host_like.rb
|
110
|
+
- lib/decidim/cdtb/participatory_spaces/add_content_blocks.rb
|
111
|
+
- lib/decidim/cdtb/participatory_spaces/manages_content_blocks.rb
|
112
|
+
- lib/decidim/cdtb/participatory_spaces/move_images_to_content_block.rb
|
109
113
|
- lib/decidim/cdtb/spam/user_spam_detector.rb
|
110
114
|
- lib/decidim/cdtb/storage/local_sharding.rb
|
111
115
|
- lib/decidim/cdtb/storage/set_local_on_blobs.rb
|
@@ -122,8 +126,10 @@ files:
|
|
122
126
|
- lib/generators/cdtb/validate_migrations_ci_generator.rb
|
123
127
|
- lib/tasks/anonymize.rake
|
124
128
|
- lib/tasks/census.rake
|
129
|
+
- lib/tasks/fix_youtube_embeds.rake
|
125
130
|
- lib/tasks/logs.rake
|
126
131
|
- lib/tasks/multitenants.rake
|
132
|
+
- lib/tasks/participatory_spaces.rake
|
127
133
|
- lib/tasks/spam.rake
|
128
134
|
- lib/tasks/storage.rake
|
129
135
|
- lib/tasks/upgrade.rake
|