From 84ea2dd62ed7b5db1a2b590a22140d0042052787 Mon Sep 17 00:00:00 2001 From: Adam Tanner Date: Sat, 1 Nov 2014 15:27:58 -0700 Subject: [PATCH] Allow projects to be blacklisted for tips. --- app/controllers/projects_controller.rb | 17 ++++++-- app/models/project.rb | 2 - app/views/projects/blacklisted.html.haml | 5 +++ config/blacklist.yml | 15 +++++++ config/initializers/blacklist.rb | 2 + config/locales/en.yml | 3 ++ lib/blacklist.rb | 42 ++++++++++++++++++++ spec/controllers/projects_controller_spec.rb | 21 ++++++++++ spec/lib/blacklist_spec.rb | 29 ++++++++++++++ spec/models/project_spec.rb | 2 +- 10 files changed, 132 insertions(+), 6 deletions(-) create mode 100644 app/views/projects/blacklisted.html.haml create mode 100644 config/blacklist.yml create mode 100644 config/initializers/blacklist.rb create mode 100644 lib/blacklist.rb create mode 100644 spec/lib/blacklist_spec.rb diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index ee02fbfa..b23115d7 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -6,14 +6,21 @@ class ProjectsController < ApplicationController def index @projects = Project.order(projects_order).page(params[:page]).per(30) + + # This will cause pages not to always include 30 results, but... oh well. + @projects = @projects.to_a.reject! {|p| BLACKLIST.include?(p.github_url) } end def search - if params[:query].present? && project = Project.find_or_create_by_url(params[:query]) + if params[:query].present? + if BLACKLIST.include?(params[:query]) + return render :blacklisted + end + + project = Project.find_or_create_by_url(params[:query]) redirect_to pretty_project_path(project) else - @projects = Project.search(params[:query].to_s).order(projects_order).page(params[:page]).per(30) - render :index + redirect_to :index end end @@ -31,6 +38,10 @@ def search end def show + if BLACKLIST.include?(@project.github_url) + return render :blacklisted + end + if @project.bitcoin_address.nil? uri = URI("https://blockchain.info/merchant/#{CONFIG["blockchain_info"]["guid"]}/new_address") params = { password: CONFIG["blockchain_info"]["password"], label:"#{@project.full_name}@tip4commit" } diff --git a/app/models/project.rb b/app/models/project.rb index 5affe082..0084d6e0 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -203,13 +203,11 @@ def check_tips_to_pay_against_avaiable_amount end def self.find_or_create_by_url project_url - project_name = project_url. gsub(/https?\:\/\/github.com\//, ''). gsub(/\#.+$/, ''). gsub(' ', '') Github.new.find_or_create_project project_name - end end diff --git a/app/views/projects/blacklisted.html.haml b/app/views/projects/blacklisted.html.haml new file mode 100644 index 00000000..095c0a8b --- /dev/null +++ b/app/views/projects/blacklisted.html.haml @@ -0,0 +1,5 @@ +%h1= t(".title") + +.row + .col-md-12 + .alert.alert-danger= t(".message") diff --git a/config/blacklist.yml b/config/blacklist.yml new file mode 100644 index 00000000..05eeddac --- /dev/null +++ b/config/blacklist.yml @@ -0,0 +1,15 @@ +- https://github.com/adamtanner/* +- https://github.com/f-list/* +- https://github.com/gae-init/gae-init +- https://github.com/ggreer/the_silver_searcher +- https://github.com/iros/* +- https://github.com/jsocol/* +- https://github.com/libretro/* +- https://github.com/lipis/* +- https://github.com/meowy/* +- https://github.com/misoproject/* +- https://github.com/mitsuhiko/* +- https://github.com/mplewis/* +- https://github.com/sczizzo/* +- https://github.com/tcrayford/* +- https://github.com/unitaker/* diff --git a/config/initializers/blacklist.rb b/config/initializers/blacklist.rb new file mode 100644 index 00000000..c1b09c04 --- /dev/null +++ b/config/initializers/blacklist.rb @@ -0,0 +1,2 @@ +# Load the blacklist. +BLACKLIST ||= Blacklist.new(YAML.load_file("config/blacklist.yml")) diff --git a/config/locales/en.yml b/config/locales/en.yml index a496ef53..82d2ef52 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -125,6 +125,9 @@ en: message: Message tip: Tip (relative to the project balance) submit: Send the selected tip amounts + blacklisted: + title: Sorry, this project doesn't accept tips! + message: The author of this project has chosen to disallow tips for this project. tips: index: tips: Tips diff --git a/lib/blacklist.rb b/lib/blacklist.rb new file mode 100644 index 00000000..c1ef8f2c --- /dev/null +++ b/lib/blacklist.rb @@ -0,0 +1,42 @@ +require "set" + +class Blacklist + def initialize(urls) + urls = urls.map {|u| normalize_url(u) } + + @urls = Set.new(urls) + end + + def include?(url) + url = normalize_url(url) + + if @urls.include?(url) + return true + end + + # Check for the author path. + # https://github.com/author/* + url[url.rindex("/")..-1] = "/*" + + @urls.include?(url) + end + + private + def normalize_url(url) + url = url.clone + + if !url.start_with?("http://", "https://", "//") + if !url.start_with?("github.com", "bitbucket.org") + # Assume it is a shortened "author/project" path and + # default to Github. + url.prepend("github.com/") + end + url.prepend("https://") + end + + uri = URI.parse(url) + + # Ignore irrelevant differences such as HTTP/HTTPS. + [uri.host, uri.path].join + end +end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 02c5bb9d..576e717d 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -7,6 +7,8 @@ allow(Project).to receive(:order).with(available_amount_cache: :desc, watchers_count: :desc, full_name: :asc).and_return(Project) allow(Project).to receive(:page).with(nil).and_return(Project) allow(Project).to receive(:per).with(30).and_return(Project) + allow(Project).to receive(:to_a).and_return(Project) + allow(Project).to receive(:reject!).and_return(Project) end it 'renders index template' do @@ -37,4 +39,23 @@ expect(assigns[:projects].name).to eq 'Project' end end + + describe '#search' do + let(:subject) { get :search, query: "https://github.com/mitsuhiko/flask" } + + it 'renders blacklisted template' do + expect(subject).to render_template :blacklisted + end + end + + describe '#show' do + context 'with existing project that has been blacklisted' do + let(:blacklisted_project) { create(:project, host: "github", full_name: "mitsuhiko/flask") } + let(:subject) { get :show, service: "github", repo: blacklisted_project.full_name } + + it 'renders blacklisted template' do + expect(subject).to render_template :blacklisted + end + end + end end diff --git a/spec/lib/blacklist_spec.rb b/spec/lib/blacklist_spec.rb new file mode 100644 index 00000000..08ab8d61 --- /dev/null +++ b/spec/lib/blacklist_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe Blacklist do + it 'handles blacklisted URLs' do + urls = [ + "https://github.com/author/notips", + "https://bitbucket.org/author/notips", + "https://github.com/notips/*", + "https://bitbucket.org/notips/*", + ] + + list = Blacklist.new(urls) + + # Blacklisted projects. + expect(list.include?("https://github.com/author/notips")).to eq(true) + expect(list.include?("http://github.com/author/notips?tips=true")).to eq(true) + expect(list.include?("https://bitbucket.org/author/notips")).to eq(true) + expect(list.include?("github.com/author/notips")).to eq(true) + expect(list.include?("author/notips")).to eq(true) + + # Non-blacklisted projects. + expect(list.include?("https://github.com/author/tipme")).to eq(false) + expect(list.include?("https://bitbucket.org/author/tipme")).to eq(false) + + # Blacklisted authors. + expect(list.include?("https://github.com/notips/tipme")).to eq(true) + expect(list.include?("https://bitbucket.org/notips/tipme")).to eq(true) + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index c1a604fb..594e378b 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -39,4 +39,4 @@ end end end -end \ No newline at end of file +end