shedcloud-partner_api 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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/release.yml +30 -0
  3. data/.gitignore +13 -0
  4. data/AGENTS.md +47 -0
  5. data/CHANGELOG.md +11 -0
  6. data/Gemfile +5 -0
  7. data/LICENSE +21 -0
  8. data/README.md +173 -0
  9. data/Rakefile +21 -0
  10. data/examples/list_lot_stock.rb +22 -0
  11. data/lib/shedcloud/partner_api/auth.rb +26 -0
  12. data/lib/shedcloud/partner_api/auth_provider.rb +95 -0
  13. data/lib/shedcloud/partner_api/client.rb +72 -0
  14. data/lib/shedcloud/partner_api/errors.rb +54 -0
  15. data/lib/shedcloud/partner_api/hosts.rb +31 -0
  16. data/lib/shedcloud/partner_api/http_client.rb +117 -0
  17. data/lib/shedcloud/partner_api/http_transport.rb +57 -0
  18. data/lib/shedcloud/partner_api/request_options.rb +32 -0
  19. data/lib/shedcloud/partner_api/resources/agreements.rb +29 -0
  20. data/lib/shedcloud/partner_api/resources/base.rb +23 -0
  21. data/lib/shedcloud/partner_api/resources/configurator_sessions.rb +13 -0
  22. data/lib/shedcloud/partner_api/resources/customers.rb +29 -0
  23. data/lib/shedcloud/partner_api/resources/documents.rb +17 -0
  24. data/lib/shedcloud/partner_api/resources/domains.rb +17 -0
  25. data/lib/shedcloud/partner_api/resources/events.rb +53 -0
  26. data/lib/shedcloud/partner_api/resources/leads.rb +33 -0
  27. data/lib/shedcloud/partner_api/resources/locations.rb +25 -0
  28. data/lib/shedcloud/partner_api/resources/lot_stock.rb +15 -0
  29. data/lib/shedcloud/partner_api/resources/orders.rb +61 -0
  30. data/lib/shedcloud/partner_api/resources/payments.rb +17 -0
  31. data/lib/shedcloud/partner_api/resources/products.rb +29 -0
  32. data/lib/shedcloud/partner_api/resources/quotes.rb +49 -0
  33. data/lib/shedcloud/partner_api/resources/stock_templates.rb +19 -0
  34. data/lib/shedcloud/partner_api/resources/users.rb +29 -0
  35. data/lib/shedcloud/partner_api/resources/work_orders.rb +33 -0
  36. data/lib/shedcloud/partner_api/scopes.rb +61 -0
  37. data/lib/shedcloud/partner_api/version.rb +7 -0
  38. data/lib/shedcloud/partner_api/webhooks.rb +72 -0
  39. data/lib/shedcloud/partner_api.rb +35 -0
  40. metadata +112 -0
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShedCloud
4
+ module PartnerApi
5
+ module Resources
6
+ class WorkOrders < Base
7
+ def list(params = {})
8
+ @http.request('GET', '/partner/v1/work-orders', query: params) || {}
9
+ end
10
+
11
+ def get(id)
12
+ @http.request('GET', "/partner/v1/work-orders/#{path_segment(id)}") || {}
13
+ end
14
+
15
+ def create(body, options: nil)
16
+ @http.request('POST', '/partner/v1/work-orders', body: body, headers: option_headers(options)) || {}
17
+ end
18
+
19
+ def update(id, body, options: nil)
20
+ @http.request('PATCH', "/partner/v1/work-orders/#{path_segment(id)}", body: body, headers: option_headers(options)) || {}
21
+ end
22
+
23
+ def update_status(id, body)
24
+ @http.request('POST', "/partner/v1/work-orders/#{path_segment(id)}/status", body: body) || {}
25
+ end
26
+
27
+ def status_history(id, params = {})
28
+ @http.request('GET', "/partner/v1/work-orders/#{path_segment(id)}/status-history", query: params) || {}
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShedCloud
4
+ module PartnerApi
5
+ module Scopes
6
+ LOT_STOCK_READ = 'partner-api.lot-stock.read'
7
+ LEADS_READ = 'partner-api.leads.read'
8
+ LEADS_WRITE = 'partner-api.leads.write'
9
+ QUOTES_READ = 'partner-api.quotes.read'
10
+ QUOTES_WRITE = 'partner-api.quotes.write'
11
+ ORDERS_READ = 'partner-api.orders.read'
12
+ ORDERS_WRITE = 'partner-api.orders.write'
13
+ WORK_ORDERS_READ = 'partner-api.work-orders.read'
14
+ WORK_ORDERS_WRITE = 'partner-api.work-orders.write'
15
+ LOCATIONS_READ = 'partner-api.locations.read'
16
+ LOCATIONS_WRITE = 'partner-api.locations.write'
17
+ CUSTOMERS_READ = 'partner-api.customers.read'
18
+ CUSTOMERS_WRITE = 'partner-api.customers.write'
19
+ PRODUCTS_READ = 'partner-api.products.read'
20
+ USERS_READ = 'partner-api.users.read'
21
+ USERS_WRITE = 'partner-api.users.write'
22
+ CONTRACTS_READ = 'partner-api.contracts.read'
23
+ PAYMENTS_READ = 'partner-api.payments.read'
24
+ PAYMENTS_WRITE = 'partner-api.payments.write'
25
+ DOCUMENTS_READ = 'partner-api.documents.read'
26
+ EVENTS_READ = 'partner-api.events.read'
27
+ CONFIGURATOR_SESSIONS_WRITE = 'partner-api.configurator-sessions.write'
28
+ DOMAINS_READ = 'partner-api.domains.read'
29
+ AGREEMENTS_READ = 'partner-api.agreements.read'
30
+ PRODUCTS_WRITE = 'partner-api.products.write'
31
+
32
+ ALL = [
33
+ LOT_STOCK_READ,
34
+ LEADS_READ,
35
+ LEADS_WRITE,
36
+ QUOTES_READ,
37
+ QUOTES_WRITE,
38
+ ORDERS_READ,
39
+ ORDERS_WRITE,
40
+ WORK_ORDERS_READ,
41
+ WORK_ORDERS_WRITE,
42
+ LOCATIONS_READ,
43
+ LOCATIONS_WRITE,
44
+ CUSTOMERS_READ,
45
+ CUSTOMERS_WRITE,
46
+ PRODUCTS_READ,
47
+ USERS_READ,
48
+ USERS_WRITE,
49
+ CONTRACTS_READ,
50
+ PAYMENTS_READ,
51
+ PAYMENTS_WRITE,
52
+ DOCUMENTS_READ,
53
+ EVENTS_READ,
54
+ CONFIGURATOR_SESSIONS_WRITE,
55
+ DOMAINS_READ,
56
+ AGREEMENTS_READ,
57
+ PRODUCTS_WRITE
58
+ ].freeze
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShedCloud
4
+ module PartnerApi
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ module ShedCloud
6
+ module PartnerApi
7
+ module Webhooks
8
+ SIGNATURE_HEADER = 'X-ShedCloud-Signature'
9
+ EVENT_ID_HEADER = 'X-ShedCloud-Event-Id'
10
+ EVENT_TYPE_HEADER = 'X-ShedCloud-Event-Type'
11
+ DEFAULT_TOLERANCE_SECONDS = 300
12
+
13
+ module_function
14
+
15
+ def compute_signature(secret, timestamp, body)
16
+ OpenSSL::HMAC.hexdigest('SHA256', secret, "#{timestamp}.#{body}")
17
+ end
18
+
19
+ def verify_signature(secret, header, body, tolerance_seconds: 0)
20
+ verify_signature_at(secret, header, body, Time.now.to_i, tolerance_seconds)
21
+ end
22
+
23
+ def verify_signature_at(secret, header, body, now, tolerance_seconds = 0)
24
+ raise ArgumentError, 'webhook signature verification failed: secret is required' if secret.to_s.empty?
25
+ raise ArgumentError, 'webhook signature verification failed: signature header is missing' if header.to_s.strip.empty?
26
+
27
+ tolerance_seconds = DEFAULT_TOLERANCE_SECONDS if tolerance_seconds <= 0
28
+
29
+ timestamp = 0
30
+ signatures = []
31
+
32
+ header.to_s.split(',').each do |part|
33
+ part = part.strip
34
+ next unless part.include?('=')
35
+
36
+ key, value = part.split('=', 2)
37
+ case key
38
+ when 't'
39
+ unless value.match?(/\A\d+\z/)
40
+ raise ArgumentError, 'webhook signature verification failed: invalid timestamp in signature header'
41
+ end
42
+
43
+ timestamp = value.to_i
44
+ when 'v1'
45
+ signatures << value
46
+ end
47
+ end
48
+
49
+ if timestamp.zero? || signatures.empty?
50
+ raise ArgumentError, 'webhook signature verification failed: signature header missing t= or v1='
51
+ end
52
+
53
+ delta = (now - timestamp).abs
54
+ if delta > tolerance_seconds
55
+ raise ArgumentError, 'webhook signature verification failed: signature timestamp outside tolerance'
56
+ end
57
+
58
+ expected = compute_signature(secret, timestamp, body)
59
+ return nil if signatures.any? { |signature| secure_compare(signature.downcase, expected) }
60
+
61
+ raise ArgumentError, 'webhook signature verification failed: signature mismatch'
62
+ end
63
+
64
+ def secure_compare(left, right)
65
+ return false unless left.bytesize == right.bytesize
66
+
67
+ left.unpack('C*').zip(right.unpack('C*')).reduce(0) { |acc, (a, b)| acc | (a ^ b) }.zero?
68
+ end
69
+ private_class_method :secure_compare
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'partner_api/version'
4
+ require_relative 'partner_api/hosts'
5
+ require_relative 'partner_api/auth'
6
+ require_relative 'partner_api/errors'
7
+ require_relative 'partner_api/scopes'
8
+ require_relative 'partner_api/request_options'
9
+ require_relative 'partner_api/http_transport'
10
+ require_relative 'partner_api/http_client'
11
+ require_relative 'partner_api/auth_provider'
12
+ require_relative 'partner_api/webhooks'
13
+ require_relative 'partner_api/resources/base'
14
+ require_relative 'partner_api/resources/lot_stock'
15
+ require_relative 'partner_api/resources/stock_templates'
16
+ require_relative 'partner_api/resources/leads'
17
+ require_relative 'partner_api/resources/quotes'
18
+ require_relative 'partner_api/resources/orders'
19
+ require_relative 'partner_api/resources/work_orders'
20
+ require_relative 'partner_api/resources/locations'
21
+ require_relative 'partner_api/resources/customers'
22
+ require_relative 'partner_api/resources/domains'
23
+ require_relative 'partner_api/resources/agreements'
24
+ require_relative 'partner_api/resources/products'
25
+ require_relative 'partner_api/resources/users'
26
+ require_relative 'partner_api/resources/payments'
27
+ require_relative 'partner_api/resources/documents'
28
+ require_relative 'partner_api/resources/events'
29
+ require_relative 'partner_api/resources/configurator_sessions'
30
+ require_relative 'partner_api/client'
31
+
32
+ module ShedCloud
33
+ module PartnerApi
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shedcloud-partner_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Corland Partners LLC
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.13'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.13'
41
+ description: Call ShedCloud Partner API endpoints (/partner/v1/*) with API keys or
42
+ OAuth2 client credentials.
43
+ email: []
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".github/workflows/release.yml"
49
+ - ".gitignore"
50
+ - AGENTS.md
51
+ - CHANGELOG.md
52
+ - Gemfile
53
+ - LICENSE
54
+ - README.md
55
+ - Rakefile
56
+ - examples/list_lot_stock.rb
57
+ - lib/shedcloud/partner_api.rb
58
+ - lib/shedcloud/partner_api/auth.rb
59
+ - lib/shedcloud/partner_api/auth_provider.rb
60
+ - lib/shedcloud/partner_api/client.rb
61
+ - lib/shedcloud/partner_api/errors.rb
62
+ - lib/shedcloud/partner_api/hosts.rb
63
+ - lib/shedcloud/partner_api/http_client.rb
64
+ - lib/shedcloud/partner_api/http_transport.rb
65
+ - lib/shedcloud/partner_api/request_options.rb
66
+ - lib/shedcloud/partner_api/resources/agreements.rb
67
+ - lib/shedcloud/partner_api/resources/base.rb
68
+ - lib/shedcloud/partner_api/resources/configurator_sessions.rb
69
+ - lib/shedcloud/partner_api/resources/customers.rb
70
+ - lib/shedcloud/partner_api/resources/documents.rb
71
+ - lib/shedcloud/partner_api/resources/domains.rb
72
+ - lib/shedcloud/partner_api/resources/events.rb
73
+ - lib/shedcloud/partner_api/resources/leads.rb
74
+ - lib/shedcloud/partner_api/resources/locations.rb
75
+ - lib/shedcloud/partner_api/resources/lot_stock.rb
76
+ - lib/shedcloud/partner_api/resources/orders.rb
77
+ - lib/shedcloud/partner_api/resources/payments.rb
78
+ - lib/shedcloud/partner_api/resources/products.rb
79
+ - lib/shedcloud/partner_api/resources/quotes.rb
80
+ - lib/shedcloud/partner_api/resources/stock_templates.rb
81
+ - lib/shedcloud/partner_api/resources/users.rb
82
+ - lib/shedcloud/partner_api/resources/work_orders.rb
83
+ - lib/shedcloud/partner_api/scopes.rb
84
+ - lib/shedcloud/partner_api/version.rb
85
+ - lib/shedcloud/partner_api/webhooks.rb
86
+ homepage: https://github.com/Corland-Partners-LLC/shedcloud-gem
87
+ licenses:
88
+ - MIT
89
+ metadata:
90
+ homepage_uri: https://github.com/Corland-Partners-LLC/shedcloud-gem
91
+ source_code_uri: https://github.com/Corland-Partners-LLC/shedcloud-gem
92
+ changelog_uri: https://github.com/Corland-Partners-LLC/shedcloud-gem/blob/main/CHANGELOG.md
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: 3.2.0
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubygems_version: 3.4.19
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Official Ruby client for the ShedCloud Partner API
112
+ test_files: []