skykick 0.2.1 → 0.3.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: 4e219c7c7f5e5af499eb2dfa75b4f26ec1b44a0feec1f388debf960f7c623e91
4
- data.tar.gz: 2cec92749ffd33a36a0ea36d583dd025f304c8672c5bf1469146986642bd72f2
3
+ metadata.gz: 2a6fddb22533868b7d481dab155eba199d22dc107614b504d7b30b2354a8f125
4
+ data.tar.gz: 4a91206b72d5ee286aa9bb974e4df2ef82631d26c4c9875c87da0308f82557fb
5
5
  SHA512:
6
- metadata.gz: b152d1d931fd129b0c921c3d9634831c6037f0d5cca1eb10f9ea16daaae1d886c5234e8a736be2a1a13b76daa3eae0b196bc81eacdc45703d42f8595e35359b0
7
- data.tar.gz: dda82313a9f6208348f1381ae01e08773591033cce4a90d2cc61d215bd8a189a9025d2bdf96aae5861b504c4de68432f230523c8309159b0c456fc643887e575
6
+ metadata.gz: b533bf98a520ca3aff074af183b8889807da2960a319dd4c5cf007491d4f49da0c15190671aeb11ccfc1c55842078453e0498f1d87271c8c28b81ea2cecca5d6
7
+ data.tar.gz: a1ba2fb65958104c88f603c893695b5d1f0c62081b578ec3a372c0e63da5f20db06b33fd29356c2025ad22e19a0d0f06679f040bc01a09191333ea69876e90f8
data/CHANGELOG.md CHANGED
@@ -1,13 +1,25 @@
1
- ## [Unreleased]
1
+ # Changelog
2
2
 
3
3
  ## [0.1.0] - 2024-02-05
4
+
4
5
  - Initial release
5
6
 
6
7
  ## [0.1.1] - 2024-02-08
8
+
7
9
  - Update OData support
8
10
 
9
11
  ## [0.2.0] - 2024-02-20
12
+
10
13
  - Exception handling harmonized
11
14
 
12
15
  ## [0.2.1] - 2024-03-06
16
+
13
17
  - Upgrade faraday 2
18
+
19
+ ## [0.2.2] - 2025-03-21
20
+
21
+ - updated documentation, filter subscription key from logs
22
+
23
+ ## [0.3.0] - 2025-09-01
24
+
25
+ - updated api endpoint to https://apis.cloudservices.connectwise.com
data/README.md CHANGED
@@ -1,11 +1,14 @@
1
1
  # Skykick Office365 backup API
