cmor_legal 0.0.45.pre

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 (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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 726b8847cf2f2dd601b19e2a2c274791519ba598ebfeddfe3507938bf11daf6e
4
+ data.tar.gz: 1f5313a37e144c24e6087d80c2a377dc64e7a3be5cd423075ecb4df4a5bd4068
5
+ SHA512:
6
+ metadata.gz: 16958f751012d2a40da403acb98d05adcb1967ced86fbb7fb78143c248cbb6a8cafde58c2241ec6ef01560ad38f20903a7007c3d950e91e2e8bf20d5cc122701
7
+ data.tar.gz: 1197a0bdc717c8754acc61c6687071e92a10ef9e6d76b186c96455fede242e7bc3bad7800b5b302a0ddd4cec5e6f1ce9ee824dc727339c04063cf89cdde22f65
@@ -0,0 +1,20 @@
1
+ Copyright 2020 Roberto Vasquez Angel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,27 @@
1
+ # Cmor::Legal
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'cmor_legal'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install cmor_legal
22
+ ```
23
+ ## Contributing
24
+ Contribution directions go here.
25
+
26
+ ## License
27
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "bundler/setup"
5
+ rescue LoadError
6
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
7
+ end
8
+
9
+ require "rdoc/task"
10
+
11
+ RDoc::Task.new(:rdoc) do |rdoc|
12
+ rdoc.rdoc_dir = "rdoc"
13
+ rdoc.title = "Cmor::Legal"
14
+ rdoc.options << "--line-numbers"
15
+ rdoc.rdoc_files.include("README.md")
16
+ rdoc.rdoc_files.include("lib/**/*.rb")
17
+ end
18
+
19
+ Bundler::GemHelper.install_tasks
20
+
21
+ require "rails/dummy/tasks"
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/cmor/legal .js
2
+ //= link_directory ../stylesheets/cmor/legal .css
@@ -0,0 +1,2 @@
1
+ //= require_tree ./application
2
+
@@ -0,0 +1,2 @@
1
+ //= require ./cmor/legal/application
2
+
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require_tree ./application
3
+ */
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require ./cmor/legal/application
3
+ */
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class PersonalDataHashBuilder
6
+ include ActiveModel::Model
7
+ attr_accessor :root, :options, :block
8
+
9
+ def initialize(attributes, options = {})
10
+ super(attributes)
11
+ @builder_options = options
12
+ invoke_block
13
+ end
14
+
15
+ def attribute(name, options = {})
16
+ if with_options?
17
+ hash[:attributes][name] = { options: options }
18
+ else
19
+ hash[:attributes] << name
20
+ end
21
+ end
22
+
23
+ def association(name, options = {}, &block)
24
+ if with_options?
25
+ hash[:associations][name] = { options: options, attributes: Cmor::Legal::PersonalDataHashBuilder.new(block: block).hash }
26
+ else
27
+ hash[name] = Cmor::Legal::PersonalDataHashBuilder.new({ block: block }, @builder_options).hash
28
+ end
29
+ end
30
+
31
+ def hash
32
+ if with_options?
33
+ @hash ||= { root: root, options: options, attributes: {}, associations: {} }
34
+ else
35
+ @hash ||= { attributes: [] }
36
+ end
37
+ end
38
+
39
+ private
40
+ def invoke_block
41
+ self.block.call(self)
42
+ end
43
+
44
+ def with_options?
45
+ @builder_options[:with_options] = true if @builder_options[:with_options].nil?
46
+ @builder_options[:with_options]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class HomeController < Cmor::Core::Backend::HomeController::Base
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class PersonalDataController < Cmor::Core::Backend::ResourcesController::Base
6
+ def self.resource_class
7
+ Cmor::Legal::PersonalData
8
+ end
9
+
10
+ def self.available_rest_actions
11
+ super - %i(edit new)
12
+ end
13
+
14
+ private
15
+ def load_collection
16
+ @collection = Kaminari.paginate_array(load_collection_scope.all).page(params[:page])
17
+ end
18
+
19
+ def permitted_params
20
+ params.require(:personal_data_registry).permit()
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class PrivacyPoliciesController < Cmor::Core::Backend::ResourcesController::Base
6
+ include Rao::ResourcesController::ActsAsPublishedConcern
7
+
8
+ def self.resource_class
9
+ Cmor::Legal::PrivacyPolicy
10
+ end
11
+
12
+ private
13
+ def permitted_params
14
+ params.require(:privacy_policy).permit(:locale, :meta_description, :title, :body, :format, :handler, :published)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class Cookie
6
+ include ActiveModel::Model
7
+
8
+ attr_accessor :identifier, :adjustable, :default, :value, :cookie_store
9
+
10
+ def initialize(attributes = {})
11
+ attributes.each do |key, value|
12
+ send("#{key}=", value)
13
+ end
14
+ end
15
+
16
+ def self.to_boolean(string)
17
+ return true if ["true", true, "1", 1].include?(string)
18
+ return false if ["false", false, "0", 0, nil].include?(string)
19
+ raise "Can't translate #{string} to boolean"
20
+ end
21
+
22
+ def self.all(cookie_store = nil)
23
+ Cmor::Legal::Configuration.cookies.call(cookie_store)
24
+ end
25
+
26
+ def self.first(cookie_store = nil)
27
+ all(cookie_store).first
28
+ end
29
+
30
+ def self.accepted(cookie_store = nil)
31
+ all(cookie_store).select { |resource| resource.accepted? }
32
+ end
33
+
34
+ def value
35
+ initialize_value if @value.nil?
36
+ self.class.to_boolean(@value)
37
+ end
38
+
39
+ def value=(value)
40
+ @value = self.class.to_boolean(value)
41
+ end
42
+
43
+ def value_from_cookie_store
44
+ cookie_store.get_value(identifier)
45
+ end
46
+
47
+ def accepted?
48
+ # First check if the user has made a decision on this cookie.
49
+ if pending?
50
+ # The user has not decided on this cookie.
51
+ #
52
+ # If the cookie can't be changed by the user take the default value
53
+ # otherwise set it to false.
54
+ readonly? ? default : false
55
+ else
56
+ # The has accepted/rejected the cookie. Use the actual value.
57
+ !!value
58
+ end
59
+ end
60
+
61
+ def readonly?
62
+ !adjustable
63
+ end
64
+
65
+ def save
66
+ cookie_store.set_value(identifier, value, default_expire)
67
+ end
68
+
69
+ def pending?
70
+ value_from_cookie_store.nil?
71
+ end
72
+
73
+ private
74
+ def default_expire
75
+ 1.year.from_now
76
+ end
77
+
78
+ def initialize_value
79
+ @value = pending? ? default : value_from_cookie_store
80
+ end
81
+
82
+ def cookie_store
83
+ @cookie_store ||= ::Cmor::Legal::CookieStore.new({})
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class CookiePreferences
6
+ include ActiveModel::Model
7
+
8
+ attr_accessor :cookies, :cookie_store
9
+
10
+ def initialize(*attrs)
11
+ super
12
+ @cookies ||= ::Cmor::Legal::Configuration.cookies.call(cookie_store)
13
+ @cookies.map(&:identifier).each do |identifier|
14
+ singleton_class.class_eval do
15
+ # attr_accessor c
16
+ define_method(identifier) do
17
+ @cookies.find { |c| c.identifier == identifier }.value
18
+ end
19
+
20
+ define_method("#{identifier}=") do |value|
21
+ @cookies.find { |c| c.identifier == identifier }.value = value
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def update_attributes(attributes)
28
+ attributes.each do |identifier, value|
29
+ @cookies.find { |c| c.identifier == identifier.to_sym }.value = value
30
+ end
31
+ save
32
+ end
33
+
34
+ def save
35
+ @cookies.each { |c| c.save }
36
+ end
37
+
38
+ def accepted?(identifier)
39
+ send(identifier)
40
+ end
41
+
42
+ def accepted_cookies
43
+ cookies.select { |c| c.accepted? }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class CookieStore
6
+ attr_accessor :cookies
7
+
8
+ def initialize(store)
9
+ @store = store
10
+ end
11
+
12
+ def self.cookie_prefix
13
+ ::Cmor::Legal::Configuration.cookie_prefix
14
+ end
15
+
16
+ def self.add_prefix_to_identifier(identifier)
17
+ "#{cookie_prefix}#{identifier}"
18
+ end
19
+
20
+ def get_value(identifier)
21
+ @store[self.class.add_prefix_to_identifier(identifier)]
22
+ end
23
+
24
+ def set_value(identifier, value, expires = nil)
25
+ if @store.is_a?(ActionDispatch::Cookies::CookieJar)
26
+ @store[self.class.add_prefix_to_identifier(identifier)] = { value: value, expires: expires }
27
+ else
28
+ @store[self.class.add_prefix_to_identifier(identifier)] = value
29
+ end
30
+ end
31
+
32
+ def cookies
33
+ @store.select { |key, value| key.to_s.start_with?(self.class.cookie_prefix) }.each_with_object({}) do |(k, v), m|
34
+ m[k.gsub(self.class.cookie_prefix, "")] = v
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cmor
4
+ module Legal
5
+ class PersonalData
6
+ include ActiveModel::Model
7
+
8
+ attr_accessor :root, :options, :block
9
+
10
+ def to_hash_with_options
11
+ @hash ||= build_hash_with_options!
12
+ end
13
+
14
+ def build_hash_with_options!
15
+ Cmor::Legal::PersonalDataHashBuilder.new({ root: root, options: options, block: block }, { with_options: true }).hash
16
+ end
17
+
18
+ def to_hash
19
+ @hash ||= build_hash!
20
+ end
21
+
22
+ def build_hash!
23
+ Cmor::Legal::PersonalDataHashBuilder.new({ root: root, options: options, block: block }, { with_options: false }).hash
24
+ end
25
+
26
+ def self.all
27
+ Cmor::Legal::PersonalDataRegistry.all
28
+ end
29
+
30
+ def self.count
31
+ Cmor::Legal::PersonalDataRegistry.count
32
+ end
33
+
34
+ def self.attribute_names
35
+ [:root, :options, :block]
36
+ end
37
+
38
+ def self.find(id)
39
+ all.find { |x| x.root == id.gsub("-", "/").camelize }
40
+ end
41
+
42
+ def id
43
+ root.underscore.gsub("/", "-")
44
+ end
45
+
46
+ def to_param
47
+ id
48
+ end
49
+
50
+ def to_s
51
+ [self.class.model_name.human, root_model_human].compact.join(" - ")
52
+ end
53
+
54
+ def root_model_human
55
+ return if root.nil?
56
+ root.constantize.model_name.human
57
+ end
58
+ end
59
+ end
60
+ end