Allow signups to be blocked by MX host

This commit is contained in:
Tom Hughes 2019-06-23 11:21:03 +01:00
parent fc67e63589
commit d2d5d48f29
5 changed files with 55 additions and 14 deletions

View file

@ -752,7 +752,13 @@ class UsersController < ApplicationController
email.split("@").last email.split("@").last
end end
if blocked = Acl.no_account_creation(request.remote_ip, domain) mx_servers = if domain.nil?
nil
else
domain_mx_servers(domain)
end
if blocked = Acl.no_account_creation(request.remote_ip, :domain => domain, :mx => mx_servers)
logger.info "Blocked signup from #{request.remote_ip} for #{email}" logger.info "Blocked signup from #{request.remote_ip} for #{email}"
render :action => "blocked" render :action => "blocked"
@ -761,6 +767,14 @@ class UsersController < ApplicationController
!blocked !blocked
end end
##
# get list of MX servers for a domains
def domain_mx_servers(domain)
Resolv::DNS.open do |dns|
dns.getresources(domain, Resolv::DNS::Resource::IN::MX).collect(&:exchange).collect(&:to_s)
end
end
## ##
# check if this user has a gravatar and set the user pref is true # check if this user has a gravatar and set the user pref is true
def gravatar_enable(user) def gravatar_enable(user)

View file

@ -7,34 +7,37 @@
# k :string not null # k :string not null
# v :string # v :string
# domain :string # domain :string
# mx :string
# #
# Indexes # Indexes
# #
# acls_k_idx (k) # acls_k_idx (k)
# index_acls_on_address (address) USING gist # index_acls_on_address (address) USING gist
# index_acls_on_domain (domain) # index_acls_on_domain (domain)
# index_acls_on_mx (mx)
# #
class Acl < ActiveRecord::Base class Acl < ActiveRecord::Base
validates :k, :presence => true validates :k, :presence => true
def self.match(address, domain = nil) def self.match(address, options = {})
if domain acls = Acl.where("address >>= ?", address)
Acl.where("address >>= ? OR domain = ?", address, domain)
else acls = acls.or(Acl.where(:domain => options[:domain])) if options[:domain]
Acl.where("address >>= ?", address) acls = acls.or(Acl.where(:mx => options[:mx])) if options[:mx]
end
acls
end end
def self.no_account_creation(address, domain = nil) def self.no_account_creation(address, options = {})
match(address, domain).where(:k => "no_account_creation").exists? match(address, options).where(:k => "no_account_creation").exists?
end end
def self.no_note_comment(address, domain = nil) def self.no_note_comment(address, domain = nil)
match(address, domain).where(:k => "no_note_comment").exists? match(address, :domain => domain).where(:k => "no_note_comment").exists?
end end
def self.no_trace_download(address, domain = nil) def self.no_trace_download(address, domain = nil)
match(address, domain).where(:k => "no_trace_download").exists? match(address, :domain => domain).where(:k => "no_trace_download").exists?
end end
end end

View file

@ -0,0 +1,9 @@
class AddMxAcls < ActiveRecord::Migration[5.2]
def change
add_column :acls, :mx, :string
safety_assured do
add_index :acls, :mx
end
end
end

View file

@ -168,7 +168,8 @@ CREATE TABLE public.acls (
address inet, address inet,
k character varying NOT NULL, k character varying NOT NULL,
v character varying, v character varying,
domain character varying domain character varying,
mx character varying
); );
@ -2078,6 +2079,13 @@ CREATE INDEX index_acls_on_address ON public.acls USING gist (address inet_ops);
CREATE INDEX index_acls_on_domain ON public.acls USING btree (domain); CREATE INDEX index_acls_on_domain ON public.acls USING btree (domain);
--
-- Name: index_acls_on_mx; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_acls_on_mx ON public.acls USING btree (mx);
-- --
-- Name: index_changeset_comments_on_created_at; Type: INDEX; Schema: public; Owner: - -- Name: index_changeset_comments_on_created_at; Type: INDEX; Schema: public; Owner: -
-- --
@ -2949,6 +2957,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20181020114000'), ('20181020114000'),
('20181031113522'), ('20181031113522'),
('20190518115041'), ('20190518115041'),
('20190623093642'),
('21'), ('21'),
('22'), ('22'),
('23'), ('23'),

View file

@ -15,8 +15,14 @@ class AclTest < ActiveSupport::TestCase
end end
def test_no_account_creation_by_domain def test_no_account_creation_by_domain
assert_not Acl.no_account_creation("192.168.1.1", "example.com") assert_not Acl.no_account_creation("192.168.1.1", :domain => "example.com")
create(:acl, :domain => "example.com", :k => "no_account_creation") create(:acl, :domain => "example.com", :k => "no_account_creation")
assert Acl.no_account_creation("192.168.1.1", "example.com") assert Acl.no_account_creation("192.168.1.1", :domain => "example.com")
end
def test_no_account_creation_by_mx
assert_not Acl.no_account_creation("192.168.1.1", :mx => "mail.example.com")
create(:acl, :mx => "mail.example.com", :k => "no_account_creation")
assert Acl.no_account_creation("192.168.1.1", :mx => "mail.example.com")
end end
end end