gdpr_admin 1.3.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9b5cc14d1e0f88e99bec3ccd100795cc1985ef86fa559fbdd2639bdd5bef1ee4
4
- data.tar.gz: 5c07836dec53a6265e3fcd6516f910a22b6834234bea5f39890030ba394d0e5c
3
+ metadata.gz: 99489f549c8f701322c68c19a73dad4796af585f7b981ac8680590b14e2b299e
4
+ data.tar.gz: c2918882ca853ded91dc6ecd8aa52ae95dd6c2a9cac99d6c829917693d7e96e5
5
5
  SHA512:
6
- metadata.gz: f4552232540bf1153c32e15ccc1ec0ed5f5a399649bd5618ded36476881124d2496a1f345deec8f5baf98ecba1ff4e0161743ca905abae45761024d9c68432e0
7
- data.tar.gz: 8169ff0b5040484ceac0084601246d19d875e222509ec2f1a2dab055822d79db13b999c6a96468167cf39adfe5cc26b0aff60b9c046bbcc31422177e2ca66684
6
+ metadata.gz: 29c763ef8b44f45c56c63c4da8fc8b275dd2a2ce3f6bdb1c8808015543343bcafc1599450d74c2d54be74a8c2020c24649fd31f94d2f0188e38fcc19bc8b6637
7
+ data.tar.gz: b68927faf70d507c7992f7a64fc2a7eab37034533ebc492d93490179e6e0f276ece51ef2855b06ba938ef03fe974230a2770145a7a263a0fcf2baf181c588b19
data/README.md CHANGED
@@ -35,6 +35,11 @@ Or install it yourself as:
35
35
  $ gem install gdpr_admin
