decidim-voca 0.0.6

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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +661 -0
  3. data/README.md +153 -0
  4. data/Rakefile +86 -0
  5. data/app/assets/config/voca_manifest.js +0 -0
  6. data/app/assets/images/decidim/voca/icon.svg +1 -0
  7. data/app/commands/decidim/voca/organization/command.rb +16 -0
  8. data/app/commands/decidim/voca/organization/organization_command.rb +17 -0
  9. data/app/commands/decidim/voca/organization/update_color_command.rb +35 -0
  10. data/app/commands/decidim/voca/organization/update_environment_command.rb +23 -0
  11. data/app/commands/decidim/voca/organization/update_feature_command.rb +32 -0
  12. data/app/commands/decidim/voca/organization/update_file_upload_command.rb +45 -0
  13. data/app/commands/decidim/voca/organization/update_locale_command.rb +53 -0
  14. data/app/commands/decidim/voca/organization/update_naming_command.rb +30 -0
  15. data/app/commands/decidim/voca/organization/update_permission_command.rb +31 -0
  16. data/app/commands/decidim/voca/organization/update_smtp_command.rb +51 -0
  17. data/app/controllers/decidim/voca/admin/application_controller.rb +15 -0
  18. data/app/controllers/decidim/voca/application_controller.rb +13 -0
  19. data/app/jobs/decidim/voca/command_job.rb +36 -0
  20. data/app/jobs/decidim/voca/webhook_notifier_job.rb +57 -0
  21. data/app/rpc/decidim/voca/decidim_service_controller.rb +68 -0
  22. data/app/rpc/decidim/voca/rpc/enum_casting.rb +58 -0
  23. data/app/rpc/decidim/voca/rpc/get_settings.rb +144 -0
  24. data/app/rpc/decidim/voca/rpc/health.rb +18 -0
  25. data/app/rpc/decidim/voca/rpc/seed_admin.rb +75 -0
  26. data/app/rpc/decidim/voca/rpc/set_settings.rb +56 -0
  27. data/app/rpc/decidim/voca/rpc/setup_db.rb +38 -0
  28. data/config/environments/development.rb +6 -0
  29. data/config/i18n-tasks.yml +9 -0
  30. data/config/locales/en.yml +6 -0
  31. data/config/spring.rb +2 -0
  32. data/lib/decidim/voca/admin.rb +10 -0
  33. data/lib/decidim/voca/admin_engine.rb +27 -0
  34. data/lib/decidim/voca/backup/app_backup.rb +169 -0
  35. data/lib/decidim/voca/backup/app_decrypt_backup_file.rb +50 -0
  36. data/lib/decidim/voca/backup/app_encrypt_backup_file.rb +49 -0
  37. data/lib/decidim/voca/backup/app_upload_to_s3.rb +49 -0
  38. data/lib/decidim/voca/engine.rb +31 -0
  39. data/lib/decidim/voca/middleware/dynamic_config_middleware.rb +42 -0
  40. data/lib/decidim/voca/rpc/decidim_pb.rb +134 -0
  41. data/lib/decidim/voca/rpc/decidim_services_pb.rb +30 -0
  42. data/lib/decidim/voca/test/factories.rb +9 -0
  43. data/lib/decidim/voca/updater.rb +50 -0
  44. data/lib/decidim/voca/version.rb +13 -0
  45. data/lib/decidim/voca.rb +22 -0
  46. data/lib/tasks/voca.rake +88 -0
  47. metadata +124 -0
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module Decidim
8
+ module Voca
9
+ class WebhookNotifierJob < ApplicationJob
10
+ queue_as :default
11
+ attr_reader :event_type
12
+ def perform(content, event_type, logger = Rails.logger)
13
+ @content = content
14
+ @event_type = event_type
15
+ @logger = logger
16
+ notify!
17
+ end
18
+
19
+ private
20
+
21
+ def hmac_key
22
+ @hmac_key ||= ENV.fetch("WEBHOOK_HMAC", "insecure_secret")
23
+ end
24
+
25
+ def content
26
+ @content.to_json
27
+ end
28
+
29
+ def webhook_uri
30
+ webhook_url = ENV.fetch("WEBHOOK_URL") + "/" + ENV.fetch("INSTANCE_UUID")
31
+ URI.parse(webhook_url)
32
+ end
33
+
34
+ def payload
35
+ {
36
+ event_type: event_type,
37
+ content: content,
38
+ content_hmac: OpenSSL::HMAC.hexdigest(
39
+ OpenSSL::Digest.new("sha256"),
40
+ hmac_key,
41
+ content
42
+ )
43
+ }
44
+ end
45
+
46
+ def notify!
47
+ header = {
48
+ "Content-Type": "application/json",
49
+ "Accept": "application/json",
50
+ "User-Agent": "VocaCity/0.0.1"
51
+ }
52
+ http = Net::HTTP.new(webhook_uri.host, webhook_uri.port)
53
+ response = http.post(webhook_uri.request_uri, payload.to_json, header)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,68 @@
1
+
2
+ require "rake"
3
+ module Decidim
4
+ module Voca
5
+ class DecidimServiceController < ::Gruf::Controllers::Base
6
+ include ::VocaDecidim
7
+ bind ::VocaDecidim::Decidim::Service
8
+
9
+ def ping
10
+ ::Decidim::Voca::Rpc::Health.new(
11
+ message
12
+ ).ping
13
+ end
14
+
15
+ def get_settings
16
+ ::Decidim::Voca::Rpc::GetSettings.new(
17
+ message,
18
+ organization
19
+ ).get_settings
20
+ rescue ActiveRecord::RecordNotFound => _e
21
+ fail!(:not_found, :organization_not_found, "No organization is ready, have you seeded?")
22
+ end
23
+
24
+ def compile_assets
25
+ `bundle exec rails assets:precompile`
26
+ ::Google::Protobuf::Empty.new
27
+ end
28
+
29
+ def setup_db
30
+ `bundle exec rails db:migrate`
31
+ ::Decidim::Voca::Rpc::SetupDb.new.seed
32
+ ::Google::Protobuf::Empty.new
33
+ end
34
+
35
+ def seed_admin
36
+ seeder = ::Decidim::Voca::Rpc::SeedAdmin.new(message)
37
+ seeder.seed
38
+ ::VocaDecidim::SeedAdminResponse.new(
39
+ admin_email: message.admin_email,
40
+ admin_password: seeder.password
41
+ )
42
+ rescue ActiveRecord::RecordNotFound => _e
43
+ fail!(:not_found, :organization_not_found, "No organization is ready, have you seeded?")
44
+ end
45
+
46
+
47
+ def set_settings
48
+ ::Decidim::Voca::Rpc::SetSettings.new(
49
+ message,
50
+ organization
51
+ ).set_settings
52
+ ::Google::Protobuf::Empty.new
53
+ rescue ActiveRecord::RecordNotFound => _e
54
+ fail!(:not_found, :organization_not_found, "No organization is ready, have you seeded?")
55
+ end
56
+
57
+ private
58
+
59
+ def message
60
+ request.message
61
+ end
62
+
63
+ def organization
64
+ ::Decidim::Organization.first!
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,58 @@
1
+ module Decidim
2
+ module Voca
3
+ module Rpc
4
+ class EnumCaster
5
+ attr_reader :decidim_rpc_mapping, :symbolic_mapping
6
+ def initialize(enum_module, decidim_rpc_mapping)
7
+ @decidim_rpc_mapping = decidim_rpc_mapping.deep_symbolize_keys
8
+ @symbolic_mapping = Hash[enum_module.descriptor.collect { |i| [i, enum_module.resolve(i)] }]
9
+ end
10
+
11
+ def decidim_to_rpc(decidim_key)
12
+ matches = decidim_rpc_mapping.find { |k, _v| k === decidim_key.to_sym }
13
+ (matches || []).last
14
+ end
15
+
16
+ def rpc_to_decidim(rpc_symbol)
17
+ rpc_value = symbolic_mapping[rpc_symbol]
18
+ matches = decidim_rpc_mapping.find { |_k, v| v === rpc_value }
19
+ (matches || []).first
20
+ end
21
+ end
22
+
23
+ module EnumCasting
24
+ include ::VocaDecidim
25
+
26
+ def self.machine_translation_display_priority
27
+ EnumCaster.new(SETTINGS_MACHINE_TRANSLATION_PRIORITY_OPTION, {
28
+ "original" => SETTINGS_MACHINE_TRANSLATION_PRIORITY_OPTION::SETTINGS_MACHINE_TRANSLATION_PRIORITY_ORIGINAL,
29
+ "translated" => SETTINGS_MACHINE_TRANSLATION_PRIORITY_OPTION::SETTINGS_MACHINE_TRANSLATION_PRIORITY_TRANSLATED
30
+ })
31
+ end
32
+
33
+ def self.users_registration_mode
34
+ EnumCaster.new(SETTINGS_REGISTER_MODE_OPTION, {
35
+ "enabled": SETTINGS_REGISTER_MODE_OPTION::SETTINGS_REGISTER_MODE_REGISTER_AND_LOGIN,
36
+ "existing": SETTINGS_REGISTER_MODE_OPTION::SETTINGS_REGISTER_MODE_LOGIN,
37
+ "disabled": SETTINGS_REGISTER_MODE_OPTION::SETTINGS_REGISTER_MODE_EXTERNAL
38
+ })
39
+ end
40
+
41
+ def self.smtp_authentication
42
+ EnumCaster.new(SETTINGS_SMTP_AUTHENTICATION_OPTION, {
43
+ "plain": SETTINGS_SMTP_AUTHENTICATION_OPTION::SETTINGS_SMTP_AUTHENTICATION_PLAIN,
44
+ "login": SETTINGS_SMTP_AUTHENTICATION_OPTION::SETTINGS_SMTP_AUTHENTICATION_LOGIN,
45
+ "cram_md5": SETTINGS_SMTP_AUTHENTICATION_OPTION::SETTINGS_SMTP_AUTHENTICATION_CRAM_MD5,
46
+ "none": SETTINGS_SMTP_AUTHENTICATION_OPTION::SETTINGS_SMTP_AUTHENTICATION_NONE
47
+ })
48
+ end
49
+ def self.smtp_openssl_verify_mode
50
+ EnumCaster.new(SETTINGS_SMTP_OPENSSL_OPTION, {
51
+ "none": SETTINGS_SMTP_OPENSSL_OPTION::SETTINGS_SMTP_OPENSSL_NONE,
52
+ "peer": SETTINGS_SMTP_OPENSSL_OPTION::SETTINGS_SMTP_OPENSSL_PEER,
53
+ })
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,144 @@
1
+
2
+
3
+ module Decidim
4
+ module Voca
5
+ module Rpc
6
+ class GetSettings
7
+ include ::VocaDecidim
8
+ attr_reader :message, :organization
9
+ def initialize(message, organization)
10
+ @message = message
11
+ @organization = organization
12
+ end
13
+
14
+ # get all the settings linked to the organization.
15
+ # @returns GetSettingsResponse
16
+ def get_settings
17
+ GetSettingsResponse.new(
18
+ id: organization.id,
19
+ permission_settings: permission_settings,
20
+ naming_settings: naming_settings,
21
+ locale_settings: locale_settings,
22
+ smtp_settings: smtp_settings,
23
+ color_settings: color_settings,
24
+ file_upload_settings: file_upload_settings,
25
+ feature_settings: feature_settings
26
+ )
27
+ end
28
+
29
+ private
30
+ def feature_settings
31
+ DecidimOrganizationFeatureFlagSettings.new(
32
+ available_authorizations: organization.available_authorizations,
33
+ badges_enabled: organization.badges_enabled,
34
+ user_groups_enabled: organization.user_groups_enabled,
35
+ enable_machine_translations: organization.enable_machine_translations,
36
+ machine_translation_display_priority: EnumCasting.machine_translation_display_priority.decidim_to_rpc(
37
+ organization.machine_translation_display_priority || "original"
38
+ )
39
+ )
40
+ end
41
+
42
+ def file_upload_settings
43
+ upload_settings = ::Decidim::OrganizationSettings.for(organization).upload
44
+ DecidimOrganizationFileUploadSettings.new(
45
+ maximum_file_size_avatar: upload_settings.maximum_file_size.avatar,
46
+ maximum_file_size_default: upload_settings.maximum_file_size.default,
47
+ allowed_content_types_admin: upload_settings.allowed_content_types.admin,
48
+ allowed_content_types_default: upload_settings.allowed_content_types.default,
49
+ allowed_file_extensions_admin: upload_settings.allowed_file_extensions.admin,
50
+ allowed_file_extensions_default: upload_settings.allowed_file_extensions.default
51
+ )
52
+ end
53
+
54
+ def color_settings
55
+ default_colors = {
56
+ "alert": "#ec5840",
57
+ "primary": "#cb3c29",
58
+ "success": "#57d685",
59
+ "warning": "#ffae00",
60
+ "highlight": "#be6400",
61
+ "secondary": "#39747f",
62
+ "highlight-alternative": "#be6400"
63
+ }
64
+ settings = default_colors.merge((organization.colors || {}).deep_symbolize_keys) { |_k, o, v| v.presence || o }.delete_if { |_k, v| v.blank? }
65
+ DecidimOrganizationColorSettings.new(
66
+ alert: settings[:alert],
67
+ primary: settings[:primary],
68
+ success: settings[:success],
69
+ warning: settings[:warning],
70
+ highlight: settings[:highlight],
71
+ secondary: settings[:secondary],
72
+ highlight_alternative: settings["highlight-alternative".to_sym]
73
+ )
74
+ end
75
+
76
+ def smtp_settings
77
+ active_mailer_config = Rails.configuration.action_mailer.smtp_settings || {}
78
+ tenant_config = organization.smtp_settings || {}
79
+ from = tenant_config.fetch("from", active_mailer_config.fetch(:from, ""))
80
+
81
+ email = Mail::Address.new(from)
82
+ current_settings = active_mailer_config.merge({
83
+ password: tenant_config["password"],
84
+ user_name: tenant_config["user_name"],
85
+ port: tenant_config["port"],
86
+ address: tenant_config["address"],
87
+ from_label: email.present? ? email.display_name : nil,
88
+ from_email: email.present? ? email.address : nil
89
+ }) { |_k, o, v| v.presence || o }.delete_if { |_k, v| v.blank? }
90
+
91
+ DecidimOrganizationSMTPSettings.new(
92
+ from_label: current_settings[:from_label],
93
+ from_email: current_settings[:from_email],
94
+ address: current_settings[:address],
95
+ port: current_settings[:port],
96
+ authentication: EnumCasting.smtp_authentication.decidim_to_rpc(
97
+ current_settings[:authentication] || "plain"
98
+ ),
99
+ username: current_settings[:user_name],
100
+ password: current_settings[:password],
101
+ domain: current_settings[:domain],
102
+ enable_starttls_auto: current_settings[:enable_starttls_auto],
103
+ openssl_verify_mode: EnumCasting.smtp_openssl_verify_mode.decidim_to_rpc(
104
+ current_settings[:openssl_verify_mode] || "peer"
105
+ )
106
+ )
107
+ end
108
+
109
+ def permission_settings
110
+ DecidimOrganizationPermissionSettings.new(
111
+ force_users_to_authenticate_before_access_organization:
112
+ organization.force_users_to_authenticate_before_access_organization,
113
+ users_registration_mode: EnumCasting.users_registration_mode.decidim_to_rpc(
114
+ organization.users_registration_mode || "enabled"
115
+ )
116
+ )
117
+ end
118
+
119
+
120
+ def locale_settings
121
+ redis_client = Redis.new(
122
+ url: ENV.fetch("REDIS_CONFIG_URL", "redis://127.0.0.1:6379/2"),
123
+ );
124
+ globals_config = redis_client.hgetall("config")
125
+ DecidimOrganizationLocaleSettings.new(
126
+ default_locale: organization.default_locale,
127
+ available_locales: organization.available_locales,
128
+ currency_unit: globals_config["currency_unit"],
129
+ timezone: globals_config["timezone"]
130
+ )
131
+ end
132
+
133
+ def naming_settings
134
+ DecidimOrganizationNamingSettings.new(
135
+ host: organization.host,
136
+ secondary_hosts: organization.secondary_hosts,
137
+ name: organization.name,
138
+ reference_prefix: organization.reference_prefix
139
+ )
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,18 @@
1
+ require "rake"
2
+ module Decidim
3
+ module Voca
4
+ module Rpc
5
+ class Health
6
+ include ::VocaDecidim
7
+
8
+ ##
9
+ # Return just a string without any caculations.
10
+ # This is done to test succesfull interaction through RPC
11
+ def ping
12
+ "pong"
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,75 @@
1
+ module Decidim
2
+ module Voca
3
+ module Rpc
4
+ class SeedAdmin
5
+ include ::VocaDecidim
6
+ attr_reader :message, :organization, :password
7
+
8
+ def initialize(message)
9
+ @message = message
10
+ @organization = ::Decidim::Organization.first!
11
+ @password = ::Devise.friendly_token.first(23)
12
+ end
13
+
14
+ # migrate the database and insert default values.
15
+ # @returns nil
16
+ def seed
17
+ seed_system_admin!
18
+ seed_admin!
19
+ end
20
+
21
+ private
22
+ def seed_system_admin!
23
+ return if ::Decidim::System::Admin.count > 0
24
+ ::Decidim::System::Admin.create!(
25
+ email: message.system_email,
26
+ password: message.system_password,
27
+ password_confirmation: message.system_password,
28
+ )
29
+ end
30
+
31
+ def seed_admin!
32
+ return update_password! if ::Decidim::User.where(admin: true).count > 0
33
+ email = message.admin_email
34
+ matches = email[/[^@]+/].split(".").map { |n| n.gsub(/[^[:alnum:]]/, "") }
35
+ name = matches.map(&:capitalize).join(" ")
36
+ nickname = matches.map(&:downcase).join("_").truncate(19, omission: "")
37
+ user = ::Decidim::User.create!(
38
+ email: email,
39
+ name: name,
40
+ nickname: nickname,
41
+ password: password,
42
+ password_confirmation: password,
43
+ organization: organization,
44
+ confirmed_at: Time.current,
45
+ locale: organization.default_locale,
46
+ admin: true,
47
+ tos_agreement: true,
48
+ personal_url: "",
49
+ about: "",
50
+ accepted_tos_version: organization.tos_version,
51
+ admin_terms_accepted_at: Time.current
52
+ )
53
+ end
54
+
55
+ def update_password!
56
+ user = ::Decidim::User.where(admin: true).first!
57
+ email = message.admin_email
58
+ matches = email[/[^@]+/].split(".").map { |n| n.gsub(/[^[:alnum:]]/, "") }
59
+ name = matches.map(&:capitalize).join(" ")
60
+ nickname = matches.map(&:downcase).join("_").truncate(19, omission: "")
61
+ user.skip_confirmation_notification!
62
+ user.skip_confirmation!
63
+ user.update(
64
+ email: email,
65
+ name: name,
66
+ nickname: nickname,
67
+ password: password,
68
+ password_confirmation: password,
69
+ )
70
+ user.confirm
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,56 @@
1
+
2
+ module Decidim
3
+ module Voca
4
+ module Rpc
5
+ class SetSettings
6
+ include ::VocaDecidim
7
+ attr_reader :message, :organization
8
+ def initialize(message, organization)
9
+ @message = message
10
+ @organization = organization
11
+ end
12
+ def set_settings
13
+ response = []
14
+ response << [
15
+ "naming_settings",
16
+ ::Decidim::Voca::Organization::UpdateNamingCommand.call(message.naming_settings)
17
+ ] unless message.naming_settings.nil?
18
+ response << [
19
+ "permission_settings",
20
+ ::Decidim::Voca::Organization::UpdatePermissionCommand.call(message.permission_settings)
21
+ ] unless message.permission_settings.nil?
22
+ response << [
23
+ "locale_settings",
24
+ ::Decidim::Voca::Organization::UpdateLocaleCommand.call(message.locale_settings)
25
+ ] unless message.locale_settings.nil?
26
+ response << [
27
+ "smtp_settings",
28
+ ::Decidim::Voca::Organization::UpdateSmtpCommand.call(message.smtp_settings)
29
+ ] unless message.smtp_settings.nil?
30
+ response << [
31
+ "color_settings",
32
+ ::Decidim::Voca::Organization::UpdateColorCommand.call(message.color_settings)
33
+ ] unless message.color_settings.nil?
34
+ response << [
35
+ "file_upload_settings",
36
+ ::Decidim::Voca::Organization::UpdateFileUploadCommand.call(message.file_upload_settings)
37
+ ] unless message.file_upload_settings.nil?
38
+ response << [
39
+ "feature_settings",
40
+ ::Decidim::Voca::Organization::UpdateFeatureCommand.call(message.feature_settings)
41
+ ] unless message.feature_settings.nil?
42
+ error_string = response.delete_if { |k, v| v.key? :ok }.map(&:first).join(", ")
43
+ unless error_string.empty?
44
+ raise error_string
45
+ end
46
+
47
+ if ::Decidim::StaticPage.count < ::Decidim::StaticPage::DEFAULT_PAGES.length
48
+ ::Decidim::System::PopulateHelp.new(organization).call
49
+ ::Decidim::System::CreateDefaultPages.new(organization).call
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,38 @@
1
+ module Decidim
2
+ module Voca
3
+ module Rpc
4
+ class SetupDb
5
+ include ::VocaDecidim
6
+
7
+ # migrate the database and insert default values.
8
+ # @returns nil
9
+ def seed
10
+ # If an organization is already present, should not seed.
11
+ return if ::Decidim::Organization.count > 0
12
+ seed_organization!
13
+ end
14
+
15
+ private
16
+
17
+ def seed_organization!
18
+ organization = ::Decidim::Organization.create!(
19
+ host: "localhost",
20
+ name: "parked instance",
21
+ default_locale: :en,
22
+ available_locales: [:en],
23
+ reference_prefix: "DOC",
24
+ available_authorizations: [],
25
+ users_registration_mode: :enabled,
26
+ tos_version: Time.current,
27
+ badges_enabled: true,
28
+ user_groups_enabled: true,
29
+ send_welcome_notification: true,
30
+ file_upload_settings: ::Decidim::OrganizationSettings.default(:upload)
31
+ )
32
+
33
+ ::Decidim::System::CreateDefaultContentBlocks.call(organization)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,6 @@
1
+ Rails.application.configure do
2
+ Rails.logger = Logger.new(STDOUT)
3
+ config.logger = ActiveSupport::Logger.new("log/#{Rails.env}.log")
4
+ Rails.logger.level = Logger::DEBUG
5
+ Rails.logger.datetime_format = "%Y-%m-%d %H:%M:%S"
6
+ end
@@ -0,0 +1,9 @@
1
+ ---
2
+ base_locale: en
3
+ locales: [en]
4
+
5
+ ignore_unused:
6
+ - "decidim.components.voca.name"
7
+
8
+ ignore_missing:
9
+ - decidim.participatory_processes.scopes.global
@@ -0,0 +1,6 @@
1
+ ---
2
+ en:
3
+ decidim:
4
+ components:
5
+ voca:
6
+ name: Voca
data/config/spring.rb ADDED
@@ -0,0 +1,2 @@
1
+
2
+ Spring.application_root = './spec/dummy'
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Voca
5
+ # This module contains all the domain logic associated to Decidim's Voca
6
+ # component admin panel.
7
+ module Admin
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module Voca
5
+ # This is the engine that runs on the public interface of `Voca`.
6
+ class AdminEngine < ::Rails::Engine
7
+ isolate_namespace Decidim::Voca::Admin
8
+
9
+ paths["db/migrate"] = nil
10
+ paths["lib/tasks"] = nil
11
+
12
+ routes do
13
+ # Add admin engine routes here
14
+ # resources :voca do
15
+ # collection do
16
+ # resources :exports, only: [:create]
17
+ # end
18
+ # end
19
+ # root to: "voca#index"
20
+ end
21
+
22
+ def load_seed
23
+ nil
24
+ end
25
+ end
26
+ end
27
+ end