Skip to content

Commit

Permalink
Add device management methods
Browse files Browse the repository at this point in the history
  • Loading branch information
jm-mailosaur committed May 12, 2022
1 parent 2ce831d commit 4bdfdb5
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 15 deletions.
2 changes: 1 addition & 1 deletion lib/Mailosaur/analysis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def initialize(conn, handle_http_error)
def spam(email)
response = conn.get "api/analysis/spam/#{email}"
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::SpamAnalysisResult.new(model)
end
end
Expand Down
83 changes: 83 additions & 0 deletions lib/Mailosaur/devices.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
module Mailosaur
class Devices
#
# Creates and initializes a new instance of the Devices class.
# @param client connection.
#
def initialize(conn, handle_http_error)
@conn = conn
@handle_http_error = handle_http_error
end

# @return [Connection] the client connection.
attr_reader :conn

#
# List all devices
#
# Returns a list of your virtual security devices.
#
# @return [DeviceListResult] operation results.
#
def list
response = conn.get 'api/devices'
@handle_http_error.call(response) unless response.status == 200
model = JSON.parse(response.body)
Mailosaur::Models::DeviceListResult.new(model)
end

#
# Create a device
#
# Creates a new virtual security device and returns it.
#
# @param device_create_options [DeviceCreateOptions]
#
# @return [Device] operation results.
#
def create(device_create_options)
response = conn.post 'api/devices', device_create_options.to_json
@handle_http_error.call(response) unless response.status == 200
model = JSON.parse(response.body)
Mailosaur::Models::Device.new(model)
end

#
# Retrieve OTP
#
# Retrieves the current one-time password for a saved device, or given base32-encoded shared secret.
#
# @param query [String] Either the unique identifier of the device, or a base32-encoded shared secret.
#
# @return [OtpResult] operation results.
#
def otp(query)
if query.include? '-'
response = conn.get "api/devices/#{query}/otp"
@handle_http_error.call(response) unless response.status == 200
model = JSON.parse(response.body)
return Mailosaur::Models::OtpResult.new(model)
end

options = Mailosaur::Models::DeviceCreateOptions.new
options.shared_secret = query
response = conn.post 'api/devices/otp', options.to_json
@handle_http_error.call(response) unless response.status == 200
model = JSON.parse(response.body)
Mailosaur::Models::OtpResult.new(model)
end

