aikido-ruby-client 0.0.1 → 0.0.2

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: e1aff36ac4f8ac9f17a073b5acfead422df83829a80e7f6f7ec3a8d68426214d
4
- data.tar.gz: 7a84efa160d1e3701ab301d04a71eb967f24e7cda172c9b34f60c34bd277e467
3
+ metadata.gz: 2195bf014566aa0b80fbbf1412abce1996457bd8a93a126280689e00bdf19d72
4
+ data.tar.gz: 2904c3cd13469f36ef32e3d74daf4a1eef837286f5f71047fc3bb53b0c23b400
5
5
  SHA512:
6
- metadata.gz: 5250c5726c5920423b88b31c982a792251fca565fca0996bee526a1e222e6dc38c27074482e93fa8752ef7a09ca89588e00f996bb4f85f3baf8369d884fc98bf
7
- data.tar.gz: f74ecf9b1df49a4e84608ed68900ded1dfa8b672e8a00cbdd5d762214bf670be3ba6117d60a21dc44a8bc5792d42498d4a574c19a4e2d18ce715a72c296e50b9
6
+ metadata.gz: 3e1e0ced53c59664ba1b3eb53f1711bf82da26e244c4fb8a8b48f05456799639314bb6d625e140802b36dc7f8d13e0e2c23cef34677aacee1ebc443cc09bf40b
7
+ data.tar.gz: c5cc2da2ed92067ef28e7c5a5b9fc6af21c8fb96675dd085b219ba26e4aa59a1a165218610104b0fd8d68345987ce7eda7807f072aad74384d9541f310fd8cd4
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml CHANGED
@@ -1,7 +1,12 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.7
3
3
  NewCops: enable
4
+ SuggestExtensions: false
4
5
 
5
6
  Naming/FileName:
6
7
  Exclude:
7
8
  - 'lib/aikido-ruby-client.rb'
