Simple implementation of retained domains API endpoint

This needed a new name, there are several classes of database object
to be included in that endpoint.

Currently, there is one list ordered by name, with each object
containing status and ascii name for convenience. Can be converted to
multiple fields (reserved and blocked separately). Also contains total
count.

Includes CORS preflight which seems to be a known problem for Rails in
the past.
This commit is contained in:
Maciej Szlosarczyk 2020-05-14 14:33:38 +03:00
parent a2bd9a7cc0
commit 18ce853420
No known key found for this signature in database
GPG key ID: 41D62D42D3B0D765
4 changed files with 113 additions and 0 deletions

View file

@ -0,0 +1,11 @@
module Repp
module V1
class RetainedDomainsController < ActionController::API
def index
domains = RetainedDomains.new
render json: { count: domains.count, domains: domains.to_jsonable }
end
end
end
end

View file

@ -0,0 +1,51 @@
# Hiding the queries behind its own class will allow us to include disputed or
# auctioned domains without meddling up with controller logic.
class RetainedDomains
RESERVED = 'reserved'.freeze
BLOCKED = 'blocked'.freeze
attr_reader :domains
def initialize
@domains = gather_domains
end
def gather_domains
blocked_domains = BlockedDomain.order(name: :desc).all
reserved_domains = ReservedDomain.order(name: :desc).all
domains = blocked_domains.to_a.union(reserved_domains.to_a)
domains.sort_by(&:name)
end
def to_jsonable
domains.map { |el| domain_to_json(el) }
end
def domain_to_json(domain)
# Smelly, but ActiveRecord objects are weird and do not respond
# to usual syntax:
# case a
# when Array then "foo"
# when Hash then "bar"
# else "baz"
# end
status = case domain.class.to_s
when 'ReservedDomain' then RESERVED
when 'BlockedDomain' then BLOCKED
end
punycode = SimpleIDN.to_ascii(domain.name)
{
name: domain.name,
status: status,
punycode_name: punycode
}
end
def count
domains.count
end
end

View file

@ -39,6 +39,18 @@ Rails.application.routes.draw do
mount Repp::API => '/'
namespace :repp do
namespace :v1 do
resources :retained_domains, only: %i[index]
end
end
match 'repp/v1/retained_domains',
controller: 'api/cors',
action: 'cors_preflight_check',
via: [:options],
as: 'repp_cors_preflight_check'
namespace :api do
namespace :v1 do
namespace :registrant do

View file

@ -0,0 +1,39 @@
require 'test_helper'
class ReppV1RetainedDomainsTest < ActionDispatch::IntegrationTest
# Uses magical fixtures, will fail once fixtures inside are changed:
# test/fixtures/blocked_domains.yml
# test/fixtures/reserved_domains.yml
def test_get_index
get repp_v1_retained_domains_path
response_json = JSON.parse(response.body, symbolize_names: true)
assert response_json[:count] == 3
expected_objects = [{ name: 'blocked.test',
status: 'blocked',
punycode_name: 'blocked.test' },
{ name: 'blockedäöüõ.test',
status: 'blocked',
punycode_name: 'xn--blocked-cxa7mj0e.test' },
{ name: 'reserved.test',
status: 'reserved',
punycode_name: 'reserved.test' }]
assert_equal response_json[:domains], expected_objects
end
def test_cors_preflight
process :options, repp_v1_retained_domains_path, headers: { 'Origin' => 'https://example.com' }
assert_equal('https://example.com', response.headers['Access-Control-Allow-Origin'])
assert_equal('POST, GET, PUT, PATCH, DELETE, OPTIONS',
response.headers['Access-Control-Allow-Methods'])
assert_equal('Origin, Content-Type, Accept, Authorization, Token, Auth-Token, Email, ' \
'X-User-Token, X-User-Email',
response.headers['Access-Control-Allow-Headers'])
assert_equal('3600', response.headers['Access-Control-Max-Age'])
assert_equal('', response.body)
end
end