Skip to content

Commit

Permalink
Add user_unique_id to free domain reservation
Browse files Browse the repository at this point in the history
- Add user_unique_id to ReservedDomain.reserve_domains_without_payment response
- Create FreeDomainReservationHolder with unique ID for free domain reservations
- Add error handling for case when no domains are available
- Update tests to cover new functionality and error cases
- Increase unique ID length from 8 to 10 characters

This change adds tracking of free domain reservations through unique IDs and improves error handling when no domains are available for reservation.
  • Loading branch information
OlegPhenomenon committed Dec 6, 2024
1 parent f739781 commit 9467854
Show file tree
Hide file tree
Showing 9 changed files with 157 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ def create
password: domain.password,
expire_at: domain.expire_at
}
end
end,
user_unique_id: result.user_unique_id
}, :created)
else
render_error(result.errors, :unprocessable_entity)
Expand Down
15 changes: 15 additions & 0 deletions app/models/free_domain_reservation_holder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class FreeDomainReservationHolder < ApplicationRecord
before_validation :set_user_unique_id
validates :user_unique_id, presence: true, uniqueness: true

def reserved_domains
ReservedDomain.where(name: domain_names)
end

private

def set_user_unique_id
self.user_unique_id = SecureRandom.uuid[0..9]
end

end
2 changes: 1 addition & 1 deletion app/models/reserve_domain_invoice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def build_invoice(attributes)
end

def generate_unique_id
SecureRandom.uuid[0..7]
SecureRandom.uuid[0..9]
end

def process_invoice(invoice)
Expand Down
11 changes: 7 additions & 4 deletions app/models/reserved_domain.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ def new_password_for(name)
record.save
end

def wrap_reserved_domains_to_struct(reserved_domains, success, errors = nil)
Struct.new(:reserved_domains, :success, :errors).new(reserved_domains, success, errors)
def wrap_reserved_domains_to_struct(reserved_domains, success, user_unique_id = nil, errors = nil)
Struct.new(:reserved_domains, :success, :user_unique_id, :errors).new(reserved_domains, success, user_unique_id, errors)
end

def reserve_domains_without_payment(domain_names)
if domain_names.count > MAX_DOMAIN_NAME_PER_REQUEST
return wrap_reserved_domains_to_struct(domain_names, false, "The maximum number of domain names per request is #{MAX_DOMAIN_NAME_PER_REQUEST}")
return wrap_reserved_domains_to_struct(domain_names, false, nil, "The maximum number of domain names per request is #{MAX_DOMAIN_NAME_PER_REQUEST}")
end

available_domains = BusinessRegistry::DomainAvailabilityCheckerService.filter_available(domain_names)
Expand All @@ -65,7 +65,10 @@ def reserve_domains_without_payment(domain_names)
reserved_domains << reserved_domain
end

wrap_reserved_domains_to_struct(reserved_domains, true)
return wrap_reserved_domains_to_struct(reserved_domains, false, nil, "No available domains") if reserved_domains.empty?

unique_id = FreeDomainReservationHolder.create!(domain_names: available_domains).user_unique_id
wrap_reserved_domains_to_struct(reserved_domains, true, unique_id)
end
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class CreateFreeDomainReservationHolders < ActiveRecord::Migration[6.1]
def change
create_table :free_domain_reservation_holders do |t|
t.string :user_unique_id, null: false, unique: true
t.string :domain_names, array: true, default: []
t.timestamps
end
end
end
50 changes: 49 additions & 1 deletion db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,38 @@ CREATE SEQUENCE public.epp_sessions_id_seq
ALTER SEQUENCE public.epp_sessions_id_seq OWNED BY public.epp_sessions.id;


--
-- Name: free_domain_reservation_holders; Type: TABLE; Schema: public; Owner: -
--

CREATE TABLE public.free_domain_reservation_holders (
id bigint NOT NULL,
user_unique_id character varying NOT NULL,
domain_names character varying[] DEFAULT '{}'::character varying[],
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);


--
-- Name: free_domain_reservation_holders_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--

CREATE SEQUENCE public.free_domain_reservation_holders_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;


--
-- Name: free_domain_reservation_holders_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--

ALTER SEQUENCE public.free_domain_reservation_holders_id_seq OWNED BY public.free_domain_reservation_holders.id;


