close_encounters 0.1.2 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20a98acff8fa4c0e6c76e3ed6395f5717ee7dbf47873c4090dc31d5017e86ef2
4
- data.tar.gz: 96af7f9bc65d6f0ad66932f87d4d6a0f6ed80416b718b787ae73bcf332058943
3
+ metadata.gz: 4954f6a9a487299009cb84b6af2571743e1d08d2703683edbcde73e0670a154b
4
+ data.tar.gz: d05d458352582236246c0ceab9f556f8ca3c2df9c3531db3e35123e854cb6485
5
5
  SHA512:
6
- metadata.gz: 8398c29adc130ca89723d8af7e05d507f6427bcb4b5037c3f587249dbbdcf3773b2821122a81cdc6c57768785bd6fade2ed665bca4d242b0e14468b94ce6c102
7
- data.tar.gz: 35fd7ce3f343d2a9fea20c875f8ef50f4c79c690fc7641d49b8797801a655694a49dc1741c42df4126b0347a0b31e9d89b5c4dd105e68093a631e9a8c874ba6c
6
+ metadata.gz: 64c3973533245763a65dd67e466c6da6b7f425853aeaebeb4712d94eb115dfc36484a49ea146a93db1e77dd5848f4c8770d1768a76c5b435d43f4acdd2f196e0
7
+ data.tar.gz: d2c569f12ce8da83cfc3d3eb8d437b0100436687212bbded9d10fee5989a74e5bd3c67d03b2f4d314c4903bdbcd90bc74990bba754cbc9ac5f9cfb5d2b612d46
data/CHANGELOG.md CHANGED
@@ -5,26 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
- ## [0.1.2] - 2024-07-11
8
+ ## [0.2.0] - 2025-02-26
9
9
 
10
- ### Added
11
-
12
- - Check if the table exits before conditionally setting up the serialize column
13
-
14
- ### Removed
10
+ ### Changed
15
11
 
16
- - Appending engine migrations to the main app's migration path
17
-
18
- ## [0.1.1] - 2024-07-11
12
+ - Test with Ruby 3.4
19
13
 
20
14
  ### Added
21
15
 
22
- - Support for Importmaps
23
- - `reissue` gem for managing releases
24
-
25
- ### Fixed
16
+ - Ability to use CloseEncounters::Middleware and CloseEncounters.auto_contact! to automatically track responses from third-party services.
17
+ - Add metadata to events for storing extra information about the event.
26
18
 
27
- - Alter newest scope to properly return a relation limited to 1 record
28
- - Update ensure_service to not overwrite existing connection_info
29
- - Allow specs to run properly locally
30
- - Incorrect manifest paths for sprockets
19
+ ## [0.1.4] - Unreleased
data/README.md CHANGED
@@ -27,6 +27,23 @@ CloseEncounters.status("SomeThirdPartyService") # => 200
27
27
  CloseEncounters.status("SomeThirdPartyService") # => 500