9
+
10
+ Metrics/BlockLength:
11
+ Exclude:
12
+ - 'spec/**/*.rb'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.0.2](https://github.com/anakinj/aikido-ruby-client/tree/v0.0.2) (2024-03-10)
4
+
5
+ **Features:**
6
+
7
+ - More api methods
8
+ - Pagination support
9
+ - Specs backed by VCR recordings
10
+
3
11
  ## [v0.0.1](https://github.com/anakinj/aikido-ruby-client/tree/v0.0.1) (2024-03-10)
4
12
 
5
13
  **Features:**
data/exe/aikido CHANGED
@@ -6,3 +6,4 @@ require 'aikido-ruby-client'
6
6
  client = Aikido::Client.new
7
7
 
8
8
  puts client.issues
9
+ puts client.code_repositories.to_a
data/lib/aikido/client.rb CHANGED
@@ -2,35 +2,68 @@
2
2
 
3
3
  require 'httpx'
4
4
 
5
+ require_relative 'errors'
6
+ require_relative 'paginated_response'
7
+
5
8
  module Aikido
6
9
  # HTTP Client to interact with the Aikido API
7
10
  # Official documentation: https://apidocs.aikido.dev/
8
11
  class Client
9
12
  def initialize(client_id: nil, client_secret: nil)
10
- @client_id = client_id || ENV.fetch('AIKIDO_CLIENT_ID', nil)
13
+ @client_id = client_id || ENV.fetch('AIKIDO_CLIENT_ID', nil)
11
14
  @client_secret = client_secret || ENV.fetch('AIKIDO_CLIENT_SECRET', nil)
12
15
  end
13
16
 
14
17
  def authorize
15
- http.plugin(:basic_auth).basic_auth(@client_id, @client_secret).post('/oauth/token',
16
- json: { grant_type: 'client_credentials' })
18
+ handle_response!(http.plugin(:basic_auth)
19
+ .basic_auth(@client_id, @client_secret)
20
+ .post('/oauth/token', json: { grant_type: 'client_credentials' }))
21
+ end
22
+
23
+ def workspace
24
+ get('/public/v1/workspace').json
25
+ end
26
+
27
+ def clouds
28
+ PaginatedResponse.new do |page|
29
+ get('/public/v1/clouds', params: { page: page }).json
30
+ end
17
31
  end
18
32
 
19
33
  def issues(params: {})
20
- authed_http.get('/public/v1/issues/export', params: params).json
34
+ get('/public/v1/issues/export', params: params).json
21
35
  end
22
36
 
23
37
  def issue(id)
24
- authed_http.get("/public/v1/issues/#{id.to_i}").json
38
+ get("/public/v1/issues/#{id.to_i}").json
39
+ end
40
+
41
+ def issue_groups
42
+ PaginatedResponse.new do |page|
43
+ get('/public/v1/open-issue-groups', params: { page: page }).json
44
+ end
45
+ end
46
+
47
+ def issue_group(id)
48
+ get("/public/v1/issues/groups/#{id.to_i}").json
25
49
  end
26
50
 
27
- def repositories
28
- # TODO: Paginated response
29
- authed_http.get('/public/v1/repositories/code', params: params).json
51
+ def code_repositories
52
+ PaginatedResponse.new do |page|
53
+ get('/public/v1/repositories/code', params: { page: page }).json
54
+ end
55
+ end
56
+
57
+ def code_repository_sbom(id, format: 'csv')
58
+ get("repositories/code/#{id.to_i}/licenses/export", params: { format: format }).body
30
59
  end
31
60
 
32
61
  private
33
62
 
63
+ def get(path, params: {})
64
+ handle_response!(authed_http.get(path, params: params))
65
+ end
66
+
34
67
  def authed_http
35
68
  http.plugin(:auth).bearer_auth(auth_token)
36
69
  end
@@ -47,5 +80,23 @@ module Aikido
47
80
  # TODO: Handle token expiration
48
81
  @auth_token ||= authorize.json['access_token']
49
82
  end
83
+
84
+ def handle_response!(response)
85
+ case response.status
86
+ when 200..299
87
+ response
88
+ else
89
+ raise_response_error!(response)
90
+ end
91
+ end
92
+
93
+ def raise_response_error!(response)
94
+ case response.status
95
+ when 401
96
+ raise Errors::UnauthorizedError, response
97
+ else
98
+ raise Errors::ApiError, response
99
+ end
100
+ end
50
101
  end
51
102
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aikido
4
+ module Errors
5
+ AikidoError = Class.new(StandardError)
6
+
7
+ # Represents an error that occurred while making an API request.
8
+ class ApiError < AikidoError
9
+ def initialize(response)
10
+ @response = response
11
+ super("API Error: #{response.status}")
12
+ end
13
+
14
+ def message
15
+ if @response.json['error_description']
16
+ "#{super} - #{@response.json['error_description']}"
17
+ else
18
+ super
19
+ end
20
+ end
21
+ end
22
+ UnauthorizedError = Class.new(ApiError)
23
+ NotFoundError = Class.new(ApiError)
24
+ end
25
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aikido
4
+ # Represents a reponse that is paginated
5
+ class PaginatedResponse
6
+ include Enumerable
7
+
8
+ def initialize(&block)
9
+ @page_loader = block
10
+ @pages = []
11
+ load_page(0)
12
+ end
13
+
14
+ def each(&block)
15
+ return enum_for(:each) unless block_given?
16
+
17
+ loop.with_index do |_, index|
18
+ page = load_page(index)
19
+ break if page.empty?
20
+
21
+ page.each(&block)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def load_page(page)
28
+ @pages[page] ||= @page_loader.call(page)
29
+ end
30
+ end
31
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aikido
4
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aikido-ruby-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joakim Antman
@@ -32,6 +32,7 @@ executables:
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
+ - ".rspec"
35
36
  - ".rubocop.yml"
36
37
  - CHANGELOG.md
37
38
  - LICENSE.txt
@@ -40,6 +41,8 @@ files:
40
41
  - exe/aikido
41
42
  - lib/aikido-ruby-client.rb
42
43
  - lib/aikido/client.rb
44
+ - lib/aikido/errors.rb
45
+ - lib/aikido/paginated_response.rb
43
46
  - lib/aikido/version.rb
44
47
  homepage: https://github.com/anakinj/aikido-ruby-client
45
48
  licenses:
@@ -47,7 +50,7 @@ licenses:
47
50
  metadata:
48
51
  homepage_uri: https://github.com/anakinj/aikido-ruby-client
49
52
  source_code_uri: https://github.com/anakinj
50
- changelog_uri: https://github.com/anakinj/jwk-loader/blob/0.0.1/CHANGELOG.md
53
+ changelog_uri: https://github.com/anakinj/jwk-loader/blob/0.0.2/CHANGELOG.md
51
54
  rubygems_mfa_required: 'true'
52
55
  post_install_message:
53
56
  rdoc_options: []