From c4e46149e88d815ea9b21c4f4f17e707cb7f5dfb Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Thu, 30 Apr 2020 13:01:01 +0500 Subject: [PATCH 01/13] Fix presence of ignored fields in history Closes #1576 --- app/models/concerns/versions.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/concerns/versions.rb b/app/models/concerns/versions.rb index 9ffd17e9a..01766b233 100644 --- a/app/models/concerns/versions.rb +++ b/app/models/concerns/versions.rb @@ -70,7 +70,8 @@ module Versions valid_columns = ver.item_type.constantize&.column_names o = new(ver.object&.slice(*valid_columns)) o.version_loader = ver - ver.object_changes.to_h.each { |k, v| o.public_send("#{k}=", v[-1]) } + changes = ver.object_changes.to_h&.slice(*valid_columns) + changes.each { |k, v| o.public_send("#{k}=", v[-1]) } o end not_in_history = where(id: (ids.to_a - from_history.map(&:id))) From 1a58d85f15fc5a3791bc11d3824d659b7aa93935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20V=C3=B5hmar?= Date: Thu, 30 Apr 2020 12:20:30 +0300 Subject: [PATCH 02/13] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a43dcff83..cdc184c6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +30.04.2020 +* Fix for internal error on opening domain history with legacy id record [#1576](https://github.com/internetee/registry/issues/1576) + 27.04.2020 * Downgrade SimpleCov to 0.17 due to incompatibiilty with CodeClimate [#1575](https://github.com/internetee/registry/pull/1575) From 90f933a5a10c56ac7d318a3dfcff89f6b5bc586e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 5 May 2020 13:38:21 +0300 Subject: [PATCH 03/13] Add revoked boolean to Certificate model --- db/migrate/20200505103316_add_revoked_to_certificate.rb | 5 +++++ db/structure.sql | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20200505103316_add_revoked_to_certificate.rb diff --git a/db/migrate/20200505103316_add_revoked_to_certificate.rb b/db/migrate/20200505103316_add_revoked_to_certificate.rb new file mode 100644 index 000000000..a52c7d14c --- /dev/null +++ b/db/migrate/20200505103316_add_revoked_to_certificate.rb @@ -0,0 +1,5 @@ +class AddRevokedToCertificate < ActiveRecord::Migration[5.2] + def change + add_column :certificates, :revoked, :boolean, null: false, default: false + end +end diff --git a/db/structure.sql b/db/structure.sql index 604238d4c..6ad181ea4 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -476,7 +476,8 @@ CREATE TABLE public.certificates ( updated_at timestamp without time zone, common_name character varying, md5 character varying, - interface character varying + interface character varying, + revoked boolean DEFAULT false NOT NULL ); @@ -4463,5 +4464,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20200130092113'), ('20200203143458'), ('20200204103125'), -('20200311114649'); +('20200311114649'), +('20200505103316'); + From 0fa7fcc771a9d1bf65f1e9273017919a4741a580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 5 May 2020 13:48:53 +0300 Subject: [PATCH 04/13] Check that certificate is not revoked --- app/models/api_user.rb | 6 ++++-- app/models/certificate.rb | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models/api_user.rb b/app/models/api_user.rb index 3dc240727..99f14ad6c 100644 --- a/app/models/api_user.rb +++ b/app/models/api_user.rb @@ -66,22 +66,24 @@ class ApiUser < User def registrar_pki_ok?(crt, cn) return false if crt.blank? || cn.blank? + crt = crt.split(' ').join("\n") crt.gsub!("-----BEGIN\nCERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\n") crt.gsub!("\n-----END\nCERTIFICATE-----", "\n-----END CERTIFICATE-----") cert = OpenSSL::X509::Certificate.new(crt) md5 = OpenSSL::Digest::MD5.new(cert.to_der).to_s - certificates.registrar.exists?(md5: md5, common_name: cn) + certificates.registrar.exists?(md5: md5, common_name: cn, revoked: false) end def api_pki_ok?(crt, cn) return false if crt.blank? || cn.blank? + crt = crt.split(' ').join("\n") crt.gsub!("-----BEGIN\nCERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\n") crt.gsub!("\n-----END\nCERTIFICATE-----", "\n-----END CERTIFICATE-----") cert = OpenSSL::X509::Certificate.new(crt) md5 = OpenSSL::Digest::MD5.new(cert.to_der).to_s - certificates.api.exists?(md5: md5, common_name: cn) + certificates.api.exists?(md5: md5, common_name: cn, revoked: false) end def linked_users diff --git a/app/models/certificate.rb b/app/models/certificate.rb index 5259403c2..f0711d4f5 100644 --- a/app/models/certificate.rb +++ b/app/models/certificate.rb @@ -116,6 +116,7 @@ class Certificate < ApplicationRecord -revoke #{crt_file.path} -key '#{ENV['ca_key_password']}' -batch") if err.match(/Data Base Updated/) || err.match(/ERROR:Already revoked/) + self.revoked = true save! @cached_status = REVOKED else From 2dbcbf1c29efb7868aa5ffa04da8c3e37d4579e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 5 May 2020 14:06:02 +0300 Subject: [PATCH 05/13] Remove redundant api check blocks --- app/api/repp/api.rb | 3 +- app/controllers/epp/sessions_controller.rb | 3 +- .../registrar/sessions_controller.rb | 5 +-- app/models/api_user.rb | 32 +++++++++---------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/app/api/repp/api.rb b/app/api/repp/api.rb index e5bda46f5..af6864cfa 100644 --- a/app/api/repp/api.rb +++ b/app/api/repp/api.rb @@ -30,7 +30,8 @@ module Repp webclient_cert_name = ENV['webclient_cert_common_name'] || 'webclient' error! "Webclient #{message} #{webclient_cert_name}", 401 if webclient_cert_name != request_name else - unless @current_user.api_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN']) + unless @current_user.pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], + request.env['HTTP_SSL_CLIENT_S_DN_CN']) error! "#{message} #{@current_user.username}", 401 end end diff --git a/app/controllers/epp/sessions_controller.rb b/app/controllers/epp/sessions_controller.rb index ef8f125ee..cf24feb33 100644 --- a/app/controllers/epp/sessions_controller.rb +++ b/app/controllers/epp/sessions_controller.rb @@ -26,7 +26,8 @@ module Epp end if !Rails.env.development? && (!webclient_request && @api_user) - unless @api_user.api_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN']) + unless @api_user.pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], + request.env['HTTP_SSL_CLIENT_S_DN_CN']) epp_errors << { msg: 'Authentication error; server closing connection (certificate is not valid)', code: '2501' diff --git a/app/controllers/registrar/sessions_controller.rb b/app/controllers/registrar/sessions_controller.rb index 2ca8f5cc7..5bebe5619 100644 --- a/app/controllers/registrar/sessions_controller.rb +++ b/app/controllers/registrar/sessions_controller.rb @@ -31,7 +31,8 @@ class Registrar end if @depp_user.pki - unless @api_user.registrar_pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], request.env['HTTP_SSL_CLIENT_S_DN_CN']) + unless @api_user.pki_ok?(request.env['HTTP_SSL_CLIENT_CERT'], + request.env['HTTP_SSL_CLIENT_S_DN_CN'], api: false) @depp_user.errors.add(:base, :invalid_cert) end end @@ -205,4 +206,4 @@ class Registrar redirect_to new_registrar_user_session_url, alert: @depp_user.errors.full_messages.first end end -end \ No newline at end of file +end diff --git a/app/models/api_user.rb b/app/models/api_user.rb index 99f14ad6c..b5efa7235 100644 --- a/app/models/api_user.rb +++ b/app/models/api_user.rb @@ -64,26 +64,14 @@ class ApiUser < User registrar.notifications.unread end - def registrar_pki_ok?(crt, cn) - return false if crt.blank? || cn.blank? + def pki_ok?(crt, com, api: true) + return false if crt.blank? || com.blank? - crt = crt.split(' ').join("\n") - crt.gsub!("-----BEGIN\nCERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\n") - crt.gsub!("\n-----END\nCERTIFICATE-----", "\n-----END CERTIFICATE-----") - cert = OpenSSL::X509::Certificate.new(crt) + origin = api ? certificates.api : certificates.registrar + cert = machine_readable_certificate(crt) md5 = OpenSSL::Digest::MD5.new(cert.to_der).to_s - certificates.registrar.exists?(md5: md5, common_name: cn, revoked: false) - end - def api_pki_ok?(crt, cn) - return false if crt.blank? || cn.blank? - - crt = crt.split(' ').join("\n") - crt.gsub!("-----BEGIN\nCERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\n") - crt.gsub!("\n-----END\nCERTIFICATE-----", "\n-----END CERTIFICATE-----") - cert = OpenSSL::X509::Certificate.new(crt) - md5 = OpenSSL::Digest::MD5.new(cert.to_der).to_s - certificates.api.exists?(md5: md5, common_name: cn, revoked: false) + origin.exists?(md5: md5, common_name: com, revoked: false) end def linked_users @@ -95,4 +83,14 @@ class ApiUser < User def linked_with?(another_api_user) another_api_user.identity_code == self.identity_code end + + private + + def machine_readable_certificate(cert) + cert = cert.split(' ').join("\n") + cert.gsub!("-----BEGIN\nCERTIFICATE-----\n", "-----BEGIN CERTIFICATE-----\n") + cert.gsub!("\n-----END\nCERTIFICATE-----", "\n-----END CERTIFICATE-----") + + OpenSSL::X509::Certificate.new(cert) + end end From e18942e8eee88276aecef5b8afee021a9550982e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 5 May 2020 16:33:33 +0300 Subject: [PATCH 06/13] Cover PKI validation with tests --- test/fixtures/certificates.yml | 7 +++++++ test/models/api_user_test.rb | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/fixtures/certificates.yml diff --git a/test/fixtures/certificates.yml b/test/fixtures/certificates.yml new file mode 100644 index 000000000..c91df3ace --- /dev/null +++ b/test/fixtures/certificates.yml @@ -0,0 +1,7 @@ +one: + api_user: api_bestnames + common_name: registry.test + crt: "-----BEGIN CERTIFICATE-----\nMIICYjCCAcugAwIBAgIBADANBgkqhkiG9w0BAQ0FADBNMQswCQYDVQQGEwJ1czEO\nMAwGA1UECAwFVGV4YXMxFjAUBgNVBAoMDVJlZ2lzdHJ5IHRlc3QxFjAUBgNVBAMM\nDXJlZ2lzdHJ5LnRlc3QwIBcNMjAwNTA1MTIzNzQxWhgPMjEyMDA0MTExMjM3NDFa\nME0xCzAJBgNVBAYTAnVzMQ4wDAYDVQQIDAVUZXhhczEWMBQGA1UECgwNUmVnaXN0\ncnkgdGVzdDEWMBQGA1UEAwwNcmVnaXN0cnkudGVzdDCBnzANBgkqhkiG9w0BAQEF\nAAOBjQAwgYkCgYEAyn+GCkUJIhdXVBOPrZH+Zj2B/tQfL5TLZwVYZQt38x6GQT+4\n6ndty467IJvKSUlHej7uMpsCzC8Ffmda4cZm16jO1vUb4hXIrmeKP84zLrrUpKag\ngZR4rBDbG2+uL4SzMyy3yeQysYuTiQ4N1i4vdhvkKYPSWIht/QFvuzdFq+0CAwEA\nAaNQME4wHQYDVR0OBBYEFD6B5j6NnMCDBnfbtjBYKBJM7sCRMB8GA1UdIwQYMBaA\nFD6B5j6NnMCDBnfbtjBYKBJM7sCRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN\nBQADgYEArtCR6VOabD3nM/KlZTmHMZVT4ntenYlNTM9FS0RatzPmdh4REhykvmZs\nOlBcpoV5tN5Y8bHOVRqY9V2e903QEhQgoccQhbt0Py6uFwfLv+WLKAUbeGnPqK9d\ndL3wXN9BQs0hJA6IZNFyz2F/gSTURrD1zWW2na3ipRzhupW5+98=\n-----END CERTIFICATE-----\n" + md5: e6771ed5dc857a1dbcc1e0a36baa1fee + interface: api + revoked: false diff --git a/test/models/api_user_test.rb b/test/models/api_user_test.rb index 20d655a9c..dd907f75c 100644 --- a/test/models/api_user_test.rb +++ b/test/models/api_user_test.rb @@ -63,6 +63,21 @@ class ApiUserTest < ActiveSupport::TestCase assert_nil ApiUser.find_by_id_card(id_card) end + def test_verifies_pki_status + certificate = certificates(:one) + + assert @user.pki_ok?(certificate.crt, certificate.common_name, api: true) + assert_not @user.pki_ok?(certificate.crt, 'invalid-cn', api: true) + + certificate.update(interface: 'registrar') + + assert @user.pki_ok?(certificate.crt, certificate.common_name, api: false) + assert_not @user.pki_ok?(certificate.crt, 'invalid-cn', api: false) + + certificate.update(revoked: true) + assert_not @user.pki_ok?(certificate.crt, certificate.common_name, api: false) + end + private def valid_user From c6fd78b4cdcd39b815d2efcce4f4a1eaa108a5ac Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Fri, 17 Apr 2020 17:03:45 +0500 Subject: [PATCH 07/13] Add registration deadline field to auction model --- ...dd_registration_deadline_date_to_models.rb | 5 + db/structure.sql | 461 +++++++++++++++++- 2 files changed, 449 insertions(+), 17 deletions(-) create mode 100644 db/migrate/20200417075720_add_registration_deadline_date_to_models.rb diff --git a/db/migrate/20200417075720_add_registration_deadline_date_to_models.rb b/db/migrate/20200417075720_add_registration_deadline_date_to_models.rb new file mode 100644 index 000000000..8614ec889 --- /dev/null +++ b/db/migrate/20200417075720_add_registration_deadline_date_to_models.rb @@ -0,0 +1,5 @@ +class AddRegistrationDeadlineDateToModels < ActiveRecord::Migration[5.2] + def change + add_column :auctions, :registration_deadline, :datetime + end +end diff --git a/db/structure.sql b/db/structure.sql index 604238d4c..eae59f5e0 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -11,6 +11,12 @@ SET check_function_bodies = false; SET xmloption = content; SET client_min_messages = warning; +-- +-- Name: audit; Type: SCHEMA; Schema: -; Owner: - +-- + +CREATE SCHEMA audit; + -- -- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - -- @@ -191,12 +197,262 @@ CREATE FUNCTION public.generate_zonefile(i_origin character varying) RETURNS tex $_$; -SET default_tablespace = ''; +-- +-- Name: process_contact_audit(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.process_contact_audit() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + IF (TG_OP = 'INSERT') THEN + INSERT INTO audit.contacts + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'UPDATE') THEN + INSERT INTO audit.contacts + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'DELETE') THEN + INSERT INTO audit.contacts + (object_id, action, recorded_at, old_value, new_value) + VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); + RETURN OLD; + END IF; + RETURN NULL; + END +$$; -SET default_with_oids = false; -- --- Name: account_activities; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: process_dnskey_audit(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.process_dnskey_audit() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + IF (TG_OP = 'INSERT') THEN + INSERT INTO audit.dnskeys + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'UPDATE') THEN + INSERT INTO audit.dnskeys + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'DELETE') THEN + INSERT INTO audit.dnskeys + (object_id, action, recorded_at, old_value, new_value) + VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); + RETURN OLD; + END IF; + RETURN NULL; + END +$$; + + +-- +-- Name: process_domain_audit(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.process_domain_audit() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + IF (TG_OP = 'INSERT') THEN + INSERT INTO audit.domains + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'UPDATE') THEN + INSERT INTO audit.domains + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'DELETE') THEN + INSERT INTO audit.domains + (object_id, action, recorded_at, old_value, new_value) + VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); + RETURN OLD; + END IF; + RETURN NULL; + END +$$; + + +-- +-- Name: process_nameserver_audit(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.process_nameserver_audit() RETURNS trigger + LANGUAGE plpgsql + AS $$ + BEGIN + IF (TG_OP = 'INSERT') THEN + INSERT INTO audit.nameservers + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'UPDATE') THEN + INSERT INTO audit.nameservers + (object_id, action, recorded_at, old_value, new_value) + VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); + RETURN NEW; + ELSEIF (TG_OP = 'DELETE') THEN + INSERT INTO audit.nameservers + (object_id, action, recorded_at, old_value, new_value) + VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); + RETURN OLD; + END IF; + RETURN NULL; + END +$$; + + +SET default_tablespace = ''; + +-- +-- Name: contacts; Type: TABLE; Schema: audit; Owner: - +-- + +CREATE TABLE audit.contacts ( + id integer NOT NULL, + object_id bigint, + action text NOT NULL, + recorded_at timestamp without time zone, + old_value jsonb, + new_value jsonb, + CONSTRAINT contacts_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) +); + + +-- +-- Name: contacts_id_seq; Type: SEQUENCE; Schema: audit; Owner: - +-- + +CREATE SEQUENCE audit.contacts_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: contacts_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - +-- + +ALTER SEQUENCE audit.contacts_id_seq OWNED BY audit.contacts.id; + + +-- +-- Name: dnskeys; Type: TABLE; Schema: audit; Owner: - +-- + +CREATE TABLE audit.dnskeys ( + id integer NOT NULL, + object_id bigint, + action text NOT NULL, + recorded_at timestamp without time zone, + old_value jsonb, + new_value jsonb, + CONSTRAINT dnskeys_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) +); + + +-- +-- Name: dnskeys_id_seq; Type: SEQUENCE; Schema: audit; Owner: - +-- + +CREATE SEQUENCE audit.dnskeys_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: dnskeys_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - +-- + +ALTER SEQUENCE audit.dnskeys_id_seq OWNED BY audit.dnskeys.id; + + +-- +-- Name: domains; Type: TABLE; Schema: audit; Owner: - +-- + +CREATE TABLE audit.domains ( + id integer NOT NULL, + object_id bigint, + action text NOT NULL, + recorded_at timestamp without time zone, + old_value jsonb, + new_value jsonb, + CONSTRAINT domains_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) +); + + +-- +-- Name: domains_id_seq; Type: SEQUENCE; Schema: audit; Owner: - +-- + +CREATE SEQUENCE audit.domains_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: domains_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - +-- + +ALTER SEQUENCE audit.domains_id_seq OWNED BY audit.domains.id; + + +-- +-- Name: nameservers; Type: TABLE; Schema: audit; Owner: - +-- + +CREATE TABLE audit.nameservers ( + id integer NOT NULL, + object_id bigint, + action text NOT NULL, + recorded_at timestamp without time zone, + old_value jsonb, + new_value jsonb, + CONSTRAINT nameservers_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) +); + + +-- +-- Name: nameservers_id_seq; Type: SEQUENCE; Schema: audit; Owner: - +-- + +CREATE SEQUENCE audit.nameservers_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: nameservers_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - +-- + +ALTER SEQUENCE audit.nameservers_id_seq OWNED BY audit.nameservers.id; + + +-- +-- Name: account_activities; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE public.account_activities ( @@ -325,7 +581,8 @@ CREATE TABLE public.auctions ( status character varying NOT NULL, uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, created_at timestamp without time zone NOT NULL, - registration_code character varying + registration_code character varying, + registration_deadline timestamp without time zone ); @@ -558,7 +815,16 @@ ALTER SEQUENCE public.contacts_id_seq OWNED BY public.contacts.id; -- --- Name: directos; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: data_migrations; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.data_migrations ( + version character varying NOT NULL +); + + +-- +-- Name: directos; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE public.directos ( @@ -745,7 +1011,8 @@ CREATE TABLE public.domains ( uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, locked_by_registrant_at timestamp without time zone, force_delete_start timestamp without time zone, - force_delete_data public.hstore + force_delete_data public.hstore, + children jsonb ); @@ -2344,14 +2611,42 @@ ALTER SEQUENCE public.zones_id_seq OWNED BY public.zones.id; -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: contacts id; Type: DEFAULT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.contacts ALTER COLUMN id SET DEFAULT nextval('audit.contacts_id_seq'::regclass); + + +-- +-- Name: dnskeys id; Type: DEFAULT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.dnskeys ALTER COLUMN id SET DEFAULT nextval('audit.dnskeys_id_seq'::regclass); + + +-- +-- Name: domains id; Type: DEFAULT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.domains ALTER COLUMN id SET DEFAULT nextval('audit.domains_id_seq'::regclass); + + +-- +-- Name: nameservers id; Type: DEFAULT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.nameservers ALTER COLUMN id SET DEFAULT nextval('audit.nameservers_id_seq'::regclass); + + +-- +-- Name: account_activities id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY public.account_activities ALTER COLUMN id SET DEFAULT nextval('public.account_activities_id_seq'::regclass); -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: accounts id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY public.accounts ALTER COLUMN id SET DEFAULT nextval('public.accounts_id_seq'::regclass); @@ -2722,7 +3017,39 @@ ALTER TABLE ONLY public.zones ALTER COLUMN id SET DEFAULT nextval('public.zones_ -- --- Name: account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: contacts contacts_pkey; Type: CONSTRAINT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.contacts + ADD CONSTRAINT contacts_pkey PRIMARY KEY (id); + + +-- +-- Name: dnskeys dnskeys_pkey; Type: CONSTRAINT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.dnskeys + ADD CONSTRAINT dnskeys_pkey PRIMARY KEY (id); + + +-- +-- Name: domains domains_pkey; Type: CONSTRAINT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.domains + ADD CONSTRAINT domains_pkey PRIMARY KEY (id); + + +-- +-- Name: nameservers nameservers_pkey; Type: CONSTRAINT; Schema: audit; Owner: - +-- + +ALTER TABLE ONLY audit.nameservers + ADD CONSTRAINT nameservers_pkey PRIMARY KEY (id); + + +-- +-- Name: account_activities account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.account_activities @@ -2730,7 +3057,7 @@ ALTER TABLE ONLY public.account_activities -- --- Name: accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: accounts accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.accounts @@ -3266,14 +3593,70 @@ ALTER TABLE ONLY public.zones -- --- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: contacts_object_id_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX contacts_object_id_idx ON audit.contacts USING btree (object_id); + + +-- +-- Name: contacts_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX contacts_recorded_at_idx ON audit.contacts USING btree (recorded_at); + + +-- +-- Name: dnskeys_object_id_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX dnskeys_object_id_idx ON audit.dnskeys USING btree (object_id); + + +-- +-- Name: dnskeys_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX dnskeys_recorded_at_idx ON audit.dnskeys USING btree (recorded_at); + + +-- +-- Name: domains_object_id_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX domains_object_id_idx ON audit.domains USING btree (object_id); + + +-- +-- Name: domains_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX domains_recorded_at_idx ON audit.domains USING btree (recorded_at); + + +-- +-- Name: nameservers_object_id_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX nameservers_object_id_idx ON audit.nameservers USING btree (object_id); + + +-- +-- Name: nameservers_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - +-- + +CREATE INDEX nameservers_recorded_at_idx ON audit.nameservers USING btree (recorded_at); + + +-- +-- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: - -- CREATE INDEX index_account_activities_on_account_id ON public.account_activities USING btree (account_id); -- --- Name: index_account_activities_on_bank_transaction_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: index_account_activities_on_bank_transaction_id; Type: INDEX; Schema: public; Owner: - -- CREATE INDEX index_account_activities_on_bank_transaction_id ON public.account_activities USING btree (bank_transaction_id); @@ -3826,21 +4209,56 @@ CREATE INDEX log_domains_object_legacy_id ON public.log_contacts USING btree ((( -- --- Name: log_nameservers_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: log_nameservers_object_legacy_id; Type: INDEX; Schema: public; Owner: - -- CREATE INDEX log_nameservers_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_domain_id'::text))::integer)); -- --- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- Name: unique_data_migrations; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX unique_data_migrations ON public.data_migrations USING btree (version); + + +-- +-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: - -- CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version); -- --- Name: contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: contacts process_contact_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_contact_audit AFTER INSERT OR DELETE OR UPDATE ON public.contacts FOR EACH ROW EXECUTE PROCEDURE public.process_contact_audit(); + + +-- +-- Name: dnskeys process_dnskey_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_dnskey_audit AFTER INSERT OR DELETE OR UPDATE ON public.dnskeys FOR EACH ROW EXECUTE PROCEDURE public.process_dnskey_audit(); + + +-- +-- Name: domains process_domain_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_domain_audit AFTER INSERT OR DELETE OR UPDATE ON public.domains FOR EACH ROW EXECUTE PROCEDURE public.process_domain_audit(); + + +-- +-- Name: nameservers process_nameserver_audit; Type: TRIGGER; Schema: public; Owner: - +-- + +CREATE TRIGGER process_nameserver_audit AFTER INSERT OR DELETE OR UPDATE ON public.nameservers FOR EACH ROW EXECUTE PROCEDURE public.process_nameserver_audit(); + + +-- +-- Name: contacts contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.contacts @@ -3848,7 +4266,7 @@ ALTER TABLE ONLY public.contacts -- --- Name: domain_contacts_contact_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: domain_contacts domain_contacts_contact_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.domain_contacts @@ -4463,5 +4881,14 @@ INSERT INTO "schema_migrations" (version) VALUES ('20200130092113'), ('20200203143458'), ('20200204103125'), -('20200311114649'); +('20200310105731'), +('20200310105736'), +('20200311114649'), +('20200319082650'), +('20200320090152'), +('20200320094842'), +('20200330111918'), +('20200408091005'), +('20200417075720'); + From 5c419ae8be7a6f0628f32329be8e7b3a218665ba Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Wed, 6 May 2020 15:17:20 +0500 Subject: [PATCH 08/13] Update whois record with auction registration_deadline if any --- app/controllers/api/v1/auctions_controller.rb | 2 ++ app/models/auction.rb | 11 +++++++++- app/models/whois/record.rb | 3 ++- test/models/whois/record_test.rb | 20 ++++++++++++++----- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/v1/auctions_controller.rb b/app/controllers/api/v1/auctions_controller.rb index bf92be930..de8e94442 100644 --- a/app/controllers/api/v1/auctions_controller.rb +++ b/app/controllers/api/v1/auctions_controller.rb @@ -30,6 +30,8 @@ module Api raise "Invalid status #{params[:status]}" end + auction.mark_deadline(params[:registration_deadline]) if params[:registration_deadline] + if auction.payment_not_received? || auction.domain_not_registered? update_whois_from_auction(Auction.pending(auction.domain)) else diff --git a/app/models/auction.rb b/app/models/auction.rb index 6ddd8e394..c4b9f6130 100644 --- a/app/models/auction.rb +++ b/app/models/auction.rb @@ -23,10 +23,19 @@ class Auction < ApplicationRecord save! end + def whois_deadline + registration_deadline.to_s + end + def mark_as_no_bids no_bids! end + def mark_deadline(registration_deadline) + self.registration_deadline = registration_deadline + save! + end + def mark_as_payment_received self.status = self.class.statuses[:payment_received] generate_registration_code @@ -69,4 +78,4 @@ class Auction < ApplicationRecord def registration_code_matches?(code) registration_code == code end -end \ No newline at end of file +end diff --git a/app/models/whois/record.rb b/app/models/whois/record.rb index ae7422403..1d827e22a 100644 --- a/app/models/whois/record.rb +++ b/app/models/whois/record.rb @@ -16,7 +16,8 @@ module Whois elsif auction.awaiting_payment? || auction.payment_received? update!(json: { name: auction.domain, status: ['PendingRegistration'], - disclaimer: self.class.disclaimer }) + disclaimer: self.class.disclaimer, + registration_deadline: auction.whois_deadline }) end end end diff --git a/test/models/whois/record_test.rb b/test/models/whois/record_test.rb index 5f2454105..64e8a894a 100644 --- a/test/models/whois/record_test.rb +++ b/test/models/whois/record_test.rb @@ -40,24 +40,34 @@ class Whois::RecordTest < ActiveSupport::TestCase end def test_updates_whois_record_from_auction_when_awaiting_payment - @auction.update!(domain: 'domain.test', status: Auction.statuses[:awaiting_payment]) + @auction.update!(domain: 'domain.test', + status: Auction.statuses[:awaiting_payment], + registration_deadline: registration_deadline) @whois_record.update!(name: 'domain.test') @whois_record.update_from_auction(@auction) @whois_record.reload assert_equal ({ 'name' => 'domain.test', 'status' => ['PendingRegistration'], - 'disclaimer' => 'disclaimer' }), @whois_record.json + 'disclaimer' => 'disclaimer', + 'registration_deadline' => registration_deadline.to_s }), @whois_record.json end def test_updates_whois_record_from_auction_when_payment_received - @auction.update!(domain: 'domain.test', status: Auction.statuses[:payment_received]) + @auction.update!(domain: 'domain.test', + status: Auction.statuses[:payment_received], + registration_deadline: registration_deadline) @whois_record.update!(name: 'domain.test') @whois_record.update_from_auction(@auction) @whois_record.reload assert_equal ({ 'name' => 'domain.test', 'status' => ['PendingRegistration'], - 'disclaimer' => 'disclaimer' }), @whois_record.json + 'disclaimer' => 'disclaimer', + 'registration_deadline' => registration_deadline.to_s }), @whois_record.json end -end \ No newline at end of file + + def registration_deadline + Time.zone.now + 10.days + end +end From d035b7727d51c6826dab07f27f57973d2a0c3772 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Thu, 7 May 2020 13:51:22 +0500 Subject: [PATCH 09/13] Add tests for registry to receive registration_deadline --- test/integration/api/v1/auctions/update_test.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/integration/api/v1/auctions/update_test.rb b/test/integration/api/v1/auctions/update_test.rb index fe4d075b0..e6ce3c683 100644 --- a/test/integration/api/v1/auctions/update_test.rb +++ b/test/integration/api/v1/auctions/update_test.rb @@ -39,6 +39,17 @@ class ApiV1AuctionUpdateTest < ActionDispatch::IntegrationTest assert @auction.awaiting_payment? end + def test_sets_registration_deadline + deadline = (Time.zone.now + 10.days).end_of_day + patch api_v1_auction_path(@auction.uuid), + params: { status: Auction.statuses[:awaiting_payment], + registration_deadline: deadline}, + as: :json + @auction.reload + + assert_in_delta @auction.registration_deadline, deadline, 1.second + end + def test_marks_as_no_bids patch api_v1_auction_path(@auction.uuid), params: { status: Auction.statuses[:no_bids] }, From 6bff8257983541364ff41375861e7a893e424146 Mon Sep 17 00:00:00 2001 From: Alex Sherman Date: Fri, 8 May 2020 13:31:05 +0500 Subject: [PATCH 10/13] Fix structure.sql --- db/structure.sql | 454 ++--------------------------------------------- 1 file changed, 14 insertions(+), 440 deletions(-) diff --git a/db/structure.sql b/db/structure.sql index eae59f5e0..511f38d2e 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -11,12 +11,6 @@ SET check_function_bodies = false; SET xmloption = content; SET client_min_messages = warning; --- --- Name: audit; Type: SCHEMA; Schema: -; Owner: - --- - -CREATE SCHEMA audit; - -- -- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - -- @@ -197,262 +191,12 @@ CREATE FUNCTION public.generate_zonefile(i_origin character varying) RETURNS tex $_$; --- --- Name: process_contact_audit(); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION public.process_contact_audit() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF (TG_OP = 'INSERT') THEN - INSERT INTO audit.contacts - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'UPDATE') THEN - INSERT INTO audit.contacts - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'DELETE') THEN - INSERT INTO audit.contacts - (object_id, action, recorded_at, old_value, new_value) - VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); - RETURN OLD; - END IF; - RETURN NULL; - END -$$; - - --- --- Name: process_dnskey_audit(); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION public.process_dnskey_audit() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF (TG_OP = 'INSERT') THEN - INSERT INTO audit.dnskeys - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'UPDATE') THEN - INSERT INTO audit.dnskeys - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'DELETE') THEN - INSERT INTO audit.dnskeys - (object_id, action, recorded_at, old_value, new_value) - VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); - RETURN OLD; - END IF; - RETURN NULL; - END -$$; - - --- --- Name: process_domain_audit(); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION public.process_domain_audit() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF (TG_OP = 'INSERT') THEN - INSERT INTO audit.domains - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'UPDATE') THEN - INSERT INTO audit.domains - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'DELETE') THEN - INSERT INTO audit.domains - (object_id, action, recorded_at, old_value, new_value) - VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); - RETURN OLD; - END IF; - RETURN NULL; - END -$$; - - --- --- Name: process_nameserver_audit(); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION public.process_nameserver_audit() RETURNS trigger - LANGUAGE plpgsql - AS $$ - BEGIN - IF (TG_OP = 'INSERT') THEN - INSERT INTO audit.nameservers - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'INSERT', now(), '{}', to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'UPDATE') THEN - INSERT INTO audit.nameservers - (object_id, action, recorded_at, old_value, new_value) - VALUES (NEW.id, 'UPDATE', now(), to_json(OLD)::jsonb, to_json(NEW)::jsonb); - RETURN NEW; - ELSEIF (TG_OP = 'DELETE') THEN - INSERT INTO audit.nameservers - (object_id, action, recorded_at, old_value, new_value) - VALUES (OLD.id, 'DELETE', now(), to_json(OLD)::jsonb, '{}'); - RETURN OLD; - END IF; - RETURN NULL; - END -$$; - - SET default_tablespace = ''; --- --- Name: contacts; Type: TABLE; Schema: audit; Owner: - --- - -CREATE TABLE audit.contacts ( - id integer NOT NULL, - object_id bigint, - action text NOT NULL, - recorded_at timestamp without time zone, - old_value jsonb, - new_value jsonb, - CONSTRAINT contacts_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) -); - +SET default_with_oids = false; -- --- Name: contacts_id_seq; Type: SEQUENCE; Schema: audit; Owner: - --- - -CREATE SEQUENCE audit.contacts_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: contacts_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - --- - -ALTER SEQUENCE audit.contacts_id_seq OWNED BY audit.contacts.id; - - --- --- Name: dnskeys; Type: TABLE; Schema: audit; Owner: - --- - -CREATE TABLE audit.dnskeys ( - id integer NOT NULL, - object_id bigint, - action text NOT NULL, - recorded_at timestamp without time zone, - old_value jsonb, - new_value jsonb, - CONSTRAINT dnskeys_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) -); - - --- --- Name: dnskeys_id_seq; Type: SEQUENCE; Schema: audit; Owner: - --- - -CREATE SEQUENCE audit.dnskeys_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: dnskeys_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - --- - -ALTER SEQUENCE audit.dnskeys_id_seq OWNED BY audit.dnskeys.id; - - --- --- Name: domains; Type: TABLE; Schema: audit; Owner: - --- - -CREATE TABLE audit.domains ( - id integer NOT NULL, - object_id bigint, - action text NOT NULL, - recorded_at timestamp without time zone, - old_value jsonb, - new_value jsonb, - CONSTRAINT domains_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) -); - - --- --- Name: domains_id_seq; Type: SEQUENCE; Schema: audit; Owner: - --- - -CREATE SEQUENCE audit.domains_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: domains_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - --- - -ALTER SEQUENCE audit.domains_id_seq OWNED BY audit.domains.id; - - --- --- Name: nameservers; Type: TABLE; Schema: audit; Owner: - --- - -CREATE TABLE audit.nameservers ( - id integer NOT NULL, - object_id bigint, - action text NOT NULL, - recorded_at timestamp without time zone, - old_value jsonb, - new_value jsonb, - CONSTRAINT nameservers_action_check CHECK ((action = ANY (ARRAY['INSERT'::text, 'UPDATE'::text, 'DELETE'::text, 'TRUNCATE'::text]))) -); - - --- --- Name: nameservers_id_seq; Type: SEQUENCE; Schema: audit; Owner: - --- - -CREATE SEQUENCE audit.nameservers_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: nameservers_id_seq; Type: SEQUENCE OWNED BY; Schema: audit; Owner: - --- - -ALTER SEQUENCE audit.nameservers_id_seq OWNED BY audit.nameservers.id; - - --- --- Name: account_activities; Type: TABLE; Schema: public; Owner: - +-- Name: account_activities; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.account_activities ( @@ -815,16 +559,7 @@ ALTER SEQUENCE public.contacts_id_seq OWNED BY public.contacts.id; -- --- Name: data_migrations; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.data_migrations ( - version character varying NOT NULL -); - - --- --- Name: directos; Type: TABLE; Schema: public; Owner: - +-- Name: directos; Type: TABLE; Schema: public; Owner: -; Tablespace: -- CREATE TABLE public.directos ( @@ -1011,8 +746,7 @@ CREATE TABLE public.domains ( uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, locked_by_registrant_at timestamp without time zone, force_delete_start timestamp without time zone, - force_delete_data public.hstore, - children jsonb + force_delete_data public.hstore ); @@ -2611,42 +2345,14 @@ ALTER SEQUENCE public.zones_id_seq OWNED BY public.zones.id; -- --- Name: contacts id; Type: DEFAULT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.contacts ALTER COLUMN id SET DEFAULT nextval('audit.contacts_id_seq'::regclass); - - --- --- Name: dnskeys id; Type: DEFAULT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.dnskeys ALTER COLUMN id SET DEFAULT nextval('audit.dnskeys_id_seq'::regclass); - - --- --- Name: domains id; Type: DEFAULT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.domains ALTER COLUMN id SET DEFAULT nextval('audit.domains_id_seq'::regclass); - - --- --- Name: nameservers id; Type: DEFAULT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.nameservers ALTER COLUMN id SET DEFAULT nextval('audit.nameservers_id_seq'::regclass); - - --- --- Name: account_activities id; Type: DEFAULT; Schema: public; Owner: - +-- Name: id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY public.account_activities ALTER COLUMN id SET DEFAULT nextval('public.account_activities_id_seq'::regclass); -- --- Name: accounts id; Type: DEFAULT; Schema: public; Owner: - +-- Name: id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY public.accounts ALTER COLUMN id SET DEFAULT nextval('public.accounts_id_seq'::regclass); @@ -3017,39 +2723,7 @@ ALTER TABLE ONLY public.zones ALTER COLUMN id SET DEFAULT nextval('public.zones_ -- --- Name: contacts contacts_pkey; Type: CONSTRAINT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.contacts - ADD CONSTRAINT contacts_pkey PRIMARY KEY (id); - - --- --- Name: dnskeys dnskeys_pkey; Type: CONSTRAINT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.dnskeys - ADD CONSTRAINT dnskeys_pkey PRIMARY KEY (id); - - --- --- Name: domains domains_pkey; Type: CONSTRAINT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.domains - ADD CONSTRAINT domains_pkey PRIMARY KEY (id); - - --- --- Name: nameservers nameservers_pkey; Type: CONSTRAINT; Schema: audit; Owner: - --- - -ALTER TABLE ONLY audit.nameservers - ADD CONSTRAINT nameservers_pkey PRIMARY KEY (id); - - --- --- Name: account_activities account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: account_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.account_activities @@ -3057,7 +2731,7 @@ ALTER TABLE ONLY public.account_activities -- --- Name: accounts accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- Name: accounts_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: -- ALTER TABLE ONLY public.accounts @@ -3593,70 +3267,14 @@ ALTER TABLE ONLY public.zones -- --- Name: contacts_object_id_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX contacts_object_id_idx ON audit.contacts USING btree (object_id); - - --- --- Name: contacts_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX contacts_recorded_at_idx ON audit.contacts USING btree (recorded_at); - - --- --- Name: dnskeys_object_id_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX dnskeys_object_id_idx ON audit.dnskeys USING btree (object_id); - - --- --- Name: dnskeys_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX dnskeys_recorded_at_idx ON audit.dnskeys USING btree (recorded_at); - - --- --- Name: domains_object_id_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX domains_object_id_idx ON audit.domains USING btree (object_id); - - --- --- Name: domains_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX domains_recorded_at_idx ON audit.domains USING btree (recorded_at); - - --- --- Name: nameservers_object_id_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX nameservers_object_id_idx ON audit.nameservers USING btree (object_id); - - --- --- Name: nameservers_recorded_at_idx; Type: INDEX; Schema: audit; Owner: - --- - -CREATE INDEX nameservers_recorded_at_idx ON audit.nameservers USING btree (recorded_at); - - --- --- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_account_activities_on_account_id ON public.account_activities USING btree (account_id); -- --- Name: index_account_activities_on_bank_transaction_id; Type: INDEX; Schema: public; Owner: - +-- Name: index_account_activities_on_bank_transaction_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX index_account_activities_on_bank_transaction_id ON public.account_activities USING btree (bank_transaction_id); @@ -4209,56 +3827,21 @@ CREATE INDEX log_domains_object_legacy_id ON public.log_contacts USING btree ((( -- --- Name: log_nameservers_object_legacy_id; Type: INDEX; Schema: public; Owner: - +-- Name: log_nameservers_object_legacy_id; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE INDEX log_nameservers_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_domain_id'::text))::integer)); -- --- Name: unique_data_migrations; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX unique_data_migrations ON public.data_migrations USING btree (version); - - --- --- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: - +-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace: -- CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version); -- --- Name: contacts process_contact_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_contact_audit AFTER INSERT OR DELETE OR UPDATE ON public.contacts FOR EACH ROW EXECUTE PROCEDURE public.process_contact_audit(); - - --- --- Name: dnskeys process_dnskey_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_dnskey_audit AFTER INSERT OR DELETE OR UPDATE ON public.dnskeys FOR EACH ROW EXECUTE PROCEDURE public.process_dnskey_audit(); - - --- --- Name: domains process_domain_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_domain_audit AFTER INSERT OR DELETE OR UPDATE ON public.domains FOR EACH ROW EXECUTE PROCEDURE public.process_domain_audit(); - - --- --- Name: nameservers process_nameserver_audit; Type: TRIGGER; Schema: public; Owner: - --- - -CREATE TRIGGER process_nameserver_audit AFTER INSERT OR DELETE OR UPDATE ON public.nameservers FOR EACH ROW EXECUTE PROCEDURE public.process_nameserver_audit(); - - --- --- Name: contacts contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: contacts_registrar_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.contacts @@ -4266,7 +3849,7 @@ ALTER TABLE ONLY public.contacts -- --- Name: domain_contacts domain_contacts_contact_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - +-- Name: domain_contacts_contact_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.domain_contacts @@ -4881,14 +4464,5 @@ INSERT INTO "schema_migrations" (version) VALUES ('20200130092113'), ('20200203143458'), ('20200204103125'), -('20200310105731'), -('20200310105736'), ('20200311114649'), -('20200319082650'), -('20200320090152'), -('20200320094842'), -('20200330111918'), -('20200408091005'), ('20200417075720'); - - From a2bd9a7cc0cd1bda76e2f55e71ba8a07860d8292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20V=C3=B5hmar?= Date: Mon, 11 May 2020 17:42:04 +0300 Subject: [PATCH 11/13] Update CHANGELOG.md auction due dates to whois --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc184c6e..e8ca16670 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +11.05.2020 +* Auction process due dates are now available over whois and rest-whois [#1201](https://github.com/internetee/registry/issues/1201) + 30.04.2020 * Fix for internal error on opening domain history with legacy id record [#1576](https://github.com/internetee/registry/issues/1576) From c2f8589044da96aa4a316b6d97e5b3d4858f2ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 12 May 2020 11:38:28 +0300 Subject: [PATCH 12/13] Verify that CN is present when uploading CSR/CRT --- app/models/certificate.rb | 29 +++++++++++++++-------------- test/fixtures/certificates.yml | 9 ++++++++- test/models/api_user_test.rb | 8 ++++++-- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/app/models/certificate.rb b/app/models/certificate.rb index f0711d4f5..940c5fdc8 100644 --- a/app/models/certificate.rb +++ b/app/models/certificate.rb @@ -32,20 +32,21 @@ class Certificate < ApplicationRecord errors.add(:base, I18n.t(:invalid_csr_or_crt)) end - before_create :parse_metadata - def parse_metadata - if crt - pc = parsed_crt.try(:subject).try(:to_s) || '' - cn = pc.scan(/\/CN=(.+)/).flatten.first - self.common_name = cn.split('/').first - self.md5 = OpenSSL::Digest::MD5.new(parsed_crt.to_der).to_s - self.interface = API - elsif csr - pc = parsed_csr.try(:subject).try(:to_s) || '' - cn = pc.scan(/\/CN=(.+)/).flatten.first - self.common_name = cn.split('/').first - self.interface = REGISTRAR - end + validate :assign_metadata + + def assign_metadata + origin = crt ? parsed_crt : parsed_csr + parse_metadata(origin) + rescue NoMethodError + errors.add(:base, I18n.t(:invalid_csr_or_crt)) + end + + def parse_metadata(origin) + pc = origin.subject.to_s + cn = pc.scan(%r{\/CN=(.+)}).flatten.first + self.common_name = cn.split('/').first + self.md5 = OpenSSL::Digest::MD5.new(origin.to_der).to_s if crt + self.interface = crt ? API : REGISTRAR end def parsed_crt diff --git a/test/fixtures/certificates.yml b/test/fixtures/certificates.yml index c91df3ace..4799743ff 100644 --- a/test/fixtures/certificates.yml +++ b/test/fixtures/certificates.yml @@ -1,7 +1,14 @@ -one: +api: api_user: api_bestnames common_name: registry.test crt: "-----BEGIN CERTIFICATE-----\nMIICYjCCAcugAwIBAgIBADANBgkqhkiG9w0BAQ0FADBNMQswCQYDVQQGEwJ1czEO\nMAwGA1UECAwFVGV4YXMxFjAUBgNVBAoMDVJlZ2lzdHJ5IHRlc3QxFjAUBgNVBAMM\nDXJlZ2lzdHJ5LnRlc3QwIBcNMjAwNTA1MTIzNzQxWhgPMjEyMDA0MTExMjM3NDFa\nME0xCzAJBgNVBAYTAnVzMQ4wDAYDVQQIDAVUZXhhczEWMBQGA1UECgwNUmVnaXN0\ncnkgdGVzdDEWMBQGA1UEAwwNcmVnaXN0cnkudGVzdDCBnzANBgkqhkiG9w0BAQEF\nAAOBjQAwgYkCgYEAyn+GCkUJIhdXVBOPrZH+Zj2B/tQfL5TLZwVYZQt38x6GQT+4\n6ndty467IJvKSUlHej7uMpsCzC8Ffmda4cZm16jO1vUb4hXIrmeKP84zLrrUpKag\ngZR4rBDbG2+uL4SzMyy3yeQysYuTiQ4N1i4vdhvkKYPSWIht/QFvuzdFq+0CAwEA\nAaNQME4wHQYDVR0OBBYEFD6B5j6NnMCDBnfbtjBYKBJM7sCRMB8GA1UdIwQYMBaA\nFD6B5j6NnMCDBnfbtjBYKBJM7sCRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN\nBQADgYEArtCR6VOabD3nM/KlZTmHMZVT4ntenYlNTM9FS0RatzPmdh4REhykvmZs\nOlBcpoV5tN5Y8bHOVRqY9V2e903QEhQgoccQhbt0Py6uFwfLv+WLKAUbeGnPqK9d\ndL3wXN9BQs0hJA6IZNFyz2F/gSTURrD1zWW2na3ipRzhupW5+98=\n-----END CERTIFICATE-----\n" md5: e6771ed5dc857a1dbcc1e0a36baa1fee interface: api revoked: false +registrar: + api_user: api_bestnames + common_name: registry.test + crt: "-----BEGIN CERTIFICATE-----\nMIICYjCCAcugAwIBAgIBADANBgkqhkiG9w0BAQ0FADBNMQswCQYDVQQGEwJ1czEO\nMAwGA1UECAwFVGV4YXMxFjAUBgNVBAoMDVJlZ2lzdHJ5IHRlc3QxFjAUBgNVBAMM\nDXJlZ2lzdHJ5LnRlc3QwIBcNMjAwNTA1MTIzNzQxWhgPMjEyMDA0MTExMjM3NDFa\nME0xCzAJBgNVBAYTAnVzMQ4wDAYDVQQIDAVUZXhhczEWMBQGA1UECgwNUmVnaXN0\ncnkgdGVzdDEWMBQGA1UEAwwNcmVnaXN0cnkudGVzdDCBnzANBgkqhkiG9w0BAQEF\nAAOBjQAwgYkCgYEAyn+GCkUJIhdXVBOPrZH+Zj2B/tQfL5TLZwVYZQt38x6GQT+4\n6ndty467IJvKSUlHej7uMpsCzC8Ffmda4cZm16jO1vUb4hXIrmeKP84zLrrUpKag\ngZR4rBDbG2+uL4SzMyy3yeQysYuTiQ4N1i4vdhvkKYPSWIht/QFvuzdFq+0CAwEA\nAaNQME4wHQYDVR0OBBYEFD6B5j6NnMCDBnfbtjBYKBJM7sCRMB8GA1UdIwQYMBaA\nFD6B5j6NnMCDBnfbtjBYKBJM7sCRMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEN\nBQADgYEArtCR6VOabD3nM/KlZTmHMZVT4ntenYlNTM9FS0RatzPmdh4REhykvmZs\nOlBcpoV5tN5Y8bHOVRqY9V2e903QEhQgoccQhbt0Py6uFwfLv+WLKAUbeGnPqK9d\ndL3wXN9BQs0hJA6IZNFyz2F/gSTURrD1zWW2na3ipRzhupW5+98=\n-----END CERTIFICATE-----\n" + md5: e6771ed5dc857a1dbcc1e0a36baa1fee + interface: registrar + revoked: false diff --git a/test/models/api_user_test.rb b/test/models/api_user_test.rb index dd907f75c..ecbff5cbb 100644 --- a/test/models/api_user_test.rb +++ b/test/models/api_user_test.rb @@ -64,18 +64,22 @@ class ApiUserTest < ActiveSupport::TestCase end def test_verifies_pki_status - certificate = certificates(:one) + certificate = certificates(:api) assert @user.pki_ok?(certificate.crt, certificate.common_name, api: true) assert_not @user.pki_ok?(certificate.crt, 'invalid-cn', api: true) - certificate.update(interface: 'registrar') + certificate = certificates(:registrar) assert @user.pki_ok?(certificate.crt, certificate.common_name, api: false) assert_not @user.pki_ok?(certificate.crt, 'invalid-cn', api: false) certificate.update(revoked: true) assert_not @user.pki_ok?(certificate.crt, certificate.common_name, api: false) + + certificate = certificates(:api) + certificate.update(revoked: true) + assert_not @user.pki_ok?(certificate.crt, certificate.common_name, api: true) end private From 36e036e2315c194a624f45c9e454ec98ecec6bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Tue, 12 May 2020 21:27:54 +0300 Subject: [PATCH 13/13] Write metadata only on create --- app/models/certificate.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/certificate.rb b/app/models/certificate.rb index 940c5fdc8..d2428365a 100644 --- a/app/models/certificate.rb +++ b/app/models/certificate.rb @@ -32,7 +32,7 @@ class Certificate < ApplicationRecord errors.add(:base, I18n.t(:invalid_csr_or_crt)) end - validate :assign_metadata + validate :assign_metadata, on: :create def assign_metadata origin = crt ? parsed_crt : parsed_csr