phi_attrs 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 02627c096610024d700d1bc934ae30f39f64cbcc
4
+ data.tar.gz: c8f2fa25466c2f1360033ed73dd7d28fb89f1d17
5
+ SHA512:
6
+ metadata.gz: 117aea4893f55a9dd57d18efd3e0f4795add98e2654d83d7ffe44a452154824ed499d8b05de61d8083d7bf9af183a2a7036e88d1532822a38bfae895692356dc
7
+ data.tar.gz: 543f080561a1d15412592ca91af1e8eb15040eb26c07c9a6e4d53758cfaa446becc96e7b1a5217288332625aca7e770a35ffda095cd86eaf8ba89050d3c612be
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ *Gemfile.lock
12
+ .byebug_history
13
+
14
+ /test/sample/tmp/
15
+ *.sqlite3
16
+ *.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rspec_status ADDED
@@ -0,0 +1,14 @@
1
+ example_id | status | run_time |
2
+ ------------------------------- | ------ | --------------- |
3
+ ./spec/phi_attrs_spec.rb[1:1] | passed | 0.0012 seconds |
4
+ ./spec/phi_attrs_spec.rb[1:2:1] | passed | 0.00702 seconds |
5
+ ./spec/phi_attrs_spec.rb[1:2:2] | passed | 0.00064 seconds |
6
+ ./spec/phi_attrs_spec.rb[1:2:3] | passed | 0.00054 seconds |
7
+ ./spec/phi_attrs_spec.rb[1:3:1] | passed | 0.00642 seconds |
8
+ ./spec/phi_attrs_spec.rb[1:3:2] | passed | 0.00121 seconds |
9
+ ./spec/phi_attrs_spec.rb[1:4:1] | passed | 0.00085 seconds |
10
+ ./spec/phi_attrs_spec.rb[1:4:2] | passed | 0.00075 seconds |
11
+ ./spec/phi_attrs_spec.rb[1:4:3] | passed | 0.00086 seconds |
12
+ ./spec/phi_attrs_spec.rb[1:5:1] | passed | 0.00068 seconds |
13
+ ./spec/phi_attrs_spec.rb[1:5:2] | passed | 0.00444 seconds |
14
+ ./spec/phi_attrs_spec.rb[1:5:3] | passed | 0.00091 seconds |
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.1
data/Appraisals ADDED
@@ -0,0 +1,4 @@
1
+ appraise 'rails-5.0' do
2
+ gem 'rails', '5.0.0'
3
+ gem 'tzinfo-data'
4
+ end
data/Dockerfile ADDED
@@ -0,0 +1,16 @@
1
+ FROM ruby:2.5.1-alpine
2
+ MAINTAINER wyatt@apsis.io
3
+
4
+ RUN apk add --no-cache --update \
5
+ bash \
6
+ alpine-sdk \
7
+ sqlite-dev
8
+
9
+ ENV APP_HOME /app
10
+ WORKDIR $APP_HOME
11
+
12
+ COPY . $APP_HOME/
13
+
14
+ EXPOSE 3000
15
+
16
+ CMD ["bash"]
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in phi_attrs.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Wyatt Kirby
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # PhiAttrs
2
+
3
+ ## Installation
4
+
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'phi_attrs'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install phi_attrs
18
+
19
+ ## Usage
20
+
21
+ ```ruby
22
+ class PatientInfo < ActiveRecord::Base
23
+ phi_model
24
+
25
+ exclude_from_phi :last_name
26
+ include_in_phi :birthday
27
+
28
+ def birthday
29
+ Time.current
30
+ end
31
+ end
32
+ ```
33
+
34
+ Access is granted on a model level:
35
+ ```ruby
36
+ info = new PatientInfo
37
+ info.allow_phi!("allowed_user@example.com", "Customer Service")
38
+ ```
39
+
40
+ or a class:
41
+ ```ruby
42
+ PatientInfo.allow_phi!("allowed_user@example.com", "Customer Service")
43
+ ```
44
+
45
+ ## Development
46
+
47
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
48
+
49
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
+
51
+ ### Docker
52
+
53
+ * `docker-compose up`
54
+ * `bin/ssh_to_container`
55
+
56
+ ## Testing
57
+
58
+ $ bundle exec appraisal rspec spec/phi_attrs_spec.rb
59
+
60
+ ## Contributing
61
+
62
+ Bug reports and pull requests are welcome on GitHub at https://github.com/wkirby/phi_attrs.
63
+
64
+ ## License
65
+
66
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'phi_attrs'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle check || bundle install
7
+ bundle exec appraisal install
@@ -0,0 +1,3 @@
1
+ #! /bin/bash
2
+
3
+ docker-compose run rails sh
data/config.ru ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ Bundler.require :default, :development
7
+
8
+ Combustion.initialize! :all
9
+ run Combustion::Application
data/docker/start.sh ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ echo "Beginning Setup"
4
+ /app/bin/setup
5
+
6
+ echo "Environment Ready"
7
+ tail -f /etc/hosts
@@ -0,0 +1,18 @@
1
+ version: '3'
2
+
3
+ services:
4
+ rails:
5
+ build: .
6
+ volumes:
7
+ - bundle_cache:/bundle
8
+ - .:/app
9
+ environment:
10
+ - BUNDLE_JOBS=5
11
+ - BUNDLE_PATH=/bundle
12
+ - BUNDLE_BIN=/bundle/bin
13
+ - GEM_HOME=/bundle
14
+ command:
15
+ - docker/start.sh
16
+
17
+ volumes:
18
+ bundle_cache:
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -0,0 +1,8 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails", "5.0.0"
6
+ gem "tzinfo-data"
7
+
8
+ gemspec path: "../"
@@ -0,0 +1,17 @@
1
+ module PhiAttrs
2
+ module Configure
3
+ @@log_path = nil
4
+
5
+ def configure
6
+ yield self if block_given?
7
+ end
8
+
9
+ def log_path
10
+ @@log_path
11
+ end
12
+
13
+ def log_path=(value)
14
+ @@log_path = value
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ module PhiAttrs
2
+ module Exceptions
3
+ class PhiAccessException < StandardError
4
+ def initialize(msg)
5
+ PhiAttrs::Logger.tagged('UNAUTHORIZED ACCESS') { PhiAttrs::Logger.error(msg) }
6
+ super(msg)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module PhiAttrs
2
+ Format = "%s %5s: %s\n".freeze
3
+
4
+ # https://github.com/ruby/ruby/blob/trunk/lib/logger.rb#L587
5
+ class Formatter < ::Logger::Formatter
6
+ def call(severity, timestamp, progname, msg)
7
+ Format % [format_datetime(timestamp), severity, msg2str(msg)]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module PhiAttrs
2
+ class Logger
3
+ class << self
4
+ cattr_accessor :logger
5
+ delegate :debug, :info, :warn, :error, :fatal, :tagged, to: :logger
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,125 @@
1
+ module PhiAttrs
2
+ PHI_ACCESS_LOG_TAG = 'PHI Access Log'.freeze
3
+
4
+ module PhiRecord
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :__phi_exclude_methods
9
+ class_attribute :__phi_include_methods
10
+ class_attribute :__phi_methods_wrapped
11
+
12
+ self.__phi_methods_wrapped = []
13
+ end
14
+
15
+ class_methods do
16
+ def exclude_from_phi(*methods)
17
+ self.__phi_exclude_methods = methods.map(&:to_s)
18
+ end
19
+
20
+ def include_in_phi(*methods)
21
+ self.__phi_include_methods = methods.map(&:to_s)
22
+ end
23
+
24
+ def allow_phi!(user_id, reason)
25
+ RequestStore.store[:phi_access] ||= {}
26
+
27
+ RequestStore.store[:phi_access][name] ||= {
28
+ phi_access_allowed: true,
29
+ user_id: user_id,
30
+ reason: reason
31
+ }
32
+ PhiAttrs::Logger.tagged(PHI_ACCESS_LOG_TAG, name) do
33
+ PhiAttrs::Logger.info("PHI Access Enabled for #{user_id}: #{reason}")
34
+ end
35
+ end
36
+
37
+ def disallow_phi!
38
+ RequestStore.store[:phi_access].delete(name) if RequestStore.store[:phi_access].present?
39
+ PhiAttrs::Logger.tagged(PHI_ACCESS_LOG_TAG, name) do
40
+ PhiAttrs::Logger.info('PHI access disabled')
41
+ end
42
+ end
43
+ end
44
+
45
+ def initialize(*args)
46
+ super(*args)
47
+
48
+ # Disable PHI access by default
49
+ @__phi_access_allowed = false
50
+ @__phi_access_logged = false
51
+
52
+ # Wrap attributes with PHI Logger and Access Control
53
+ __phi_wrapped_methods.each { |attr| phi_wrap_method(attr) }
54
+ end
55
+
56
+ def __phi_wrapped_methods
57
+ attribute_names - self.class.__phi_exclude_methods.to_a + self.class.__phi_include_methods.to_a - [self.class.primary_key]
58
+ end
59
+
60
+ def allow_phi!(user_id, reason)
61
+ PhiAttrs::Logger.tagged( *phi_log_keys ) do
62
+ @__phi_access_allowed = true
63
+ @__phi_user_id = user_id
64
+ @__phi_access_reason = reason
65
+
66
+ PhiAttrs::Logger.info("PHI Access Enabled for '#{user_id}': #{reason}")
67
+ end
68
+ end
69
+
70
+ def disallow_phi!
71
+ PhiAttrs::Logger.tagged(*phi_log_keys) do
72
+ @__phi_access_allowed = false
73
+ @__phi_user_id = nil
74
+ @__phi_access_reason = nil
75
+
76
+ PhiAttrs::Logger.info('PHI access disabled')
77
+ end
78
+ end
79
+
80
+ def phi_allowed?
81
+ @__phi_access_allowed || RequestStore.store.dig(:phi_access, self.class.name, :phi_access_allowed)
82
+ end
83
+
84
+ def phi_allowed_by
85
+ @__phi_user_id || RequestStore.store.dig(:phi_access, self.class.name, :user_id)
86
+ end
87
+
88
+ def phi_access_reason
89
+ @__phi_access_reason || RequestStore.store.dig(:phi_access, self.class.name, :reason)
90
+ end
91
+
92
+ private
93
+
94
+ def phi_log_keys
95
+ @__phi_log_id = persisted? ? "Key: #{attributes[self.class.primary_key]}" : "Object: #{object_id}"
96
+ @__phi_log_keys = [PHI_ACCESS_LOG_TAG, self.class.name, @__phi_log_id]
97
+ end
98
+
99
+ def phi_wrap_method(method_name)
100
+ return if self.class.__phi_methods_wrapped.include? method_name
101
+
102
+ wrapped_method = :"__#{method_name}_phi_wrapped"
103
+ unwrapped_method = :"__#{method_name}_phi_unwrapped"
104
+
105
+ self.class.send(:define_method, wrapped_method) do |*args, &block|
106
+ PhiAttrs::Logger.tagged(*phi_log_keys) do
107
+ raise PhiAttrs::Exceptions::PhiAccessException, "Attempted PHI access for #{self.class.name} #{@__phi_user_id}" unless phi_allowed?
108
+
109
+ unless @__phi_access_logged
110
+ PhiAttrs::Logger.info("'#{phi_allowed_by}' accessing #{self.class.name}.\n\t access logging triggered by method: #{method_name}")
111
+ @__phi_access_logged = true
112
+ end
113
+
114
+ send(unwrapped_method, *args, &block)
115
+ end
116
+ end
117
+
118
+ # method_name => wrapped_method => unwrapped_method
119
+ self.class.send(:alias_method, unwrapped_method, method_name)
120
+ self.class.send(:alias_method, method_name, wrapped_method)
121
+
122
+ self.class.__phi_methods_wrapped << method_name
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,12 @@
1
+ require 'phi_attrs'
2
+ require 'rails'
3
+
4
+ module PhiAttrs
5
+ class Railtie < Rails::Railtie
6
+ initializer 'rolify.initialize' do
7
+ ActiveSupport.on_load(:active_record) do
8
+ ActiveRecord::Base.send :extend, PhiAttrs
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module PhiAttrs
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/phi_attrs.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'rails'
2
+ require 'active_support'
3
+ require 'request_store'
4
+
5
+ require 'phi_attrs/version'
6
+ require 'phi_attrs/configure'
7
+ require 'phi_attrs/railtie' if defined?(Rails)
8
+ require 'phi_attrs/formatter'
9
+ require 'phi_attrs/logger'
10
+ require 'phi_attrs/exceptions'
11
+ require 'phi_attrs/phi_record'
12
+
13
+ module PhiAttrs
14
+ def phi_model(with: nil, except: nil)
15
+ include PhiRecord
16
+ logger = ActiveSupport::Logger.new(PhiAttrs.log_path)
17
+ logger.formatter = Formatter.new
18
+ file_logger = ActiveSupport::TaggedLogging.new(logger)
19
+
20
+ PhiAttrs::Logger.logger = file_logger
21
+ end
22
+
23
+ @@log_path = nil
24
+
25
+ def self.configure
26
+ yield self if block_given?
27
+ end
28
+
29
+ def self.log_path
30
+ @@log_path
31
+ end
32
+
33
+ def self.log_path=(value)
34
+ @@log_path = value
35
+ end
36
+ end
data/phi_attrs.gemspec ADDED
@@ -0,0 +1,35 @@
1
+
2
+ lib = File.expand_path('lib', __dir__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'phi_attrs/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'phi_attrs'
8
+ spec.version = PhiAttrs::VERSION
9
+ spec.authors = ['Wyatt Kirby']
10
+ spec.email = ['wyatt@apsis.io']
11
+
12
+ spec.summary = 'PHI Access Restriction & Logging for Rails ActiveRecord'
13
+ spec.homepage = 'http://www.apsis.io'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_runtime_dependency 'rails', '>= 4.2.0'
24
+ spec.add_runtime_dependency 'request_store', '~> 1.4'
25
+
26
+ spec.add_development_dependency 'appraisal', '~> 2.1'
27
+ spec.add_development_dependency 'bundler', '~> 1.16'
28
+ spec.add_development_dependency 'byebug'
29
+ spec.add_development_dependency 'combustion', '~> 0.9.1'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rspec', '~> 3.7'
32
+ spec.add_development_dependency 'rspec-rails', '~> 3.7'
33
+ spec.add_development_dependency 'simplecov', '~> 0.16'
34
+ spec.add_development_dependency 'sqlite3', '~> 1.3'
35
+ end
metadata ADDED
@@ -0,0 +1,225 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phi_attrs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Wyatt Kirby
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-07-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: request_store
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: appraisal
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.16'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.16'
69
+ - !ruby/object:Gem::Dependency
70
+ name: byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: combustion
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.9.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.9.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.7'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.7'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-rails
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.7'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.7'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.16'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.16'
153
+ - !ruby/object:Gem::Dependency
154
+ name: sqlite3
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.3'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.3'
167
+ description:
168
+ email:
169
+ - wyatt@apsis.io
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".gitignore"
175
+ - ".rspec"
176
+ - ".rspec_status"
177
+ - ".travis.yml"
178
+ - Appraisals
179
+ - Dockerfile
180
+ - Gemfile
181
+ - LICENSE.txt
182
+ - README.md
183
+ - Rakefile
184
+ - bin/console
185
+ - bin/setup
186
+ - bin/ssh_to_container
187
+ - config.ru
188
+ - docker-compose.yml
189
+ - docker/start.sh
190
+ - gemfiles/.bundle/config
191
+ - gemfiles/rails_5.0.gemfile
192
+ - lib/phi_attrs.rb
193
+ - lib/phi_attrs/configure.rb
194
+ - lib/phi_attrs/exceptions.rb
195
+ - lib/phi_attrs/formatter.rb
196
+ - lib/phi_attrs/logger.rb
197
+ - lib/phi_attrs/phi_record.rb
198
+ - lib/phi_attrs/railtie.rb
199
+ - lib/phi_attrs/version.rb
200
+ - phi_attrs.gemspec
201
+ homepage: http://www.apsis.io
202
+ licenses:
203
+ - MIT
204
+ metadata: {}
205
+ post_install_message:
206
+ rdoc_options: []
207
+ require_paths:
208
+ - lib
209
+ required_ruby_version: !ruby/object:Gem::Requirement
210
+ requirements:
211
+ - - ">="
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ required_rubygems_version: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: '0'
219
+ requirements: []
220
+ rubyforge_project:
221
+ rubygems_version: 2.6.13
222
+ signing_key:
223
+ specification_version: 4
224
+ summary: PHI Access Restriction & Logging for Rails ActiveRecord
225
+ test_files: []