cmor_legal 0.0.45.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +27 -0
- data/Rakefile +21 -0
- data/app/assets/config/manifest.js +2 -0
- data/app/assets/javascripts/cmor/legal/application.js +2 -0
- data/app/assets/javascripts/cmor/legal/application/keep.js +0 -0
- data/app/assets/javascripts/cmor_legal.js +2 -0
- data/app/assets/stylesheets/cmor/legal/application.css +3 -0
- data/app/assets/stylesheets/cmor/legal/application/keep.css +0 -0
- data/app/assets/stylesheets/cmor_legal.css +3 -0
- data/app/builders/cmor/legal/personal_data_hash_builder.rb +50 -0
- data/app/controllers/cmor/legal/home_controller.rb +8 -0
- data/app/controllers/cmor/legal/personal_data_controller.rb +24 -0
- data/app/controllers/cmor/legal/privacy_policies_controller.rb +18 -0
- data/app/models/cmor/legal/cookie.rb +87 -0
- data/app/models/cmor/legal/cookie_preferences.rb +47 -0
- data/app/models/cmor/legal/cookie_store.rb +39 -0
- data/app/models/cmor/legal/personal_data.rb +60 -0
- data/app/models/cmor/legal/privacy_policy.rb +24 -0
- data/app/registries/cmor/legal/personal_data_registry.rb +42 -0
- data/app/resolvers/cmor/legal/privacy_policy_resolver.rb +8 -0
- data/app/view_helpers/cmor/legal/application_view_helper.rb +8 -0
- data/app/views/cmor/legal/home/_index_extras.html.haml +22 -0
- data/app/views/cmor/legal/personal_data/_index_table.haml +1 -0
- data/app/views/cmor/legal/personal_data/_show_extras.haml +1 -0
- data/app/views/cmor/legal/personal_data/_show_table.haml +1 -0
- data/app/views/cmor/legal/privacy_policies/_form.haml +14 -0
- data/app/views/cmor/legal/privacy_policies/_index_table.haml +6 -0
- data/app/views/cmor/legal/privacy_policies/_show_table.html.haml +8 -0
- data/config/initializers/assets.rb +2 -0
- data/config/initializers/cmor.rb +3 -0
- data/config/locales/de.yml +20 -0
- data/config/locales/en.yml +15 -0
- data/config/routes.rb +7 -0
- data/lib/cmor/legal/configuration.rb +64 -0
- data/lib/cmor/legal/engine.rb +7 -0
- data/lib/cmor/legal/version.rb +9 -0
- data/lib/cmor_legal.rb +15 -0
- data/lib/generators/cmor/legal/install/install_generator.rb +26 -0
- data/lib/generators/cmor/legal/install/templates/initializer.rb +69 -0
- data/lib/generators/cmor/legal/install/templates/routes.source +4 -0
- data/lib/tasks/cmor/legal_tasks.rake +8 -0
- data/spec/factories/cmor_legal_privacy_policies.rb +7 -0
- data/spec/features/de/backend/juristisches/privacy_policies_feature_spec.rb +60 -0
- data/spec/lib/cmor/legal/version_spec.rb +7 -0
- data/spec/models/cmor/legal/cookie_spec.rb +63 -0
- data/spec/rails_helper.rb +62 -0
- data/spec/spec_helper.rb +98 -0
- data/spec/support/active_job.rb +3 -0
- data/spec/support/capybara.rb +3 -0
- data/spec/support/factory_bot.rb +16 -0
- data/spec/support/pry.rb +3 -0
- data/spec/support/rao-shoulda_matchers.rb +7 -0
- 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,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> " }.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,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
|
+
|
data/config/routes.rb
ADDED
@@ -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
|
data/lib/cmor_legal.rb
ADDED
@@ -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,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
|