36
36
  ```
37
37
 
38
+ Then install the migrations:
39
+ ```bash
40
+ $ rails gdpr_admin:install:migrations
41
+ ```
42
+
38
43
  ## Usage
39
44
 
40
45
  Create your data policies file within `app/gdpr` _(configurable)_ and inherit from `GdprAdmin::ApplicationDataPolicy`.
@@ -138,6 +143,41 @@ same anonymized value. _(note: different values may also yield the same value)_
138
143
 
139
144
  To use the built-in anonymizer functions, you need to install the gem `faker`.
140
145
 
146
+ ## Data Policy Hooks
147
+ For advanced use cases, you may install hooks that are run at different stages of the data policy process.
148
+
149
+ ### `before_process`
150
+ Will be run before the policy is executed. Calling `skip_data_policy!` will raise `GdprAdmin::SkipDataPolicyError` and
151
+ stop the execution of the data policy.
152
+
153
+ ```ruby
154
+ class ContactDataPolicy < GdprAdmin::ApplicationDataPolicy
155
+ before_process :skip_internal_contacts!
156
+
157
+ private
158
+
159
+ def skip_internal_contacts!
160
+ skip_data_policy! if contact.email =~ /.*@company\.com/
161
+ end
162
+ end
163
+ ```
164
+
165
+ ### `before_process_record`
166
+ Called before processing a record (either erasing or exporting). Calling `skip_record!` will raise `GdprAdmin::SkipRecordError` and
167
+ skip processing that particular record.
168
+
169
+ ```ruby
170
+ class UserDataPolicy < GdprAdmin::ApplicationDataPolicy
171
+ before_process :skip_super_admins!
172
+
173
+ private
174
+
175
+ def skip_super_admins!(user)
176
+ skip_record! if user.role == 'super_admin'
177
+ end
178
+ end
179
+ ```
180
+
141
181
  ## GDPR Request
142
182
  A GDPR Request (`GdprAdmin::Request`) represents a request to remove a subject's data, tenant's data, or export subject data.
143
183
 
@@ -35,7 +35,7 @@ module GdprAdmin
35
35
  GdprAdmin.load_data_policies
36
36
  with_lock { processing! }
37
37
  with_lock do
38
- GdprAdmin.config.tenant_adapter.with_tenant(tenant) { process_policies }
38
+ process_policies
39
39
  completed!
40
40
  end
41
41
  rescue StandardError
@@ -63,13 +63,7 @@ module GdprAdmin
63
63
 
64
64
  def process_policies
65
65
  ApplicationDataPolicy.descendants.each do |policy_class|
66
- policy = policy_class.new(self)
67
- policy.scope.find_each do |record|
68
- policy.export(record) if export?
69
- policy.erase(record) if erase?
70
- end
71
- rescue SkipDataPolicyError
72
- next
66
+ policy_class.process(self)
73
67
  end
74
68
  end
75
69
 
@@ -2,15 +2,34 @@
2
2
 
3
3
  module GdprAdmin
4
4
  class ApplicationDataPolicy
5
+ include Helpers::DataPolicyHelper
5
6
  include Helpers::EraseHelper
6
7
  include Helpers::ScopeHelper
7
8
 
9
+ class << self
10
+ attr_reader :before_process_hooks, :before_process_record_hooks
11
+
12
+ def before_process(method)
13
+ @before_process_hooks ||= []
14
+ @before_process_hooks << method
15
+ end
16
+
17
+ def before_process_record(method)
18
+ @before_process_record_hooks ||= []
19
+ @before_process_record_hooks << method
20
+ end
21
+
22
+ def process(request)
23
+ new(request).process
24
+ end
25
+ end
26
+
8
27
  def initialize(request)
9
28
  @request = request
10
29
  end
11
30
 
12
31
  def scope
13
- raise SkipDataPolicyError
32
+ skip_data_policy!
14
33
  end
15
34
 
16
35
  def export(_record)
@@ -21,8 +40,57 @@ module GdprAdmin
21
40
  raise NotImplementedError
22
41
  end
23
42
 
43
+ def process
44
+ GdprAdmin.config.tenant_adapter.with_tenant(request.tenant) do
45
+ run_preprocessors
46
+ process_scope(scope)
47
+ rescue SkipDataPolicyError
48
+ nil
49
+ end
50
+ end
51
+
52
+ def process_scope(scope)
53
+ scope.find_each do |record|
54
+ process_record(record)
55
+ end
56
+ end
57
+
24
58
  protected
25
59
 
26
60
  attr_reader :request
61
+
62
+ def process_record(record)
63
+ run_record_preprocessors(record)
64
+ export(record) if request.export?
65
+ erase(record) if request.erase?
66
+ rescue SkipRecordError
67
+ nil
68
+ end
69
+
70
+ def run_preprocessors
71
+ before_process_hooks = self.class.before_process_hooks || []
72
+ before_process_hooks.each do |hook|
73
+ call_hook(hook)
74
+ end
75
+ end
76
+
77
+ def run_record_preprocessors(record)
78
+ before_process_record_hooks = self.class.before_process_record_hooks || []
79
+ before_process_record_hooks.each do |hook|
80
+ call_hook(hook, record)
81
+ end
82
+ end
83
+
84
+ def call_hook(hook, value = nil)
85
+ hook = method(hook) unless hook.respond_to?(:call)
86
+
87
+ arity = arity_of(hook)
88
+ args = [value].take(arity).reverse
89
+ instance_exec(*args, &hook)
90
+ end
91
+
92
+ def arity_of(method_or_proc)
93
+ defined?(T::Utils.arity) ? T::Utils.arity(method_or_proc) : method_or_proc.arity
94
+ end
27
95
  end
28
96
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GdprAdmin
4
+ module Helpers
5
+ module DataPolicyHelper
6
+ def skip_data_policy!
7
+ raise SkipDataPolicyError
8
+ end
9
+
10
+ def skip_record!
11
+ raise SkipRecordError
12
+ end
13
+
14
+ def model_data_policy_class(model)
15
+ model = model.constantize if model.is_a?(String)
16
+ return model.data_policy_class if model.respond_to?(:data_policy_class)
17
+
18
+ prefix = model.data_policy_prefix if model.respond_to?(:data_policy_prefix)
19
+ "#{prefix}#{model}DataPolicy".constantize
20
+ rescue NameError
21
+ nil
22
+ end
23
+ end
24
+ end
25
+ end
@@ -9,13 +9,7 @@ module GdprAdmin
9
9
 
10
10
  def erase(version, item_fields = nil)
11
11
  item_fields ||= infer_item_fields(version)
12
- return if item_fields.nil?
13
-
14
- base_changes = {
15
- object: anonymize_version_object(version, item_fields),
16
- object_changes: anonymize_version_object_changes(version, item_fields),
17
- }.compact
18
- erase_fields(version, fields, base_changes)
12
+ erase_fields(version, fields, base_changes(version, item_fields))
19
13
  end
20
14
 
21
15
  def fields
@@ -24,18 +18,21 @@ module GdprAdmin
24
18
 
25
19
  private
26
20
 
21
+ def base_changes(version, item_fields)
22
+ return {} if item_fields.blank?
23
+
24
+ {
25
+ object: anonymize_version_object(version, item_fields),
26
+ object_changes: anonymize_version_object_changes(version, item_fields),
27
+ }.compact
28
+ end
29
+
27
30
  def infer_item_fields(version)
28
31
  infer_data_policy_class(version)&.new(request)&.try(:fields)
29
32
  end
30
33
 
31
34
  def infer_data_policy_class(version)
32
- model = version.item_type.constantize.new
33
- return model.data_policy_class if model.respond_to?(:data_policy_class)
34
-
35
- prefix = model.data_policy_prefix if model.respond_to?(:data_policy_prefix)
36
- "#{prefix}#{version.item_type}DataPolicy".constantize
37
- rescue NameError
38
- nil
35
+ model_data_policy_class(version.item_type)
39
36
  end
40
37
  end
41
38
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GdprAdmin
4
+ class SkipRecordError < StandardError; end
5
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  # :nocov:
4
4
  module GdprAdmin
5
- VERSION = '1.3.0'
5
+ VERSION = '1.4.1'
6
6
  end
7
7
  # :nocov:
data/lib/gdpr_admin.rb CHANGED
@@ -6,6 +6,8 @@ require 'gdpr_admin/configuration'
6
6
  require 'gdpr_admin/error'
7
7
  require 'gdpr_admin/invalid_status_error'
8
8
  require 'gdpr_admin/skip_data_policy_error'
9
+ require 'gdpr_admin/skip_record_error'
10
+ require 'gdpr_admin/helpers/data_policy_helper'
9
11
  require 'gdpr_admin/helpers/erase_helper'
10
12
  require 'gdpr_admin/helpers/scope_helper'
11
13
  require 'gdpr_admin/application_data_policy'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gdpr_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Colex
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-01 00:00:00.000000000 Z
11
+ date: 2023-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -165,6 +165,7 @@ files:
165
165
  - lib/gdpr_admin/configuration.rb
166
166
  - lib/gdpr_admin/engine.rb
167
167
  - lib/gdpr_admin/error.rb
168
+ - lib/gdpr_admin/helpers/data_policy_helper.rb
168
169
  - lib/gdpr_admin/helpers/erase_helper.rb
169
170
  - lib/gdpr_admin/helpers/field_anonymizer_helper.rb
170
171
  - lib/gdpr_admin/helpers/paper_trail_helper.rb
@@ -172,6 +173,7 @@ files:
172
173
  - lib/gdpr_admin/invalid_status_error.rb
173
174
  - lib/gdpr_admin/paper_trail/version_data_policy.rb
174
175
  - lib/gdpr_admin/skip_data_policy_error.rb
176
+ - lib/gdpr_admin/skip_record_error.rb
175
177
  - lib/gdpr_admin/tenant_adapters/acts_as_tenant_adapter.rb
176
178
  - lib/gdpr_admin/version.rb
177
179
  - lib/tasks/gdpr_admin_tasks.rake