cased-ruby 0.3.3

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 (93) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rubocop.yml +21 -0
  3. data/.github/workflows/ruby.yml +46 -0
  4. data/.gitignore +10 -0
  5. data/.rubocop.yml +88 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +7 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +8 -0
  10. data/Gemfile.lock +107 -0
  11. data/LICENSE +21 -0
  12. data/README.md +661 -0
  13. data/Rakefile +12 -0
  14. data/bin/console +15 -0
  15. data/bin/rubocop +29 -0
  16. data/cased-ruby.gemspec +48 -0
  17. data/lib/cased-ruby.rb +3 -0
  18. data/lib/cased.rb +260 -0
  19. data/lib/cased/clients.rb +21 -0
  20. data/lib/cased/collection_response.rb +117 -0
  21. data/lib/cased/config.rb +172 -0
  22. data/lib/cased/context.rb +50 -0
  23. data/lib/cased/context/expander.rb +33 -0
  24. data/lib/cased/error.rb +8 -0
  25. data/lib/cased/http/client.rb +83 -0
  26. data/lib/cased/http/error.rb +99 -0
  27. data/lib/cased/instrumentation/controller.rb +34 -0
  28. data/lib/cased/instrumentation/log_subscriber.rb +31 -0
  29. data/lib/cased/integrations/sidekiq.rb +17 -0
  30. data/lib/cased/integrations/sidekiq/client_middleware.rb +14 -0
  31. data/lib/cased/integrations/sidekiq/server_middleware.rb +20 -0
  32. data/lib/cased/model.rb +98 -0
  33. data/lib/cased/policy.rb +24 -0
  34. data/lib/cased/publishers.rb +6 -0
  35. data/lib/cased/publishers/active_support_publisher.rb +16 -0
  36. data/lib/cased/publishers/base.rb +17 -0
  37. data/lib/cased/publishers/error.rb +11 -0
  38. data/lib/cased/publishers/http_publisher.rb +15 -0
  39. data/lib/cased/publishers/null_publisher.rb +11 -0
  40. data/lib/cased/publishers/test_publisher.rb +19 -0
  41. data/lib/cased/query.rb +87 -0
  42. data/lib/cased/rack_middleware.rb +15 -0
  43. data/lib/cased/response.rb +37 -0
  44. data/lib/cased/sensitive.rb +4 -0
  45. data/lib/cased/sensitive/handler.rb +54 -0
  46. data/lib/cased/sensitive/processor.rb +78 -0
  47. data/lib/cased/sensitive/range.rb +54 -0
  48. data/lib/cased/sensitive/result.rb +8 -0
  49. data/lib/cased/sensitive/string.rb +43 -0
  50. data/lib/cased/test_helper.rb +188 -0
  51. data/lib/cased/version.rb +5 -0
  52. data/vendor/cache/activesupport-6.0.3.4.gem +0 -0
  53. data/vendor/cache/addressable-2.7.0.gem +0 -0
  54. data/vendor/cache/ast-2.4.0.gem +0 -0
  55. data/vendor/cache/byebug-11.0.1.gem +0 -0
  56. data/vendor/cache/concurrent-ruby-1.1.7.gem +0 -0
  57. data/vendor/cache/connection_pool-2.2.2.gem +0 -0
  58. data/vendor/cache/crack-0.4.3.gem +0 -0
  59. data/vendor/cache/docile-1.3.2.gem +0 -0
  60. data/vendor/cache/dotpath-0.1.0.gem +0 -0
  61. data/vendor/cache/faraday-1.1.0.gem +0 -0
  62. data/vendor/cache/faraday_middleware-1.0.0.gem +0 -0
  63. data/vendor/cache/hashdiff-1.0.1.gem +0 -0
  64. data/vendor/cache/i18n-1.8.5.gem +0 -0
  65. data/vendor/cache/jaro_winkler-1.5.4.gem +0 -0
  66. data/vendor/cache/json-2.3.1.gem +0 -0
  67. data/vendor/cache/minitest-5.13.0.gem +0 -0
  68. data/vendor/cache/mocha-1.11.2.gem +0 -0
  69. data/vendor/cache/multipart-post-2.1.1.gem +0 -0
  70. data/vendor/cache/net-http-persistent-3.1.0.gem +0 -0
  71. data/vendor/cache/parallel-1.19.1.gem +0 -0
  72. data/vendor/cache/parser-2.7.1.3.gem +0 -0
  73. data/vendor/cache/public_suffix-4.0.5.gem +0 -0
  74. data/vendor/cache/rack-2.2.2.gem +0 -0
  75. data/vendor/cache/rack-protection-2.0.8.1.gem +0 -0
  76. data/vendor/cache/rainbow-3.0.0.gem +0 -0
  77. data/vendor/cache/rake-10.5.0.gem +0 -0
  78. data/vendor/cache/redis-4.1.4.gem +0 -0
  79. data/vendor/cache/rubocop-0.78.0.gem +0 -0
  80. data/vendor/cache/rubocop-performance-1.5.2.gem +0 -0
  81. data/vendor/cache/ruby-progressbar-1.10.1.gem +0 -0
  82. data/vendor/cache/ruby2_keywords-0.0.2.gem +0 -0
  83. data/vendor/cache/safe_yaml-1.0.5.gem +0 -0
  84. data/vendor/cache/sidekiq-6.0.7.gem +0 -0
  85. data/vendor/cache/simplecov-0.18.5.gem +0 -0
  86. data/vendor/cache/simplecov-html-0.12.2.gem +0 -0
  87. data/vendor/cache/thread_safe-0.3.6.gem +0 -0
  88. data/vendor/cache/tzinfo-1.2.7.gem +0 -0
  89. data/vendor/cache/unicode-display_width-1.6.1.gem +0 -0
  90. data/vendor/cache/webmock-3.8.3.gem +0 -0
  91. data/vendor/cache/yard-0.9.24.gem +0 -0
  92. data/vendor/cache/zeitwerk-2.4.0.gem +0 -0
  93. metadata +375 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 45c422e1920ea510d16c5c8a5b91016ac2a4eedb9a2b880ff29018dc18580a13