28
28
  ```
29
29
 
30
+ ### Rack Middleware
31
+
32
+ Setup your middleware in your `config/application.rb` or `config/environments/production.rb`.
33
+
34
+ ```ruby
35
+ config.middleware.use CloseEncounters::Middleware
36
+ ```
37
+
38
+ This will automatically track responses from third-party services when you store a "domain" key in the
39
+ `connection_info` in the ParticipantService records.
40
+
41
+ Alternatively, you can use the `auto_contact!` method to automatically turn on the rack middleware:
42
+
43
+ ```ruby
44
+ CloseEncounters.auto_contact!
45
+ ```
46
+
30
47
  ### TODO
31
48
 
32
49
  - [ ] Add JS to the gem to track events on the front-end.
@@ -6,5 +6,9 @@ module CloseEncounters
6
6
  foreign_key: "close_encounters_participant_service_id"
7
7
 
8
8
  scope :newest, -> { order(created_at: :desc).limit(1) }
9
+
10
+ unless ActiveRecord::Base.connection.adapter_name.downcase.include?("postgresql")
11
+ serialize :metadata, coder: JSON
12
+ end
9
13
  end
10
14
  end
@@ -6,18 +6,21 @@ module CloseEncounters
6
6
 
7
7
  validates :name, presence: true
8
8
 
9
- # if the table exists, then we can check the column type
10
- if connection.table_exists?(table_name) && (
11
- columns_hash = connection.schema_cache.columns_hash(table_name)
12
- )
13
- if columns_hash["connection_info"].type == :text
14
- serialize :connection_info, coder: JSON
15
- end
16
- end
17
-
18
9
  # ONLY encrypt if you have the necessary keys
19
10
  if Rails.application.credentials.close_encounters_encryption_key.present?
20
11
  encrypts :connection_info
21
12
  end
13
+
14
+ def connection_info
15
+ if super.is_a?(String)
16
+ JSON.parse(super)
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def connection_info=(value)
23
+ super(value.to_json)
24
+ end
22
25
  end
23
26
  end
@@ -0,0 +1,9 @@
1
+ class AddMetadataToCloseEncountersParticipantEvents < ActiveRecord::Migration[7.1]
2
+ def change
3
+ if ActiveRecord::Base.connection.adapter_name.downcase.include?("postgresql")
4
+ add_column :close_encounters_participant_events, :metadata, :jsonb
5
+ else
6
+ add_column :close_encounters_participant_events, :metadata, :text
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,4 @@
1
+ require_relative "middleware"
1
2
  module CloseEncounters
2
3
  class Engine < ::Rails::Engine
3
4
  isolate_namespace CloseEncounters
@@ -6,6 +7,10 @@ module CloseEncounters
6
7
  g.test_framework :minitest, spec: true
7
8
  end
8
9
 
10
+ initializer "close_encounters.middleware" do |app|
11
+ app.middleware.use CloseEncounters::Middleware if CloseEncounters.auto_contact?
12
+ end
13
+
9
14
  if defined?(Importmap)
10
15
  initializer "close_encounters.importmap", before: "importmap" do |app|
11
16
  app.config.importmap.paths << root.join("config/importmap.rb")
@@ -0,0 +1,31 @@
1
+ module CloseEncounters
2
+ class Middleware
3
+ def initialize(app, tracker: CloseEncounters)
4
+ @app = app
5
+ @tracker = tracker
6
+ end
7
+
8
+ def call(env)
9
+ status, headers, response = @app.call(env)
10
+
11
+ record_contact(env["SERVER_NAME"], status, response)
12
+
13
+ [status, headers, response]
14
+ end
15
+
16
+ private
17
+
18
+ def record_contact(host, status, response)
19
+ if (name = participant_services[host])
20
+ @tracker.contact(name, status:, response:)
21
+ end
22
+ end
23
+
24
+ def participant_services
25
+ @participant_services ||= CloseEncounters::ParticipantService.all
26
+ .map do |service|
27
+ [service.connection_info["domain"], service.name]
28
+ end.to_h
29
+ end
30
+ end
31
+ end
@@ -1,3 +1,3 @@
1
1
  module CloseEncounters
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -19,6 +19,39 @@ module CloseEncounters
19
19
  end
20
20
  end
21
21
 
22
+ # Record a verification of a contact with a third party service where the
23
+ # verification is a callable which must also respond to to_s.
24
+ #
25
+ # For example, provide a callable which checks the JSON Schema for a response body
26
+ # and will record an event if calling the verification returns false.
27
+ #
28
+ # @param name [String] the name of the service
29
+ # @param status [Integer] the HTTP status of the contact
30
+ # @param response [String] the response object
31
+ # @param verifier [Proc] the verification callable which must also respond to to_s
32
+ def verify(name, status:, response:, verifier:)
33
+ service = ParticipantService.find_by!(name:)
34
+ unless service.events.newest.pick(:status) == status && (verified = verifier.call(response))
35
+ service.events.create!(status:, response:, metadata: {verified:, verification: verifier.to_s})
36
+ end
37
+ end
38
+
39
+ # Determine if contacts with third party services should be recorded automatically
40
+ # using the Rack Middleware
41
+ #
42
+ # Set the CLOSE_ENCOUNTERS_AUTO_CONTACT environment variable to enable this feature
43
+ # or call CloseEncounters.auto_contact! in an initializer
44
+ #
45
+ # @return [Boolean] whether or not to automatically record contacts
46
+ def auto_contact?
47
+ !!(ENV["CLOSE_ENCOUNTERS_AUTO_CONTACT"] || @auto_contact)
48
+ end
49
+
50
+ # Enable automatic contact recording in the Rack Middleware
51
+ def auto_contact!
52
+ @auto_contact = true
53
+ end
54
+
22
55
  # Get the status of the most recent contact with a third party service
23
56
  #
24
57
  # @param name [String] the name of the service
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: close_encounters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-11 00:00:00.000000000 Z
11
+ date: 2025-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -112,13 +112,14 @@ files:
112
112
  - app/models/close_encounters/application_record.rb
113
113
  - app/models/close_encounters/participant_event.rb
114
114
  - app/models/close_encounters/participant_service.rb
115
- - app/views/layouts/close_encounters/application.html.erb
116
115
  - config/importmap.rb
117
116
  - db/migrate/20240430173723_create_close_encounters_participant_services.rb
118
117
  - db/migrate/20240430173725_create_close_encounters_participant_events.rb
119
118
  - db/migrate/20240508190642_add_close_ecounters_indexes.rb
119
+ - db/migrate/20250225232551_add_metadata_to_close_encounters_participant_events.rb
120
120
  - lib/close_encounters.rb
121
121
  - lib/close_encounters/engine.rb
122
+ - lib/close_encounters/middleware.rb
122
123
  - lib/close_encounters/version.rb
123
124
  - lib/tasks/close_encounters.rake
124
125
  homepage: https://github.com/SOFware/close_encounters
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Close encounters</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
7
-
8
- <%= stylesheet_link_tag "close_encounters/application", media: "all" %>
9
- </head>
10
- <body>
11
-
12
- <%= yield %>
13
-
14
- </body>
15
- </html>