decidim 0.23.5 → 0.24.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of decidim might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Rakefile +1 -0
- data/docs/README.adoc +74 -0
- data/docs/antora.yml +7 -0
- data/docs/modules/configure/pages/environment_variables.adoc +69 -0
- data/docs/modules/configure/pages/index.adoc +16 -0
- data/docs/modules/configure/pages/initializer.adoc +376 -0
- data/docs/modules/customize/assets/images/header-snippet.png +0 -0
- data/docs/modules/customize/assets/images/menu.png +0 -0
- data/docs/modules/customize/assets/images/organization-colors.png +0 -0
- data/docs/modules/customize/pages/authorizations.adoc +22 -0
- data/docs/{customization/code.md → modules/customize/pages/code.adoc} +12 -9
- data/docs/{customization/gemfile.md → modules/customize/pages/gemfile.adoc} +5 -4
- data/docs/modules/customize/pages/images.adoc +7 -0
- data/docs/modules/customize/pages/javascript.adoc +59 -0
- data/docs/modules/customize/pages/menu.adoc +25 -0
- data/docs/modules/customize/pages/oauth.adoc +33 -0
- data/docs/modules/customize/pages/styles.adoc +64 -0
- data/docs/modules/customize/pages/texts.adoc +30 -0
- data/docs/modules/customize/pages/users_registration_mode.adoc +17 -0
- data/docs/{customization/views.md → modules/customize/pages/views.adoc} +13 -13
- data/docs/modules/develop/assets/images/barcelona.png +0 -0
- data/docs/modules/develop/assets/images/helsinki.png +0 -0
- data/docs/modules/develop/assets/images/indices.png +0 -0
- data/docs/{advanced/api.md → modules/develop/pages/api.adoc} +2 -2
- data/docs/{advanced/authorship.md → modules/develop/pages/authorable.adoc} +5 -5
- data/docs/modules/develop/pages/c4_component.adoc +91 -0
- data/docs/modules/develop/pages/c4_container.adoc +42 -0
- data/docs/modules/develop/pages/c4_context.adoc +35 -0
- data/docs/{advanced/components.md → modules/develop/pages/components.adoc} +47 -10
- data/docs/{advanced/content_blocks.md → modules/develop/pages/content_blocks.adoc} +16 -13
- data/docs/{advanced/content_processors.md → modules/develop/pages/content_processors.adoc} +25 -19
- data/docs/modules/develop/pages/data-picker.adoc +85 -0
- data/docs/modules/develop/pages/deploy.adoc +15 -0
- data/docs/modules/develop/pages/docker.adoc +12 -0
- data/docs/{advanced/embeddable.md → modules/develop/pages/embeddable.adoc} +6 -6
- data/docs/{advanced/endorsable.md → modules/develop/pages/endorsable.adoc} +31 -25
- data/docs/{advanced/fixing_locales.md → modules/develop/pages/fixing_locales.adoc} +36 -23
- data/docs/{advanced/followers.md → modules/develop/pages/followable.adoc} +9 -8
- data/docs/modules/develop/pages/guide.adoc +16 -0
- data/docs/modules/develop/pages/guide_architecture.adoc +17 -0
- data/docs/modules/develop/pages/guide_changelog.adoc +8 -0
- data/docs/modules/develop/pages/guide_commands.adoc +86 -0
- data/docs/modules/develop/pages/guide_development_app.adoc +44 -0
- data/docs/modules/develop/pages/guide_development_with_custom_seed_data.adoc +31 -0
- data/docs/modules/develop/pages/guide_development_with_localhost_ssl.adoc +63 -0
- data/docs/modules/develop/pages/guide_example_apps.adoc +59 -0
- data/docs/modules/develop/pages/guide_git_conventions.adoc +75 -0
- data/docs/modules/develop/pages/guide_github_projects.adoc +42 -0
- data/docs/modules/develop/pages/guide_semver.adoc +7 -0
- data/docs/{advanced/how_to_fix_metrics.md → modules/develop/pages/how_to_fix_metrics.adoc} +76 -59
- data/docs/modules/develop/pages/machine_translations.adoc +42 -0
- data/docs/modules/develop/pages/managing_translations_i18n.adoc +24 -0
- data/docs/modules/develop/pages/maps.adoc +499 -0
- data/docs/modules/develop/pages/metrics.adoc +119 -0
- data/docs/{advanced/modules.md → modules/develop/pages/modules.adoc} +16 -6
- data/docs/{advanced/newsletter_templates.md → modules/develop/pages/newsletter_templates.adoc} +12 -10
- data/docs/{advanced/notifications.md → modules/develop/pages/notifications.adoc} +40 -38
- data/docs/{advanced/open-data.md → modules/develop/pages/open-data.adoc} +4 -3
- data/docs/modules/develop/pages/permissions.adoc +92 -0
- data/docs/{advanced/profiling.md → modules/develop/pages/profiling.adoc} +15 -12
- data/docs/modules/develop/pages/releases.adoc +148 -0
- data/docs/modules/develop/pages/reportable.adoc +31 -0
- data/docs/modules/develop/pages/security.adoc +33 -0
- data/docs/{advanced/share_tokens.md → modules/develop/pages/share_tokens.adoc} +18 -14
- data/docs/{advanced/templates.md → modules/develop/pages/templates.adoc} +14 -12
- data/docs/{advanced/testing.md → modules/develop/pages/testing.adoc} +21 -20
- data/docs/{advanced/activity_log.md → modules/develop/pages/traceable.adoc} +31 -26
- data/docs/modules/develop/pages/turbolinks.adoc +7 -0
- data/docs/{advanced/view_hooks.md → modules/develop/pages/view_hooks.adoc} +29 -23
- data/docs/modules/develop/pages/view_models_aka_cells.adoc +105 -0
- data/docs/modules/install/pages/checklist.adoc +39 -0
- data/docs/modules/install/pages/index.adoc +148 -0
- data/docs/{manual-installation.md → modules/install/pages/manual.adoc} +54 -42
- data/docs/modules/install/pages/update.adoc +95 -0
- data/docs/{services/activejob.md → modules/services/pages/activejob.adoc} +3 -3
- data/docs/modules/services/pages/elections_bulletin_board.adoc +52 -0
- data/docs/{services/etherpad.md → modules/services/pages/etherpad.adoc} +15 -12
- data/docs/modules/services/pages/maps.adoc +311 -0
- data/docs/modules/services/pages/smtp.adoc +10 -0
- data/docs/modules/services/pages/social_providers.adoc +122 -0
- data/lib/decidim/gem_manager.rb +5 -5
- data/lib/decidim/version.rb +1 -1
- metadata +135 -98
- data/README.md +0 -157
- data/docs/advanced/add_authorizable_action.md +0 -63
- data/docs/advanced/adding_fixtures_aka_dummy_content.md +0 -9
- data/docs/advanced/data-picker.md +0 -83
- data/docs/advanced/deploy.md +0 -9
- data/docs/advanced/how_to_create_a_module.md +0 -9
- data/docs/advanced/machine_translation_service.md +0 -12
- data/docs/advanced/managing_translations_i18n.md +0 -24
- data/docs/advanced/metrics.md +0 -114
- data/docs/advanced/permissions.md +0 -23
- data/docs/advanced/releases.md +0 -114
- data/docs/advanced/tradeoffs.md +0 -14
- data/docs/advanced/view_models_aka_cells.md +0 -99
- data/docs/checklist.md +0 -55
- data/docs/customization/authorizations.md +0 -5
- data/docs/customization/images.md +0 -7
- data/docs/customization/javascript.md +0 -9
- data/docs/customization/machine_translations.md +0 -30
- data/docs/customization/maps.md +0 -610
- data/docs/customization/oauth.md +0 -50
- data/docs/customization/styles.md +0 -11
- data/docs/customization/texts.md +0 -27
- data/docs/customization/users_registration_mode.md +0 -17
- data/docs/development_guide.md +0 -166
- data/docs/getting_started.md +0 -191
- data/docs/possible_flows_for_proposal.png +0 -0
- data/docs/services/analytics.md +0 -23
- data/docs/services/elections_bulletin_board.md +0 -38
- data/docs/services/maps.md +0 -362
- data/docs/services/social_providers.md +0 -98
@@ -0,0 +1,119 @@
|
|
1
|
+
= Metrics
|
2
|
+
|
3
|
+
Metrics calculations must be executed everyday. Some `rake task` have been added to perform it.
|
4
|
+
|
5
|
+
* To execute all metrics at once. Related to previous date from _today_
|
6
|
+
+
|
7
|
+
[source,ruby]
|
8
|
+
----
|
9
|
+
bundle exec rake decidim:metrics:all
|
10
|
+
----
|
11
|
+
|
12
|
+
* To execute an specific metric. Related to previous date from _today_
|
13
|
+
+
|
14
|
+
[source,ruby]
|
15
|
+
----
|
16
|
+
bundle exec rake decidim:metrics:one["<metric name>"]
|
17
|
+
----
|
18
|
+
|
19
|
+
* To execute metrics for a given date (all or an specific one)
|
20
|
+
+
|
21
|
+
[source,ruby]
|
22
|
+
----
|
23
|
+
bundle exec rake decidim:metrics:all["YYYY-MM-DD"]
|
24
|
+
bundle exec rake decidim:metrics:one["<metric name>","YYYY-MM-DD"]
|
25
|
+
----
|
26
|
+
|
27
|
+
* It is possible to rebuild one or all metrics since some specific day. This is useful in case current metrics are no generated or corrupt. *Depending on the size of the database this can take a long time!*. The command will execute the same calculations as the commands above for *each* day between _today_ and the date specified.
|
28
|
+
* To rebuild metrics since a given date (all or an specific one)
|
29
|
+
+
|
30
|
+
[source,ruby]
|
31
|
+
----
|
32
|
+
bundle exec rake decidim:metrics:rebuild["YYYY-MM-DD"]
|
33
|
+
bundle exec rake decidim:metrics:rebuild["<metric name>","YYYY-MM-DD"]
|
34
|
+
----
|
35
|
+
|
36
|
+
== Available metrics
|
37
|
+
|
38
|
+
* Use the command `decidim:metrics:list` to list all available metrics using the console:
|
39
|
+
|
40
|
+
[source,ruby]
|
41
|
+
----
|
42
|
+
bundle exec rake decidim:metrics:list
|
43
|
+
----
|
44
|
+
|
45
|
+
Currently, available metrics are:
|
46
|
+
|
47
|
+
* *users*, created `Users`
|
48
|
+
* *proposals*, published, not withdrawn and not _hidden_ `Proposals`
|
49
|
+
* *accepted_proposals*, accepted `Proposals`
|
50
|
+
* *supports*, supports given to `Proposals`
|
51
|
+
* *assemblies*, published `Assemblies`
|
52
|
+
* *participatory_processes*, published `ParticipatoryProcesses`
|
53
|
+
* *results*, `Results` in `Accountability`
|
54
|
+
* *comments*, `Comments` generated by users, related to public elements and not _hidden_
|
55
|
+
* *meetings*, public `Meetings`
|
56
|
+
|
57
|
+
Only available for `ParticipatorySpaces` (restricted to `ParticipatoryProcesses`)
|
58
|
+
|
59
|
+
* *participants*, unique users who make at least one of the following actions:
|
60
|
+
** Answer a survey
|
61
|
+
** Create a debate
|
62
|
+
** Create a proposal
|
63
|
+
** Endorse a proposal
|
64
|
+
** Leave a comment
|
65
|
+
** Support a proposal
|
66
|
+
** Vote a participatory budgeting project
|
67
|
+
* *followers*, unique users who follow any participatory element in a `ParticipatorySpace`
|
68
|
+
* *endorsements*, number of `Endorsements` in `Proposals`, within a `ParticipatorySpace`
|
69
|
+
* *debates*, number of `Debates` within a `ParticipatorySpace`
|
70
|
+
* *survey_answers*, number of answered `Surveys` by users within a `ParticipatorySpace`
|
71
|
+
|
72
|
+
== Configuration
|
73
|
+
|
74
|
+
* A *crontab* line must be added to your server to maintain them updated daily. You could use https://github.com/javan/whenever[Whenever] to manage it directly from the APP. You probably want to schedule a `bundle exec rake decidim:metrics:all` every night.
|
75
|
+
* An *ActiveJob* queue, like https://github.com/mperham/sidekiq[Sidekiq] or https://github.com/collectiveidea/delayed_job/[DelayedJob]
|
76
|
+
|
77
|
+
== Persistence
|
78
|
+
|
79
|
+
The metrics module percomutes calculations and persists them into
|
80
|
+
`decidim_metrics` database table. So this module only uses one single table to
|
81
|
+
persist metrics from all times and types.
|
82
|
+
|
83
|
+
The `decidim_metrics` table has the following fields:
|
84
|
+
|
85
|
+
* `day`: the day for which the metric has been computed.
|
86
|
+
* `metric_type`: the type of the metric. One of: users, proposals, accepted_proposals, supports, assemblies.
|
87
|
+
* `cumulative`: quantity accumulated to day `"day`".
|
88
|
+
* `quantity`: quantity for the current day, `"day`".
|
89
|
+
* `decidim_organization_id`: the FK to the organization to which this Metric belongs to.
|
90
|
+
* `participatory_space_type` + `participatory_space_id`: the FK to the participatory space to which this Metric belongs to, if any.
|
91
|
+
* `related_object_type` + `related_object_id`: the FK to the object to which this Metric belongs to, if any.
|
92
|
+
* `decidim_category_id`: the FK to the category for this Metric, if any.
|
93
|
+
|
94
|
+
Relations around `decidim_metrics` table:
|
95
|
+
|
96
|
+
[source,ascii]
|
97
|
+
----
|
98
|
+
+------------------------+
|
99
|
+
+--------------+ | ParticipatoryProcesses |
|
100
|
+
| Organization | +----+------------------------+
|
101
|
+
+------+-------+ |
|
102
|
+
| +--------------------+ | +------------+
|
103
|
+
| | | +----+ Assemblies |
|
104
|
+
| +----->+ ParticipatorySpace +<----+ +------------+
|
105
|
+
| | | | | +-------------+
|
106
|
+
| | +--------------------+ +----+ Initiatives |
|
107
|
+
| | | +-------------+
|
108
|
+
| | |
|
109
|
+
| | | +---------------+
|
110
|
+
+-----+-------+---+ +----+ Consultations |
|
111
|
+
| | +---------------+
|
112
|
+
| decidim_metrics |
|
113
|
+
| |
|
114
|
+
+--------+--------+ +----------------+
|
115
|
+
| | related_object |
|
116
|
+
+--------------->+ |
|
117
|
+
| [polymorphic] |
|
118
|
+
+----------------+
|
119
|
+
----
|
@@ -1,15 +1,26 @@
|
|
1
|
-
|
1
|
+
= Modules
|
2
2
|
|
3
3
|
Modules are subapplications that are run as application plugins.
|
4
4
|
They're used to define pieces of functionality that are pluggable to Decidim.
|
5
5
|
|
6
6
|
Decidim's modules are no more than Ruby on Rails engines that should be required in the application's `Gemfile`.
|
7
7
|
|
8
|
-
|
8
|
+
You can see some of our more popular modules at https://decidim.org/modules[Decidim's Modules].
|
9
|
+
|
10
|
+
== Types
|
11
|
+
|
12
|
+
You can have multiple modules types:
|
13
|
+
|
14
|
+
* For Spaces
|
15
|
+
* For xref:develop:components.adoc[Components]
|
16
|
+
* For Verifications
|
17
|
+
|
18
|
+
== Example
|
9
19
|
|
10
20
|
A typical engine looks like the following:
|
11
21
|
|
12
|
-
|
22
|
+
[source,ruby]
|
23
|
+
----
|
13
24
|
module Decidim
|
14
25
|
module Verifications
|
15
26
|
module MyVerifier
|
@@ -39,14 +50,13 @@ module Decidim
|
|
39
50
|
end
|
40
51
|
end
|
41
52
|
end
|
42
|
-
|
53
|
+
----
|
43
54
|
|
44
55
|
It is a standard Ruby on Rails engine.
|
45
56
|
|
46
|
-
|
57
|
+
== Decidim gotchas with engines
|
47
58
|
|
48
59
|
If you have an external module that defines rake tasks and more than one
|
49
60
|
engine, you probably want to add `paths["lib/tasks"]= nil` to all engines but
|
50
61
|
the main one, otherwise the tasks you define are probably running multiple
|
51
62
|
times unintentionally. Check #3892 for more details.
|
52
|
-
|
data/docs/{advanced/newsletter_templates.md → modules/develop/pages/newsletter_templates.adoc}
RENAMED
@@ -1,14 +1,15 @@
|
|
1
|
-
|
1
|
+
= Newsletter templates
|
2
2
|
|
3
3
|
The newsletter templates allow the user to select a template amongst a set of of them, and use it as base to send newsletters. This allow for more customization on newsletter, tematic newsletters, etc.
|
4
4
|
|
5
|
-
Code-wise, they use the content blocks system internally, so
|
5
|
+
Code-wise, they use the content blocks system internally, so https://github.com/decidim/decidim/blob/develop/docs/advanced/content_blocks.md[check the docs] for that section first.
|
6
6
|
|
7
|
-
|
7
|
+
== Adding a new template
|
8
8
|
|
9
9
|
You'll first need to register the template as a content block, but specifying `:newsletter_template` as its scope:
|
10
10
|
|
11
|
-
|
11
|
+
[source,ruby]
|
12
|
+
----
|
12
13
|
Decidim.content_blocks.register(:newsletter_template, :my_template) do |content_block|
|
13
14
|
content_block.cell "decidim/newsletter_templates/my_template"
|
14
15
|
content_block.settings_form_cell = "decidim/newsletter_templates/my_template_settings_form"
|
@@ -31,7 +32,7 @@ Decidim.content_blocks.register(:newsletter_template, :my_template) do |content_
|
|
31
32
|
)
|
32
33
|
end
|
33
34
|
end
|
34
|
-
|
35
|
+
----
|
35
36
|
|
36
37
|
You'll need to add this into an initializer. Note that if you're adding this from a module, then you need to add it from the `engine.rb` file (check the docs for content blocks for more info).
|
37
38
|
|
@@ -43,15 +44,16 @@ Then we define the cell that will be used to render the form in the admin sectio
|
|
43
44
|
|
44
45
|
In the third line inside the block we define the I18n path to the public name of the template. This name will serve as identifier for the users who write the newsletters, so be sure to make it descriptive.
|
45
46
|
|
46
|
-
After that we define the images this newsletter supports. We give it a unique name, the class name of the uploader we'll use (the example one is the default one, but you might want to customize this value) and a way to preview this image. This preview image will only be used in the "Preview" page of the template, it's not a fallback. If you want a fallback, please implement it through a custom uploader (see
|
47
|
+
After that we define the images this newsletter supports. We give it a unique name, the class name of the uploader we'll use (the example one is the default one, but you might want to customize this value) and a way to preview this image. This preview image will only be used in the "Preview" page of the template, it's not a fallback. If you want a fallback, please implement it through a custom uploader (see ``carrierwave``'s docs for that). There's no limit of the amount of images you add.
|
47
48
|
|
48
49
|
Finally, we define the attributes for the newsletter. In this case we define a body attribute, which is a translatable text. Whether this text require an editor or not will be defined by the settings cell. We also have a way to preview that attribute. There's no limit on the number of attributes you define.
|
49
50
|
|
50
|
-
|
51
|
+
== Interpolating the recipient name
|
51
52
|
|
52
|
-
Decidim accepts
|
53
|
+
Decidim accepts `+%{name}+` as a placeholder for the recipient name. If you want your template to use it, you'll need to call `parse_interpolations` in your public cell:
|
53
54
|
|
54
|
-
|
55
|
+
[source,ruby]
|
56
|
+
----
|
55
57
|
class Decidim::NewsletterTemplates::MyTemplate < Decidim::ViewModel
|
56
58
|
include Decidim::NewslettersHelper
|
57
59
|
|
@@ -59,6 +61,6 @@ class Decidim::NewsletterTemplates::MyTemplate < Decidim::ViewModel
|
|
59
61
|
parse_interpolations(uninterpolated_body, recipient_user, newsletter.id)
|
60
62
|
end
|
61
63
|
end
|
62
|
-
|
64
|
+
----
|
63
65
|
|
64
66
|
The newsletter subject is automatically interpolated.
|
@@ -1,19 +1,20 @@
|
|
1
|
-
|
1
|
+
= Notifications
|
2
2
|
|
3
3
|
In Decidim, notifications may mean two things:
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
* he concept of notifying an event to a user. This is the wider use of "notification".
|
6
|
+
* the notification's participant space, which lists the ``Decidim::Notification``s she has received.
|
7
7
|
|
8
8
|
So, in the wider sense, notifications are messages that are sent to the users, admins or participants, when something interesting occurs in the platform.
|
9
9
|
|
10
10
|
Each notification is sent via two communication channels: email and internal notifications.
|
11
11
|
|
12
|
-
|
12
|
+
== A Decidim Event
|
13
13
|
|
14
14
|
Technically, a Decidim event is nothing but an `ActiveSupport::Notification` with a payload of the form
|
15
15
|
|
16
|
-
|
16
|
+
[source,ruby]
|
17
|
+
----
|
17
18
|
ActiveSupport::Notifications.publish(
|
18
19
|
event,
|
19
20
|
event_class: event_class.name,
|
@@ -22,11 +23,12 @@ ActiveSupport::Notifications.publish(
|
|
22
23
|
followers: followers.uniq.compact,
|
23
24
|
extra: extra
|
24
25
|
)
|
25
|
-
|
26
|
+
----
|
26
27
|
|
27
28
|
To publish an event to send a notification, Decidim's `EventManager` should be used:
|
28
29
|
|
29
|
-
|
30
|
+
[source,ruby]
|
31
|
+
----
|
30
32
|
# Note the convention between the `event` key, and the `event_class` that will be used later to wrap the payload and be used as the email or notification model.
|
31
33
|
data = {
|
32
34
|
event: "decidim.events.comments.comment_created",
|
@@ -40,75 +42,75 @@ data = {
|
|
40
42
|
}
|
41
43
|
|
42
44
|
Decidim::EventsManager.publish(data)
|
43
|
-
|
45
|
+
----
|
44
46
|
|
45
47
|
Both, `EmailNotificationGenerator` and `NotificationGenerator` are use the same arguments:
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
* *event*: A String with the name of the event.
|
50
|
+
* *event_class*: A class that wraps the event.
|
51
|
+
* *resource*: an instance of a class implementing the `Decidim::Resource` concern.
|
52
|
+
* *followers*: a collection of Users that receive the notification because they're following it.
|
53
|
+
* *affected_users*: a collection of Users that receive the notification because they're affected by it.
|
54
|
+
* *force_send*: boolean indicating if EventPublisherJob should skip the `notifiable?` check it performs before notifying.
|
55
|
+
* *extra*: a Hash with extra information to be included in the notification.
|
54
56
|
|
55
57
|
Again, both generators will check for each user
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
+
* in the _followers_ array, if she has the `notification_types` set to "all" or "followed-only".
|
60
|
+
* in the _affected_users_ array, if she has the `notification_types` set to "all" or "own-only".
|
59
61
|
|
60
62
|
Event names must start with "decidim.events." (the `event` data key). This way `Decidim::EventPublisherJob` will automatically process them. Otherwise no artifact in Decidim will process them, and will be the developer's responsibility to subscribe to them and process.
|
61
63
|
|
62
64
|
Sometimes, when something that must be notified to users happen, a service is defined to manage the logic involved to decide which events should be published. See for example `Decidim::Comments::NewCommentNotificationCreator`.
|
63
65
|
|
64
|
-
Please refer to
|
66
|
+
Please refer to https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html[Ruby on Rails Notifications documentation] if you need to hack the Decidim's events system.
|
65
67
|
|
66
|
-
|
68
|
+
== How Decidim's `EventPublisherJob` processes the events?
|
67
69
|
|
68
|
-
The `EventPublisherJob` in Decidim's core engine subscribes to all notifications matching the regular expression
|
70
|
+
The `EventPublisherJob` in Decidim's core engine subscribes to all notifications matching the regular expression `+/^decidim\.events\./+`. This is, starting with "decidim.events.". It will then be invoked when an imaginary event named "decidim.events.harmonica_blues" is published.
|
69
71
|
|
70
72
|
When invoked it simply performs some validations and enqueue an `EmailNotificationGeneratorJob` and a `NotificationGeneratorJob`.
|
71
73
|
|
72
74
|
The validations it performs check if the resource, the component, or the participatory space are published (when the concept applies to the artifact).
|
73
75
|
|
74
|
-
|
76
|
+
== The *Event class
|
75
77
|
|
76
78
|
Generates the email and notification messages from the information related with the notification.
|
77
79
|
|
78
80
|
Event classes are subclasses of `Decidim::Events::SimpleEvent`.
|
79
81
|
A subset of the payload of the notification is passed to the event class's constructor:
|
80
82
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
* The `resource`
|
84
|
+
* The `event` name
|
85
|
+
* The notified user, either from the `followers` or from the `affected_users` arrays
|
86
|
+
* The `extra` hash, with content specific for the given SimpleEvent subclass
|
87
|
+
* The user_role, either :follower or :affected_user
|
86
88
|
|
87
89
|
With the previous information the event class is able to generate the following contents.
|
88
90
|
|
89
91
|
Developers will be able to customize those messages by adding translations to the `config/locales/en.yml` file of the corresponding module.
|
90
92
|
The keys to be used will have the translation scope corresponding to the event name ("decidim.events.comments.comment_by_followed_user" for example) and the key will be the content to override (email_subject, email_intro, etc.)
|
91
93
|
|
92
|
-
|
94
|
+
=== Email contents
|
93
95
|
|
94
96
|
The following are the parts of the notification email:
|
95
97
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
* _email_subject_, to be customized
|
99
|
+
* email_greeting, with a good default, usually there's no need to cusomize it
|
100
|
+
* _email_intro_, to be customized
|
101
|
+
* _resource_text_ (optional), rendered `html_safe` if present
|
102
|
+
* _resource_url_, a link to the involved resource if resource_url and resource_title are present
|
103
|
+
* _email_outro_
|
102
104
|
|
103
105
|
All contents except the `email_greeting` use to require customization on each notification.
|
104
106
|
|
105
|
-
|
107
|
+
=== Notification contents
|
106
108
|
|
107
109
|
Only the `notification_title` is generated in the event class. The rest of the contents are produced by the templates from the `resource` and the `notification` objects.
|
108
110
|
|
109
|
-
|
111
|
+
== Testing notifications
|
110
112
|
|
111
|
-
|
112
|
-
|
113
|
+
* Test that the event has been published (usually a command test)
|
114
|
+
* Test the event returns the expected contents for the email and the notification.
|
113
115
|
|
114
|
-
Developers should we aware when adding URLs in the email's content, be sure to use absolute URLs and not relative paths.
|
116
|
+
Developers should we aware when adding URLs in the email's content, be sure to use absolute URLs and not relative paths.
|
@@ -1,9 +1,10 @@
|
|
1
|
-
|
1
|
+
= Open Data
|
2
2
|
|
3
3
|
In order for users to be able to download Open Data files they have to be generated previously, since generating them on the fly would take too much time and resources.
|
4
4
|
|
5
5
|
You should schedule this command to be run everyday, using `cron` or `whenever` or your favorite tool:
|
6
6
|
|
7
|
-
|
7
|
+
[source,ruby]
|
8
|
+
----
|
8
9
|
bundle exec rake decidim:open_data:export
|
9
|
-
|
10
|
+
----
|
@@ -0,0 +1,92 @@
|
|
1
|
+
= Permissions
|
2
|
+
|
3
|
+
Since Decidim has multiple roles, we needed a permissions system to discover what actions can a user perform, given their roles. The basis of the current permissions system were added on https://github.com/decidim/decidim/pull/3029[#3029], so be sure to check that PR (and the related ones) to read the discussion and the motivations behind the change.
|
4
|
+
|
5
|
+
== Overview
|
6
|
+
|
7
|
+
When checking for permission to perform an action, we check this chain:
|
8
|
+
|
9
|
+
. The component permissions
|
10
|
+
. The participatory space permissions
|
11
|
+
. The core permissions
|
12
|
+
|
13
|
+
This way we're going from more specific to more general.
|
14
|
+
|
15
|
+
== Explanation
|
16
|
+
|
17
|
+
We wrap the permission and its context in a `PermissionsAction` object. It also holds the state of the permission (whether it's been allowed or not).
|
18
|
+
|
19
|
+
Each component and space must define a `Permissions` class, inheriting from `Decidim::DefaultPermissions`. The `Permissions` class must define a `permissions` instance method. this class will receive the permission action, and the `permissions` method must return the permission action. The `Permissions` class can set the action as allowed or disallowed.
|
20
|
+
|
21
|
+
There's a small limitation in the permission action state machine: once it's been disallowed it can't be reallowed. This is to avoid mischievous modules modifying permissions.
|
22
|
+
|
23
|
+
Permission actions have a scope. It's usually either `:public` or `:admin`, and the `Permissions` class usually handles the `:public` scope, while it delegates the `:admin` one to another specialized class.
|
24
|
+
|
25
|
+
== Add a new Action
|
26
|
+
|
27
|
+
=== Proposals example
|
28
|
+
|
29
|
+
We're going to reproduce the steps to add an action (endorse) for a proposal step by step.
|
30
|
+
|
31
|
+
==== Configuring a new 'endorse' action
|
32
|
+
|
33
|
+
. Edit decidim-proposals/lib/decidim/proposals/component.rb
|
34
|
+
. Add the new 'endorse' action into the `component.actions` array and save the file:
|
35
|
+
|
36
|
+
[source,ruby]
|
37
|
+
----
|
38
|
+
component.actions = %w(endorse vote create)
|
39
|
+
----
|
40
|
+
|
41
|
+
. Translate the action for the corresponding key: `en.decidim.components.proposals.actions.endorse = Endorse`
|
42
|
+
. Edit `app/permissions/decidim/proposals/permissions.rb` and add the corresponding permission, using `authorized?` method to run the `authorization handler` logic.
|
43
|
+
. In the endorse proposals controller, enforce that the user has permissions to perform the `endorse` action before actually doing it, using the `enforce_permission_to` method:
|
44
|
+
|
45
|
+
[source,ruby]
|
46
|
+
----
|
47
|
+
enforce_permission_to :endorse, :proposal, proposal: proposal
|
48
|
+
----
|
49
|
+
|
50
|
+
. In the proposals templates, change regular links and buttons to endorse a proposal with calls to `action_authorized_link_to` and `action_authorized_button_to` helpers.
|
51
|
+
. Restart the server to pick up the changes.
|
52
|
+
|
53
|
+
==== Using the new 'endorse' action
|
54
|
+
|
55
|
+
. Now an admin user should be able to go to a participatory space with a `proposals` component panel and click on its `Permissions` link (the icon with a key). There, an `authorization handler` can be set for the `endorse` action.
|
56
|
+
. Go to a Proposal detail in the front-end
|
57
|
+
. Try to endorse the current proposal
|
58
|
+
** If the user has not granted the selected permission, the 'endorse' button should block the action and allow the user to grant the permission with the selected `authorization handler` logic.
|
59
|
+
** If the logger user has already granted the selected permission, the user should be able to perform the endorsement.
|
60
|
+
|
61
|
+
==== Allow to configure the related permissions at resource level
|
62
|
+
|
63
|
+
Permissions settings could also be set for an specific resources appart from the full component. Actions should also be related to the resource.
|
64
|
+
|
65
|
+
. Edit decidim-proposals/lib/decidim/proposals/component.rb
|
66
|
+
. Add the 'endorse' action into the `resource.actions` array for the `proposal` resource definition and save the file:
|
67
|
+
|
68
|
+
[source,ruby]
|
69
|
+
----
|
70
|
+
resource.actions = %w(endorse vote)
|
71
|
+
----
|
72
|
+
|
73
|
+
. Only if this is the first resource action added, edit the proposals admin templates and use the `resource_permissions_link` helper to link the resource permissions page from each resource in the listing.
|
74
|
+
|
75
|
+
[source,erb]
|
76
|
+
----
|
77
|
+
<%= resource_permissions_link(proposal) %>
|
78
|
+
----
|
79
|
+
|
80
|
+
. In the proposals permission class, pass an extra `resource` named parameter to the calls to the `authorized?` method.
|
81
|
+
|
82
|
+
[source,ruby]
|
83
|
+
----
|
84
|
+
authorized?(:endorse, resource: proposal)
|
85
|
+
----
|
86
|
+
|
87
|
+
. In the proposals templates, also add the extra `resource` parameter to the `action_authorized_link_to` and `action_authorized_button_to` helpers.
|
88
|
+
. Restart the server to pick up the changes.
|
89
|
+
|
90
|
+
==== Using permissions at resource level
|
91
|
+
|
92
|
+
. Now an admin user should be able to go to a participatory space with a `proposals` component panel and click on its `Permissions` link (the icon with a key). There, an `authorization handler` can be set for the `endorse` action.
|