2
+
2
3
  [![Version](https://img.shields.io/gem/v/skykick.svg)](https://rubygems.org/gems/skykick)
3
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/a340908aaf944745eeda/maintainability)](https://codeclimate.com/github/jancotanis/skykick/maintainability)
4
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/a340908aaf944745eeda/test_coverage)](https://codeclimate.com/github/jancotanis/skykick/test_coverage)
5
6
 
6
- This is a wrapper for the Skykick Office365 backup API. You can see the API endpoints here https://developers.skykick.com/apis
7
+ This is a wrapper for the Skykick Office365 backup API.
8
+ You can see the [API endpoints](https://developers.skykick.com/apis)
7
9
 
8
- Currently only the GET requests to endpoints /Backup and /Alerts are implemented (readonly).
10
+ Currently only the GET requests to endpoints /Backup and /Alerts
11
+ are implemented (readonly).
9
12
 
10
13
  ## Installation
11
14
 
@@ -17,15 +20,20 @@ gem 'skykick'
17
20
 
18
21
  And then execute:
19
22
 
20
- $ bundle install
23
+ ```console
24
+ > bundle install
25
+ ```
21
26
 
22
27
  Or install it yourself as:
23
28
 
24
- $ gem install skykick
29
+ ```console
30
+ > gem install skykick
31
+ ```
25
32
 
26
33
  ## Usage
27
34
 
28
- Before you start making the requests to API provide the client id and client secret and email/password using the configuration wrapping.
35
+ Before you start making the requests to API provide the client id and client secret
36
+ and email/password using the configuration wrapping.
29
37
 
30
38
  ```ruby
31
39
  require 'skykick'
@@ -45,41 +53,46 @@ end
45
53
  ```
46
54
 
47
55
  ## Resources
56
+
48
57
  ### Authentication
58
+
49
59
  ```ruby
50
60
  # setup configuration
51
61
  #
52
62
  client.login
53
63
  ```
54
- |Resource|API endpoint|Description|
55
- |:--|:--|:--|
56
- |.auth_token or .login|https://apis.skykick.com/auth/token|
57
64
 
65
+ |Resource|API endpoint|
66
+ |:--|:--|
67
+ |.auth_token or .login|https://apis.cloudservices.connectwise.com/auth/token|
58
68
 
59
69
  ### Backup
60
- Endpoint for backup related requests
70
+
71
+ Endpoint for backup related requests
72
+
61
73
  ```ruby
62
74
  subscriptions = client.subscriptions
63
75
  ```
64
76
 
65
77
  |Resource|API endpoint|
66
78
  |:--|:--|
67
- |autodiscover |https://apis.skykick.com/Backup/{id}/autodiscover |
68
- |datacenters |https://apis.skykick.com/Backup/datacenters |
69
- |exchange_mailboxe |https://apis.skykick.com/Backup/{id}/mailboxes/{mailboxId} |
70
- |exchange_mailboxes |https://apis.skykick.com/Backup/{id}/mailboxes |
71
- |lastsnapshotstats |https://apis.skykick.com/Backup/{backupServiceId}/lastsnapshotstats |
72
- |retention_periods |https://apis.skykick.com/Backup/{id}/retentionperiod |
73
- |sharePoint_sites |https://apis.skykick.com/Backup/{id}/sites |
74
- |sku |https://apis.skykick.com/Backup/{id}/sku |
75
- |storage_settings |https://apis.skykick.com/Backup/{id}/storagesettings |
76
- |subscription_settings |https://apis.skykick.com/Backup/{id}/subscriptionsettings |
77
- |subscriptions |https://apis.skykick.com/Backup/ |
78
- |partner_subscriptions(partner_id)|https://apis.skykick.com/Backup/{partner_id} |
79
-
79
+ |autodiscover |https://apis.cloudservices.connectwise.com/Backup/{id}/autodiscover|
80
+ |datacenters |https://apis.cloudservices.connectwise.com/Backup/datacenters|
81
+ |exchange_mailboxe |https://apis.cloudservices.connectwise.com/Backup/{id}/mailboxes/{mailboxId}|
82
+ |exchange_mailboxes |https://apis.cloudservices.connectwise.com/Backup/{id}/mailboxes|
83
+ |lastsnapshotstats |https://apis.cloudservices.connectwise.com/Backup/{backupServiceId}/lastsnapshotstats|
84
+ |retention_periods |https://apis.cloudservices.connectwise.com/Backup/{id}/retentionperiod|
85
+ |sharePoint_sites |https://apis.cloudservices.connectwise.com/Backup/{id}/sites|
86
+ |sku |https://apis.cloudservices.connectwise.com/Backup/{id}/sku|
87
+ |storage_settings |https://apis.cloudservices.connectwise.com/Backup/{id}/storagesettings|
88
+ |subscription_settings |https://apis.cloudservices.connectwise.com/Backup/{id}/subscriptionsettings|
89
+ |subscriptions |https://apis.cloudservices.connectwise.com/Backup/|
90
+ |partner_subscriptions(partner_id)|https://apis.cloudservices.connectwise.com/Backup/{partner_id}|
80
91
 
81
92
  ### Alerts
93
+
82
94
  Returns Alerts for a provided Email Migration Order ID or Backup service ID.
95
+
83
96
  ```ruby
84
97
  subscriptions = client.subscriptions
85
98
  alerts = client.alerts(subscriptions.first.id)
@@ -92,7 +105,7 @@ alerts = client.alerts(subscriptions.first.id)
92
105
 
93
106
  ## Contributing
94
107
 
95
- Bug reports and pull requests are welcome on GitHub at https://github.com/jancotanis/skykick.
108
+ Bug reports and pull requests are welcome on [GitHub](https://github.com/jancotanis/skykick).
96
109
 
97
110
  ## License
98
111
 
data/lib/skykick/api.rb CHANGED
@@ -1,29 +1,55 @@
1
- require "wrapi"
1
+ # frozen_string_literal: true
2
+
3
+ require 'wrapi'
2
4
  require File.expand_path('connection', __dir__)
3
5
  require File.expand_path('authentication', __dir__)
4
6
 
5
7
  module Skykick
6
- # @private
8
+ # The `Skykick::API` class manages the core configuration and settings for the API client.
9
+ # It allows customization of options like endpoint, user agent, and pagination handling.
10
+ # This class copies configuration settings from the Skykick singleton and provides methods to retrieve the client configuration.
7
11
  class API
8
- # @private
9
- attr_accessor *WrAPI::Configuration::VALID_OPTIONS_KEYS
12
+ # Dynamically create accessor methods for all valid configuration keys.
13
+ attr_accessor(*WrAPI::Configuration::VALID_OPTIONS_KEYS)
10
14
 
11
- # Creates a new API and copies settings from singleton
15
+ # Initializes a new `Skykick::API` instance with the given options.
16
+ # The options are merged with the global Skykick settings to allow both global and per-instance customization.
17
+ #
18
+ # @param options [Hash] A hash of configuration options.
19
+ # These options can override the global Skykick configuration.
20
+ #
21
+ # @example Create a new API instance with custom options:
22
+ # api = Skykick::API.new(endpoint: "https://custom-api.endpoint.com", user_agent: "MyApp UA/1.0")
23
+ #
24
+ # @return [Skykick::API] A new instance of the Skykick API with the specified options.
12
25
  def initialize(options = {})
26
+ # Merge the provided options with the global Skykick configuration.
13
27
  options = Skykick.options.merge(options)
28
+
29
+ # Set each configuration key dynamically using the merged options.
14
30
  WrAPI::Configuration::VALID_OPTIONS_KEYS.each do |key|
15
31
  send("#{key}=", options[key])
16
32
  end
17
33
  end
18
34
 
35
+ # Retrieves the current API configuration as a hash.
36
+ #
37
+ # @return [Hash] A hash containing the current configuration settings.
38
+ # The keys in the hash are the same as `VALID_OPTIONS_KEYS`.
39
+ #
40
+ # @example Retrieve the current API configuration:
41
+ # api = Skykick::API.new
42
+ # api.config # => { :endpoint => "https://apis.skykick.com", :user_agent => "Skykick API/1.0", ... }
19
43
  def config
20
44
  conf = {}
45
+ # Iterate over each valid configuration key and retrieve its current value.
21
46
  WrAPI::Configuration::VALID_OPTIONS_KEYS.each do |key|
22
47
  conf[key] = send key
23
48
  end
24
49
  conf
25
50
  end
26
51
 
52
+ # Include core modules for API functionality, including HTTP connections, request handling, and authentication.
27
53
  include Connection
28
54
  include WrAPI::Request
29
55
  include WrAPI::Authentication
@@ -1,31 +1,51 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('error', __dir__)
2
4
  require 'uri'
3
5
 
4
6
  module Skykick
5
- # Deals with authentication flow and stores it within global configuration
7
+ # The `Skykick::Authentication` module handles the authentication flow for the Skykick API.
8
+ # It manages access tokens and stores them in the global configuration.
9
+ # This module provides methods to log in to the Skykick portal using client credentials.
10
+ #
11
+ # @see https://developers.skykick.com/Guides/Authentication
6
12
  module Authentication
7
- # Authorize to the Skykick portal and return access_token
8
- # @see https://developers.skykick.com/Guides/Authentication
9
- def auth_token(options = {})
13
+ # Authenticates with the Skykick API and retrieves an access token.
14
+ #
15
+ # This method performs a client credentials flow to authenticate with the Skykick API.
16
+ # The access token is stored in the global configuration for subsequent API calls.
17
+ #
18
+ # @param _options [Hash] Options for the authentication request (currently unused).
19
+ # @return [String] The access token for authenticated API requests.
20
+ #
21
+ # @raise [ConfigurationError] If `client_id` or `client_secret` is not configured.
22
+ # @raise [AuthenticationError] If the authentication fails due to invalid credentials or other issues.
23
+ #
24
+ # @example Authenticate and retrieve an access token:
25
+ # token = Skykick::Authentication.auth_token
26
+ def auth_token(_options = {})
10
27
  raise ConfigurationError.new 'Client id and/or secret not configured' unless client_id && client_secret
11
28
 
12
- c = connection
13
- c.request :authorization, :basic, client_id, client_secret
14
- response = c.post('/auth/token') do |request|
29
+ con = connection
30
+ con.request :authorization, :basic, client_id, client_secret
31
+ response = con.post('/auth/token') do |request|
15
32
  request.headers['Content-Type'] = 'application/x-www-form-urlencoded'
16
- request.body = URI.encode_www_form( api_access_token_params )
33
+ request.body = URI.encode_www_form(api_access_token_params)
17
34
  end
18
35
 
19
36
  api_process_token(response.body)
20
37
 
21
38
  self.access_token
22
39
  rescue Faraday::ForbiddenError => e
23
- raise AuthenticationError.new 'Unauthorized; response ' + e.to_s
40
+ raise AuthenticationError.new "Unauthorized; response #{e}"
24
41
  end
25
42
  alias login auth_token
26
43
 
27
- private
44
+ private
28
45
 
46
+ # Prepares the parameters required for the authentication request.
47
+ #
48
+ # @return [Hash] The parameters for the API access token request.
29
49
  def api_access_token_params
30
50
  {
31
51
  grant_type: 'client_credentials',
@@ -33,13 +53,22 @@ module Skykick
33
53
  }
34
54
  end
35
55
 
56
+ # Processes the response from the Skykick API and extracts authentication details.
57
+ #
58
+ # @param response [Hash] The parsed response body from the API.
59
+ #
60
+ # @return [void]
61
+ #
62
+ # @raise [AuthorizationError] If the response does not include a valid `access_token`.
36
63
  def api_process_token(response)
37
64
  self.access_token = response['access_token']
38
65
  self.token_type = response['token_type']
39
66
  self.refresh_token = response['refresh_token']
40
67
  self.token_expires = response['expires_in']
41
68
 
42
- raise AuthorizationError.new 'Could not find valid access_token; response ' + response.to_s if self.access_token.nil? || self.access_token.empty?
69
+ if self.access_token.nil? || self.access_token.empty?
70
+ raise AuthorizationError.new "Could not find valid access_token; response #{response}"
71
+ end
43
72
  end
44
73
  end
45
74
  end
@@ -1,19 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skykick
2
4
  class Client
3
-
4
- # All alert related api calls
5
- # @see https://developers.skykick.com/
5
+ # Contains all alert-related API calls for managing alerts in Skykick.
6
+ # This module provides methods to retrieve alerts and mark them as complete.
7
+ #
8
+ # @see https://developers.skykick.com/ Skykick Developer Documentation
6
9
  module Alerts
7
-
8
- # Returns first 500 Alerts for a provided Email Migration Order ID or Backup service ID.
10
+ # Retrieves the first 500 alerts for a given Email Migration Order ID or Backup Service ID.
11
+ # This method utilizes OData query parameters like `$top`, which defaults to 25 results
12
+ # and allows a maximum of 500 results per call.
13
+ #
14
+ # @note The `$top` query parameter is not explicitly implemented but can be configured on the endpoint.
15
+ # @param id [String] The unique identifier for an Email Migration Order or Backup Service.
16
+ # @return [Array<Hash>] A list of alerts associated with the specified ID.
17
+ # @example Retrieve alerts for a given order or service
18
+ # client.alerts('12345') # Returns up to 500 alerts
9
19
  def alerts(id)
10
- # This endpoint supports the following OData query parameters: $top
11
- # $top - default of 25 and max of 500
12
- # this is not implemented
20
+ # Retrieves paged results for alerts using the "Alerts" API endpoint.
13
21
  get_paged("Alerts/#{id}")
14
22
  end
15
23
 
16
- # Mark an Alert as complete.
24
+ # Marks a specific alert as complete.
25
+ #
26
+ # @param id [String] The unique identifier for the alert to be marked as complete.
27
+ # @return [Hash] The response from the API after marking the alert as complete.
28
+ # @example Mark an alert as complete
29
+ # client.mark_as_complete('alert123') # Marks alert with ID 'alert123' as complete
17
30
  def mark_as_complete(id)
18
31
  post("Alerts/#{id}")
19
32
  end
@@ -1,76 +1,123 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skykick
2
4
  class Client
3
-
4
- # All backup related api calls
5
- # @see https://developers.skykick.com/
5
+ # Contains all backup-related API calls for managing Skykick backup subscriptions and settings.
6
+ # This module provides methods to interact with backup services, including retrieving subscription
7
+ # settings, storage settings, and mailbox information.
8
+ #
9
+ # @see https://developers.skykick.com/ Skykick Developer Documentation
6
10
  module Backup
7
-
8
- # Returns a list of supported Azure data centers.
11
+ # Retrieves a list of supported Azure data centers.
12
+ # @return [Array<Hash>] A list of Azure data centers supported by Skykick.
13
+ # @example Fetch available data centers
14
+ # client.datacenters # => Returns a list of supported data centers
9
15
  def datacenters
10
- get('Backup/datacenters')
16
+ get('Backup/datacenters')
11
17
  end
12
18
 
13
- # Gets a list of placed Backup subscription orders
14
- def subscriptions()
15
- get('Backup')
19
+ # Retrieves a list of placed Backup subscription orders.
20
+ # @return [Array<Hash>] A list of backup subscriptions.
21
+ # @example Get all backup subscriptions
22
+ # client.subscriptions # => Returns a list of placed backup subscription orders
23
+ def subscriptions
24
+ get('Backup')
16
25
  end
17
26
 
18
- # Gets a list of placed Backup subscription orders
27
+ # Retrieves a list of backup subscription orders for a specific partner.
28
+ # @param partner_id [String] The unique identifier of the partner.
29
+ # @return [Array<Hash>] A list of partner-specific backup subscriptions.
30
+ # @example Get partner backup subscriptions
31
+ # client.partner_subscriptions('partner123') # => Returns subscriptions for the partner
19
32
  def partner_subscriptions(partner_id)
20
- get("Backup/#{partner_id}")
33
+ get("Backup/#{partner_id}")
21
34
  end
22
35
 
23
- # Returns Backup subscription settings. Settings include the enabled
24
- # state for Exchange and SharePoint Backups and total count of enabled
25
- # Exchange mailboxes and SharePoint sites as well as the state of the subscription.
36
+ # Retrieves backup subscription settings, including the state of Exchange and SharePoint Backups,
37
+ # the number of enabled mailboxes and SharePoint sites, and the subscription state.
38
+ # @param id [String] The subscription ID.
39
+ # @return [Hash] Backup subscription settings.
40
+ # @example Fetch subscription settings
41
+ # client.subscription_settings('sub123') # => Returns backup subscription settings
26
42
  def subscription_settings(id)
27
- get("Backup/#{id}/subscriptionsettings")
43
+ get("Backup/#{id}/subscriptionsettings")
28
44
  end
29
45
 
30
- # Returns storage settings for a Backup subscription.
46
+ # Retrieves storage settings for a backup subscription.
47
+ # @param id [String] The subscription ID.
48
+ # @return [Hash] Storage settings for the specified subscription.
49
+ # @example Get storage settings
50
+ # client.storage_settings('sub123') # => Returns storage settings
31
51
  def storage_settings(id)
32
- get("Backup/#{id}/storagesettings")
52
+ get("Backup/#{id}/storagesettings")
33
53
  end
34
54
 
35
- # Gets SKU/promo details for a Backup service.
55
+ # Retrieves SKU or promotional details for a backup service.
56
+ # @param id [String] The subscription ID.
57
+ # @return [Hash] SKU or promotional details.
58
+ # @example Fetch SKU details
59
+ # client.sku('sub123') # => Returns SKU or promo details
36
60
  def sku(id)
37
- get("Backup/#{id}/sku")
61
+ get("Backup/#{id}/sku")
38
62
  end
39
63
 
40
- # Returns a list of SharePoint site URLs and statuses (enabled/disabled)
41
- # for a Backup subscription.
64
+ # Retrieves a list of SharePoint site URLs and their statuses (enabled/disabled) for a backup subscription.
65
+ # @param id [String] The subscription ID.
66
+ # @return [Array<Hash>] A list of SharePoint site URLs and statuses.
67
+ # @example Get SharePoint sites
68
+ # client.sharepoint_sites('sub123') # => Returns a list of SharePoint sites and their statuses
42
69
  def sharepoint_sites(id)
43
- get("Backup/#{id}/sites")
70
+ get("Backup/#{id}/sites")
44
71
  end
45
72
 
46
- # Returns the data retention periods for a Backup subscription. There are different
47
- # retention periods for Exchange and SharePoint Data.
73
+ # Retrieves the data retention periods for a backup subscription.
74
+ # Different retention periods apply for Exchange and SharePoint data.
48
75
  #
49
- # Please Note: We are aware of the spelling error of the word "retention" in the response
50
- # field ExchangeRentionPeriodInDays. This is not a mistake in the documentation, but has
51
- # been left this way as not to disrupt any existing integrations with this endpoint.
76
+ # @note There is a known spelling issue in the response field: `ExchangeRentionPeriodInDays`.
77
+ # This is intentional to avoid breaking existing integrations.
78
+ # @param id [String] The subscription ID.
79
+ # @return [Hash] Retention period details.
80
+ # @example Get retention periods
81
+ # client.retentionperiod('sub123') # => Returns retention periods for Exchange and SharePoint data
52
82
  def retentionperiod(id)
53
- get("Backup/#{id}/retentionperiod")
83
+ get("Backup/#{id}/retentionperiod")
54
84
  end
55
85
 
56
- # Gets stats for snapshots from SKDataWarehouse for all mailboxes of a given backupServiceId
86
+ # Retrieves snapshot statistics from SKDataWarehouse for all mailboxes in a given backup subscription.
87
+ # @param id [String] The subscription ID.
88
+ # @return [Hash] Snapshot statistics for the mailboxes.
89
+ # @example Fetch last snapshot stats
90
+ # client.lastsnapshotstats('sub123') # => Returns snapshot stats for the subscription's mailboxes
57
91
  def lastsnapshotstats(id)
58
- get("Backup/#{id}/lastsnapshotstats")
92
+ get("Backup/#{id}/lastsnapshotstats")
59
93
  end
60
94
 
61
- # Returns a list of Exchange mailboxes and statuses (enabled/disabled) for a Backup subscription.
95
+ # Retrieves a list of Exchange mailboxes and their statuses (enabled/disabled) for a backup subscription.
96
+ # @param id [String] The subscription ID.
97
+ # @return [Array<Hash>] A list of Exchange mailboxes and their statuses.
98
+ # @example Get Exchange mailboxes
99
+ # client.exchange_mailboxes('sub123') # => Returns a list of Exchange mailboxes and statuses
62
100
  def exchange_mailboxes(id)
63
- get("Backup/#{id}/mailboxes")
101
+ get("Backup/#{id}/mailboxes")
64
102
  end
65
103
 
66
- # Returns a list of Exchange mailboxes and statuses (enabled/disabled) for a Backup subscription.
104
+ # Retrieves details of a specific Exchange mailbox in a backup subscription.
105
+ # @param id [String] The subscription ID.
106
+ # @param mailbox_id [String] The unique identifier of the mailbox.
107
+ # @return [Hash] Details of the specified Exchange mailbox.
108
+ # @example Get details of a specific mailbox
109
+ # client.exchange_mailbox('sub123', 'mailbox123') # => Returns mailbox details
67
110
  def exchange_mailbox(id, mailbox_id)
68
- get("Backup/#{id}/mailboxes/#{mailbox_id}")
111
+ get("Backup/#{id}/mailboxes/#{mailbox_id}")
69
112
  end
70
113
 
71
- # Returns the Exchange and SharePoint auto-discover states (enabled/disabled) of a Backup subscription.
114
+ # Retrieves the auto-discover state (enabled/disabled) for Exchange and SharePoint backups in a subscription.
115
+ # @param id [String] The subscription ID.
116
+ # @return [Hash] Auto-discover states for Exchange and SharePoint.
117
+ # @example Check auto-discover state
118
+ # client.autodiscover('sub123') # => Returns the auto-discover state of the subscription
72
119
  def autodiscover(id)
73
- get("Backup/#{id}/autodiscover")
120
+ get("Backup/#{id}/autodiscover")
74
121
  end
75
122
  end
76
123
  end
@@ -1,11 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skykick
2
- # Wrapper for the Skykick REST API
4
+ # The `Skykick::Client` class acts as a wrapper for the Skykick REST API.
5
+ # This class inherits from the `Skykick::API` class and includes modules that group
6
+ # the API methods according to the structure in the Skykick API documentation.
3
7
  #
4
- # @note All methods have been separated into modules and follow the same grouping used in api docs
8
+ # @note All methods are grouped in separate modules for better organization and follow the structure provided in the official API documentation.
5
9
  # @see https://developers.skykick.com/Guides/Authentication
6
10
  class Client < API
11
+ # Dynamically require all files in the `client` directory.
12
+ # This will load additional API modules as separate files for better modularity and code organization.
7
13
  Dir[File.expand_path('client/*.rb', __dir__)].each { |f| require f }
8
14
 
15
+ # Include API client modules for specific Skykick API functionalities.
16
+ # These modules provide methods for interacting with specific parts of the Skykick API,
17
+ # such as managing backups and handling alerts.
9
18
  include Skykick::Client::Backup
10
19
  include Skykick::Client::Alerts
11
20
  end
@@ -1,31 +1,44 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
 
3
5
  module Skykick
4
-
5
- # Create connection including authorization parameters with default Accept format and User-Agent
6
- # By default
7
- # - Bearer authorization is access_token is not nil override with @setup_authorization
8
- # - Headers setup for Ocp-Apim-Subscription-Key when client_id and client_secret are not nil @setup_headers
9
- # @private
6
+ # The `Skykick::Connection` module is responsible for establishing an API connection.
7
+ # It includes authorization and header setup and ensures that sensitive information
8
+ # (e.g., access tokens, client secrets, etc.) is filtered from logs for security purposes.
9
+ #
10
+ # @note This module is designed to extend and customize the `WrAPI::Connection` functionalities.
10
11
  module Connection
11
12
  include WrAPI::Connection
12
13
 
13
- # callback method to setup api headers
14
+ # Sets up API headers for the Skykick connection.
15
+ # If `client_secret` is present, it adds the `Ocp-Apim-Subscription-Key` header.
16
+ #
17
+ # @param connection [Faraday::Connection] The connection object used to configure headers.
18
+ # @return [void]
14
19
  def setup_headers(connection)
15
20
  connection.headers['Ocp-Apim-Subscription-Key'] = client_secret if client_secret
16
21
  end
17
22
 
18
- # callback method to setup logger
23
+ # Configures a logger with filters to redact sensitive data from logs.
24
+ # This method sets up a logger that captures and logs request headers and bodies while
25
+ # filtering sensitive information such as passwords, access tokens, and authorization headers.
26
+ #
27
+ # @param connection [Faraday::Connection] The connection object where the logger is applied.
28
+ # @param logger [Logger] The logger instance that records request and response information.
29
+ # @return [void]
19
30
  def setup_logger_filtering(connection, logger)
20
31
  connection.response :logger, logger, { headers: true, bodies: true } do |l|
21
- # filter json content
32
+ # Filter sensitive data from JSON content
22
33
  l.filter(/("password":")(.+?)(".*)/, '\1[REMOVED]\3')
23
34
  l.filter(/("accessToken":")(.+?)(".*)/, '\1[REMOVED]\3')
24
- # filter header content
35
+
36
+ # Filter sensitive data from request headers
25
37
  l.filter(/(client-secret:.)([^&]+)/, '\1[REMOVED]')
26
38
  l.filter(/(Authorization:.)([^&]+)/, '\1[REMOVED]')
27
- # skykick
28
- l.filter(/(Ocp-Apim-Subscription-Key: ")(.+?)(\")/, '\1[REMOVED]\3')
39
+
40
+ # Filter Skykick-specific sensitive header and token information
41
+ l.filter(/(Ocp-Apim-Subscription-Key: ")(.+?)(")/, '\1[REMOVED]\3')
29
42
  l.filter(/("access_token":")(.+?)(".*)/, '\1[REMOVED]\3')
30
43
  end
31
44
  end
data/lib/skykick/error.rb CHANGED
@@ -1,11 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Skykick
2
-
3
- # Generic error to be able to rescue all Skykick errors
4
+ # Base error class for all exceptions raised by the Skykick API.
5
+ # This allows rescuing all Skykick-related errors in a single block if desired.
6
+ # Example:
7
+ # begin
8
+ # # Code that interacts with the Skykick API
9
+ # rescue Skykick::SkykickError => e
10
+ # puts "An error occurred: #{e.message}"
11
+ # end
4
12
  class SkykickError < StandardError; end
5
13
 
6
- # Error when configuration not sufficient
14
+ # Raised when the Skykick API configuration is incomplete or incorrect.
15
+ # This might occur if required configuration options such as `client_id`, `client_secret`,
16
+ # or `endpoint` are missing or improperly set.
17
+ #
18
+ # Example:
19
+ # raise Skykick::ConfigurationError, "Client ID and secret must be configured"
7
20
  class ConfigurationError < SkykickError; end
8
21
 
9
- # Error when authentication fails
22
+ # Raised when authentication to the Skykick API fails.
23
+ # This might be due to incorrect credentials, an expired token, or insufficient permissions.
24
+ #
25
+ # Example:
26
+ # raise Skykick::AuthenticationError, "Invalid client credentials"
27
+ #
28
+ # @see https://developers.skykick.com/Guides/Authentication
10
29
  class AuthenticationError < SkykickError; end
11
- end
30
+ end
@@ -1,43 +1,79 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
  require 'json'
3
5
 
4
6
  module Skykick
5
- # Defines HTTP request methods
6
- # required attributes format
7
+ # Defines HTTP request pagination methods for Skykick's API.
8
+ # This module handles the pagination strategy required when dealing with paginated
9
+ # API results. Skykick uses OData pagination, which supports parameters like `$top` but not `$skip`.
10
+ #
11
+ # Note: Using `$skip` in requests results in an error:
12
+ # "The query specified in the URI is not valid. Query option 'Skip' is not allowed.
13
+ # To allow it, set the 'AllowedQueryOptions' property on EnableQueryAttribute or QueryValidationSettings."
7
14
  module RequestPagination
8
-
9
- # Skykick uses Odata pagination but unfortunately does not support skipping pages.
10
- # Using skip responds with "The query specified in the URI is not valid. Query option
11
- # 'Skip' is not allowed. To allow it, set the 'AllowedQueryOptions' property on
12
- # EnableQueryAttribute or QueryValidationSettings."
15
+ # Handles OData pagination.
16
+ # This class maintains pagination state, including the offset, limit (page size), and total results.
17
+ # Since skipping pages isn't allowed by Skykick, the pagination assumes a simplified logic with a single page.
18
+ #
19
+ # @example Pagination Initialization
20
+ # paginator = Skykick::RequestPagination::ODataPagination.new(100)
21
+ # options = paginator.page_options
22
+ #
23
+ # @see https://docs.oasis-open.org/odata/odata/v4.0/os/abnf/odata-abnf-construction-rules.html OData Query Parameters
13
24
  class ODataPagination
14
25
  attr_reader :offset, :limit, :total
26
+
27
+ # Initializes the pagination object with the specified page size.
28
+ # Assumes that pagination starts at the first page (offset 0).
29
+ #
30
+ # @param page_size [Integer] Number of results per page
15
31
  def initialize(page_size)
16
32
  @offset = 0
17
33
  @limit = page_size
18
- # we always have a first page
34
+ # Assume we have at least one page initially
19
35
  @total = @limit
20
36
  end
37
+
38
+ # Returns the pagination options to be sent as query parameters.
39
+ # Due to Skykick's limitation, only the `$top` parameter is included.
40
+ #
41
+ # @return [Hash<Symbol, Integer>] Query parameters for pagination
21
42
  def page_options
22
- { '$top': @limit, '$skip': @offset }
23
43
  { '$top': @limit }
24
44
  end
45
+
46
+ # Updates the pagination state for the next page based on the current page's data.
47
+ # Skykick's API does not allow skipping, so the offset and total are adjusted
48
+ # based on the size of the current data.
49
+ #
50
+ # @param data [Array] The data array from the current page
25
51
  def next_page!(data)
26
- # assume array
52
+ # Update the total number of results based on the size of the current data set.
27
53
  if data.count
28
54
  @total = data.count
29
55
  else
30
- @total = 1
56
+ @total = 1
31
57
  end
32
58
  @offset += @limit
33
59
  end
34
60
 
35
- def self.data(body)
61
+ # Processes the API response body and returns it unchanged.
62
+ # This method can be overridden to handle specific response parsing needs.
63
+ #
64
+ # @param body [Hash, Array, String] The response body from the API
65
+ # @return [Hash, Array, String] Processed data (unchanged)
66
+ def self.data(body)
36
67
  body
37
68
  end
38
- # only single page available
69
+
70
+ # Checks if more pages are available.
71
+ # Since Skykick's API supports only a single page (no `$skip`), this method
72
+ # returns `true` only if the offset is at its initial value (indicating the first page).
73
+ #
74
+ # @return [Boolean] `true` if more pages are available, `false` otherwise
39
75
  def more_pages?
40
- @offset == 0
76
+ @offset.zero?
41
77
  end
42
78
  end
43
79
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Skykick
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.0'
5
5
  end
data/lib/skykick.rb CHANGED
@@ -1,19 +1,41 @@
1
- require "wrapi"
1
+ # frozen_string_literal: true
2
+
3
+ require 'wrapi'
2
4
  require File.expand_path('skykick/api', __dir__)
3
5
  require File.expand_path('skykick/client', __dir__)
4
6
  require File.expand_path('skykick/pagination', __dir__)
5
7
  require File.expand_path('skykick/version', __dir__)
6
8
 
9
+ # The `Skykick` module is a wrapper around Skykick's API.
10
+ # It provides a client configuration, including default settings like endpoint URL, user agent,
11
+ # and pagination handling. This module extends `WrAPI::Configuration` to provide configuration
12
+ # options and `WrAPI::RespondTo` for dynamic response handling.
7
13
  module Skykick
8
14
  extend WrAPI::Configuration
9
15
  extend WrAPI::RespondTo
10
16
 
11
- DEFAULT_ENDPOINT = 'https://apis.skykick.com'.freeze
12
- DEFAULT_UA = "Skykick Ruby API wrapper #{Skykick::VERSION}".freeze
17
+ # Default API endpoint for the Skykick service.
18
+ DEFAULT_ENDPOINT = 'https://apis.cloudservices.connectwise.com'
19
+
20
+ # Default User-Agent header sent with API requests, including gem version information.
21
+ DEFAULT_UA = "Skykick Ruby API wrapper #{Skykick::VERSION}"
22
+
23
+ # Default pagination class used for handling paginated API responses.
13
24
  DEFAULT_PAGINATION = Skykick::RequestPagination::ODataPagination
14
25
 
26
+ # Creates and returns a new Skykick API client with the given options.
27
+ #
28
+ # @param options [Hash] A hash of configuration options to initialize the client.
29
+ # This method merges the provided options with default values such as endpoint, user agent, and pagination class.
15
30
  #
16
- # @return [Skykick::Client]
31
+ # @option options [String] :endpoint The base URL for the Skykick API (default: `DEFAULT_ENDPOINT`).
32
+ # @option options [String] :user_agent The User-Agent header to send with each API request (default: `DEFAULT_UA`).
33
+ # @option options [Class] :pagination_class The pagination class to handle paginated responses (default: `DEFAULT_PAGINATION`).
34
+ #
35
+ # @return [Skykick::Client] A new instance of the Skykick API client.
36
+ #
37
+ # @example Create a Skykick client:
38
+ # client = Skykick.client(endpoint: "https://api.custom-endpoint.com", user_agent: "Custom UA/1.0")
17
39
  def self.client(options = {})
18
40
  Skykick::Client.new({
19
41
  endpoint: DEFAULT_ENDPOINT,
@@ -22,6 +44,15 @@ module Skykick
22
44
  }.merge(options))
23
45
  end
24
46
 
47
+ # Resets the Skykick configuration to default values.
48
+ #
49
+ # This method resets the configuration values to their defaults:
50
+ # - `DEFAULT_ENDPOINT` for the API endpoint
51
+ # - `DEFAULT_UA` for the User-Agent
52
+ # - `DEFAULT_PAGINATION` for the pagination handling class
53
+ #
54
+ # @example Reset the Skykick configuration:
55
+ # Skykick.reset
25
56
  def self.reset
26
57
  super
27
58
  self.endpoint = DEFAULT_ENDPOINT
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skykick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janco Tanis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-07 00:00:00.000000000 Z
11
+ date: 2025-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -139,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
139
  - !ruby/object:Gem::Version
140
140
  version: '0'
141
141
  requirements: []
142
- rubygems_version: 3.2.3
142
+ rubygems_version: 3.1.6
143
143
  signing_key:
144
144
  specification_version: 4
145
145
  summary: A Ruby wrapper for the Skykick backup Portal REST APIs (readonly)