--
-- Name: invoice_items; Type: TABLE; Schema: public; Owner: -
--
Expand Down Expand Up @@ -3186,6 +3218,13 @@ ALTER TABLE ONLY public.epp_logs ALTER COLUMN id SET DEFAULT nextval('public.epp
ALTER TABLE ONLY public.epp_sessions ALTER COLUMN id SET DEFAULT nextval('public.epp_sessions_id_seq'::regclass);


--
-- Name: free_domain_reservation_holders id; Type: DEFAULT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.free_domain_reservation_holders ALTER COLUMN id SET DEFAULT nextval('public.free_domain_reservation_holders_id_seq'::regclass);


--
-- Name: invoice_items id; Type: DEFAULT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -3715,6 +3754,14 @@ ALTER TABLE ONLY public.epp_sessions
ADD CONSTRAINT epp_sessions_pkey PRIMARY KEY (id);


--
-- Name: free_domain_reservation_holders free_domain_reservation_holders_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.free_domain_reservation_holders
ADD CONSTRAINT free_domain_reservation_holders_pkey PRIMARY KEY (id);


--
-- Name: invoice_items invoice_items_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -5669,6 +5716,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20241104104620'),
('20241112093540'),
('20241112124405'),
('20241129095711');
('20241129095711'),
('20241206085817');


Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def setup
test "should reserve multiple domains successfully" do
domain_names = ["new1.test", "new2.test"]

assert_difference 'ReservedDomain.count', 2 do
assert_difference ['ReservedDomain.count'], 2 do
post api_v1_business_registry_reserve_domains_path,
params: { domain_names: domain_names },
headers: @auth_headers
Expand All @@ -40,6 +40,8 @@ def setup
json_response = JSON.parse(response.body)
assert_equal "Domains reserved successfully", json_response['message']
assert_equal 2, json_response['reserved_domains'].length
assert_not_nil json_response['user_unique_id']
assert_equal 10, json_response['user_unique_id'].length

json_response['reserved_domains'].each do |domain|
assert domain_names.include?(domain['name'])
Expand Down Expand Up @@ -127,4 +129,18 @@ def setup
expire_at = Time.parse(domain['expire_at'])
assert_in_delta Time.current + ReservedDomain::FREE_RESERVATION_EXPIRY, expire_at, 5.seconds
end

test "should return error when no domains are available" do
domain_names = ["new1.test", "new2.test"]

BusinessRegistry::DomainAvailabilityCheckerService.stub :filter_available, [] do
post api_v1_business_registry_reserve_domains_path,
params: { domain_names: domain_names },
headers: @auth_headers

assert_response :unprocessable_entity
json_response = JSON.parse(response.body)
assert_equal "No available domains", json_response['error']
end
end
end
33 changes: 33 additions & 0 deletions test/models/free_domain_reservation_holder_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'test_helper'

class FreeDomainReservationHolderTest < ActiveSupport::TestCase
def setup
@holder = FreeDomainReservationHolder.create!(domain_names: ['example1.test', 'example2.test'])
end

test "should be valid with valid attributes" do
holder = FreeDomainReservationHolder.new(
domain_names: ['example1.test', 'example2.test']
)
assert holder.valid?
end

test "should generate user_unique_id before create" do
holder = FreeDomainReservationHolder.create(
domain_names: ['example.test']
)
assert_not_nil holder.user_unique_id
assert_equal 10, holder.user_unique_id.length
end


test "should have many reserved domains" do
holder = FreeDomainReservationHolder.create(
domain_names: ['example.test']
)
reserved_domain = ReservedDomain.create(
name: 'example.test',
)
assert_includes holder.reserved_domains, reserved_domain
end
end
24 changes: 24 additions & 0 deletions test/models/reserved_domain_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class ReservedDomainTest < ActiveSupport::TestCase
result = ReservedDomain.reserve_domains_without_payment(domain_names)

assert_not result.success
p result
assert_includes result.errors, "The maximum number of domain names per request is #{ReservedDomain::MAX_DOMAIN_NAME_PER_REQUEST}"
end

Expand Down Expand Up @@ -131,4 +132,27 @@ class ReservedDomainTest < ActiveSupport::TestCase
@reserved_domain.destroy_if_expired
end
end

test "reserve_domains_without_payment should create holder and return unique_id" do
domain_names = ['test1.test', 'test2.test']

result = ReservedDomain.reserve_domains_without_payment(domain_names)

assert result.success
assert_not_nil result.user_unique_id
assert_equal 10, result.user_unique_id.length
assert_equal domain_names.count, result.reserved_domains.count
end

test "reserve_domains_without_payment should return error when no domains available" do
domain_names = ['test1.test']

BusinessRegistry::DomainAvailabilityCheckerService.stub :filter_available, [] do
result = ReservedDomain.reserve_domains_without_payment(domain_names)

assert_not result.success
assert_nil result.user_unique_id
assert_equal "No available domains", result.errors
end
end
end

0 comments on commit 9467854

Please sign in to comment.