starkcore 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 597f29968666f97ec42b8c6bef044896258eb166daf282d88a20bf1428f96a6e
4
+ data.tar.gz: f4ae2a817c7db41b8bd14f03600297e1439332804f4d7dcce75f49217f52b5c4
5
+ SHA512:
6
+ metadata.gz: 1794d7632dcb540c513ff403643b9770d73e32610d7a5505157d3f63209873d65ec781f543a7b6e65d4a0cdc0ff463981c98fa36ed9afba6f4ace418b4b9717a
7
+ data.tar.gz: 28eb48e9984fe0fa24949f7785c7f87224c1f0912382e96f953400c53615bf170cc31585062dbd3416f38419bdc0c4dd9275ad6c742afcb443136d45f8eb9a1a
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StarkCore
4
+ class Environment
5
+ PRODUCTION = 'production'
6
+ SANDBOX = 'sandbox'
7
+
8
+ public_constant :PRODUCTION, :SANDBOX;
9
+ end
10
+ end
data/lib/error.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('json')
4
+
5
+ module StarkCore
6
+ module Error
7
+ class StarkCoreError < StandardError
8
+ attr_reader :message
9
+ def initialize(message)
10
+ @message = message
11
+ super(message)
12
+ end
13
+ end
14
+
15
+ class Error < StarkCoreError
16
+ attr_reader :code, :message
17
+ def initialize(code, message)
18
+ @code = code
19
+ @message = message
20
+ super("#{code}: #{message}")
21
+ end
22
+ end
23
+
24
+ class InputErrors < StarkCoreError
25
+ attr_reader :errors
26
+ def initialize(content)
27
+ errors = []
28
+ content.each do |error|
29
+ errors << Error.new(error['code'], error['message'])
30
+ end
31
+ @errors = errors
32
+ super(content.to_json)
33
+ end
34
+ end
35
+
36
+ class InternalServerError < StarkCoreError
37
+ def initialize(message = 'Houston, we have a problem.')
38
+ super(message)
39
+ end
40
+ end
41
+
42
+ class UnknownError < StarkCoreError
43
+ def initialize(message)
44
+ super("Unknown exception encountered: #{message}")
45
+ end
46
+ end
47
+
48
+ class InvalidSignatureError < StarkCoreError
49
+ end
50
+ end
51
+ end
data/lib/key.rb ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('fileutils')
4
+ require('starkbank-ecdsa')
5
+
6
+ module StarkCore
7
+ module Key
8
+ # # Generate a new key pair
9
+ # Generates a secp256k1 ECDSA private/public key pair to be used in the API
10
+ # authentications
11
+ #
12
+ # ## Parameters (optional):
13
+ # - path [string]: path to save the keys .pem files. No files will be saved if this parameter isn't provided
14
+ #
15
+ # ## Return:
16
+ # - private and public key pems
17
+ def self.create(path=nil)
18
+ private_key = EllipticCurve::PrivateKey.new
19
+ public_key = private_key.publicKey
20
+
21
+ private_key_pem = private_key.toPem
22
+ public_key_pem = public_key.toPem
23
+
24
+ unless path.nil?
25
+ FileUtils.mkdir_p(path)
26
+ File.write(File.join(path, 'private.pem'), private_key_pem)
27
+ File.write(File.join(path, 'public.pem'), public_key_pem)
28
+ end
29
+
30
+ [private_key_pem, public_key_pem]
31
+ end
32
+ end
33
+ end
data/lib/starkcore.rb ADDED
@@ -0,0 +1,24 @@
1
+ require_relative "user/organization"
2
+ require_relative "user/project"
3
+ require_relative "user/user"
4
+ require_relative "utils/api"
5
+ require_relative "utils/cache"
6
+ require_relative "utils/case"
7
+ require_relative "utils/checks"
8
+ require_relative "utils/enum"
9
+ require_relative "utils/host"
10
+ require_relative "utils/parse"
11
+ require_relative "utils/request"
12
+ require_relative "utils/resource"
13
+ require_relative "utils/rest"
14
+ require_relative "utils/sub_resource"
15
+ require_relative "utils/url"
16
+ require_relative "environment"
17
+ require_relative "error"
18
+ require_relative "key"
19
+
20
+ module StarkCore
21
+ @user = nil
22
+ @language = 'en-US'
23
+ class << self; attr_accessor :user, :language; end
24
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('user')
4
+
5
+ module StarkCore
6
+ # # Organization object
7
+ # The Organization object is an authentication entity for the SDK that
8
+ # represents your entire Organization, being able to access any Workspace
9
+ # underneath it and even create new Workspaces. Only a legal representative
10
+ # of your organization can register or change the Organization credentials.
11
+ # All requests to the Stark Bank and Stark Infra API must be authenticated via an SDK user,
12
+ # which must have been previously created at the Stark Bank or Stark Infra websites
13
+ # [https://web.sandbox.starkbank.com] or [https://web.starkbank.com]
14
+ # before you can use it in this SDK. Organizations may be passed as the user parameter on
15
+ # each request or may be defined as the default user at the start (See README).
16
+ # If you are accessing a specific Workspace using Organization credentials, you should
17
+ # specify the workspace ID when building the Organization object or by request, using
18
+ # the Organization.replace(organization, workspace_id) method, which creates a copy of the organization
19
+ # object with the altered workspace ID. If you are listing or creating new Workspaces, the
20
+ # workspace_id should be nil.
21
+ #
22
+ # ## Parameters (required):
23
+ # - environment [string]: environment where the organization is being used. ex: 'sandbox' or 'production'
24
+ # - id [string]: unique id required to identify organization. ex: '5656565656565656'
25
+ # - private_key [string]: PEM string of the private key linked to the organization. ex: '-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEyTIHK6jYuik6ktM9FIF3yCEYzpLjO5X/\ntqDioGM+R2RyW0QEo+1DG8BrUf4UXHSvCjtQ0yLppygz23z0yPZYfw==\n-----END PUBLIC KEY-----'
26
+ # - workspace_id [string]: unique id of the accessed Workspace, if any. ex: nil or '4848484848484848'
27
+ #
28
+ # ## Attributes (return-only):
29
+ # - pem [string]: private key in pem format. ex: '-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEyTIHK6jYuik6ktM9FIF3yCEYzpLjO5X/\ntqDioGM+R2RyW0QEo+1DG8BrUf4UXHSvCjtQ0yLppygz23z0yPZYfw==\n-----END PUBLIC KEY-----'
30
+ class Organization < StarkCore::User
31
+ attr_reader :workspace_id
32
+ def initialize(id:, environment:, private_key:, workspace_id: nil)
33
+ super(environment, id, private_key)
34
+ @workspace_id = workspace_id
35
+ end
36
+
37
+ def access_id
38
+ return "organization/#{@id}/workspace/#{@workspace_id}" if @workspace_id
39
+
40
+ return "organization/#{@id}"
41
+ end
42
+
43
+ def self.replace(organization, workspace_id)
44
+ Organization.new(
45
+ environment: organization.environment,
46
+ id: organization.id,
47
+ private_key: organization.pem,
48
+ workspace_id: workspace_id
49
+ )
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('user')
4
+
5
+ module StarkCore
6
+ # # Project object
7
+ #
8
+ # The Project object is an authentication entity for the SDK that is permanently
9
+ # linked to a specific Workspace.
10
+ # All requests to the Stark Bank API must be authenticated via an SDK user,
11
+ # which must have been previously created at the Stark Bank website
12
+ # [https://web.sandbox.starkbank.com] or [https://web.starkbank.com]
13
+ # before you can use it in this SDK. Projects may be passed as the user parameter on
14
+ # each request or may be defined as the default user at the start (See README).
15
+ #
16
+ # ## Parameters (required):
17
+ # - id [string]: unique id required to identify project. ex: '5656565656565656'
18
+ # - private_key [string]: PEM string of the private key linked to the project. ex: '-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEyTIHK6jYuik6ktM9FIF3yCEYzpLjO5X/\ntqDioGM+R2RyW0QEo+1DG8BrUf4UXHSvCjtQ0yLppygz23z0yPZYfw==\n-----END PUBLIC KEY-----'
19
+ # - environment [string]: environment where the project is being used. ex: 'sandbox' or 'production'
20
+ #
21
+ # ## Attributes (return-only):
22
+ # - name [string, default '']: project name. ex: 'MyProject'
23
+ # - allowed_ips [list of strings]: list containing the strings of the ips allowed to make requests on behalf of this project. ex: ['190.190.0.50']
24
+ # - pem [string]: private key in pem format. ex: '-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEyTIHK6jYuik6ktM9FIF3yCEYzpLjO5X/\ntqDioGM+R2RyW0QEo+1DG8BrUf4UXHSvCjtQ0yLppygz23z0yPZYfw==\n-----END PUBLIC KEY-----'
25
+ class Project < StarkCore::User
26
+ attr_reader :name, :allowed_ips
27
+ def initialize(environment:, id:, private_key:, name: '', allowed_ips: nil)
28
+ super(environment, id, private_key)
29
+ @name = name
30
+ @allowed_ips = allowed_ips
31
+ end
32
+
33
+ def access_id
34
+ "project/#{@id}"
35
+ end
36
+ end
37
+ end
data/lib/user/user.rb ADDED
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('starkbank-ecdsa')
4
+ require_relative('../utils/resource')
5
+
6
+ module StarkCore
7
+ class User < StarkCore::Utils::Resource
8
+ attr_reader :pem, :environment
9
+ def initialize(environment, id, private_key)
10
+ super(id)
11
+ @pem = StarkCore::Utils::Checks.check_private_key(private_key)
12
+ @environment = StarkCore::Utils::Checks.check_environment(environment)
13
+ end
14
+
15
+ def private_key
16
+ return EllipticCurve::PrivateKey.fromPem(@pem)
17
+ end
18
+ end
19
+ end
data/lib/utils/api.rb ADDED
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('case')
4
+
5
+ module StarkCore
6
+ module Utils
7
+ module API
8
+ def self.build_entity_hash(entity)
9
+ entity_hash = {}
10
+ entity_hash = entity if entity.is_a?(Hash)
11
+
12
+ entity.instance_variables.each do |key|
13
+ variable = entity.instance_variable_get(key)
14
+ entity_hash[key[1..-1]] = variable.is_a?(StarkCore::Utils::SubResource) ? build_entity_hash(variable) : entity.instance_variable_get(key)
15
+ end
16
+ return entity_hash
17
+ end
18
+
19
+ def self.api_json(entity)
20
+ built_hash = build_entity_hash(entity)
21
+ cast_json_to_api_format(built_hash)
22
+ end
23
+
24
+ def self.cast_json_to_api_format(hash)
25
+ entity_hash = {}
26
+ hash.each do |key, value|
27
+ next if value.nil?
28
+ entity_hash[StarkCore::Utils::Case.snake_to_camel(key)] = parse_value(value)
29
+ end
30
+ return entity_hash
31
+ end
32
+
33
+ def self.parse_value(value)
34
+ return api_json(value) if value.is_a?(SubResource)
35
+ return value.strftime('%Y-%m-%d') if value.is_a?(Date)
36
+ return value.strftime('%Y-%m-%dT%H:%M:%S+00:00') if value.is_a?(DateTime) || value.is_a?(Time)
37
+ return cast_json_to_api_format(value) if value.is_a?(Hash)
38
+ return value unless value.is_a?(Array)
39
+
40
+ list = []
41
+ value.each do |v|
42
+ if v.is_a?(Hash)
43
+ list << cast_json_to_api_format(v)
44
+ next
45
+ end
46
+ if v.is_a?(SubResource)
47
+ list << api_json(v)
48
+ next
49
+ end
50
+ list << v
51
+ end
52
+ return list
53
+ end
54
+
55
+ def self.from_api_json(resource_maker, json)
56
+ snakes = {}
57
+ json.each do |key, value|
58
+ snakes[StarkCore::Utils::Case.camel_to_snake(key)] = value
59
+ end
60
+
61
+ resource_maker.call(snakes)
62
+ end
63
+
64
+ def self.endpoint(resource_name)
65
+ kebab = StarkCore::Utils::Case.camel_to_kebab(resource_name)
66
+ kebab.sub!('-log', '/log')
67
+ kebab.sub!('-attempt', '/attempt')
68
+ return kebab
69
+ end
70
+
71
+ def self.last_name_plural(resource_name)
72
+ base = last_name(resource_name)
73
+
74
+ return base if base[-1].eql?('s')
75
+ return "#{base}s" if base[-2..-1].eql?('ey')
76
+ return "#{base[0...-1]}ies" if base[-1].eql?('y')
77
+
78
+ return "#{base}s"
79
+ end
80
+
81
+ def self.last_name(resource_name)
82
+ return StarkCore::Utils::Case.camel_to_kebab(resource_name).split('-').last
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StarkCore
4
+ module Utils
5
+ module Cache
6
+ @starkbank_public_key = nil
7
+ class << self; attr_accessor :starkbank_public_key; end
8
+ end
9
+ end
10
+ end
data/lib/utils/case.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StarkCore
4
+ module Utils
5
+ module Case
6
+ def self.camel_to_snake(camel)
7
+ return camel.to_s.gsub(/([a-z])([A-Z\d])/, '\1_\2').downcase
8
+ end
9
+
10
+ def self.snake_to_camel(snake)
11
+ camel = snake.to_s.split('_').map(&:capitalize).join
12
+ camel[0] = camel[0].downcase
13
+ return camel
14
+ end
15
+
16
+ def self.camel_to_kebab(camel)
17
+ return camel_to_snake(camel).tr('_', '-')
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('date')
4
+ require('starkbank-ecdsa')
5
+ require_relative('../environment')
6
+ require_relative('../user/user')
7
+
8
+ module StarkCore
9
+ module Utils
10
+ class Checks
11
+ def self.check_environment(environment)
12
+ environments = StarkCore::Environment.constants(false).map { |c| StarkCore::Environment.const_get(c) }
13
+ raise(ArgumentError, "Select a valid environment: #{environments.join(', ')}") unless environments.include?(environment)
14
+ return environment
15
+ end
16
+
17
+ def self.check_private_key(pem)
18
+ EllipticCurve::PrivateKey.fromPem(pem)
19
+ return pem
20
+ rescue
21
+ raise(ArgumentError, 'Private-key must be a valid secp256k1 ECDSA string in pem format')
22
+ end
23
+
24
+ def self.check_user(user)
25
+ return user if user.is_a?(StarkCore::User)
26
+ user = user.nil? ? StarkCore.user : user
27
+ raise(ArgumentError, 'A user is required to access our API. Check our README: https://github.com/starkbank/sdk-ruby/') if user.nil?
28
+ return user
29
+ end
30
+
31
+ def self.check_language(language)
32
+ language = language.nil? ? StarkCore.language : language
33
+ accepted_languages = %w[en-US pt-BR]
34
+ raise(ArgumentError, "Select a valid language: #{accepted_languages.join(', ')}") unless accepted_languages.include?(language)
35
+ return language
36
+ end
37
+
38
+ def self.check_date_or_datetime(data)
39
+ return if data.nil?
40
+
41
+ return data if data.is_a?(Time) || data.is_a?(DateTime)
42
+
43
+ return data if data.is_a?(Date)
44
+
45
+ data, type = check_datetime_string(data)
46
+ type == 'date' ? Date.new(data.year, data.month, data.day) : data
47
+ end
48
+
49
+ def self.check_datetime(data)
50
+ return if data.nil?
51
+
52
+ return data if data.is_a?(Time) || data.is_a?(DateTime)
53
+
54
+ return Time.new(data.year, data.month, data.day) if data.is_a?(Date)
55
+
56
+ data, _type = check_datetime_string(data)
57
+ return data
58
+ end
59
+
60
+ def self.check_date(data)
61
+ return if data.nil?
62
+
63
+ return Date.new(data.year, data.month, data.day) if data.is_a?(Time) || data.is_a?(DateTime)
64
+
65
+ return data if data.is_a?(Date)
66
+
67
+ data, type = check_datetime_string(data)
68
+
69
+ type == 'date' ? Date.new(data.year, data.month, data.day) : data
70
+ end
71
+
72
+ class << self
73
+ private
74
+
75
+ def check_datetime_string(data)
76
+ data = data.to_s
77
+
78
+ begin
79
+ return [DateTime.strptime(data, '%Y-%m-%dT%H:%M:%S.%L+00:00'), 'datetime']
80
+ rescue ArgumentError
81
+ end
82
+
83
+ begin
84
+ return [DateTime.strptime(data, '%Y-%m-%dT%H:%M:%S+00:00'), 'datetime']
85
+ rescue ArgumentError
86
+ end
87
+
88
+ begin
89
+ return [DateTime.strptime(data, '%Y-%m-%d'), 'date']
90
+ rescue ArgumentError
91
+ raise(ArgumentError, 'invalid datetime string ' + data)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
data/lib/utils/enum.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StarkCore
4
+ module Utils
5
+ class Enum
6
+ def values
7
+ list = []
8
+ self.class.constants.each do |constant|
9
+ unless constant[0] == '_' and constant.respond_to?(:call)
10
+ list.push(self.class.const_get(constant))
11
+ end
12
+ end
13
+ return list
14
+ end
15
+
16
+ def is_valid
17
+ return values.include?(self)
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/utils/host.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StarkCore
4
+ module Utils
5
+ class StarkHost < Enum
6
+ INFRA = "infra"
7
+ BANK = "bank"
8
+ SIGN = "sign"
9
+
10
+ public_constant :INFRA, :BANK, :SIGN
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('json')
4
+ require('starkbank-ecdsa')
5
+ require_relative('api')
6
+ require_relative('cache')
7
+ require_relative('request')
8
+ require_relative('../error')
9
+
10
+ module StarkCore
11
+ module Utils
12
+ module Parse
13
+ def self.parse_and_verify(content:, signature:, sdk_version:, api_version:,
14
+ host:, resource: nil, user:, language:, timeout:, key: nil)
15
+ content = verify(content: content, signature: signature, sdk_version: sdk_version,
16
+ api_version: api_version, host: host, user: user, language: language,
17
+ timeout: timeout)
18
+ json = JSON.parse(content)
19
+ json = JSON.parse(content)[key] unless key.nil?
20
+
21
+ StarkCore::Utils::API.from_api_json(resource[:resource_maker], json)
22
+ end
23
+
24
+ def self.verify(content:, signature:, sdk_version:, api_version:, host:,
25
+ user:, language:, timeout:)
26
+ begin
27
+ signature = EllipticCurve::Signature.fromBase64(signature)
28
+ rescue
29
+ raise(StarkCore::Error::InvalidSignatureError, 'The provided signature is not valid')
30
+ end
31
+
32
+ if verify_signature(content: content, signature: signature, sdk_version: sdk_version,
33
+ host: host, api_version: api_version, user: user,
34
+ language: language, timeout: timeout)
35
+ return content
36
+ end
37
+
38
+ if verify_signature(content: content, signature: signature, sdk_version: sdk_version,
39
+ host: host, api_version: api_version, user: user,
40
+ language: language, timeout: timeout, refresh: true)
41
+ return content
42
+ end
43
+
44
+ raise(StarkCore::Error::InvalidSignatureError, 'The provided signature and content do not match the Stark bank public key')
45
+ end
46
+
47
+ def self.verify_signature(content:, signature:, sdk_version:, host:, api_version:,
48
+ user:, language:, timeout:, refresh: false)
49
+ public_key = get_public_key_pem(
50
+ sdk_version: sdk_version,
51
+ host: host,
52
+ api_version: api_version,
53
+ user: user,
54
+ language: language,
55
+ timeout: timeout,
56
+ refresh: refresh
57
+ )
58
+ return EllipticCurve::Ecdsa.verify(content, signature, public_key)
59
+ end
60
+
61
+ def self.get_public_key_pem(sdk_version:, host:, api_version:, user:, language:, timeout:, refresh: false, **query)
62
+ public_key = StarkCore::Utils::Cache.starkbank_public_key
63
+ return public_key unless (public_key.nil? || refresh)
64
+
65
+ pem = StarkCore::Utils::Rest.get_raw(
66
+ sdk_version: sdk_version,
67
+ host: host,
68
+ api_version: api_version,
69
+ path: "public-key",
70
+ user: user,
71
+ language: language,
72
+ timeout: timeout,
73
+ limit: 1
74
+ )['publicKeys'][0]['content']
75
+ public_key = EllipticCurve::PublicKey.fromPem(pem)
76
+ StarkCore::Utils::Cache.starkbank_public_key = public_key
77
+ return public_key
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('json')
4
+ require('starkbank-ecdsa')
5
+ require('net/http')
6
+ require_relative('url')
7
+ require_relative('checks')
8
+ require_relative('../error')
9
+
10
+ module StarkCore
11
+ module Utils
12
+ module Request
13
+ class Response
14
+ attr_reader :status, :content
15
+ def initialize(status, content)
16
+ @status = status
17
+ @content = content
18
+ end
19
+
20
+ def json
21
+ JSON.parse(@content)
22
+ end
23
+ end
24
+
25
+ def self.fetch(host:, sdk_version:, user:, method:, path:, payload: nil, query: nil,
26
+ api_version: "v2", language: "en-US", timeout: 15)
27
+ user = Checks.check_user(user)
28
+ language = Checks.check_language(language)
29
+
30
+ service = {
31
+ StarkCore::Utils::StarkHost::INFRA => "starkinfra",
32
+ StarkCore::Utils::StarkHost::BANK => "starkbank",
33
+ StarkCore::Utils::StarkHost::SIGN => "starksign",
34
+ }[host]
35
+
36
+ base_url = {
37
+ Environment::PRODUCTION => "https://api.#{service}.com/",
38
+ Environment::SANDBOX => "https://sandbox.api.#{service}.com/"
39
+ }[user.environment] + 'v2'
40
+
41
+ url = "#{base_url}/#{path}#{StarkCore::Utils::URL.urlencode(query)}"
42
+ uri = URI(url)
43
+
44
+ access_time = Time.now.to_i
45
+ body = payload.nil? ? '' : payload.to_json
46
+ message = "#{user.access_id}:#{access_time}:#{body}"
47
+ signature = EllipticCurve::Ecdsa.sign(message, user.private_key).toBase64
48
+
49
+ case method
50
+ when 'GET'
51
+ req = Net::HTTP::Get.new(uri)
52
+ when 'DELETE'
53
+ req = Net::HTTP::Delete.new(uri)
54
+ when 'POST'
55
+ req = Net::HTTP::Post.new(uri)
56
+ req.body = body
57
+ when 'PATCH'
58
+ req = Net::HTTP::Patch.new(uri)
59
+ req.body = body
60
+ when 'PUT'
61
+ req = Net::HTTP::Put.new(uri)
62
+ req.body = body
63
+ else
64
+ raise(ArgumentError, 'unknown HTTP method ' + method)
65
+ end
66
+
67
+ req['Access-Id'] = user.access_id
68
+ req['Access-Time'] = access_time
69
+ req['Access-Signature'] = signature
70
+ req['Content-Type'] = 'application/json'
71
+ req['User-Agent'] = "Ruby-#{RUBY_VERSION}-SDK-#{host}-#{sdk_version}"
72
+ req['Accept-Language'] = language
73
+
74
+ request = Net::HTTP.start(uri.hostname, use_ssl: true) { |http| http.request(req) }
75
+
76
+ response = Response.new(Integer(request.code, 10), request.body)
77
+
78
+ raise(StarkCore::Error::InternalServerError) if response.status == 500
79
+ raise(StarkCore::Error::InputErrors, response.json['errors']) if response.status == 400
80
+ raise(StarkCore::Error::UnknownError, response.content) unless response.status == 200
81
+
82
+ return response
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative("sub_resource")
4
+
5
+ module StarkCore
6
+ module Utils
7
+ class Resource < StarkCore::Utils::SubResource
8
+ attr_reader :id
9
+ def initialize(id = nil)
10
+ @id = id
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/utils/rest.rb ADDED
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('request')
4
+ require_relative('api')
5
+
6
+ module StarkCore
7
+ module Utils
8
+ module Rest
9
+ def self.get_page(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, language:, timeout:, **query)
10
+ json = StarkCore::Utils::Request.fetch(
11
+ host: host,
12
+ sdk_version: sdk_version,
13
+ user: user,
14
+ method: 'GET',
15
+ path: StarkCore::Utils::API.endpoint(resource_name),
16
+ query: query,
17
+ api_version: api_version,
18
+ language: language,
19
+ timeout: timeout,
20
+ ).json
21
+ entities = []
22
+ json[StarkCore::Utils::API.last_name_plural(resource_name)].each do |entity_json|
23
+ entities << StarkCore::Utils::API.from_api_json(resource_maker, entity_json)
24
+ end
25
+ return entities, json['cursor']
26
+ end
27
+
28
+ def self.get_stream(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, language:, timeout:, **query)
29
+ limit = query[:limit]
30
+ query[:limit] = limit.nil? ? limit : [limit, 100].min
31
+
32
+ Enumerator.new do |enum|
33
+ loop do
34
+ json = StarkCore::Utils::Request.fetch(
35
+ host: host,
36
+ sdk_version: sdk_version,
37
+ user: user,
38
+ method: 'GET',
39
+ path: StarkCore::Utils::API.endpoint(resource_name),
40
+ query: query,
41
+ api_version: api_version,
42
+ language: language,
43
+ timeout: timeout,
44
+ ).json
45
+ entities = json[StarkCore::Utils::API.last_name_plural(resource_name)]
46
+
47
+ entities.each do |entity|
48
+ enum << StarkCore::Utils::API.from_api_json(resource_maker, entity)
49
+ end
50
+
51
+ unless limit.nil?
52
+ limit -= 100
53
+ query[:limit] = [limit, 100].min
54
+ end
55
+
56
+ cursor = json['cursor']
57
+ query['cursor'] = cursor
58
+ break if cursor.nil? || cursor.empty? || (!limit.nil? && limit <= 0)
59
+ end
60
+ end
61
+ end
62
+
63
+ def self.get_id(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, id:, language:, timeout:, **query)
64
+ json = StarkCore::Utils::Request.fetch(
65
+ host: host,
66
+ sdk_version: sdk_version,
67
+ user: user,
68
+ method: 'GET',
69
+ path: "#{StarkCore::Utils::API.endpoint(resource_name)}/#{id}",
70
+ query: query,
71
+ api_version: api_version,
72
+ language: language,
73
+ timeout: timeout,
74
+ ).json
75
+ entity = json[StarkCore::Utils::API.last_name(resource_name)]
76
+ return StarkCore::Utils::API.from_api_json(resource_maker, entity)
77
+ end
78
+
79
+ def self.get_content(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, language:, timeout:, sub_resource_name:, id:, **query)
80
+ return StarkCore::Utils::Request.fetch(
81
+ host: host,
82
+ sdk_version: sdk_version,
83
+ user: user,
84
+ method: 'GET',
85
+ path: "#{StarkCore::Utils::API.endpoint(resource_name)}/#{id}/#{StarkCore::Utils::API.endpoint(sub_resource_name)}",
86
+ query: query,
87
+ api_version: api_version,
88
+ language: language,
89
+ timeout: timeout,
90
+ ).content
91
+ end
92
+
93
+ def self.get_sub_resource(resource_name:, sub_resource_maker:, sub_resource_name:, sdk_version:, host:, api_version:, user:, language:, timeout:, id:, **query)
94
+ json = StarkCore::Utils::Request.fetch(
95
+ host: host,
96
+ sdk_version: sdk_version,
97
+ user: user,
98
+ method: 'GET',
99
+ path: "#{StarkCore::Utils::API.endpoint(resource_name)}/#{id}/#{StarkCore::Utils::API.endpoint(sub_resource_name)}",
100
+ query: StarkCore::Utils::API.cast_json_to_api_format(query),
101
+ api_version: api_version,
102
+ timeout: timeout,
103
+ ).json
104
+ entity = json[StarkCore::Utils::API.last_name(sub_resource_name)]
105
+ return StarkCore::Utils::API.from_api_json(sub_resource_maker, entity)
106
+ end
107
+
108
+ def self.get_sub_resources(resource_name:, sub_resource_maker:, sub_resource_name:, sdk_version:, host:, api_version:, user:, language:, timeout:, id:, **query)
109
+ json = StarkCore::Utils::Request.fetch(
110
+ host: host,
111
+ sdk_version: sdk_version,
112
+ user: user,
113
+ method: 'GET',
114
+ path: "#{StarkCore::Utils::API.endpoint(resource_name)}/#{id}/#{StarkCore::Utils::API.endpoint(sub_resource_name)}",
115
+ query: StarkCore::Utils::API.cast_json_to_api_format(query),
116
+ api_version: api_version,
117
+ timeout: timeout,
118
+ ).json
119
+ returned_jsons = json[StarkCore::Utils::API.last_name_plural(sub_resource_name)]
120
+ entities = []
121
+ returned_jsons.each do |returned_json|
122
+ entities << StarkCore::Utils::API.from_api_json(sub_resource_maker, returned_json)
123
+ end
124
+ return entities
125
+ end
126
+
127
+ def self.post(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, language:, timeout:, entities:, **query)
128
+
129
+ jsons = []
130
+ entities.each do |entity|
131
+ jsons << StarkCore::Utils::API.api_json(entity)
132
+ end
133
+ payload = { StarkCore::Utils::API.last_name_plural(resource_name) => jsons }
134
+
135
+ json = StarkCore::Utils::Request.fetch(
136
+ host: host,
137
+ sdk_version: sdk_version,
138
+ user: user,
139
+ method: 'POST',
140
+ path: StarkCore::Utils::API.endpoint(resource_name),
141
+ query: query,
142
+ payload: payload,
143
+ api_version: api_version,
144
+ timeout: timeout
145
+ ).json
146
+ returned_jsons = json[StarkCore::Utils::API.last_name_plural(resource_name)]
147
+ entities = []
148
+ returned_jsons.each do |returned_json|
149
+ entities << StarkCore::Utils::API.from_api_json(resource_maker, returned_json)
150
+ end
151
+ return entities
152
+ end
153
+
154
+ def self.post_single(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, language:, timeout:, entity:)
155
+ payload = StarkCore::Utils::API.api_json(entity)
156
+ json = StarkCore::Utils::Request.fetch(
157
+ host: host,
158
+ sdk_version: sdk_version,
159
+ user: user,
160
+ method: 'POST',
161
+ path: StarkCore::Utils::API.endpoint(resource_name),
162
+ payload: payload,
163
+ api_version: api_version,
164
+ timeout: timeout
165
+ ).json
166
+ entity_json = json[StarkCore::Utils::API.last_name(resource_name)]
167
+ return StarkCore::Utils::API.from_api_json(resource_maker, entity_json)
168
+ end
169
+
170
+ def self.delete_id(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, language:, timeout:, id:)
171
+ json = StarkCore::Utils::Request.fetch(
172
+ host: host,
173
+ sdk_version: sdk_version,
174
+ user: user,
175
+ method: 'DELETE',
176
+ path: "#{StarkCore::Utils::API.endpoint(resource_name)}/#{id}",
177
+ api_version: api_version,
178
+ timeout: timeout
179
+ ).json
180
+ entity = json[StarkCore::Utils::API.last_name(resource_name)]
181
+ return StarkCore::Utils::API.from_api_json(resource_maker, entity)
182
+ end
183
+
184
+ def self.patch_id(resource_name:, resource_maker:, sdk_version:, host:, api_version:, user:, language:, timeout:, id:, **payload)
185
+ json = StarkCore::Utils::Request.fetch(
186
+ host: host,
187
+ sdk_version: sdk_version,
188
+ user: user,
189
+ method: 'PATCH',
190
+ path: "#{StarkCore::Utils::API.endpoint(resource_name)}/#{id}",
191
+ payload: StarkCore::Utils::API.cast_json_to_api_format(payload),
192
+ api_version: api_version,
193
+ timeout: timeout
194
+ ).json
195
+ entity = json[StarkCore::Utils::API.last_name(resource_name)]
196
+ return StarkCore::Utils::API.from_api_json(resource_maker, entity)
197
+ end
198
+
199
+ def self.get_raw(sdk_version:, host:, api_version:, path:, user:, language:, timeout:, **query)
200
+ return json = StarkCore::Utils::Request.fetch(
201
+ host: host,
202
+ sdk_version: sdk_version,
203
+ user: user,
204
+ method: 'GET',
205
+ path: path,
206
+ api_version: api_version,
207
+ timeout: timeout
208
+ ).json
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StarkCore
4
+ module Utils
5
+ class SubResource
6
+ def to_s
7
+ string_vars = []
8
+ instance_variables.each do |key|
9
+ value = instance_variable_get(key).to_s.lines.map(&:chomp).join("\n ")
10
+ string_vars << "#{key[1..-1]}: #{value}"
11
+ end
12
+ fields = string_vars.join(",\n ")
13
+ "#{class_name}(\n #{fields}\n)"
14
+ end
15
+
16
+ def class_name
17
+ self.class.name.split('::').last.downcase
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/utils/url.rb ADDED
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module StarkCore
6
+ module Utils
7
+ module URL
8
+ # generates query string from hash
9
+ def self.urlencode(params)
10
+ return '' if params.nil?
11
+
12
+ params = StarkCore::Utils::API.cast_json_to_api_format(params)
13
+ return '' if params.empty?
14
+
15
+ string_params = {}
16
+ params.each do |key, value|
17
+ string_params[key] = value.is_a?(Array) ? value.join(',') : value
18
+ end
19
+
20
+ query_list = []
21
+ string_params.each do |key, value|
22
+ query_list << "#{key}=#{ERB::Util.url_encode(value)}"
23
+ end
24
+ return '?' + query_list.join('&')
25
+ end
26
+ end
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: starkcore
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - starkinfra
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: starkbank-ecdsa
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 5.14.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 5.14.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.81'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.81'
69
+ description:
70
+ email:
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - lib/environment.rb
76
+ - lib/error.rb
77
+ - lib/key.rb
78
+ - lib/starkcore.rb
79
+ - lib/user/organization.rb
80
+ - lib/user/project.rb
81
+ - lib/user/user.rb
82
+ - lib/utils/api.rb
83
+ - lib/utils/cache.rb
84
+ - lib/utils/case.rb
85
+ - lib/utils/checks.rb
86
+ - lib/utils/enum.rb
87
+ - lib/utils/host.rb
88
+ - lib/utils/parse.rb
89
+ - lib/utils/request.rb
90
+ - lib/utils/resource.rb
91
+ - lib/utils/rest.rb
92
+ - lib/utils/sub_resource.rb
93
+ - lib/utils/url.rb
94
+ homepage: https://github.com/starkinfra/core-ruby
95
+ licenses:
96
+ - MIT
97
+ metadata: {}
98
+ post_install_message:
99
+ rdoc_options: []
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '2.3'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubygems_version: 3.0.3.1
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Basic SDK functionalities for the starkbank and starkinfra SDKs
117
+ test_files: []