magic-admin 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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