gatekeeper_api_client 1.0.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
+ SHA256:
3
+ metadata.gz: 9bbeca19cfee61257aa8fa4dea9cc09e371da8240c97821723ccda148e552ddc
4
+ data.tar.gz: d9782808bedfa188148d7d44e0d53d53bb365cba3d33387a3dbe84bca5d92ccf
5
+ SHA512:
6
+ metadata.gz: c545e300c3b2d004897be956516f2077d4593a5b68c0a8469269e509430037a5d701d5c7cbe5b930d31ff78ff7dd06631d49670f88c74f2b0bdf499a4b4a1f76
7
+ data.tar.gz: d63eed0e59cfcb27d32579522a1585b3e6c47e36205810b7973eef8e85d844b94199550290e3f93cf7b30d9df9e9742e02d00f46ca08fe56f374f566e10a18fc
@@ -0,0 +1,29 @@
1
+ name: continuous-integration
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - '*'
7
+ push:
8
+ branches:
9
+ - main
10
+ jobs:
11
+ build:
12
+ # https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md
13
+ runs-on: ubuntu-22.04
14
+ if: "! contains(github.event.head_commit.message, 'skip ci')"
15
+
16
+ steps:
17
+ - uses: actions/checkout@v3
18
+
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ # ruby-version: from .ruby-version
23
+ bundler-cache: true
24
+
25
+ - name: Run RSpec
26
+ run: |
27
+ bin/rspec spec --fail-fast --format progress
28
+ env:
29
+ RUBYOPT: -W0
@@ -0,0 +1,29 @@
1
+ name: publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ release:
9
+ # https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
10
+ runs-on: ubuntu-24.04
11
+
12
+ permissions:
13
+ id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
14
+ contents: write # IMPORTANT: this permission is required for `rake release` to push the release tag
15
+
16
+
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Set up Ruby
22
+ uses: ruby/setup-ruby@v1
23
+ with:
24
+ bundler-cache: true
25
+ ruby-version: ruby
26
+
27
+ # Publish the gem to RubyGems
28
+ - uses: rubygems/release-gem@v1
29
+
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.7
data/GEM_VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
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 gatekeeper_api_client.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ gatekeeper_api_client (1.0.0)
5
+ rollbar (~> 3.6)
6
+ tzinfo (~> 2.0)
7
+ tzinfo-data (~> 1.2025)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ concurrent-ruby (1.3.5)
13
+ diff-lcs (1.6.1)
14
+ rake (13.2.1)
15
+ rollbar (3.6.2)
16
+ rspec (3.13.0)
17
+ rspec-core (~> 3.13.0)
18
+ rspec-expectations (~> 3.13.0)
19
+ rspec-mocks (~> 3.13.0)
20
+ rspec-core (3.13.3)
21
+ rspec-support (~> 3.13.0)
22
+ rspec-expectations (3.13.3)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.13.0)
25
+ rspec-mocks (3.13.2)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.13.0)
28
+ rspec-support (3.13.2)
29
+ tzinfo (2.0.6)
30
+ concurrent-ruby (~> 1.0)
31
+ tzinfo-data (1.2025.2)
32
+ tzinfo (>= 1.0.0)
33
+
34
+ PLATFORMS
35
+ arm64-darwin-24
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bundler (~> 2.6)
40
+ gatekeeper_api_client!
41
+ rake (~> 13.2)
42
+ rspec (~> 3.13)
43
+
44
+ BUNDLED WITH
45
+ 2.6.7
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # Gatekeeper API Client
2
+ Common logic for consuming the GateKeeper API.
3
+
4
+ ## Installation
5
+ Add this line to your application's Gemfile:
6
+ ```
7
+ source "https://rubygems.pkg.github.com/inforlife" do
8
+ gem "gatekeeper_api_client", "1.0.0"
9
+ end
10
+ ```
11
+
12
+ ## Usage
13
+ The application using this gem must have defined the following environemnt variables:
14
+ - `GATEKEEPER_API_KEY`
15
+ - `GATEKEEPER_TIMEZONE`
16
+ - `GATEKEEPER_URL`
17
+
18
+ ### Transit
19
+ To post a `transit`, build an object with a record and send the `post` message to it.
20
+
21
+ ```
22
+ Transit.new(record).post
23
+ ```
24
+
25
+ The record must respond to:
26
+ - `authorized`
27
+ - `badge_number`
28
+ - `date`
29
+ - `sensor_code`
30
+ - `time`
31
+ - `valid?`
32
+
33
+ ### Employee
34
+ To post an `employee`, build an object with a record and send the `post` message to it.
35
+
36
+ ```
37
+ Employee.new(record).post
38
+ ```
39
+
40
+ The record must respond to:
41
+ - `employee_name`
42
+ - `badge_number`
43
+ - `department_name`
44
+ - `valid?`
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
data/bin/rspec ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("rspec-core", "rspec")
@@ -0,0 +1,30 @@
1
+ version = File.read(File.expand_path("GEM_VERSION", __dir__)).strip
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "gatekeeper_api_client"
5
+ s.version = version
6
+ s.summary = "The GateKeeper API Client."
7
+ s.description = "The common logic for consuming the GateKeeper API."
8
+
9
+ s.required_ruby_version = ">= 3.3.7"
10
+
11
+ s.license = "MIT"
12
+
13
+ s.author = "Sigfrid Dusci"
14
+ s.email = "sig@inforlife.ch"
15
+ s.homepage = "https://github.com/inforlife/gatekeeper-api-client"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
21
+ end
22
+
23
+ s.add_runtime_dependency "tzinfo", "~> 2.0"
24
+ s.add_runtime_dependency "tzinfo-data", "~> 1.2025"
25
+ s.add_runtime_dependency "rollbar", "~> 3.6"
26
+
27
+ s.add_development_dependency "bundler", "~> 2.6"
28
+ s.add_development_dependency "rake", "~> 13.2"
29
+ s.add_development_dependency "rspec", "~> 3.13"
30
+ end
@@ -0,0 +1,2 @@
1
+ class ClientError < StandardError
2
+ end
@@ -0,0 +1,5 @@
1
+ class ErrorHandler
2
+ def self.call(error)
3
+ Rollbar.error(error)
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ class Gateway
2
+ ENDPOINTS = { Transit: "transits",
3
+ Employee: "employees" }.freeze
4
+
5
+ def initialize(object)
6
+ @object = object
7
+ end
8
+
9
+ def post
10
+ uri = URI.parse("#{ENV["GATEKEEPER_URL"]}/api/#{ENDPOINTS[@object.class.name.to_sym]}")
11
+ http = Net::HTTP.new(uri.host, uri.port)
12
+ http.use_ssl = true
13
+
14
+ request = Net::HTTP::Post.new(uri.request_uri)
15
+ request.content_type = "application/json"
16
+ request["Authorization"] = "Bearer #{ENV["GATEKEEPER_API_KEY"]}"
17
+ request.body = JSON.generate(@object.to_json)
18
+
19
+ response = http.request(request)
20
+
21
+ raise ClientError, response.body if Integer(response.code) != 201
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ class Employee < Resource
2
+ def initialize(record, on_error: ErrorHandler)
3
+ super(record, on_error: on_error)
4
+ end
5
+
6
+ def to_json
7
+ {"employee":
8
+ {
9
+ "name": @record.employee_name,
10
+ "badge_number": @record.badge_number,
11
+ "department_name": @record.department_name
12
+ }
13
+ }
14
+ end
15
+ end
16
+
17
+
@@ -0,0 +1,14 @@
1
+ class Resource
2
+ def initialize(record, on_error: ErrorHandler)
3
+ @record = record
4
+ @error_handler = on_error
5
+ end
6
+
7
+ def post
8
+ if @record.valid?
9
+ RetryingGateway.new(Gateway.new(self)).post
10
+ else
11
+ @error_handler.call(@record)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ class Transit < Resource
2
+ def initialize(record, on_error: ErrorHandler)
3
+ super(record, on_error: on_error)
4
+ end
5
+
6
+ def to_json
7
+ {"transit":
8
+ {
9
+ "occurred_at": UtcTime.parse(@record.date, @record.time),
10
+ "badge_number": @record.badge_number,
11
+ "sensor_code": @record.sensor_code,
12
+ "authorized": @record.authorized == "1"
13
+ }
14
+ }
15
+ end
16
+ end
17
+
18
+
@@ -0,0 +1,16 @@
1
+ class RetryingGateway < DelegateClass(Gateway)
2
+ def initialize(inner, on_error: ErrorHandler)
3
+ super(inner)
4
+ @error_handler = on_error
5
+ end
6
+
7
+ def post(tries: 3)
8
+ super()
9
+ rescue => error
10
+ if (tries -= 1) > 0
11
+ retry
12
+ else
13
+ @error_handler.call(error)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ class UtcTime
2
+ def self.parse(record_date, record_time)
3
+ date = record_date.tr('.', '-')
4
+ time = record_time.tr('.', ':')
5
+
6
+ timezone.local_to_utc(Time.parse([date, time].join(" ")))
7
+ end
8
+
9
+ def self.timezone
10
+ TZInfo::Timezone.get(ENV["GATEKEEPER_TIMEZONE"])
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ require "net/http"
2
+ require "rollbar"
3
+ require "tzinfo"
4
+ require "delegate"
5
+
6
+ require "gatekeeper_api_client/client_error"
7
+ require "gatekeeper_api_client/error_handler"
8
+ require "gatekeeper_api_client/gateway"
9
+ require "gatekeeper_api_client/retrying_gateway"
10
+ require "gatekeeper_api_client/utc_time"
11
+
12
+ require "gatekeeper_api_client/resources/resource"
13
+ require "gatekeeper_api_client/resources/employee"
14
+ require "gatekeeper_api_client/resources/transit"
15
+
16
+ module GateKeerApiClient
17
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gatekeeper_api_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sigfrid Dusci
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: tzinfo
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: tzinfo-data
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.2025'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.2025'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rollbar
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.6'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.6'
54
+ - !ruby/object:Gem::Dependency
55
+ name: bundler
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.6'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.6'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rake
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '13.2'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '13.2'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rspec
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.13'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.13'
96
+ description: The common logic for consuming the GateKeeper API.
97
+ email: sig@inforlife.ch
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - ".github/workflows/continuous-integration.yml"
103
+ - ".github/workflows/publish.yml"
104
+ - ".gitignore"
105
+ - ".rspec"
106
+ - ".ruby-version"
107
+ - GEM_VERSION
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - README.md
111
+ - Rakefile
112
+ - bin/rspec
113
+ - gatekeeper_api_client.gemspec
114
+ - lib/gatekeeper_api_client.rb
115
+ - lib/gatekeeper_api_client/client_error.rb
116
+ - lib/gatekeeper_api_client/error_handler.rb
117
+ - lib/gatekeeper_api_client/gateway.rb
118
+ - lib/gatekeeper_api_client/resources/employee.rb
119
+ - lib/gatekeeper_api_client/resources/resource.rb
120
+ - lib/gatekeeper_api_client/resources/transit.rb
121
+ - lib/gatekeeper_api_client/retrying_gateway.rb
122
+ - lib/gatekeeper_api_client/utc_time.rb
123
+ homepage: https://github.com/inforlife/gatekeeper-api-client
124
+ licenses:
125
+ - MIT
126
+ metadata: {}
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: 3.3.7
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubygems_version: 3.6.7
142
+ specification_version: 4
143
+ summary: The GateKeeper API Client.
144
+ test_files: []