4
+ data.tar.gz: 83e14abb44637e8d61a3fff592d8b434cbf8373cd8a4c8afede513cf89852f8a
5
+ SHA512:
6
+ metadata.gz: 5beffb4be2a539b74e6145c4d4b7b96ae6aea94c2bb5cdf9a79dfb90bfaeac615c80b537db0249702d807acb7f69727ff7b81cfc62896d03ad6e2c44124c1360
7
+ data.tar.gz: 8ae4ac844f566981de31a5d51ecfe28d4e665f9cebd5c6f5327a596b052e43e92ab0d7db9bb07029211f0786db5baf00035db8022a376b5ea3ba30ac512dbbda
@@ -0,0 +1,21 @@
1
+ name: Rubocop
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ timeout-minutes: 10
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v2
12
+
13
+ - uses: actions/setup-ruby@v1
14
+ with:
15
+ ruby-version: 2.6
16
+
17
+ - name: Install dependencies
18
+ run: |
19
+ gem install bundler
20
+ bundle install --local
21
+ - run: bin/rubocop
@@ -0,0 +1,46 @@
1
+ name: Ruby
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ timeout-minutes: 10
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ matrix:
11
+ ruby:
12
+ - "2.5"
13
+ - "2.6"
14
+ - "2.7"
15
+ name: Ruby ${{ matrix.ruby }} test
16
+ steps:
17
+ - uses: actions/checkout@v2
18
+
19
+ - uses: actions/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ gem install bundler
26
+ bundle install --local
27
+
28
+ - name: Run Tests
29
+ run: |
30
+ bundle exec rake test
31
+
32
+ - name: Generate yard documentation
33
+ run: |
34
+ bundle exec yard
35
+
36
+ - name: Upload test coverage report
37
+ uses: actions/upload-artifact@v2
38
+ with:
39
+ name: coverage
40
+ path: coverage/**/*
41
+
42
+ - name: Upload generated yard documentation
43
+ uses: actions/upload-artifact@v2
44
+ with:
45
+ name: yard
46
+ path: doc/**/*
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ .DS_Store
10
+ .byebug_history
@@ -0,0 +1,88 @@
1
+ AllCops:
2
+ Exclude:
3
+ - "db/**/*"
4
+ - "config/**/*"
5
+ - "script/**/*"
6
+ - "bin/{rails,rake,bundle}"
7
+ - "node_modules/**/*"
8
+ - "app/views/**/*"
9
+
10
+ Style/Documentation:
11
+ Enabled: false
12
+
13
+ Style/StringLiterals:
14
+ Exclude:
15
+ - db/schema.rb
16
+
17
+ Style/DoubleNegation:
18
+ Enabled: false
19
+
20
+ Style/TrailingCommaInHashLiteral:
21
+ EnforcedStyleForMultiline: comma
22
+
23
+ Style/TrailingCommaInArrayLiteral:
24
+ EnforcedStyleForMultiline: comma
25
+
26
+ Style/TrailingCommaInArguments:
27
+ EnforcedStyleForMultiline: comma
28
+
29
+ Metrics/CyclomaticComplexity:
30
+ Enabled: false
31
+
32
+ Metrics/BlockLength:
33
+ Enabled: false
34
+
35
+ Metrics/ClassLength:
36
+ Enabled: false
37
+
38
+ Metrics/ModuleLength:
39
+ Enabled: false
40
+
41
+ Naming/FileName:
42
+ Exclude:
43
+ - lib/cased-ruby.rb
44
+
45
+ Naming/MethodParameterName:
46
+ Enabled: false
47
+
48
+ Metrics/AbcSize:
49
+ Enabled: false
50
+
51
+ Style/ConditionalAssignment:
52
+ Enabled: false
53
+
54
+ Style/IfUnlessModifier:
55
+ Enabled: false
56
+
57
+ Metrics/PerceivedComplexity:
58
+ Enabled: false
59
+
60
+ Metrics/MethodLength:
61
+ Enabled: false
62
+
63
+ Layout/LineLength:
64
+ Enabled: false
65
+
66
+ Layout/RescueEnsureAlignment:
67
+ Enabled: false
68
+
69
+ Layout/ArgumentAlignment:
70
+ Enabled: false
71
+
72
+ Layout/EndAlignment:
73
+ Enabled: false
74
+
75
+ Layout/ElseAlignment:
76
+ Enabled: false
77
+
78
+ Layout/IndentationWidth:
79
+ Enabled: false
80
+
81
+ Layout/FirstHashElementIndentation:
82
+ Enabled: false
83
+
84
+ Layout/MultilineMethodCallIndentation:
85
+ Enabled: false
86
+
87
+ Layout/CaseIndentation:
88
+ Enabled: false
@@ -0,0 +1 @@
1
+ 2.6.5
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.3
7
+ before_install: gem install bundler -v 2.0.2
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at me@garrettbjerkhoel.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in cased-ruby.gemspec
6
+ gemspec
7
+
8
+ gem 'simplecov', '0.18.5', require: false
@@ -0,0 +1,107 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cased-ruby (0.3.3)
5
+ activesupport (~> 6)
6
+ dotpath (= 0.1.0)
7
+ faraday (~> 1.0)
8
+ faraday_middleware (~> 1.0)
9
+ json (~> 2)
10
+ net-http-persistent (~> 3.0)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ activesupport (6.0.3.4)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 0.7, < 2)
18
+ minitest (~> 5.1)
19
+ tzinfo (~> 1.1)
20
+ zeitwerk (~> 2.2, >= 2.2.2)
21
+ addressable (2.7.0)
22
+ public_suffix (>= 2.0.2, < 5.0)
23
+ ast (2.4.0)
24
+ byebug (11.0.1)
25
+ concurrent-ruby (1.1.7)
26
+ connection_pool (2.2.2)
27
+ crack (0.4.3)
28
+ safe_yaml (~> 1.0.0)
29
+ docile (1.3.2)
30
+ dotpath (0.1.0)
31
+ faraday (1.1.0)
32
+ multipart-post (>= 1.2, < 3)
33
+ ruby2_keywords
34
+ faraday_middleware (1.0.0)
35
+ faraday (~> 1.0)
36
+ hashdiff (1.0.1)
37
+ i18n (1.8.5)
38
+ concurrent-ruby (~> 1.0)
39
+ jaro_winkler (1.5.4)
40
+ json (2.3.1)
41
+ minitest (5.13.0)
42
+ mocha (1.11.2)
43
+ multipart-post (2.1.1)
44
+ net-http-persistent (3.1.0)
45
+ connection_pool (~> 2.2)
46
+ parallel (1.19.1)
47
+ parser (2.7.1.3)
48
+ ast (~> 2.4.0)
49
+ public_suffix (4.0.5)
50
+ rack (2.2.2)
51
+ rack-protection (2.0.8.1)
52
+ rack
53
+ rainbow (3.0.0)
54
+ rake (10.5.0)
55
+ redis (4.1.4)
56
+ rubocop (0.78.0)
57
+ jaro_winkler (~> 1.5.1)
58
+ parallel (~> 1.10)
59
+ parser (>= 2.6)
60
+ rainbow (>= 2.2.2, < 4.0)
61
+ ruby-progressbar (~> 1.7)
62
+ unicode-display_width (>= 1.4.0, < 1.7)
63
+ rubocop-performance (1.5.2)
64
+ rubocop (>= 0.71.0)
65
+ ruby-progressbar (1.10.1)
66
+ ruby2_keywords (0.0.2)
67
+ safe_yaml (1.0.5)
68
+ sidekiq (6.0.7)
69
+ connection_pool (>= 2.2.2)
70
+ rack (~> 2.0)
71
+ rack-protection (>= 2.0.0)
72
+ redis (>= 4.1.0)
73
+ simplecov (0.18.5)
74
+ docile (~> 1.1)
75
+ simplecov-html (~> 0.11)
76
+ simplecov-html (0.12.2)
77
+ thread_safe (0.3.6)
78
+ tzinfo (1.2.7)
79
+ thread_safe (~> 0.1)
80
+ unicode-display_width (1.6.1)
81
+ webmock (3.8.3)
82
+ addressable (>= 2.3.6)
83
+ crack (>= 0.3.2)
84
+ hashdiff (>= 0.4.0, < 2.0.0)
85
+ yard (0.9.24)
86
+ zeitwerk (2.4.0)
87
+
88
+ PLATFORMS
89
+ ruby
90
+
91
+ DEPENDENCIES
92
+ bundler (= 2.1.4)
93
+ byebug (= 11.0.1)
94
+ cased-ruby!
95
+ minitest (= 5.13.0)
96
+ mocha (= 1.11.2)
97
+ rack (= 2.2.2)
98
+ rake (= 10.5.0)
99
+ rubocop (= 0.78.0)
100
+ rubocop-performance (= 1.5.2)
101
+ sidekiq (= 6.0.7)
102
+ simplecov (= 0.18.5)
103
+ webmock (= 3.8.3)
104
+ yard (= 0.9.24)
105
+
106
+ BUNDLED WITH
107
+ 2.1.4
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Cased, Inc.
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.
@@ -0,0 +1,661 @@
1
+ # cased-ruby
2
+
3
+ A Cased client for Ruby applications in your organization to control and monitor the access of information within your organization.
4
+
5
+ ## Overview
6
+
7
+ - [Installation](#installation)
8
+ - [Configuration](#configuration)
9
+ - [Usage](#usage)
10
+ - [Publishing events to Cased](#publishing-events-to-cased)
11
+ - [Retrieving events from a Cased Policy](#retrieving-events-from-a-cased-policy)
12
+ - [Retrieving events from a Cased Policy containing variables](#retrieving-events-from-a-cased-policy-containing-variables)
13
+ - [Retrieving events from multiple Cased Policies](#retrieving-events-from-multiple-cased-policies)
14
+ - [Exporting events](#exporting-events)
15
+ - [Masking & filtering sensitive information](#masking-and-filtering-sensitive-information)
16
+ - [Disable publishing events](#disable-publishing-events)
17
+ - [Context](#context)
18
+ - [Testing](#testing)
19
+ - [Customizing cased-ruby](#customizing-cased-ruby)
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'cased-ruby'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ $ bundle
32
+
33
+ Or install it yourself as:
34
+
35
+ $ gem install cased-ruby
36
+
37
+ ## Configuration
38
+
39
+ All configuration options available in cased-ruby are available to be configured by an environment variable or manually.
40
+
41
+ ```ruby
42
+ Cased.configure do |config|
43
+ # CASED_POLICY_KEY=policy_live_1dQpY5JliYgHSkEntAbMVzuOROh
44
+ config.policy_key = 'policy_live_1dQpY5JliYgHSkEntAbMVzuOROh'
45
+
46
+ # CASED_USERS_POLICY_KEY=policy_live_1dQpY8bBgEwdpmdpVrrtDzMX4fH
47
+ # CASED_ORGANIZATIONS_POLICY_KEY=policy_live_1dSHQRurWX8JMYMbkRdfzVoo62d
48
+ config.policy_keys = {
49
+ users: 'policy_live_1dQpY8bBgEwdpmdpVrrtDzMX4fH',
50
+ organizations: 'policy_live_1dSHQRurWX8JMYMbkRdfzVoo62d',
51
+ }
52
+
53
+ # CASED_PUBLISH_KEY=publish_live_1dQpY1jKB48kBd3418PjAotmEwA
54
+ config.publish_key = 'publish_live_1dQpY1jKB48kBd3418PjAotmEwA'
55
+
56
+ # CASED_PUBLISH_URL=https://publish.cased.com
57
+ config.publish_url = 'https://publish.cased.com'
58
+
59
+ # CASED_API_URL=https://api.cased.com
60
+ config.api_url = 'https://api.cased.com'
61
+
62
+ # CASED_RAISE_ON_ERRORS=1
63
+ config.raise_on_errors = false
64
+
65
+ # CASED_SILENCE=1
66
+ config.silence = false
67
+
68
+ # CASED_HTTP_OPEN_TIMEOUT=5
69
+ config.http_open_timeout = 5
70
+
71
+ # CASED_HTTP_READ_TIMEOUT=10
72
+ config.http_read_timeout = 10
73
+ end
74
+ ```
75
+
76
+ ## Usage
77
+
78
+ ### Publishing events to Cased
79
+
80
+ There are two ways to publish your first Cased event.
81
+
82
+ **Manually**
83
+
84
+ ```ruby
85
+ require 'cased-ruby'
86
+
87
+ Cased.configure do |config|
88
+ config.publish_key = 'publish_live_1dQpY1jKB48kBd3418PjAotmEwA'
89
+ end
90
+
91
+ Cased.publish(
92
+ action: 'credit_card.charge',
93
+ amount: 2000,
94
+ currency: 'usd',
95
+ source: 'tok_amex',
96
+ description: 'My First Test Charge (created for API docs)',
97
+ credit_card_id: 'card_1dQpXqQwXxsQs9sohN9HrzRAV6y',
98
+ )
99
+ ```
100
+
101
+ **Cased::Model**
102
+
103
+ cased-ruby provides a class mixin that gives you a framework to publish events.
104
+
105
+ ```ruby
106
+ require 'cased-ruby'
107
+
108
+ Cased.configure do |config|
109
+ config.publish_key = 'publish_live_1dQpY1jKB48kBd3418PjAotmEwA'
110
+ end
111
+
112
+ class CreditCard
113
+ include Cased::Model
114
+
115
+ def initialize(amount:, currency:, source:, description:)
116
+ @amount = amount
117
+ @currency = currency
118
+ @source = source
119
+ @description = description
120
+ end
121
+
122
+ def charge
123
+ Stripe::Charge.create({
124
+ amount: @amount,
125
+ currency: @currency,
126
+ source: @source,
127
+ description: @description,
128
+ })
129
+
130
+ cased(:charge, payload: {
131
+ amount: @amount,
132
+ currency: @currency,
133
+ description: @description,
134
+ })
135
+ end
136
+
137
+ def cased_id
138
+ 'card_1dQpXqQwXxsQs9sohN9HrzRAV6y'
139
+ end
140
+
141
+ def cased_payload
142
+ {
143
+ credit_card: self,
144
+ }
145
+ end
146
+ end
147
+
148
+ credit_card = CreditCard.new(
149
+ amount: 2000,
150
+ currency: 'usd',
151
+ source: 'tok_amex',
152
+ description: 'My First Test Charge (created for API docs)',
153
+ )
154
+
155
+ credit_card.charge
156
+ ```
157
+
158
+ Both examples above are equivelent in that they publish the following `credit_card.charge` event to Cased:
159
+
160
+ ```json
161
+ {
162
+ "cased_id": "5f8559cd-4cd9-48c3-b1d0-6eedc4019ec1",
163
+ "action": "credit_card.charge",
164
+ "amount": 2000,
165
+ "currency": "usd",
166
+ "source": "tok_amex",
167
+ "description": "My First Test Charge (created for API docs)",
168
+ "credit_card_id": "card_1dQpXqQwXxsQs9sohN9HrzRAV6y",
169
+ "timestamp": "2020-06-23T02:02:39.932759Z"
170
+ }
171
+ ```
172
+
173
+ ### Retrieving events from a Cased Policy
174
+
175
+ If you plan on retrieving events from your audit trails you must use an Cased Policy token.
176
+
177
+ ```ruby
178
+ require 'cased-ruby'
179
+
180
+ Cased.configure do |config|
181
+ config.policy_key = 'policy_live_1dQpY5JliYgHSkEntAbMVzuOROh'
182
+ end
183
+
184
+ query = Cased.policy.events.limit(25).page(1)
185
+ results = query.results
186
+ results.each do |event|
187
+ puts event['action'] # => credit_card.charge
188
+ puts event['timestamp'] # => 2020-06-23T02:02:39.932759Z
189
+ end
190
+ query.total_count # => 2,366
191
+ query.total_pages # => 95
192
+ query.success? # => true
193
+ query.error? # => false
194
+ ```
195
+
196
+ ### Retrieving events from a Cased Policy containing variables
197
+
198
+ Cased policies allow you to filter events by providing variables to your Cased Policy events query. One example of a Cased Policy is to have a single Cased Policy that you can use to query events for any user in your database without having to create a Cased Policy for each user.
199
+
200
+ ```ruby
201
+ require 'cased-ruby'
202
+
203
+ Cased.configure do |config|
204
+ config.policy_key = 'policy_live_1dQpY5JliYgHSkEntAbMVzuOROh'
205
+ end
206
+
207
+ variables = {
208
+ user_id: 'user_1dSHQSNtAH90KA8zGTooMnmMdiD',
209
+ }
210
+ query = Cased.policy(variables: variables).events.limit(25).page(1)
211
+ results = query.results
212
+ results.each do |event|
213
+ puts event['action'] # => credit_card.charge
214
+ puts event['timestamp'] # => 2020-06-23T02:02:39.932759Z
215
+ end
216
+ ```
217
+
218
+ ### Retrieving events from multiple Cased Policies
219
+
220
+ To retrieve events from one or more Cased Policies you can configure multiple Cased Policy API keys and retrieve events for each one.
221
+
222
+ ```ruby
223
+ require 'cased-ruby'
224
+
225
+ Cased.configure do |config|
226
+ config.policy_keys = {
227
+ users: 'policy_live_1dQpY8bBgEwdpmdpVrrtDzMX4fH',
228
+ organizations: 'policy_live_1dSHQRurWX8JMYMbkRdfzVoo62d',
229
+ }
230
+ end
231
+
232
+ query = Cased.policy[:users].events.limit(25).page(1)
233
+ results = query.results
234
+ results.each do |event|
235
+ puts event['action'] # => user.login
236
+ puts event['timestamp'] # => 2020-06-23T02:02:39.932759Z
237
+ end
238
+
239
+ query = Cased.policy[:organizations].events.limit(25).page(1)
240
+ results = query.results
241
+ results.each do |event|
242
+ puts event['action'] # => organization.create
243
+ puts event['timestamp'] # => 2020-06-22T22:16:31.055655Z
244
+ end
245
+ ```
246
+
247
+ ### Exporting events
248
+
249
+ Exporting events from a Cased Policy allows you to provide users with exports of their own data or to respond to data requests.
250
+
251
+ ```ruby
252
+ require 'cased-ruby'
253
+
254
+ Cased.configure do |config|
255
+ config.policy_key = 'policy_live_1dQpY5JliYgHSkEntAbMVzuOROh'
256
+ end
257
+
258
+ export = Cased.policy.exports.create(
259
+ format: :json,
260
+ phrase: 'action:credit_card.charge',
261
+ )
262
+ export.download_url # => https://api.cased.com/exports/export_1dSHQSNtAH90KA8zGTooMnmMdiD/download?token=eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoidXNlcl8xZFFwWThiQmdFd2RwbWRwVnJydER6TVg0ZkgiLCJ
263
+ ```
264
+
265
+ ### Masking & filtering sensitive information
266
+
267
+ If you are handling sensitive information on behalf of your users you should consider masking or filtering any sensitive information.
268
+
269
+ ```ruby
270
+ require 'cased-ruby'
271
+
272
+ Cased.configure do |config|
273
+ config.publish_key = 'publish_live_1dQpY1jKB48kBd3418PjAotmEwA'
274
+ end
275
+
276
+ Cased.publish(
277
+ action: 'credit_card.charge',
278
+ user: Cased::Sensitive::String.new('john@organization.com', label: :email)
279
+ )
280
+ ```
281
+
282
+ ### Console Usage
283
+
284
+ Most Cased events will be created by users from actions on the website from
285
+ custom defined events or lifecycle callbacks. The exception is any console
286
+ session where models may generate Cased events as you start to modify records.
287
+
288
+ By default any console session will include the hostname of where the console
289
+ session takes place. Since every event must have an actor, you must set the
290
+ actor at the beginning of your console session. If you don't know the user,
291
+ it's recommended you create a system/robot user.
292
+
293
+ ```ruby
294
+ # OTHER CONSOLE INITIALIZATION HERE
295
+ Cased.context.push(actor: @actor)
296
+ ```
297
+
298
+ ### Disable publishing events
299
+
300
+ Although rare, there may be times where you wish to disable publishing events to Cased. To do so wrap your transaction inside of a `Cased.disable` block:
301
+
302
+ ```ruby
303
+ Cased.disable do
304
+ user.cased(:login)
305
+ end
306
+ ```
307
+
308
+ Or you can configure the entire process to disable publishing events.
309
+
310
+ ```
311
+ CASED_DISABLE_PUBLISHING=1 bundle exec ruby crawl.rb
312
+ ```
313
+
314
+ ### Context
315
+
316
+ One of the most easiest ways to publish detailed events to Cased is to push contextual information on to the Cased context.
317
+
318
+ ```ruby
319
+ require 'cased-ruby'
320
+
321
+ Cased.configure do |config|
322
+ config.publish_key = 'publish_live_1dQpY1jKB48kBd3418PjAotmEwA'
323
+ end
324
+
325
+ Cased.context.merge(location: 'hostname.local')
326
+
327
+ Cased.publish(
328
+ action: 'console.start',
329
+ user: 'john',
330
+ )
331
+ ```
332
+
333
+ Any information stored in `Cased.context` will be included anytime an event is published.
334
+
335
+ ```json
336
+ {
337
+ "cased_id": "5f8559cd-4cd9-48c3-b1d0-6eedc4019ec1",
338
+ "action": "user.login",
339
+ "user": "john",
340
+ "location": "hostname.local",
341
+ "timestamp": "2020-06-22T21:43:06.157336"
342
+ }
343
+ ```
344
+
345
+ You can provide `Cased.context.merge` a block and the context will only be present for the duration of the block:
346
+
347
+ ```ruby
348
+ Cased.context.merge(location: 'hostname.local') do
349
+ # Will include { "location": "hostname.local" }
350
+ Cased.publish(
351
+ action: 'console.start',
352
+ user: 'john',
353
+ )
354
+ end
355
+
356
+ # Will not include { "location": "hostname.local" }
357
+ Cased.publish(
358
+ action: 'console.end',
359
+ user: 'john',
360
+ )
361
+ ```
362
+
363
+ To clear/reset the context:
364
+
365
+ ```ruby
366
+ Cased.context.clear
367
+ ```
368
+
369
+ ### Testing
370
+
371
+ cased-ruby provides a test helper class that you can use to test events are being published to Cased.
372
+
373
+ ```ruby
374
+ require 'test-helper'
375
+
376
+ class CreditCardTest < Test::Unit::TestCase
377
+ include Cased::TestHelper
378
+
379
+ def test_charging_credit_card_publishes_credit_card_create_event
380
+ credit_card = CreditCard.new(
381
+ amount: 2000,
382
+ currency: 'usd',
383
+ source: 'tok_amex',
384
+ description: 'My First Test Charge (created for API docs)',
385
+ )
386
+
387
+ credit_card.charge
388
+
389
+ assert_cased_events 1, action: 'credit_card.charge', amount: 2000
390
+ end
391
+
392
+ def test_charging_credit_card_publishes_credit_card_create_event_with_block
393
+ credit_card = CreditCard.new(
394
+ amount: 2000,
395
+ currency: 'usd',
396
+ source: 'tok_amex',
397
+ description: 'My First Test Charge (created for API docs)',
398
+ )
399
+
400
+ assert_cased_events 1, action: 'credit_card.charge', amount: 2000 do
401
+ credit_card.charge
402
+ end
403
+ end
404
+
405
+ def test_charging_credit_card_with_zero_amount_does_not_publish_credit_card_create_event
406
+ credit_card = CreditCard.new(
407
+ amount: 0,
408
+ currency: 'usd',
409
+ source: 'tok_amex',
410
+ description: 'My First Test Charge (created for API docs)',
411
+ )
412
+
413
+ assert_no_cased_events do
414
+ credit_card.charge
415
+ end
416
+ end
417
+ end
418
+ ```
419
+
420
+ ## Customizing cased-ruby
421
+
422
+ Out of the box cased-ruby takes care of serializing objects for you to the best of its ability, but you can customize cased-ruby should you like to fit your products needs.
423
+
424
+ Let's look at each of these methods independently as they all work together to
425
+ create the event.
426
+
427
+ `Cased::Model#cased`
428
+
429
+ This method is what publishes events for you to Cased. You include information specific to a particular event when calling `Cased::Model#cased`:
430
+
431
+ ```ruby
432
+ class CreditCard
433
+ include Cased::Model
434
+
435
+ # ...
436
+
437
+ def charge
438
+ Stripe::Charge.create({
439
+ amount: @amount,
440
+ currency: @currency,
441
+ source: @source,
442
+ description: @description,
443
+ })
444
+
445
+ cased(:charge, payload: {
446
+ amount: @amount,
447
+ currency: @currency,
448
+ description: @description,
449
+ })
450
+ end
451
+ end
452
+ ```
453
+
454
+ Or you can customize information that is included anytime `Cased::Model#cased` is called in your class:
455
+
456
+ ```ruby
457
+ class CreditCard
458
+ include Cased::Model
459
+
460
+ # ...
461
+
462
+ def charge
463
+ Stripe::Charge.create({
464
+ amount: @amount,
465
+ currency: @currency,
466
+ source: @source,
467
+ description: @description,
468
+ })
469
+
470
+ cased(:charge)
471
+ end
472
+
473
+ def cased_payload
474
+ {
475
+ credit_card: self,
476
+ amount: @amount,
477
+ currency: @currency,
478
+ description: @description,
479
+ }
480
+ end
481
+ end
482
+ ```
483
+
484
+ Both examples are equivelent.
485
+
486
+ `Cased::Model#cased_category`
487
+
488
+ By default `cased_category` will use the underscore class name to generate the
489
+ prefix for all events generated by this class. If you published a
490
+ `CreditCard#charge` event it would be delivered to Cased `credit_card.charge`. If you want to
491
+ customize what cased-ruby uses you can do so by re-opening the method:
492
+
493
+ ```ruby
494
+ class CreditCard
495
+ include Cased::Model
496
+
497
+ def cased_category
498
+ :card
499
+ end
500
+ end
501
+ ```
502
+
503
+ `Cased::Model#cased_id`
504
+
505
+ Per our guide on [Human and machine readable information](https://docs.cased.com/guides/design-audit-trail-events#human-and-machine-readable-information) for [Designing audit trail events](https://docs.cased.com/guides/design-audit-trail-events) we encourage you to publish a unique identifier that will never change to Cased along with your events. This way when you [retrieve events](#retrieving-events-from-a-cased-policy) from Cased you'll be able to locate the corresponding object in your system.
506
+
507
+ ```ruby
508
+ class User
509
+ include Cased::Model
510
+
511
+ def cased_id
512
+ database_id
513
+ end
514
+ end
515
+ ```
516
+
517
+ `Cased::Model#cased_context`
518
+
519
+ To assist you in publishing events to Cased that are consistent and predictable, cased-ruby attempts to build your `cased_context` as long as you implement either `to_s` or `cased_id` in your class:
520
+
521
+ ```ruby
522
+ class Plan
523
+ include Cased::Model
524
+
525
+ def initialize(name)
526
+ @name = name
527
+ end
528
+
529
+ def cased_id
530
+ database_id
531
+ end
532
+
533
+ def to_s
534
+ @name
535
+ end
536
+ end
537
+
538
+ plan = Plan.new('Free')
539
+ plan.to_s # => 'Free'
540
+ plan.cased_id # => 'plan_1dQpY1jKB48kBd3418PjAotmEwA'
541
+ plan.cased_context # => { plan: 'Free', plan_id: 'plan_1dQpY1jKB48kBd3418PjAotmEwA' }
542
+ ```
543
+
544
+ If your class does not implement `to_s` it will only include `cased_id`:
545
+
546
+ ```ruby
547
+ class Plan
548
+ include Cased::Model
549
+
550
+ def initialize(name)
551
+ @name = name
552
+ end
553
+
554
+ def cased_id
555
+ database_id
556
+ end
557
+ end
558
+
559
+ plan = Plan.new('Free')
560
+ plan.to_s # => '#<Plan:0x00007feadf63b7e0>'
561
+ plan.cased_context # => { plan_id: 'plan_1dQpY1jKB48kBd3418PjAotmEwA' }
562
+ ```
563
+
564
+ Or you can customize it if your `to_s` implementation is not suitable for Cased:
565
+
566
+ ```ruby
567
+ class Plan
568
+ include Cased::Model
569
+
570
+ def initialize(name)
571
+ @name = name
572
+ end
573
+
574
+ def cased_id
575
+ 'plan_1dQpY1jKB48kBd3418PjAotmEwA'
576
+ end
577
+
578
+ def to_s
579
+ @name
580
+ end
581
+
582
+ def cased_context(category: cased_category)
583
+ {
584
+ "#{category}_id".to_sym => cased_id,
585
+ category => @name.parameterize,
586
+ }
587
+ end
588
+ end
589
+
590
+ class CreditCard
591
+ include Cased::Model
592
+
593
+ def initialize(amount:, currency:, source:, description:)
594
+ @amount = amount
595
+ @currency = currency
596
+ @source = source
597
+ @description = description
598
+ end
599
+
600
+ def charge
601
+ Stripe::Charge.create({
602
+ amount: @amount,
603
+ currency: @currency,
604
+ source: @source,
605
+ description: @description,
606
+ })
607
+
608
+ cased(:charge, payload: {
609
+ amount: @amount,
610
+ currency: @currency,
611
+ description: @description,
612
+ })
613
+ end
614
+
615
+ def plan
616
+ Plan.new('Free')
617
+ end
618
+
619
+ def cased_id
620
+ 'card_1dQpXqQwXxsQs9sohN9HrzRAV6y'
621
+ end
622
+
623
+ def cased_payload
624
+ {
625
+ credit_card: self,
626
+ plan: plan,
627
+ }
628
+ end
629
+ end
630
+
631
+ credit_card = CreditCard.new(
632
+ amount: 2000,
633
+ currency: 'usd',
634
+ source: 'tok_amex',
635
+ description: 'My First Test Charge (created for API docs)',
636
+ )
637
+
638
+ credit_card.charge
639
+ ```
640
+
641
+ Results in:
642
+
643
+ ```json
644
+ {
645
+ "cased_id": "5f8559cd-4cd9-48c3-b1d0-6eedc4019ec1",
646
+ "action": "credit_card.charge",
647
+ "credit_card": "personal",
648
+ "credit_card_id": "card_1dQpXqQwXxsQs9sohN9HrzRAV6y",
649
+ "plan": "Free",
650
+ "plan_id": "plan_1dQpY1jKB48kBd3418PjAotmEwA",
651
+ "timestamp": "2020-06-22T20:24:04.815758"
652
+ }
653
+ ```
654
+
655
+ ## Contributing
656
+
657
+ 1. Fork it ( https://github.com/cased/cased-ruby/fork )
658
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
659
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
660
+ 4. Push to the branch (`git push origin my-new-feature`)
661
+ 5. Create a new Pull Request