phi_attrs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []