magic-admin 0.0.0 → 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.
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "irb"
5
+ require "irb/completion"
6
+ require "byebug"
7
+ require "#{::File.dirname(__FILE__)}/../lib/magic-admin"
8
+
9
+ # Config IRB to enable --simple-prompt and auto indent
10
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
11
+ IRB.conf[:AUTO_INDENT] = true
12
+
13
+ puts "Loaded gem 'magic-admin'"
14
+ IRB.start
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Magic Ruby bindings
4
+ require "etc"
5
+ require "json"
6
+ require "net/http"
7
+ require "uri"
8
+ require "base64"
9
+ require "eth"
10
+
11
+ # Version
12
+ require "magic-admin/version"
13
+
14
+ # Magic API Classes
15
+ require "magic-admin/util"
16
+ require "magic-admin/config"
17
+ require "magic-admin/errors"
18
+
19
+ # HTTP Classes
20
+ require "magic-admin/http/client"
21
+ require "magic-admin/http/request"
22
+ require "magic-admin/http/response"
23
+
24
+ # Magic Resource Classes
25
+ require "magic-admin/resource/token"
26
+ require "magic-admin/resource/user"
27
+
28
+ # Magic Class to access resources
29
+ class Magic
30
+ RETRIES = 3
31
+ TIMEOUT = 5
32
+ BACKOFF = 0.02
33
+
34
+ # attribute reader for magic api secret key
35
+ attr_reader :secret_key
36
+
37
+ # attribute reader for magic http client
38
+ attr_reader :http_client
39
+
40
+ # The constructor allows you to specify your own API secret key
41
+ # and HTTP request strategy when your application interacting
42
+ # with the Magic API.
43
+ #
44
+ # It will automatically configure required arguments
45
+ # using the following environment variables
46
+ # MAGIC_API_SECRET_KEY
47
+ # MAGIC_API_RETRIES
48
+ # MAGIC_API_TIMEOUT
49
+ # MAGIC_API_BACKOFF
50
+ #
51
+ # Arguments:
52
+ # api_secret_key: Your API Secret Key retrieved from the Magic Dashboard.
53
+ # retries: Total number of retries to allow.
54
+ # timeout: A period of time the request is going to wait for a response.
55
+ # backoff: A backoff factor to apply between retry attempts.
56
+ #
57
+ # Returns:
58
+ # A Magic object that provides access to all the supported resources.
59
+ #
60
+ # Examples:
61
+ #
62
+ # Magic.new
63
+ # Magic.new api_secret_key: "SECRET_KEY>"
64
+ # Magic.new api_secret_key: "SECRET_KEY>",
65
+ # retries: 2,
66
+ # timeout: 2,
67
+ # backoff: 0.2
68
+ #
69
+ #
70
+
71
+ def initialize(api_secret_key: nil,
72
+ retries: nil,
73
+ timeout: nil,
74
+ backoff: nil)
75
+ secret_key!(api_secret_key)
76
+ http_client!(retries, timeout, backoff)
77
+ end
78
+
79
+ # Description:
80
+ # Method provides you User object
81
+ # for interacting with the Magic API.
82
+ #
83
+ # Returns:
84
+ # A User object that provides access to
85
+ # all the supported resources.
86
+
87
+ def user
88
+ MagicAdmin::Resource::User.new(self)
89
+ end
90
+
91
+ # Description:
92
+ # Method provides you Token object
93
+ # for various utility methods of Token.
94
+ #
95
+ # Returns:
96
+ # A Token object that provides access to
97
+ # all the supported resources.
98
+
99
+ def token
100
+ MagicAdmin::Resource::Token.new
101
+ end
102
+
103
+ private
104
+
105
+ def secret_key?
106
+ !(secret_key.nil? || secret_key.empty?)
107
+ end
108
+
109
+ def secret_key!(api_secret_key)
110
+ @secret_key = api_secret_key || ENV["MAGIC_API_SECRET_KEY"]
111
+ message = "Magic api secret key was not found."
112
+
113
+ raise MagicAdmin::MagicError, message unless secret_key?
114
+ end
115
+
116
+ def configure_retries(retries)
117
+ retries || ENV["MAGIC_API_RETRIES"] || RETRIES
118
+ end
119
+
120
+ def configure_timeout(timeout)
121
+ timeout || ENV["MAGIC_API_TIMEOUT"] || TIMEOUT
122
+ end
123
+
124
+ def configure_backoff(backoff)
125
+ backoff || ENV["MAGIC_API_BACKOFF"] || BACKOFF
126
+ end
127
+
128
+ def http_client!(retries, timeout, backoff)
129
+ @http_client = MagicAdmin::Http::Client
130
+ .new(MagicAdmin::Config.api_base,
131
+ configure_retries(retries),
132
+ configure_timeout(timeout),
133
+ configure_backoff(backoff))
134
+ end
135
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MagicAdmin
4
+
5
+ module Config
6
+
7
+ # Description:
8
+ # Method provides you platform information
9
+ #
10
+ # Returns:
11
+ # user platform information
12
+ def self.platform
13
+ RUBY_PLATFORM
14
+ end
15
+
16
+ # Description:
17
+ # Method provides you sdk programming language
18
+ #
19
+ # Returns:
20
+ # sdk programming language
21
+ def self.language
22
+ "ruby"
23
+ end
24
+
25
+ # Description:
26
+ # Method provides you sdk programming language version
27
+ #
28
+ # Returns:
29
+ # sdk programming language version
30
+ def self.language_version
31
+ RUBY_VERSION
32
+ end
33
+
34
+ # Description:
35
+ # Method provides you installation machine user_name
36
+ #
37
+ # Returns:
38
+ # installation machine user_name
39
+ def self.user_name
40
+ Etc.getpwnam(Etc.getlogin).gecos.split(/,/).first
41
+ end
42
+
43
+ # Description:
44
+ # Method provides you sdk publisher name
45
+ #
46
+ # Returns:
47
+ # sdk publisher name
48
+ def self.publisher
49
+ "MagicLabs"
50
+ end
51
+
52
+ # Description:
53
+ # Method provides you api base url
54
+ #
55
+ # Returns:
56
+ # api base url
57
+ def self.api_base
58
+ "https://api.magic.link"
59
+ end
60
+
61
+ # Description:
62
+ # Method provides you nbf grace period
63
+ #
64
+ # Returns:
65
+ # nbf grace period
66
+ def self.nbf_grace_period
67
+ 300
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MagicAdmin
4
+
5
+ # MagicAdmin::MagicError class
6
+ class MagicError < StandardError
7
+
8
+ # attribute reader for error message
9
+ attr_reader :message
10
+
11
+ # Description:
12
+ # The constructor allows you to specify error message
13
+ #
14
+ # Arguments:
15
+ # message: error message.
16
+ def initialize(message)
17
+ @message = message
18
+ end
19
+ end
20
+
21
+ # MagicAdmin::MagicError class
22
+ class DIDTokenError < MagicError; end
23
+
24
+ # RequestError Class
25
+ class RequestError < MagicError
26
+ # attribute reader for http response status
27
+ attr_reader :http_status
28
+
29
+ # attribute reader for http response code
30
+ attr_reader :http_code
31
+
32
+ # attribute reader for http response
33
+ attr_reader :http_response
34
+
35
+ # attribute reader for http response message
36
+ attr_reader :http_message
37
+
38
+ # attribute reader for http response error code
39
+ attr_reader :http_error_code
40
+
41
+ # attribute reader for http request params
42
+ attr_reader :http_request_params
43
+
44
+ # attribute reader for http request data
45
+ attr_reader :http_request_data
46
+
47
+ # attribute reader for http request method
48
+ attr_reader :http_method
49
+
50
+ # Description:
51
+ # The constructor allows you to specify error message
52
+ # and HTTP request and response info
53
+ #
54
+ # Arguments:
55
+ # message: request error message.
56
+ # opt: hash of request and response info of following keys:
57
+ # http_status
58
+ # http_code
59
+ # http_response
60
+ # http_message
61
+ # http_error_code
62
+ # http_request_params
63
+ # http_request_data
64
+ # http_method
65
+ # Returns:
66
+ # A Error object that provides additional error info for magic api call.
67
+ def initialize(message, opt = {})
68
+ super(message)
69
+ @http_status = opt[:http_status]
70
+ @http_code = opt[:http_code]
71
+ @http_response = opt[:http_response]
72
+ @http_message = opt[:http_message]
73
+ @http_error_code = opt[:http_error_code]
74
+ @http_request_params = opt[:http_request_params]
75
+ @http_request_data = opt[:http_request_data]
76
+ @http_method = opt[:http_method]
77
+ end
78
+ end
79
+
80
+ # MagicAdmin::MagicError class
81
+ class APIConnectionError < RequestError; end
82
+
83
+ # MagicAdmin::RateLimitingError class
84
+ class RateLimitingError < RequestError; end
85
+
86
+ # MagicAdmin::BadRequestError class
87
+ class BadRequestError < RequestError; end
88
+
89
+ # MagicAdmin::AuthenticationError class
90
+ class AuthenticationError < RequestError; end
91
+
92
+ # MagicAdmin::ForbiddenError class
93
+ class ForbiddenError < RequestError; end
94
+
95
+ # MagicAdmin::APIError class
96
+ class APIError < RequestError; end
97
+
98
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MagicAdmin
4
+
5
+ module Http
6
+
7
+ # Http Client and its methods are accessible
8
+ # on the Magic instance by the http_client attribute.
9
+ # It provides methods to interact with the http client.
10
+ class Client
11
+
12
+ # attribute reader for magic api max retries
13
+ attr_reader :retries
14
+
15
+ # attribute reader for magic api backoff factor
16
+ attr_reader :backoff
17
+
18
+ # attribute reader for magic api timeout
19
+ attr_reader :timeout
20
+
21
+ # attribute reader for magic api base api url
22
+ attr_reader :base_url
23
+
24
+ # attribute reader for magic http request class
25
+ attr_reader :http_request
26
+
27
+ # attribute reader for magic http response class
28
+ attr_reader :http_response
29
+
30
+ # The constructor allows you to configure HTTP request strategy
31
+ # when your application interacting with the Magic API
32
+ #
33
+ # Arguments:
34
+ # api_base: api base url.
35
+ # req_retries: Total number of retries to allow.
36
+ # req_timeout: A period of time the request is going
37
+ # to wait for a response.
38
+ # req_backoff: A backoff factor to apply between retry attempts.
39
+ #
40
+ # Returns:
41
+ # A Http Client object that provides access to
42
+ # all the supported resources.
43
+ #
44
+ # Examples:
45
+ # Client.new(<api_base>, <req_retries>, <req_timeout>, <req_backoff>)
46
+ def initialize(api_base, req_retries, req_timeout, req_backoff)
47
+ @retries = req_retries.to_i
48
+ @backoff = req_backoff.to_f
49
+ @timeout = req_timeout.to_f
50
+ @base_url = api_base
51
+ @http_request = Request
52
+ @http_response = Response
53
+ end
54
+
55
+ # Description:
56
+ # call create http request and provide response
57
+ #
58
+ # Arguments:
59
+ # method: http method
60
+ # path: api path
61
+ # options: a hash contains params and headers for request
62
+ #
63
+ # Returns:
64
+ # A response object
65
+ def call(method, path, options)
66
+ url = URI("#{base_url}#{path}")
67
+ req = http_request.request(method, url, options)
68
+ resp = backoff_retries(retries, backoff) do
69
+ base_client(url, req, timeout)
70
+ end
71
+ http_response.from_net_http(resp, req)
72
+ end
73
+
74
+ private
75
+
76
+ # Description:
77
+ # backoff_retries implementations of retries strategy
78
+ # with backoff factor
79
+ #
80
+ # Arguments:
81
+ # max_retries: max retries count
82
+ # backoff_factor: backoff factor for configure delay in retries
83
+ # block: block of code that uses retries backoff strategy
84
+ #
85
+ # Returns:
86
+ # it returns, block return object
87
+ def backoff_retries(max_retries, backoff_factor, &block)
88
+ attempts = 0
89
+ begin
90
+ attempts += 1
91
+ block.call
92
+ rescue StandardError => e
93
+ raise e if attempts >= max_retries
94
+
95
+ sleep_seconds = backoff_factor * (2**(attempts - 1))
96
+ sleep sleep_seconds
97
+ retry
98
+ end
99
+ end
100
+
101
+ # Description:
102
+ # use_ssl? provide true if url uses https protocol otherwise false
103
+ #
104
+ # Arguments:
105
+ # url: max retries count
106
+ #
107
+ # Returns:
108
+ # boolean value
109
+ def use_ssl?(url)
110
+ url.scheme == "https"
111
+ end
112
+
113
+ # Description:
114
+ # base_client is base http request/response mechanism
115
+ #
116
+ # Arguments:
117
+ # url: request url
118
+ # request: request object
119
+ # read_timeout: read_timeout for request
120
+ #
121
+ # Returns:
122
+ # response
123
+ def base_client(url, request, read_timeout)
124
+ begin
125
+ Net::HTTP.start(url.host, url.port, use_ssl: use_ssl?(url)) do |http|
126
+ http.read_timeout = read_timeout
127
+ http.request(request)
128
+ end
129
+ rescue SocketError => e
130
+ raise APIConnectionError.new(e.message)
131
+ end
132
+ end
133
+
134
+ end
135
+ end
136
+ end