#
# Delete a device
#
# Permanently deletes a device. This operation cannot be undone.
#
# @param id [String] The identifier of the device to be deleted.
#
def delete(id)
response = conn.delete "api/devices/#{id}"
@handle_http_error.call(response) unless response.status == 204
nil
end
end
end
12 changes: 6 additions & 6 deletions lib/Mailosaur/messages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def get(server, criteria, timeout: 10_000, received_after: DateTime.now - (1.0 /
def get_by_id(id)
response = conn.get "api/messages/#{id}"
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::Message.new(model)
end

Expand Down Expand Up @@ -96,7 +96,7 @@ def list(server, page: nil, items_per_page: nil, received_after: nil)

@handle_http_error.call(response) unless response.status == 200

model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::MessageListResult.new(model)
end

Expand Down Expand Up @@ -151,7 +151,7 @@ def search(server, criteria, page: nil, items_per_page: nil, timeout: nil, recei

@handle_http_error.call(response) unless response.status == 200

model = JSON.load(response.body)
model = JSON.parse(response.body)
return Mailosaur::Models::MessageListResult.new(model) if timeout.to_i.zero? || !model['items'].empty?

delay_pattern = (response.headers['x-ms-delay'] || '1000').split(',').map(&:to_i)
Expand Down Expand Up @@ -186,7 +186,7 @@ def search(server, criteria, page: nil, items_per_page: nil, timeout: nil, recei
def create(server, message_create_options)
response = conn.post "api/messages?server=#{server}", message_create_options.to_json
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::Message.new(model)
end

Expand All @@ -204,7 +204,7 @@ def create(server, message_create_options)
def forward(id, message_forward_options)
response = conn.post "api/messages/#{id}/forward", message_forward_options.to_json
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::Message.new(model)
end

Expand All @@ -223,7 +223,7 @@ def forward(id, message_forward_options)
def reply(id, message_reply_options)
response = conn.post "api/messages/#{id}/reply", message_reply_options.to_json
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::Message.new(model)
end
end
Expand Down
16 changes: 16 additions & 0 deletions lib/Mailosaur/models/device.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Mailosaur
module Models
class Device < BaseModel
def initialize(data = {})
@id = data['id']
@name = data['name']
end

# @return [String] Unique identifier for the device.
attr_accessor :id

# @return [String] The name of the device.
attr_accessor :name
end
end
end
16 changes: 16 additions & 0 deletions lib/Mailosaur/models/device_create_options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Mailosaur
module Models
class DeviceCreateOptions < BaseModel
def initialize(data = {})
@name = data['name']
@shared_secret = data['shared_secret']
end

# @return [String] A name used to identify the device.
attr_accessor :name

# @return [String] The base32-encoded shared secret for this device.
attr_accessor :shared_secret
end
end
end
13 changes: 13 additions & 0 deletions lib/Mailosaur/models/device_list_result.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module Mailosaur
module Models
class DeviceListResult < BaseModel
def initialize(data = {})
@items = []
(data['items'] || []).each { |i| @items << Mailosaur::Models::Device.new(i) }
end

# @return [Array<Device>] The individual devices forming the result.
attr_accessor :items
end
end
end
16 changes: 16 additions & 0 deletions lib/Mailosaur/models/otp_result.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Mailosaur
module Models
class OtpResult < BaseModel
def initialize(data = {})
@code = data['code']
@expires = data['expires']
end

# @return [String] The current one-time password.
attr_accessor :code

# @return [String] The expiry date/time of the current one-time password.
attr_accessor :expires
end
end
end
12 changes: 6 additions & 6 deletions lib/Mailosaur/servers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def initialize(conn, handle_http_error)
def list
response = conn.get 'api/servers'
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::ServerListResult.new(model)
end

Expand All @@ -39,7 +39,7 @@ def list
def create(server_create_options)
response = conn.post 'api/servers', server_create_options.to_json
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::Server.new(model)
end

Expand All @@ -56,7 +56,7 @@ def create(server_create_options)
def get(id)
response = conn.get "api/servers/#{id}"
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::Server.new(model)
end

Expand All @@ -73,7 +73,7 @@ def get(id)
def get_password(id)
response = conn.get "api/servers/#{id}/password"
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
model['value']
end

Expand All @@ -90,7 +90,7 @@ def get_password(id)
def update(id, server)
response = conn.put "api/servers/#{id}", server.to_json
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::Server.new(model)
end

Expand All @@ -110,7 +110,7 @@ def delete(id)

def generate_email_address(server)
host = ENV['MAILOSAUR_SMTP_HOST'] || 'mailosaur.net'
'%s@%s.%s' % [SecureRandom.hex(3), server, host]
format('%s@%s.%s', SecureRandom.hex(3), server, host)
end
end
end
4 changes: 2 additions & 2 deletions lib/Mailosaur/usage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def initialize(conn, handle_http_error)
def limits
response = conn.get 'api/usage/limits'
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::UsageAccountLimits.new(model)
end

Expand All @@ -34,7 +34,7 @@ def limits
def transactions
response = conn.get 'api/usage/transactions'
@handle_http_error.call(response) unless response.status == 200
model = JSON.load(response.body)
model = JSON.parse(response.body)
Mailosaur::Models::UsageTransactionListResult.new(model)
end
end
Expand Down
10 changes: 10 additions & 0 deletions lib/mailosaur.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Mailosaur
autoload :Messages, 'Mailosaur/messages.rb'
autoload :Servers, 'Mailosaur/servers.rb'
autoload :Usage, 'Mailosaur/usage.rb'
autoload :Devices, 'Mailosaur/devices.rb'
autoload :MailosaurError, 'Mailosaur/mailosaur_error.rb'

module Models
Expand Down Expand Up @@ -42,6 +43,10 @@ module Models
autoload :UsageAccountLimit, 'Mailosaur/models/usage_account_limit.rb'
autoload :UsageTransactionListResult, 'Mailosaur/models/usage_transaction_list_result.rb'
autoload :UsageTransaction, 'Mailosaur/models/usage_transaction.rb'
autoload :Device, 'Mailosaur/models/device.rb'
autoload :DeviceListResult, 'Mailosaur/models/device_list_result.rb'
autoload :DeviceCreateOptions, 'Mailosaur/models/device_create_options.rb'
autoload :OtpResult, 'Mailosaur/models/otp_result.rb'
autoload :BaseModel, 'Mailosaur/models/base_model.rb'
end

Expand Down Expand Up @@ -81,6 +86,11 @@ def usage
@usage ||= Usage.new(connection, method(:handle_http_error))
end

# @return [Devices] usage
def devices
@devices ||= Devices.new(connection, method(:handle_http_error))
end

private

def connection
Expand Down
47 changes: 47 additions & 0 deletions test/devices_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require 'mailosaur'
require 'test/unit'
require 'shoulda/context'

module Mailosaur
class DevicesTest < Test::Unit::TestCase
setup do
api_key = ENV['MAILOSAUR_API_KEY']
base_url = ENV['MAILOSAUR_BASE_URL']

raise ArgumentError, 'Missing necessary environment variables - refer to README.md' if api_key.nil?

@client = MailosaurClient.new(api_key, base_url)
end

should 'perform CRUD operations' do
device_name = 'My test'
shared_secret = 'ONSWG4TFOQYTEMY='

# Create a new device
create_options = Mailosaur::Models::DeviceCreateOptions.new
create_options.name = device_name
create_options.shared_secret = shared_secret

created_device = @client.devices.create(create_options)
assert_not_nil(created_device.id)
assert_equal(device_name, created_device.name)

# Retrieve an otp via device ID
otp_result = @client.devices.otp(created_device.id)
assert_equal(6, otp_result.code.length)

list_result = @client.devices.list
assert_equal(1, list_result.items.length)
@client.devices.delete(created_device.id)
list_result = @client.devices.list
assert_equal(0, list_result.items.length)
end

should 'return OTP given via a shared secret' do
shared_secret = 'ONSWG4TFOQYTEMY='

otp_result = @client.devices.otp(shared_secret)
assert_equal(6, otp_result.code.length)
end
end
end

0 comments on commit 4bdfdb5

Please sign in to comment.