From 1652aa4bd30fbcf6faa79b399451fd995a0ffefa Mon Sep 17 00:00:00 2001 From: Seth Call Date: Tue, 9 Feb 2016 12:58:54 -0600 Subject: [PATCH] * VRFS-3922 - update ip blacklist/whitelist behavior to offer more admin flexibilyt --- admin/app/admin/ip_whitelist.rb | 13 ++++++++ admin/app/admin/user_whitelist.rb | 13 ++++++++ db/manifest | 3 +- db/up/whitelist.sql | 18 +++++++++++ ruby/lib/jam_ruby.rb | 2 ++ ruby/lib/jam_ruby/models/download_tracker.rb | 18 ++++++++--- ruby/lib/jam_ruby/models/ip_blacklist.rb | 8 +++-- ruby/lib/jam_ruby/models/ip_whitelist.rb | 30 +++++++++++++++++++ ruby/lib/jam_ruby/models/user_blacklist.rb | 8 ++++- ruby/lib/jam_ruby/models/user_whitelist.rb | 29 ++++++++++++++++++ ruby/spec/factories.rb | 16 ++++++++++ .../spec/jam_ruby/models/ip_blacklist_spec.rb | 27 +++++++++++++++++ .../jam_ruby/models/user_blacklist_spec.rb | 29 ++++++++++++++++++ web/app/helpers/sessions_helper.rb | 20 +++++++++++-- 14 files changed, 224 insertions(+), 10 deletions(-) create mode 100644 admin/app/admin/ip_whitelist.rb create mode 100644 admin/app/admin/user_whitelist.rb create mode 100644 db/up/whitelist.sql create mode 100644 ruby/lib/jam_ruby/models/ip_whitelist.rb create mode 100644 ruby/lib/jam_ruby/models/user_whitelist.rb create mode 100644 ruby/spec/jam_ruby/models/ip_blacklist_spec.rb create mode 100644 ruby/spec/jam_ruby/models/user_blacklist_spec.rb diff --git a/admin/app/admin/ip_whitelist.rb b/admin/app/admin/ip_whitelist.rb new file mode 100644 index 000000000..e5e53b228 --- /dev/null +++ b/admin/app/admin/ip_whitelist.rb @@ -0,0 +1,13 @@ +ActiveAdmin.register JamRuby::IpWhitelist, :as => 'IP Whitelist' do + + menu :label => 'IP Whitelist', :parent => 'Operations' + + config.sort_order = 'created_at desc' + config.batch_actions = false + + index do + column :remote_ip + column :notes + column :created_at + end +end \ No newline at end of file diff --git a/admin/app/admin/user_whitelist.rb b/admin/app/admin/user_whitelist.rb new file mode 100644 index 000000000..16fc8790a --- /dev/null +++ b/admin/app/admin/user_whitelist.rb @@ -0,0 +1,13 @@ +ActiveAdmin.register JamRuby::UserWhitelist, :as => 'User Whitelist' do + + menu :label => 'User Whitelist', :parent => 'Operations' + + config.sort_order = 'created_at desc' + config.batch_actions = false + + index do + column :user + column :notes + column :created_at + end +end \ No newline at end of file diff --git a/db/manifest b/db/manifest index be7e53729..f67ef865e 100755 --- a/db/manifest +++ b/db/manifest @@ -330,4 +330,5 @@ download_tracker_fingerprints.sql connection_active.sql chat_channel.sql jamblaster.sql -test_drive_lessons.sql \ No newline at end of file +test_drive_lessons.sql +whitelist.sql diff --git a/db/up/whitelist.sql b/db/up/whitelist.sql new file mode 100644 index 000000000..9bb1eb97e --- /dev/null +++ b/db/up/whitelist.sql @@ -0,0 +1,18 @@ + + +CREATE TABLE ip_whitelists ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + remote_ip VARCHAR(400) UNIQUE NOT NULL, + notes VARCHAR, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); + + +CREATE TABLE user_whitelists ( + id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(), + user_id VARCHAR(64) UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE, + notes VARCHAR, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/ruby/lib/jam_ruby.rb b/ruby/lib/jam_ruby.rb index 996a0714f..76f6e2db0 100755 --- a/ruby/lib/jam_ruby.rb +++ b/ruby/lib/jam_ruby.rb @@ -114,6 +114,8 @@ require "jam_ruby/models/machine_extra" require "jam_ruby/models/download_tracker" require "jam_ruby/models/ip_blacklist" require "jam_ruby/models/user_blacklist" +require "jam_ruby/models/ip_whitelist" +require "jam_ruby/models/user_whitelist" require "jam_ruby/models/fraud_alert" require "jam_ruby/models/fingerprint_whitelist" require "jam_ruby/models/review" diff --git a/ruby/lib/jam_ruby/models/download_tracker.rb b/ruby/lib/jam_ruby/models/download_tracker.rb index 05d6b107e..19e416a81 100644 --- a/ruby/lib/jam_ruby/models/download_tracker.rb +++ b/ruby/lib/jam_ruby/models/download_tracker.rb @@ -36,13 +36,16 @@ module JamRuby def self.check(user, remote_ip, target, owned, fingerprint, is_client) - return false unless APP_CONFIG.guard_against_browser_fraud + return false if user.admin + + return false if UserWhitelist.listed(user) + create(user, remote_ip, target, owned, fingerprint, is_client) # let's check the following - blacklisted = alert_freebies_snarfer(remote_ip) + blacklisted = alert_freebies_snarfer(remote_ip, owned) alert_user_sharer(user) @@ -96,9 +99,16 @@ module JamRuby end end - def self.alert_freebies_snarfer(remote_ip) + def self.alert_freebies_snarfer(remote_ip, owned) + + if owned + return false + end + + if !IpWhitelist.listed(remote_ip) + violation = check_freebie_snarfer(APP_CONFIG.max_multiple_users_same_ip, remote_ip).first + end - violation = check_freebie_snarfer(APP_CONFIG.max_multiple_users_same_ip, remote_ip).first if violation body = "IP Address: #{remote_ip}\n" diff --git a/ruby/lib/jam_ruby/models/ip_blacklist.rb b/ruby/lib/jam_ruby/models/ip_blacklist.rb index a7099cba8..021427cf0 100644 --- a/ruby/lib/jam_ruby/models/ip_blacklist.rb +++ b/ruby/lib/jam_ruby/models/ip_blacklist.rb @@ -5,10 +5,14 @@ module JamRuby @@log = Logging.logger[IpBlacklist] - validates :remote_ip, presence:true, uniqueness:true + validates :remote_ip, presence: true, uniqueness: true + + def self.banned(remote_ip) + IpBlacklist.count(:conditions => "remote_ip = '#{remote_ip}' AND remote_ip not in (select remote_ip from ip_whitelists where remote_ip = '#{remote_ip}')") == 1 + end def self.listed(remote_ip) - IpBlacklist.count(:conditions => "remote_ip = '#{remote_ip}'") == 1 + IpBlacklist.where(:conditions => "remote_ip = '#{remote_ip}'") == 1 end def self.admin_url diff --git a/ruby/lib/jam_ruby/models/ip_whitelist.rb b/ruby/lib/jam_ruby/models/ip_whitelist.rb new file mode 100644 index 000000000..e4d1ed15e --- /dev/null +++ b/ruby/lib/jam_ruby/models/ip_whitelist.rb @@ -0,0 +1,30 @@ +module JamRuby + class IpWhitelist< ActiveRecord::Base + + attr_accessible :remote_ip, :notes, as: :admin + + @@log = Logging.logger[IpWhitelist] + + validates :remote_ip, presence:true, uniqueness:true + + def self.listed(remote_ip) + IpWhitelist.count(:conditions => "remote_ip = '#{remote_ip}'") == 1 + end + + def self.admin_url + APP_CONFIG.admin_root_url + "/admin/ip_whitelists/" + end + + def self.admin_activity_url(remote_ip) + APP_CONFIG.admin_root_url + "/admin/download_trackers?q[remote_ip_equals]=#{URI.escape(remote_ip)}&commit=Filter&order=id_desc" + end + + def admin_url + APP_CONFIG.admin_root_url + "/admin/ip_whitelists/" + id + end + + def to_s + remote_ip + end + end +end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/user_blacklist.rb b/ruby/lib/jam_ruby/models/user_blacklist.rb index 287ae5391..a0738edd0 100644 --- a/ruby/lib/jam_ruby/models/user_blacklist.rb +++ b/ruby/lib/jam_ruby/models/user_blacklist.rb @@ -6,7 +6,13 @@ module JamRuby belongs_to :user, :class_name => "JamRuby::User" - validates :user, presence:true, uniqueness: true + validates :user, presence: true + + validates_uniqueness_of :user_id + + def self.banned(user) + UserBlacklist.count(:conditions => "user_id = '#{user.id}' AND user_id not in (select user_id from user_whitelists where user_id = '#{user.id}')") == 1 + end def self.listed(user) UserBlacklist.count(:conditions => "user_id= '#{user.id}'") == 1 diff --git a/ruby/lib/jam_ruby/models/user_whitelist.rb b/ruby/lib/jam_ruby/models/user_whitelist.rb new file mode 100644 index 000000000..17ed1e68c --- /dev/null +++ b/ruby/lib/jam_ruby/models/user_whitelist.rb @@ -0,0 +1,29 @@ +module JamRuby + class UserWhitelist < ActiveRecord::Base + + attr_accessible :user_id, :notes, as: :admin + @@log = Logging.logger[UserWhitelist] + + belongs_to :user, :class_name => "JamRuby::User" + + validates :user, presence:true + + validates_uniqueness_of :user_id + + def self.listed(user) + UserWhitelist.count(:conditions => "user_id= '#{user.id}'") == 1 + end + + def self.admin_url + APP_CONFIG.admin_root_url + "/admin/user_whitelists/" + end + + def admin_url + APP_CONFIG.admin_root_url + "/admin/user_whitelists/" + id + end + + def to_s + user + end + end +end \ No newline at end of file diff --git a/ruby/spec/factories.rb b/ruby/spec/factories.rb index eb629c4de..5233c4b7b 100644 --- a/ruby/spec/factories.rb +++ b/ruby/spec/factories.rb @@ -906,5 +906,21 @@ FactoryGirl.define do sequence(:sibling_client_id ) { |n| "sibling_client_id#{n}" } sequence(:sibling_key ) { |n| "sibling_key#{n}" } end + + factory :ip_blacklist, class: "JamRuby::IpBlacklist" do + remote_ip '1.1.1.1' + end + + factory :ip_whitelist, class: "JamRuby::IpWhitelist" do + remote_ip '1.1.1.1' + end + + factory :user_blacklist, class: "JamRuby::UserBlacklist" do + association :user, factory: :user + end + + factory :user_whitelist, class: "JamRuby::UserWhitelist" do + association :user, factory: :user + end end diff --git a/ruby/spec/jam_ruby/models/ip_blacklist_spec.rb b/ruby/spec/jam_ruby/models/ip_blacklist_spec.rb new file mode 100644 index 000000000..4f0416c30 --- /dev/null +++ b/ruby/spec/jam_ruby/models/ip_blacklist_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe IpBlacklist do + + describe "#banned" do + it "returns false if no ban" do + IpBlacklist.banned('1.1.1.1').should eq false + end + + it "returns true if banned" do + FactoryGirl.create(:ip_blacklist, remote_ip: "1.1.1.1") + IpBlacklist.banned('1.1.1.1').should eq true + end + + it "returns false if whitelisted" do + FactoryGirl.create(:ip_whitelist, remote_ip: "1.1.1.1") + IpBlacklist.banned('1.1.1.1').should eq false + end + + + it "returns false if whitelisted and blacklisted too" do + FactoryGirl.create(:ip_blacklist, remote_ip: "1.1.1.1") + FactoryGirl.create(:ip_whitelist, remote_ip: "1.1.1.1") + IpBlacklist.banned('1.1.1.1').should eq false + end + end +end \ No newline at end of file diff --git a/ruby/spec/jam_ruby/models/user_blacklist_spec.rb b/ruby/spec/jam_ruby/models/user_blacklist_spec.rb new file mode 100644 index 000000000..48668d123 --- /dev/null +++ b/ruby/spec/jam_ruby/models/user_blacklist_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe UserBlacklist do + + let(:user) { FactoryGirl.create(:user) } + + describe "#banned" do + it "returns false if no ban" do + UserBlacklist.banned(user).should eq false + end + + it "returns true if banned" do + FactoryGirl.create(:user_blacklist, user: user) + UserBlacklist.banned(user).should eq true + end + + it "returns false if whitelisted" do + FactoryGirl.create(:user_whitelist, user: user) + UserBlacklist.banned(user).should eq false + end + + + it "returns false if whitelisted and blacklisted too" do + FactoryGirl.create(:user_blacklist, user: user) + FactoryGirl.create(:user_whitelist, user: user) + UserBlacklist.banned(user).should eq false + end + end +end \ No newline at end of file diff --git a/web/app/helpers/sessions_helper.rb b/web/app/helpers/sessions_helper.rb index ce11a8abb..831659613 100644 --- a/web/app/helpers/sessions_helper.rb +++ b/web/app/helpers/sessions_helper.rb @@ -140,14 +140,30 @@ module SessionsHelper end def ip_blacklist - if IpBlacklist.listed(request.remote_ip) + if current_user && current_user.admin + return + end + + if @jam_track_right && !@jam_track_right.redeemed + return + end + + if IpBlacklist.banned(request.remote_ip) && (current_user && !UserWhitelist.listed(current_user)) Stats.write('web.blacklist.ip', {value: 1, remote_ip: request.remote_ip}) render :json => { :message => "IP blacklisted"}, :status => 403 end end def user_blacklist - if UserBlacklist.listed(current_user) + if current_user && current_user.admin + return + end + + if @jam_track_right && !@jam_track_right.redeemed + return + end + + if UserBlacklist.banned(current_user) Stats.write('web.blacklist.user', {value: 1, user_id: current_user.id}) render :json => { :message => "User blacklisted"}, :status => 403 end