phi_attrs 0.2.1 → 0.2.2
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.
- checksums.yaml +4 -4
- data/.github/workflows/publish.yml +28 -0
- data/lib/phi_attrs/phi_record.rb +87 -28
- data/lib/phi_attrs/rspec.rb +43 -0
- data/lib/phi_attrs/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0c95e0078a0816fa79591bab794e8c423d70d8792354cbb09cb69cda60b93d4b
|
|
4
|
+
data.tar.gz: 7af031bbc1cc1aa2ba308dc778611b590faf33b4e572e9e264477dde4fb24ace
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a13b688097f56ad46044a7da0f91402565e582383e80f522f6ef3829fc75e677a5518a3190e261114713177ab6ab746783eb10bec4cc83215cf8089ca17cbc35
|
|
7
|
+
data.tar.gz: 323f3337e8d687e5e8e781324fd284008344a9ee8c15ff737840b736908face774331b762783076ffd5bb9e37a150452e4d712129a4a30fc169a33edde3abec9
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: Publish Gem
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- "main"
|
|
7
|
+
tags:
|
|
8
|
+
- v*
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v2
|
|
15
|
+
- uses: actions/setup-ruby@v1
|
|
16
|
+
with:
|
|
17
|
+
ruby-version: '2.6'
|
|
18
|
+
- name: Install dependencies
|
|
19
|
+
run: |
|
|
20
|
+
gem install bundler:2.1.4
|
|
21
|
+
bundle install
|
|
22
|
+
- name: Release Gem
|
|
23
|
+
if: contains(github.ref, 'refs/tags/v')
|
|
24
|
+
uses: cadwallion/publish-rubygems-action@master
|
|
25
|
+
env:
|
|
26
|
+
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
|
27
|
+
RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
|
|
28
|
+
RELEASE_COMMAND: bundle exec rake release
|
data/lib/phi_attrs/phi_record.rb
CHANGED
|
@@ -107,8 +107,32 @@ module PhiAttrs
|
|
|
107
107
|
# end
|
|
108
108
|
# # PHI Access Disallowed
|
|
109
109
|
#
|
|
110
|
-
def allow_phi(user_id = nil, reason = nil, allow_only: nil)
|
|
111
|
-
|
|
110
|
+
def allow_phi(user_id = nil, reason = nil, allow_only: nil, &block)
|
|
111
|
+
get_phi(user_id, reason, allow_only: allow_only, &block)
|
|
112
|
+
return
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# Enable PHI access for any instance of this class in the block given only
|
|
117
|
+
# returning whatever the block returns.
|
|
118
|
+
#
|
|
119
|
+
# @param [String] user_id A unique identifier for the person accessing the PHI
|
|
120
|
+
# @param [String] reason The reason for accessing PHI
|
|
121
|
+
# @param [collection of PhiRecord] allow_only Specific PhiRecords to allow access to
|
|
122
|
+
# &block [block] The block in which PHI access is allowed for the class
|
|
123
|
+
#
|
|
124
|
+
# @example
|
|
125
|
+
# results = Foo.allow_phi('user@example.com', 'viewing patient record') do
|
|
126
|
+
# Foo.search(params)
|
|
127
|
+
# end
|
|
128
|
+
#
|
|
129
|
+
# @example
|
|
130
|
+
# loaded_foo = Foo.allow_phi('user@example.com', 'exporting patient list', allow_only: list_of_foos) do
|
|
131
|
+
# Bar.find_by(foo: list_of_foos).include(:foo)
|
|
132
|
+
# end
|
|
133
|
+
#
|
|
134
|
+
def get_phi(user_id = nil, reason = nil, allow_only: nil)
|
|
135
|
+
raise ArgumentError, 'block required' unless block_given?
|
|
112
136
|
|
|
113
137
|
if allow_only.present?
|
|
114
138
|
raise ArgumentError, 'allow_only must be iterable with each' unless allow_only.respond_to?(:each)
|
|
@@ -125,7 +149,7 @@ module PhiAttrs
|
|
|
125
149
|
allow_only.each { |t| t.allow_phi!(user_id, reason) }
|
|
126
150
|
end
|
|
127
151
|
|
|
128
|
-
yield if block_given?
|
|
152
|
+
result = yield if block_given?
|
|
129
153
|
|
|
130
154
|
__instances_with_extended_phi.each do |obj|
|
|
131
155
|
if frozen_instances.include?(obj)
|
|
@@ -143,6 +167,8 @@ module PhiAttrs
|
|
|
143
167
|
allow_only.each { |t| t.disallow_last_phi!(preserve_extensions: true) }
|
|
144
168
|
# We've handled any newly extended allowances ourselves above
|
|
145
169
|
end
|
|
170
|
+
|
|
171
|
+
result
|
|
146
172
|
end
|
|
147
173
|
|
|
148
174
|
# Explicitly disallow phi access in a specific area of code. This does not
|
|
@@ -335,17 +361,41 @@ module PhiAttrs
|
|
|
335
361
|
# end
|
|
336
362
|
# # PHI Access Disallowed Here
|
|
337
363
|
#
|
|
338
|
-
def allow_phi(user_id = nil, reason = nil)
|
|
339
|
-
|
|
364
|
+
def allow_phi(user_id = nil, reason = nil, &block)
|
|
365
|
+
get_phi(user_id, reason, &block)
|
|
366
|
+
return
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
# Enable PHI access for a single instance of this class inside the block.
|
|
371
|
+
# Returns whatever is returned from the block.
|
|
372
|
+
# Nested calls to get_phi will log once per nested call
|
|
373
|
+
#s
|
|
374
|
+
# @param [String] user_id A unique identifier for the person accessing the PHI
|
|
375
|
+
# @param [String] reason The reason for accessing PHI
|
|
376
|
+
# @yield The block in which phi access is allowed
|
|
377
|
+
#
|
|
378
|
+
# @return PHI
|
|
379
|
+
#
|
|
380
|
+
# @example
|
|
381
|
+
# foo = Foo.find(1)
|
|
382
|
+
# phi_data = foo.get_phi('user@example.com', 'viewing patient record') do
|
|
383
|
+
# foo.phi_field
|
|
384
|
+
# end
|
|
385
|
+
#
|
|
386
|
+
def get_phi(user_id = nil, reason = nil)
|
|
387
|
+
raise ArgumentError, 'block required' unless block_given?
|
|
340
388
|
|
|
341
389
|
extended_instances = @__phi_relations_extended.clone
|
|
342
390
|
allow_phi!(user_id, reason)
|
|
343
391
|
|
|
344
|
-
yield if block_given?
|
|
392
|
+
result = yield if block_given?
|
|
345
393
|
|
|
346
394
|
new_extensions = @__phi_relations_extended - extended_instances
|
|
347
395
|
disallow_last_phi!(preserve_extensions: true)
|
|
348
396
|
revoke_extended_phi!(new_extensions) if new_extensions.any?
|
|
397
|
+
|
|
398
|
+
result
|
|
349
399
|
end
|
|
350
400
|
|
|
351
401
|
# Revoke all PHI access for a single instance of this class.
|
|
@@ -412,6 +462,25 @@ module PhiAttrs
|
|
|
412
462
|
end
|
|
413
463
|
end
|
|
414
464
|
|
|
465
|
+
|
|
466
|
+
# The unique identifier for whom access has been allowed on this instance.
|
|
467
|
+
# This is what was passed in when PhiRecord#allow_phi! was called.
|
|
468
|
+
#
|
|
469
|
+
# @return [String] the user_id passed in to allow_phi!
|
|
470
|
+
#
|
|
471
|
+
def phi_allowed_by
|
|
472
|
+
phi_context[:user_id]
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
# The access reason for allowing access to this instance.
|
|
476
|
+
# This is what was passed in when PhiRecord#allow_phi! was called.
|
|
477
|
+
#
|
|
478
|
+
# @return [String] the reason passed in to allow_phi!
|
|
479
|
+
#
|
|
480
|
+
def phi_access_reason
|
|
481
|
+
phi_context[:reason]
|
|
482
|
+
end
|
|
483
|
+
|
|
415
484
|
# Whether PHI access is allowed for a single instance of this class
|
|
416
485
|
#
|
|
417
486
|
# @example
|
|
@@ -424,6 +493,18 @@ module PhiAttrs
|
|
|
424
493
|
!phi_context.nil? && phi_context[:phi_access_allowed]
|
|
425
494
|
end
|
|
426
495
|
|
|
496
|
+
# Require phi access. Raises an error pre-emptively if it has not been granted.
|
|
497
|
+
#
|
|
498
|
+
# @example
|
|
499
|
+
# def use_phi(patient_record)
|
|
500
|
+
# patient_record.require_phi!
|
|
501
|
+
# # ...use PHI Freely
|
|
502
|
+
# end
|
|
503
|
+
#
|
|
504
|
+
def require_phi!
|
|
505
|
+
raise PhiAccessException, 'PHI Access required, please call allow_phi or allow_phi! first' unless phi_allowed?
|
|
506
|
+
end
|
|
507
|
+
|
|
427
508
|
def reload
|
|
428
509
|
@__phi_relations_extended.clear
|
|
429
510
|
super
|
|
@@ -479,28 +560,6 @@ module PhiAttrs
|
|
|
479
560
|
@__phi_log_keys = [PHI_ACCESS_LOG_TAG, self.class.name, @__phi_log_id]
|
|
480
561
|
end
|
|
481
562
|
|
|
482
|
-
# The unique identifier for whom access has been allowed on this instance.
|
|
483
|
-
# This is what was passed in when PhiRecord#allow_phi! was called.
|
|
484
|
-
#
|
|
485
|
-
# @private
|
|
486
|
-
#
|
|
487
|
-
# @return [String] the user_id passed in to allow_phi!
|
|
488
|
-
#
|
|
489
|
-
def phi_allowed_by
|
|
490
|
-
phi_context[:user_id]
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
# The access reason for allowing access to this instance.
|
|
494
|
-
# This is what was passed in when PhiRecord#allow_phi! was called.
|
|
495
|
-
#
|
|
496
|
-
# @private
|
|
497
|
-
#
|
|
498
|
-
# @return [String] the reason passed in to allow_phi!
|
|
499
|
-
#
|
|
500
|
-
def phi_access_reason
|
|
501
|
-
phi_context[:reason]
|
|
502
|
-
end
|
|
503
|
-
|
|
504
563
|
def phi_context
|
|
505
564
|
instance_phi_context || class_phi_context
|
|
506
565
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'rspec/expectations'
|
|
2
|
+
|
|
3
|
+
DO_NOT_SPECIFY = "do not specify `allowed_by` or `with_access_reason` for negated `allow_phi_access`"
|
|
4
|
+
|
|
5
|
+
RSpec::Matchers.define :allow_phi_access do
|
|
6
|
+
match do |result|
|
|
7
|
+
@allowed = result.phi_allowed?
|
|
8
|
+
@user_id_matches = @user_id.nil? || @user_id == result.phi_allowed_by
|
|
9
|
+
@reason_matches = @reason.nil? || @reason == result.phi_access_reason
|
|
10
|
+
|
|
11
|
+
@allowed && @user_id_matches && @reason_matches
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
match_when_negated do |result|
|
|
15
|
+
raise ArgumentError, DO_NOT_SPECIFY unless @user_id.nil? && @reason.nil?
|
|
16
|
+
|
|
17
|
+
!result.phi_allowed?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
chain :allowed_by do |user_id|
|
|
21
|
+
@user_id = user_id
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
chain :with_access_reason do |reason|
|
|
25
|
+
@reason = reason
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# :nocov:
|
|
29
|
+
failure_message do |result|
|
|
30
|
+
msgs = []
|
|
31
|
+
|
|
32
|
+
msgs = ['PHI Access was not allowed.'] unless @allowed
|
|
33
|
+
msgs << "PHI Access was allowed by '#{result.phi_allowed_by}' (not '#{@user_id}')." unless @user_id_matches
|
|
34
|
+
msgs << "PHI Access was allowed because '#{result.phi_access_reason}' (not because '#{@reason}')." unless @reason_matches
|
|
35
|
+
|
|
36
|
+
msgs.join "\n"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
failure_message_when_negated do |result|
|
|
40
|
+
"PHI access was allowed by '#{result.phi_allowed_by}', because '#{result.phi_access_reason}'"
|
|
41
|
+
end
|
|
42
|
+
# :nocov:
|
|
43
|
+
end
|
data/lib/phi_attrs/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: phi_attrs
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Wyatt Kirby
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-11-
|
|
11
|
+
date: 2020-11-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -228,6 +228,7 @@ extensions: []
|
|
|
228
228
|
extra_rdoc_files: []
|
|
229
229
|
files:
|
|
230
230
|
- ".github/workflows/build.yml"
|
|
231
|
+
- ".github/workflows/publish.yml"
|
|
231
232
|
- ".gitignore"
|
|
232
233
|
- ".rspec"
|
|
233
234
|
- ".rubocop.yml"
|
|
@@ -259,6 +260,7 @@ files:
|
|
|
259
260
|
- lib/phi_attrs/logger.rb
|
|
260
261
|
- lib/phi_attrs/phi_record.rb
|
|
261
262
|
- lib/phi_attrs/railtie.rb
|
|
263
|
+
- lib/phi_attrs/rspec.rb
|
|
262
264
|
- lib/phi_attrs/version.rb
|
|
263
265
|
- phi_attrs.gemspec
|
|
264
266
|
homepage: http://www.apsis.io
|