cmor_legal 0.0.45.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +27 -0
  4. data/Rakefile +21 -0
  5. data/app/assets/config/manifest.js +2 -0
  6. data/app/assets/javascripts/cmor/legal/application.js +2 -0
  7. data/app/assets/javascripts/cmor/legal/application/keep.js +0 -0
  8. data/app/assets/javascripts/cmor_legal.js +2 -0
  9. data/app/assets/stylesheets/cmor/legal/application.css +3 -0
  10. data/app/assets/stylesheets/cmor/legal/application/keep.css +0 -0
  11. data/app/assets/stylesheets/cmor_legal.css +3 -0
  12. data/app/builders/cmor/legal/personal_data_hash_builder.rb +50 -0
  13. data/app/controllers/cmor/legal/home_controller.rb +8 -0
  14. data/app/controllers/cmor/legal/personal_data_controller.rb +24 -0
  15. data/app/controllers/cmor/legal/privacy_policies_controller.rb +18 -0
  16. data/app/models/cmor/legal/cookie.rb +87 -0
  17. data/app/models/cmor/legal/cookie_preferences.rb +47 -0
  18. data/app/models/cmor/legal/cookie_store.rb +39 -0
  19. data/app/models/cmor/legal/personal_data.rb +60 -0
  20. data/app/models/cmor/legal/privacy_policy.rb +24 -0
  21. data/app/registries/cmor/legal/personal_data_registry.rb +42 -0
  22. data/app/resolvers/cmor/legal/privacy_policy_resolver.rb +8 -0
  23. data/app/view_helpers/cmor/legal/application_view_helper.rb +8 -0
  24. data/app/views/cmor/legal/home/_index_extras.html.haml +22 -0
  25. data/app/views/cmor/legal/personal_data/_index_table.haml +1 -0
  26. data/app/views/cmor/legal/personal_data/_show_extras.haml +1 -0
  27. data/app/views/cmor/legal/personal_data/_show_table.haml +1 -0
  28. data/app/views/cmor/legal/privacy_policies/_form.haml +14 -0
  29. data/app/views/cmor/legal/privacy_policies/_index_table.haml +6 -0
  30. data/app/views/cmor/legal/privacy_policies/_show_table.html.haml +8 -0
  31. data/config/initializers/assets.rb +2 -0
  32. data/config/initializers/cmor.rb +3 -0
  33. data/config/locales/de.yml +20 -0
  34. data/config/locales/en.yml +15 -0
  35. data/config/routes.rb +7 -0
  36. data/lib/cmor/legal/configuration.rb +64 -0
  37. data/lib/cmor/legal/engine.rb +7 -0
  38. data/lib/cmor/legal/version.rb +9 -0
  39. data/lib/cmor_legal.rb +15 -0
  40. data/lib/generators/cmor/legal/install/install_generator.rb +26 -0
  41. data/lib/generators/cmor/legal/install/templates/initializer.rb +69 -0
  42. data/lib/generators/cmor/legal/install/templates/routes.source +4 -0
  43. data/lib/tasks/cmor/legal_tasks.rake +8 -0
  44. data/spec/factories/cmor_legal_privacy_policies.rb +7 -0
  45. data/spec/features/de/backend/juristisches/privacy_policies_feature_spec.rb +60 -0
  46. data/spec/lib/cmor/legal/version_spec.rb +7 -0
  47. data/spec/models/cmor/legal/cookie_spec.rb +63 -0
  48. data/spec/rails_helper.rb +62 -0
  49. data/spec/spec_helper.rb +98 -0
  50. data/spec/support/active_job.rb +3 -0
  51. data/spec/support/capybara.rb +3 -0
  52. data/spec/support/factory_bot.rb +16 -0
  53. data/spec/support/pry.rb +3 -0
  54. data/spec/support/rao-shoulda_matchers.rb +7 -0
  55. metadata +447 -0
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class PrivacyPolicy < Cmor::Cms::Page
6
+ after_initialize :set_defaults, if: :new_record?
7
+ before_validation :set_locale_dependent_defaults, if: :new_record?
8
+
9
+ default_scope { where(pathname: "/cmor/legal/", basename: "show") }
10
+
11
+ private
12
+ def set_defaults
13
+ self.pathname ||= "/cmor/legal/"
14
+ self.basename ||= "privacy_policy"
15
+ self.handler ||= "textile"
16
+ end
17
+
18
+ def set_locale_dependent_defaults
19
+ return unless self.locale.present?
20
+ self.title ||= I18n.with_locale(self.locale) { I18n.t("cmor.legal.privacy_policy.default_title") }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class PersonalDataRegistry
6
+ extend ActiveModel::Translation
7
+ extend ActiveModel::Naming
8
+
9
+ attr_accessor :personal_data
10
+
11
+ delegate :first, :last, :[], :each, :map, :collect, to: :personal_data
12
+
13
+ def initialize
14
+ @personal_data = []
15
+ end
16
+
17
+ def self.instance
18
+ @@instance
19
+ end
20
+
21
+ def self.all
22
+ instance.personal_data
23
+ end
24
+
25
+ def self.count
26
+ instance.personal_data.size
27
+ end
28
+
29
+ def self.attribute_names
30
+ [:personal_data]
31
+ end
32
+
33
+ def register(root, options, &block)
34
+ self.personal_data << PersonalData.new(root: root, options: options, block: block)
35
+ end
36
+
37
+ @@instance = Cmor::Legal::PersonalDataRegistry.new
38
+
39
+ private_class_method :new
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class PrivacyPolicyResolver < Cmor::Cms::PageResolver
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class ApplicationViewHelper < Rao::ViewHelper::Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ = resource_table(resource: Cmor::Legal::Configuration) do |t|
2
+ = t.row :enforce_ssl do |resource|
3
+ - capture_haml do
4
+ - if resource.enforce_ssl
5
+ %span.label.label-success= t('true')
6
+ - else
7
+ %span.label.label-danger= t('false')
8
+ = t.row :filtered_log_parameters do |resource|
9
+ - resource.filter_personal_data_attributes.collect { |p| "<span class=\"label label-success\">#{p}</span>&nbsp;" }.join.html_safe
10
+ = t.row :enable_cookie_consent_banner do |resource|
11
+ - capture_haml do
12
+ - if resource.enable_cookie_consent_banner
13
+ %span.label.label-success= t('true')
14
+ - else
15
+ %span.label.label-danger= t('false')
16
+ - I18n.available_locales.each do |locale|
17
+ = t.row "privacy_policy_available_for_#{locale}" do |resource|
18
+ - capture_haml do
19
+ - if resource.privacy_policy_available_for(locale)
20
+ %span.label.label-success= t('true')
21
+ - else
22
+ %span.label.label-danger= t('false')
@@ -0,0 +1 @@
1
+ = table.column :root
@@ -0,0 +1 @@
1
+ = ap(@resource.to_hash.as_json).html_safe
@@ -0,0 +1 @@
1
+ = table.row :root
@@ -0,0 +1,14 @@
1
+ .well
2
+ = form.input :locale, collection: I18n.available_locales.map(&:to_s)
3
+
4
+ .well
5
+ ~ form.input :title
6
+ ~ form.input :meta_description, as: :string
7
+ ~ form.input :body
8
+
9
+ .well
10
+ = form.input :format, collection: Mime::SET.symbols
11
+ = form.input :handler, collection: ActionView::Template::Handlers.extensions
12
+
13
+ .well
14
+ = form.input :published, as: :boolean
@@ -0,0 +1,6 @@
1
+ = table.column :locale, sort: true
2
+ = table.acts_as_published_actions
3
+ - if table.method(:timestamps).arity > 0
4
+ = table.timestamps(sort: true)
5
+ - else
6
+ = table.timestamps
@@ -0,0 +1,8 @@
1
+ = table.row :locale
2
+ = table.row :meta_description
3
+ = table.row :body do |resource|
4
+ - capture_haml do
5
+ %pre= resource.body
6
+ = table.row :layout
7
+ = table.timestamp :published_at
8
+ = table.timestamps
@@ -0,0 +1,2 @@
1
+ Rails.application.config.assets.precompile += %w( cmor_legal.css )
2
+ Rails.application.config.assets.precompile += %w( cmor_legal.js )
@@ -0,0 +1,3 @@
1
+ Cmor.configure do |config|
2
+ config.administrador.register_engine('Cmor::Legal::Engine', {})
3
+ end
@@ -0,0 +1,20 @@
1
+ de:
2
+ classes:
3
+ cmor/legal/engine: Juristisches
4
+ routes:
5
+ cmor-legal-engine: juristisches
6
+ activerecord:
7
+ models:
8
+ cmor/legal/privacy_policy:
9
+ one: Datenschutzerklärung
10
+ other: Datenschutzerklärungen
11
+ activemodel:
12
+ models:
13
+ cmor/legal/cookie_preferences:
14
+ one: Cookie-Einstellungen
15
+ other: Cookie-Einstellungen
16
+ cmor/legal/personal_data:
17
+ one: Persönliche Daten
18
+ other: Persönliche Daten
19
+
20
+
@@ -0,0 +1,15 @@
1
+ en:
2
+ classes:
3
+ cmor/legal/engine: Legal
4
+ routes:
5
+ cmor-legal-engine: legal
6
+ activemodel:
7
+ models:
8
+ cmor/legal/cookie_preferences:
9
+ one: Cookie preferences
10
+ other: Cookie preferences
11
+ cmor/legal/personal_data:
12
+ one: Personal Data
13
+ other: Personal Data
14
+
15
+
@@ -0,0 +1,7 @@
1
+ Cmor::Legal::Engine.routes.draw do
2
+ resources :privacy_policies do
3
+ post :toggle_published, on: :member
4
+ end
5
+ resources :personal_data, :only => [:index, :show]
6
+ root to: 'home#index'
7
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Legal
4
+ module Configuration
5
+ def configure
6
+ yield self
7
+ end
8
+
9
+ mattr_accessor :resources_controllers do
10
+ -> { [] }
11
+ end
12
+
13
+ mattr_accessor :resource_controllers do
14
+ -> { [] }
15
+ end
16
+
17
+ mattr_accessor :service_controllers do
18
+ -> { [] }
19
+ end
20
+
21
+ mattr_accessor :sidebar_controllers do
22
+ -> { [] }
23
+ end
24
+
25
+ mattr_accessor :resources do
26
+ {}
27
+ end
28
+ mattr_accessor(:personal_data_root_classes) { [] }
29
+ mattr_accessor(:filter_personal_data_attributes) { [:email, :firstname, :lastname, :birthdate] }
30
+ mattr_accessor(:enforce_ssl) { true }
31
+ mattr_accessor(:enable_cookie_consent_banner) { true }
32
+ mattr_accessor(:cookies) do
33
+ ->(cookie_store = ::Cmor::Legal::CookieStore.new({})) { [
34
+ ::Cmor::Legal::Cookie.new(identifier: :basic, adjustable: false, default: true, cookie_store: cookie_store)
35
+ ]}
36
+ end
37
+ mattr_accessor(:cookie_prefix) { "#{Rails.application.class.name.deconstantize.underscore}-eu_gdpr-" }
38
+ mattr_accessor(:cookie_storage) { :cookies }
39
+
40
+ def personal_data
41
+ @personal_data ||= ::Cmor::Legal::PersonalDataRegistry.instance
42
+ end
43
+
44
+ def self.enforce_ssl?
45
+ enforce_ssl
46
+ end
47
+
48
+ def self.enable_cookie_consent_banner?
49
+ enable_cookie_consent_banner
50
+ end
51
+
52
+ def self.privacy_policy_defaults_for(locale)
53
+ privacy_policy_defaults[locale.to_sym]
54
+ end
55
+
56
+ def self.privacy_policy_available_for(locale)
57
+ Cmor::Legal::PrivacyPolicy.where(locale: locale).any?
58
+ end
59
+
60
+ def self.filtered_log_parameters
61
+ Rails.application.config.filter_parameters
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Legal
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace Cmor::Legal
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cmor/version"
4
+
5
+ module Cmor
6
+ module Legal
7
+ VERSION = ::Cmor::VERSION
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cmor_core"
4
+ require "cmor_core_backend"
5
+ require "cmor_cms"
6
+
7
+ require "cmor/legal/version"
8
+ require "cmor/legal/configuration"
9
+ require "cmor/legal/engine"
10
+
11
+ module Cmor
12
+ module Legal
13
+ extend Configuration
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor::Legal
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ desc "Generates the initializer"
7
+
8
+ source_root File.expand_path("../templates", __FILE__)
9
+
10
+ attr_reader :base_controller_class_name
11
+
12
+ def initialize(*args)
13
+ super
14
+ @base_controller_class_name = ENV.fetch("BASE_CONTROLLER_CLASS_NAME") { "::ApplicationController" }
15
+ end
16
+
17
+ def generate_initializer
18
+ template "initializer.rb", "config/initializers/cmor_legal.rb"
19
+ end
20
+
21
+ def generate_routes
22
+ route File.read(File.join(File.expand_path("../templates", __FILE__), "routes.source"))
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,69 @@
1
+ Cmor::Legal.configure do |config|
2
+ # Set the resources, that will be shown in the backend menu.
3
+ #
4
+ # Default: config.registered_controllers = -> {[
5
+ # Cmor::Legal::PrivacyPoliciesController,
6
+ # Cmor::Legal::PersonalDataController
7
+ # ]}
8
+ #
9
+ config.resources_controllers = -> {[
10
+ Cmor::Legal::PrivacyPoliciesController,
11
+ Cmor::Legal::PersonalDataController
12
+ ]}
13
+
14
+ # Add these attributes to the rails logging filter
15
+ #
16
+ # default: config.filter_personal_data_attributes = [:email, :firstname, :lastname, :birthdate]
17
+ #
18
+ config.filter_personal_data_attributes = [:email, :firstname, :lastname, :birthdate]
19
+
20
+ # If set to true and force_ssl is not set to true in production it will raise
21
+ # an exception when trying to boot rails.
22
+ #
23
+ # default: config.enforce_ssl = true
24
+ #
25
+ config.enforce_ssl = true
26
+
27
+ # Enables or disables the cookie message.
28
+ #
29
+ # default: config.enable_cookie_consent_banner = true
30
+ #
31
+ config.enable_cookie_consent_banner = true
32
+
33
+ config.cookies = ->(cookie_store = Cmor::Legal::CookieStore.new({})) {[
34
+ Cmor::Legal::Cookie.new(identifier: :basic, adjustable: false, default: true, cookie_store: cookie_store),
35
+ Cmor::Legal::Cookie.new(identifier: :analytics, adjustable: true, default: true, cookie_store: cookie_store),
36
+ Cmor::Legal::Cookie.new(identifier: :marketing, adjustable: true, default: true, cookie_store: cookie_store),
37
+ Cmor::Legal::Cookie.new(identifier: :social_media, adjustable: true, default: false, cookie_store: cookie_store)
38
+ ]}
39
+
40
+ # Sets the prefix to use for the consent cookies
41
+ #
42
+ # default: config.cookie_prefix = "#{Rails.application.class.name.deconstantize.underscore}-eu_gdpr-"
43
+ #
44
+ config.cookie_prefix = "#{Rails.application.class.name.deconstantize.underscore}-eu_gdpr-"
45
+
46
+ # Sets the cookie storage method. Can be either :session or :cookies
47
+ #
48
+ # default: config.cookie_storage = :cookies
49
+ #
50
+ config.cookie_storage = :cookies
51
+
52
+ # config.personal_data.register('User', log_removals: true, forget_with: :anonymization) do |u|
53
+ # u.attribute(:email, anonymize_with: :scrambler)
54
+ # u.attribute(:firstname, anonymize_with: :scrambler)
55
+ # u.attribute(:lastname, anonymize_with: :scrambler)
56
+ # u.attribute(:last_ip, anonymize_with: :nullifier)
57
+ # u.association(:posts) do |p|
58
+ # p.attribute(:title)
59
+ # p.attribute(:body)
60
+ # p.association(:gallery) do |g|
61
+ # g.attribute(:name)
62
+ # g.association(:pictures) do |p|
63
+ # p.attribute(:title)
64
+ # p.attribute(:asset) { |r| r.base64_encoded_asset }
65
+ # end
66
+ # end
67
+ # end
68
+ # end
69
+ end
@@ -0,0 +1,4 @@
1
+
2
+ localized do
3
+ mount Cmor::Legal::Engine, at: '/backend/cmor-legal-engine'
4
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # namespace :cmor_legal do
4
+ # desc "Explaining what the task does"
5
+ # task :example do
6
+ # # Task goes here
7
+ # end
8
+ # end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ factory :cmor_legal_privacy_policy, class: Cmor::Legal::PrivacyPolicy do
5
+ locale { I18n.locale }
6
+ end
7
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails_helper"
4
+
5
+ RSpec.describe "/de/backend/juristisches/privacy_policies", type: :feature do
6
+ # let(:resource_class) { EuGdpr::PrivacyPolicy }
7
+ let(:resource_class) { Cmor::Legal::PrivacyPolicy }
8
+ let(:resource) { create(:cmor_legal_privacy_policy) }
9
+ let(:resources) { I18n.available_locales.map { |l| create(:cmor_legal_privacy_policy, locale: l) } }
10
+
11
+ # List
12
+ it { resources; expect(subject).to implement_index_action(self) }
13
+
14
+ # Create
15
+ it {
16
+ expect(subject).to implement_create_action(self)
17
+ .for(resource_class)
18
+ .within_form("#new_privacy_policy") {
19
+ # fill the needed form inputs via capybara here
20
+ #
21
+ # Example:
22
+ #
23
+ # select 'de', from: 'slider[locale]'
24
+ # fill_in 'slider[name]', with: 'My first slider'
25
+ # check 'slider[auto_start]'
26
+ # fill_in 'slider[interval]', with: '3'
27
+ select "en", from: "privacy_policy[locale]"
28
+ fill_in "privacy_policy[title]", with: "Privacy Policy"
29
+ fill_in "privacy_policy[body]", with: "<h1>Privacy Policy</h1>"
30
+ }
31
+ .increasing { Cmor::Legal::PrivacyPolicy.count }.by(1)
32
+ }
33
+
34
+ # Read
35
+ it { expect(subject).to implement_show_action(self).for(resource) }
36
+
37
+ # Update
38
+ it {
39
+ expect(subject).to implement_update_action(self)
40
+ .for(resource)
41
+ .within_form(".edit_privacy_policy") {
42
+ # fill the needed form inputs via capybara here
43
+ #
44
+ # Example:
45
+ #
46
+ # fill_in 'slider[name]', with: 'New name'
47
+ fill_in "privacy_policy[body]", with: "<h1>Privacy Policy (v2.0)</h1>"
48
+ }
49
+ .updating
50
+ .from(resource.attributes)
51
+ .to("body" => "<h1>Privacy Policy (v2.0)</h1>") # Example: .to({ 'name' => 'New name' })
52
+ }
53
+
54
+ # Delete
55
+ it {
56
+ expect(subject).to implement_delete_action(self)
57
+ .for(resource)
58
+ .reducing { resource_class.count }.by(1)
59
+ }
60
+ end