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
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}"
render :action => "blocked"
@ -761,6 +767,14 @@ class UsersController < ApplicationController
!blocked
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
def gravatar_enable(user)

View file

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

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,
k character varying NOT NULL,
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);
--
-- 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: -
--
@ -2949,6 +2957,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20181020114000'),
('20181031113522'),
('20190518115041'),
('20190623093642'),
('21'),
('22'),
('23'),

View file

@ -15,8 +15,14 @@ class AclTest < ActiveSupport::TestCase
end
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")
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