decidim-voca 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +661 -0
- data/README.md +153 -0
- data/Rakefile +86 -0
- data/app/assets/config/voca_manifest.js +0 -0
- data/app/assets/images/decidim/voca/icon.svg +1 -0
- data/app/commands/decidim/voca/organization/command.rb +16 -0
- data/app/commands/decidim/voca/organization/organization_command.rb +17 -0
- data/app/commands/decidim/voca/organization/update_color_command.rb +35 -0
- data/app/commands/decidim/voca/organization/update_environment_command.rb +23 -0
- data/app/commands/decidim/voca/organization/update_feature_command.rb +32 -0
- data/app/commands/decidim/voca/organization/update_file_upload_command.rb +45 -0
- data/app/commands/decidim/voca/organization/update_locale_command.rb +53 -0
- data/app/commands/decidim/voca/organization/update_naming_command.rb +30 -0
- data/app/commands/decidim/voca/organization/update_permission_command.rb +31 -0
- data/app/commands/decidim/voca/organization/update_smtp_command.rb +51 -0
- data/app/controllers/decidim/voca/admin/application_controller.rb +15 -0
- data/app/controllers/decidim/voca/application_controller.rb +13 -0
- data/app/jobs/decidim/voca/command_job.rb +36 -0
- data/app/jobs/decidim/voca/webhook_notifier_job.rb +57 -0
- data/app/rpc/decidim/voca/decidim_service_controller.rb +68 -0
- data/app/rpc/decidim/voca/rpc/enum_casting.rb +58 -0
- data/app/rpc/decidim/voca/rpc/get_settings.rb +144 -0
- data/app/rpc/decidim/voca/rpc/health.rb +18 -0
- data/app/rpc/decidim/voca/rpc/seed_admin.rb +75 -0
- data/app/rpc/decidim/voca/rpc/set_settings.rb +56 -0
- data/app/rpc/decidim/voca/rpc/setup_db.rb +38 -0
- data/config/environments/development.rb +6 -0
- data/config/i18n-tasks.yml +9 -0
- data/config/locales/en.yml +6 -0
- data/config/spring.rb +2 -0
- data/lib/decidim/voca/admin.rb +10 -0
- data/lib/decidim/voca/admin_engine.rb +27 -0
- data/lib/decidim/voca/backup/app_backup.rb +169 -0
- data/lib/decidim/voca/backup/app_decrypt_backup_file.rb +50 -0
- data/lib/decidim/voca/backup/app_encrypt_backup_file.rb +49 -0
- data/lib/decidim/voca/backup/app_upload_to_s3.rb +49 -0
- data/lib/decidim/voca/engine.rb +31 -0
- data/lib/decidim/voca/middleware/dynamic_config_middleware.rb +42 -0
- data/lib/decidim/voca/rpc/decidim_pb.rb +134 -0
- data/lib/decidim/voca/rpc/decidim_services_pb.rb +30 -0
- data/lib/decidim/voca/test/factories.rb +9 -0
- data/lib/decidim/voca/updater.rb +50 -0
- data/lib/decidim/voca/version.rb +13 -0
- data/lib/decidim/voca.rb +22 -0
- data/lib/tasks/voca.rake +88 -0
- metadata +124 -0
data/README.md
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
[![coverage](https://git.octree.ch/decidim/vocacity/tasks/badges/main/coverage.svg?job=coverage-024)](https://github.com/octree-gva/voca-tasks)
|
2
|
+
|
3
|
+
[![release](https://git.octree.ch/decidim/vocacity/tasks/badges/main/release.svg)](https://github.com/octree-gva/voca-tasks)
|
4
|
+
|
5
|
+
# Voca
|
6
|
+
|
7
|
+
Create&Manage Decidim instances on-the-fly, deploy all its ecosystem.
|
8
|
+
Voca focuses on Decidim, released on [APGL-3 open-source license](LICENSE.md) and all the ecosystem around the platform. As _Decidim is not a tool, but a framework for digital democratic participation, many tools gravitates around Decidim._
|
9
|
+
|
10
|
+
# RPC private API for Decidim
|
11
|
+
This gem add internal functionalities to Decidim in order to be managed remotly. We do mostly:
|
12
|
+
|
13
|
+
- Setup [gruf](https://github.com/bigcommerce/gruf) to run a gRPC server
|
14
|
+
- Implement the [decidim.proto](https://raw.githubusercontent.com/octree-gva/voca-system/main/backend/contrib/rpc-protos/decidim/decidim.proto) spec
|
15
|
+
- Add a middleware two dynamically set config data.
|
16
|
+
|
17
|
+
|
18
|
+
## RPC
|
19
|
+
From the .proto file, two files are generated, lib/decidim/voca/rpc/decidim_pb.rb and lib/decidim/voca/rpc/decidim_services_pb.rb. These files describe the skeletton of the input and response we need to comply.
|
20
|
+
|
21
|
+
In the controller `Decidim::Voca::DecidimServiceController`, we bind its method to these services and execute Commands for each methods.
|
22
|
+
For example, a compile method is implemented this way:
|
23
|
+
|
24
|
+
```
|
25
|
+
## Compile assets.
|
26
|
+
def compile_assets
|
27
|
+
`bundle exec rails assets:precompile`
|
28
|
+
::Google::Protobuf::Empty.new
|
29
|
+
end
|
30
|
+
```
|
31
|
+
|
32
|
+
When the code to resolves a RPC methods take more than 2 lines, we do a Command to isolate the code in one class. This is the case for most of the code. You can find the in the [rpc directory](./app/rpc/decidim/voca/rpc).
|
33
|
+
|
34
|
+
### Casting
|
35
|
+
As RPC is a generic way to build APIs, we have to translate constants in appropriate string for the application.
|
36
|
+
|
37
|
+
For example, `SETTINGS_REGISTER_MODE_OPTION::SETTINGS_REGISTER_MODE_REGISTER_AND_LOGIN` is actually just `enable` for the user_register_mode Decidim settings. To do so,
|
38
|
+
we have an utility class `Decidim::Voca::Rpc::EnumCaster`.
|
39
|
+
|
40
|
+
## Middleware
|
41
|
+
We get inspiration on [this article](https://pawelurbanek.com/rails-dynamic-config) to setup a middleware that retrieve config values from redis and then inject it into the code.
|
42
|
+
|
43
|
+
For every query, we do a small step of getting data from our Redis store,
|
44
|
+
and inject the configuration object in Decidim. Like this:
|
45
|
+
```
|
46
|
+
# ./lib/decidim/voca/middleware/dynamic_config_middleware.rb
|
47
|
+
if config_data["currency_unit"].present?
|
48
|
+
Decidim.currency_unit = config_data["currency_unit"]
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
This is particularly usefull as it allows us to include Decidim configurations in our `decidim.proto` file, and set the redis value when needed.
|
53
|
+
|
54
|
+
```
|
55
|
+
# ./app/commands/decidim/voca/organization/update_locale_command.rb
|
56
|
+
global_configuration = locale_settings.select do |key|
|
57
|
+
"#{key}" == "currency_unit" || "#{key}" == "timezone"
|
58
|
+
end.delete_if { |_k, v| v.blank? }
|
59
|
+
unless global_configuration.empty?
|
60
|
+
redis_client = Redis.new(
|
61
|
+
url: ENV.fetch("REDIS_CONFIG_URL", "redis://127.0.0.1:6379/2"),
|
62
|
+
);
|
63
|
+
global_configuration.each do |key, value|
|
64
|
+
# Update the Redis hash values
|
65
|
+
redis_client.hset("config", "#{key}", "#{value}")
|
66
|
+
end
|
67
|
+
# Close the Redis connection
|
68
|
+
redis_client.quit
|
69
|
+
end
|
70
|
+
```
|
71
|
+
## Repositories
|
72
|
+
|
73
|
+
| repo | info | stable version |
|
74
|
+
| -------------------------------------------------------- | --------------------------------------------------------------------------- | -------------- |
|
75
|
+
| [voca-system](https://github.com/octree-gva/voca-system) | Install and manage decidim instances through a Dashboard | v0.1.0 |
|
76
|
+
| [voca-tasks](https://github.com/octree-gva/voca-tasks) | Gem embedded in our Decidim image. Manipulate and manage decidim instances. | v0.1.0 |
|
77
|
+
| [voca-jps](https://github.com/octree-gva/voca-jps) | Jelastic Manifest to deploy Decidim images | v0.1.0 |
|
78
|
+
| [voca-docker](https://github.com/octree-gva/voca-docker) | Build Decidim docker images for Voca | v0.1.0 |
|
79
|
+
| [voca-protos](https://github.com/octree-gva/voca-protos) | RPC prototypes for voca | v0.1.0 |
|
80
|
+
|
81
|
+
# Decidim::Voca
|
82
|
+
|
83
|
+
This Gem allows configuring a Decidim instance with gRPC. This is a domain-specific gem, which is useful only if you host your own Voca system.
|
84
|
+
|
85
|
+
## Readings before starting
|
86
|
+
|
87
|
+
* [gruf, a RPC gem for rails](https://github.com/bigcommerce/gruf)
|
88
|
+
* [GRPC for ruby](https://grpc.io/docs/languages/ruby/)
|
89
|
+
* [proto3 Styleguide](https://developers.google.com/protocol-buffers/docs/style)
|
90
|
+
|
91
|
+
## Repository structure
|
92
|
+
|
93
|
+
### Generated client
|
94
|
+
The client is generated with `bundle exec rails update_voca_proto`, and
|
95
|
+
save the client and service in [`/lib/decidim/voca/rpc`](./lib/decidim/voca/rpc)
|
96
|
+
|
97
|
+
### RPC Decidim Service
|
98
|
+
The entry point for RPC Decidim Service is in [`/app/rpc/decidim/voca/decidim_service_controller.rb`](./app/rpc/decidim/voca/decidim_service_controller.rb).
|
99
|
+
This controller have a method per registered message, and will call some concerns in the `/app/rpc/decidim/voca/rpc` folder.
|
100
|
+
|
101
|
+
### Updating commands
|
102
|
+
We use Rectify::Command in `/app/commmands/decidim/voca` for all update-related command.
|
103
|
+
|
104
|
+
|
105
|
+
## Installation
|
106
|
+
|
107
|
+
Add this line to your application's Gemfile:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
gem "decidim-voca"
|
111
|
+
```
|
112
|
+
|
113
|
+
And then execute:
|
114
|
+
|
115
|
+
```sh
|
116
|
+
bundle install
|
117
|
+
```
|
118
|
+
|
119
|
+
## Development
|
120
|
+
|
121
|
+
We suppose you have docker installed in your environment.
|
122
|
+
|
123
|
+
```sh
|
124
|
+
docker-compose up -d
|
125
|
+
docker-compose run --rm app bash -c "cd $RAILS_ROOT && rails db:migrate"
|
126
|
+
```
|
127
|
+
|
128
|
+
Your development app with the gem is ready on `http://localhost:3000`
|
129
|
+
|
130
|
+
### Run tests
|
131
|
+
|
132
|
+
`test_app` will create a `spec/dummy` app, and will run a local PostGres container.
|
133
|
+
This command has to be done before executing tests.
|
134
|
+
|
135
|
+
```sh
|
136
|
+
bundle && bundle exec rails test_app
|
137
|
+
```
|
138
|
+
|
139
|
+
Once this command pass, execute:
|
140
|
+
|
141
|
+
```sh
|
142
|
+
bundle exec rspec spec
|
143
|
+
```
|
144
|
+
|
145
|
+
to run the unit tests.
|
146
|
+
|
147
|
+
## Contributing
|
148
|
+
|
149
|
+
See [Contributing](CONTRIBUTING.md).
|
150
|
+
|
151
|
+
## License
|
152
|
+
|
153
|
+
See [License](LICENSE.md).
|
data/Rakefile
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/dev/common_rake"
|
4
|
+
|
5
|
+
def install_module(path)
|
6
|
+
Dir.chdir(path) do
|
7
|
+
# system("bundle exec rake decidim_voca:install:migrations")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def seed_db(path)
|
12
|
+
Dir.chdir(path) do
|
13
|
+
system("bundle exec rails db:seed")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Prepare for testing"
|
18
|
+
task :prepare_tests do
|
19
|
+
# Remove previous existing db, and recreate one.
|
20
|
+
disable_docker_compose = ENV.fetch("DISABLED_DOCKER_COMPOSE", "false") == "true"
|
21
|
+
unless disable_docker_compose
|
22
|
+
system("docker-compose -f docker-compose.yml down -v")
|
23
|
+
system("docker-compose -f docker-compose.yml up -d --remove-orphans")
|
24
|
+
end
|
25
|
+
ENV["RAILS_ENV"] = "test"
|
26
|
+
databaseYml = {
|
27
|
+
"test" => {
|
28
|
+
"adapter" => "postgresql",
|
29
|
+
"encoding" => "unicode",
|
30
|
+
"host" => ENV.fetch("DATABASE_HOST", "localhost"),
|
31
|
+
"port" => ENV.fetch("DATABASE_PORT", "5432").to_i,
|
32
|
+
"username" => ENV.fetch("DATABASE_USERNAME", "decidim"),
|
33
|
+
"password" => ENV.fetch("DATABASE_PASSWORD", "TEST-baeGhi4Ohtahcee5eejoaxaiwaezaiGo"),
|
34
|
+
"database" => "decidim_test"
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
config_file = File.expand_path("spec/dummy/config/database.yml", __dir__)
|
39
|
+
File.open(config_file, "w") { |f| YAML.dump(databaseYml, f) }
|
40
|
+
Dir.chdir("spec/dummy") do
|
41
|
+
system("bundle exec rails db:migrate")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Generates a dummy app for testing"
|
46
|
+
task :test_app do
|
47
|
+
Bundler.with_original_env do
|
48
|
+
generate_decidim_app(
|
49
|
+
"spec/dummy",
|
50
|
+
"--app_name",
|
51
|
+
"decidim_test",
|
52
|
+
"--path",
|
53
|
+
"../..",
|
54
|
+
"--skip_spring",
|
55
|
+
"--demo",
|
56
|
+
"--force_ssl",
|
57
|
+
"false",
|
58
|
+
"--locales",
|
59
|
+
"en,fr,es"
|
60
|
+
)
|
61
|
+
end
|
62
|
+
install_module("spec/dummy")
|
63
|
+
Rake::Task["prepare_tests"].invoke
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Generates a development app"
|
67
|
+
task :development_app do
|
68
|
+
Bundler.with_original_env do
|
69
|
+
generate_decidim_app(
|
70
|
+
"development_app",
|
71
|
+
"--app_name",
|
72
|
+
"#{base_app_name}_development_app",
|
73
|
+
"--path",
|
74
|
+
"..",
|
75
|
+
"--recreate_db",
|
76
|
+
"--demo"
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "Update protos for voca"
|
82
|
+
task :update_voca_proto do
|
83
|
+
%x(rm -rf ./lib/decidim/voca/rpc && mkdir -p ./lib/decidim/voca/rpc)
|
84
|
+
%x(curl -H 'Cache-Control: no-cache, no-store' -H 'Pragma: no-cache' https://raw.githubusercontent.com/octree-gva/voca-protos/main/clients/decidim-ruby-client.tar.gz | tar -xz -C ./lib/decidim/voca/rpc)
|
85
|
+
puts "✅ /lib/decidim/voca/rpc udpated"
|
86
|
+
end
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 35 35"><path d="M17.5 35A17.5 17.5 0 1 1 35 17.5 17.52 17.52 0 0 1 17.5 35zm0-33.06A15.56 15.56 0 1 0 33.06 17.5 15.57 15.57 0 0 0 17.5 1.94zm9.5 13.7H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zm0 3.68H8a1 1 0 0 1 0-1.94h19a1 1 0 0 1 0 1.94zM22.26 23H8a1 1 0 0 1 0-1.94h14.26a1 1 0 0 1 0 1.94z"/></svg>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Voca
|
5
|
+
module Organization
|
6
|
+
# maintains compatibility with v0.26 which uses Rectify
|
7
|
+
if defined? ::Decidim::Command
|
8
|
+
class Command < ::Decidim::Command
|
9
|
+
end
|
10
|
+
else
|
11
|
+
class Command < ::Rectify::Command
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class OrganizationCommand < ::Command
|
5
|
+
def organization
|
6
|
+
@organization ||= ::Decidim::Organization.first
|
7
|
+
end
|
8
|
+
def self.command_name
|
9
|
+
name.demodulize.camelize.stub(/_command/, "")
|
10
|
+
end
|
11
|
+
def command_name
|
12
|
+
self.command_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdateColorCommand < OrganizationCommand
|
5
|
+
attr_reader :color_settings
|
6
|
+
def initialize(color_settings)
|
7
|
+
@color_settings = with_defaults(color_settings.to_h.with_indifferent_access)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
organization.update!(
|
12
|
+
colors: (organization.colors || []).merge(color_settings.delete_if { |_k, v| v.blank? })
|
13
|
+
)
|
14
|
+
broadcast(:ok)
|
15
|
+
rescue e
|
16
|
+
Rails.logger.error(e)
|
17
|
+
broadcast(:fail)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def with_defaults(colors)
|
22
|
+
{
|
23
|
+
"alert": "#ec5840",
|
24
|
+
"primary": "#cb3c29",
|
25
|
+
"success": "#57d685",
|
26
|
+
"warning": "#ffae00",
|
27
|
+
"highlight": "#be6400",
|
28
|
+
"secondary": "#39747f",
|
29
|
+
"highlight-alternative": "#be6400"
|
30
|
+
}.merge(colors)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdateEnvironmentCommand < OrganizationCommand
|
5
|
+
attr_reader :config
|
6
|
+
def initialize(config)
|
7
|
+
@config = config.to_h.with_indifferent_access
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
redis = Redis.new(url: ENV["REDIS_CONFIG_URL"])
|
12
|
+
config.each do |key, value|
|
13
|
+
redis.hset("config",key,value)
|
14
|
+
end
|
15
|
+
broadcast(:ok)
|
16
|
+
rescue
|
17
|
+
Rails.logger.error("ERROR")
|
18
|
+
broadcast(:fail)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdateFeatureCommand < OrganizationCommand
|
5
|
+
attr_reader :feature_settings
|
6
|
+
def initialize(feature_settings)
|
7
|
+
@feature_settings = with_enums(
|
8
|
+
feature_settings.to_h.with_indifferent_access
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
organization.update!(
|
14
|
+
feature_settings.delete_if { |_k, v| v.blank? }
|
15
|
+
)
|
16
|
+
broadcast(:ok)
|
17
|
+
rescue e
|
18
|
+
Rails.logger.error(e)
|
19
|
+
broadcast(:fail)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def with_enums(settings)
|
24
|
+
settings["machine_translation_display_priority"] = Decidim::Voca::Rpc::EnumCasting.machine_translation_display_priority.rpc_to_decidim(
|
25
|
+
settings["machine_translation_display_priority"]
|
26
|
+
)
|
27
|
+
settings
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdateFileUploadCommand < OrganizationCommand
|
5
|
+
attr_reader :file_upload_settings
|
6
|
+
def initialize(file_upload_settings)
|
7
|
+
@file_upload_settings = with_defaults(
|
8
|
+
file_upload_settings.to_h.with_indifferent_access
|
9
|
+
)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
organization.update!(
|
14
|
+
file_upload_settings: file_upload_settings
|
15
|
+
)
|
16
|
+
broadcast(:ok)
|
17
|
+
rescue e
|
18
|
+
Rails.logger.error(e)
|
19
|
+
broadcast(:fail)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def with_defaults(settings)
|
24
|
+
uploads = ::Decidim::OrganizationSettings.for(
|
25
|
+
organization
|
26
|
+
).upload
|
27
|
+
uploads.to_h.merge({
|
28
|
+
maximum_file_size: uploads.maximum_file_size.to_h.merge({
|
29
|
+
avatar: settings[:maximum_file_size_avatar].to_i,
|
30
|
+
default: settings[:maximum_file_size_default].to_i,
|
31
|
+
}.delete_if { |_k, v| v == 0.0}),
|
32
|
+
allowed_content_types: uploads.allowed_content_types.to_h.merge({
|
33
|
+
admin: settings[:allowed_content_types_admin],
|
34
|
+
default: settings[:allowed_content_types_default],
|
35
|
+
}.delete_if { |_k, v| v.blank?}),
|
36
|
+
allowed_file_extensions: uploads.allowed_file_extensions.to_h.merge({
|
37
|
+
admin: settings[:allowed_file_extensions_admin],
|
38
|
+
default: settings[:allowed_file_extensions_default],
|
39
|
+
}.delete_if { |_k, v| v.blank?}),
|
40
|
+
}.delete_if { |_k, v| v.blank?})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdateLocaleCommand < OrganizationCommand
|
5
|
+
attr_reader :locale_settings
|
6
|
+
def initialize(locale_settings)
|
7
|
+
@locale_settings = locale_settings.to_h
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
# update languages
|
12
|
+
organization_configuration = locale_settings.select do |key|
|
13
|
+
"#{key}" == "available_locales" || "#{key}" == "default_locale"
|
14
|
+
end.delete_if { |_k, v| v.blank? }
|
15
|
+
organization.update!(organization_configuration)
|
16
|
+
after_updating_languages
|
17
|
+
# update localization settings (currency, timezone)
|
18
|
+
global_configuration = locale_settings.select do |key|
|
19
|
+
"#{key}" == "currency_unit" || "#{key}" == "timezone"
|
20
|
+
end.delete_if { |_k, v| v.blank? }
|
21
|
+
unless global_configuration.empty?
|
22
|
+
redis_client = Redis.new(
|
23
|
+
url: ENV.fetch("REDIS_CONFIG_URL", "redis://127.0.0.1:6379/2"),
|
24
|
+
);
|
25
|
+
global_configuration.each do |key, value|
|
26
|
+
# Update the Redis hash values
|
27
|
+
redis_client.hset("config", "#{key}", "#{value}")
|
28
|
+
end
|
29
|
+
# Close the Redis connection
|
30
|
+
redis_client.quit
|
31
|
+
end
|
32
|
+
broadcast(:ok)
|
33
|
+
rescue StandardError => e
|
34
|
+
Rails.logger.error(e)
|
35
|
+
broadcast(:fail)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def after_updating_languages
|
40
|
+
# Rebuild locales
|
41
|
+
`bundle exec rails decidim:locales:sync_all`
|
42
|
+
# Rebuild search tree
|
43
|
+
`bundle exec rails decidim:locales:rebuild_search`
|
44
|
+
org = organization.reload
|
45
|
+
# Update user locales (they might not have a locale that is now supported)
|
46
|
+
::Decidim::User.where.not(locale: org.available_locales).each do |user|
|
47
|
+
user.update(locale: org.default_locale)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdateNamingCommand < OrganizationCommand
|
5
|
+
attr_reader :naming_settings
|
6
|
+
def initialize(naming_settings)
|
7
|
+
@naming_settings = naming_settings.to_h
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
organization.update!(naming_settings.delete_if { |_k, v| v.blank? })
|
12
|
+
broadcast(:ok)
|
13
|
+
rescue e
|
14
|
+
Rails.logger.error(e)
|
15
|
+
broadcast(:fail)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def update_host
|
21
|
+
# Todo call Voca system to update the redirection
|
22
|
+
end
|
23
|
+
|
24
|
+
def update_subdomain
|
25
|
+
# Todo call Voca system to update aliases
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdatePermissionCommand < OrganizationCommand
|
5
|
+
attr_reader :permission_settings
|
6
|
+
def initialize(permission_settings)
|
7
|
+
@permission_settings = cast_permission_settings(permission_settings.to_h)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
organization.update!(permission_settings.delete_if { |_k, v| v.blank? })
|
12
|
+
broadcast(:ok)
|
13
|
+
rescue e
|
14
|
+
Rails.logger.error(e)
|
15
|
+
broadcast(:fail)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def cast_permission_settings(permission_settings)
|
21
|
+
# Convert enums
|
22
|
+
casting = ::Decidim::Voca::Rpc::EnumCasting.users_registration_mode
|
23
|
+
permission_settings[:users_registration_mode] = casting.rpc_to_decidim(
|
24
|
+
permission_settings[:users_registration_mode]
|
25
|
+
)
|
26
|
+
permission_settings
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Decidim
|
2
|
+
module Voca
|
3
|
+
module Organization
|
4
|
+
class UpdateSmtpCommand < OrganizationCommand
|
5
|
+
attr_reader :smtp_settings
|
6
|
+
def initialize(smtp_settings)
|
7
|
+
@smtp_settings = transform_settings(smtp_settings.to_h.with_indifferent_access)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
organization.update!(
|
12
|
+
smtp_settings: smtp_settings.delete_if { |_k, v| v.blank? }
|
13
|
+
)
|
14
|
+
broadcast(:ok)
|
15
|
+
rescue => e
|
16
|
+
Rails.logger.error(e)
|
17
|
+
broadcast(:fail)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def transform_settings(settings)
|
23
|
+
from_label = settings.delete("from_label")
|
24
|
+
from_email = settings.delete("from_email")
|
25
|
+
username = settings.delete("username")
|
26
|
+
settings["openssl_verify_mode"] = Decidim::Voca::Rpc::EnumCasting.smtp_openssl_verify_mode.rpc_to_decidim(
|
27
|
+
settings["openssl_verify_mode"]
|
28
|
+
)
|
29
|
+
settings["authentication"] = Decidim::Voca::Rpc::EnumCasting.smtp_authentication.rpc_to_decidim(
|
30
|
+
settings["authentication"]
|
31
|
+
)
|
32
|
+
settings["user_name"] = username unless username.blank?
|
33
|
+
if from_email.blank? && !from_label.blank?
|
34
|
+
active_mailer_config = Rails.configuration.action_mailer.smtp_settings || {}
|
35
|
+
current = organization.smtp_settings || {}
|
36
|
+
mail = Mail::Address.new(
|
37
|
+
current.fetch("from", active_mailer_config.fetch(:from, "example@decidim.org"))
|
38
|
+
)
|
39
|
+
mail.display_name = from_label
|
40
|
+
settings[:from] = mail.to_s
|
41
|
+
elsif !from_email.blank?
|
42
|
+
mail = Mail::Address.new(from_email)
|
43
|
+
mail.display_name = from_label unless from_label.nil?
|
44
|
+
settings[:from] = mail.to_s
|
45
|
+
end
|
46
|
+
settings
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Voca
|
5
|
+
module Admin
|
6
|
+
# This controller is the abstract class from which all other controllers of
|
7
|
+
# this engine inherit.
|
8
|
+
#
|
9
|
+
# Note that it inherits from `Decidim::Admin::Components::BaseController`, which
|
10
|
+
# override its layout and provide all kinds of useful methods.
|
11
|
+
class ApplicationController < Decidim::Admin::Components::BaseController
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Voca
|
5
|
+
# This controller is the abstract class from which all other controllers of
|
6
|
+
# this engine inherit.
|
7
|
+
#
|
8
|
+
# Note that it inherits from `Decidim::Components::BaseController`, which
|
9
|
+
# override its layout and provide all kinds of useful methods.
|
10
|
+
class ApplicationController < Decidim::Components::BaseController
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
module Decidim
|
5
|
+
module Voca
|
6
|
+
class CommandJob < ApplicationJob
|
7
|
+
attr_reader :logger, :variables, :command_name
|
8
|
+
def perform(command_name, variables = {}, logger = Rails.logger)
|
9
|
+
@command_name = command_name
|
10
|
+
@variables = variables
|
11
|
+
@logger = logger
|
12
|
+
invoke!
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def invoke!
|
18
|
+
raise ::Decidim::Voca::Error unless valid?
|
19
|
+
::Rake::Task["voca:#{command_name}"].invoke(task_args)
|
20
|
+
end
|
21
|
+
|
22
|
+
def task_args
|
23
|
+
variables.reduce([]) do |acc, (key, value)|
|
24
|
+
acc << "#{key}=\"#{value}\""
|
25
|
+
end.join(" ") unless variables.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid?
|
29
|
+
Rake::Task["voca:#{command_name}"]
|
30
|
+
true
|
31
|
+
rescue RuntimeError
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|