Skip to content

Commit

Permalink
Implement EmailBlackList (mastodon#5109)
Browse files Browse the repository at this point in the history
* Implement BlacklistedEmailDomain

* Use Faker::Internet.domain_name

* Remove note column

* Add frozen_string_literal comment

* Delete unnecessary codes

* Sort alphabetically

* Change of wording

* Rename BlacklistedEmailDomain to EmailDomainBlock
  • Loading branch information
utam0k authored and Gargron committed Oct 4, 2017
1 parent d509138 commit b3af3f9
Show file tree
Hide file tree
Showing 15 changed files with 207 additions and 1 deletion.
40 changes: 40 additions & 0 deletions app/controllers/admin/email_domain_blocks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module Admin
class EmailDomainBlocksController < BaseController
before_action :set_email_domain_block, only: [:show, :destroy]

def index
@email_domain_blocks = EmailDomainBlock.page(params[:page])
end

def new
@email_domain_block = EmailDomainBlock.new
end

def create
@email_domain_block = EmailDomainBlock.new(resource_params)

if @email_domain_block.save
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.created_msg')
else
render :new
end
end

def destroy
@email_domain_block.destroy
redirect_to admin_email_domain_blocks_path, notice: I18n.t('admin.email_domain_blocks.destroyed_msg')
end

private

def set_email_domain_block
@email_domain_block = EmailDomainBlock.find(params[:id])
end

def resource_params
params.require(:email_domain_block).permit(:domain)
end
end
end
17 changes: 17 additions & 0 deletions app/models/email_domain_block.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: email_domain_blocks
#
# id :integer not null, primary key
# domain :string not null
# created_at :datetime not null
# updated_at :datetime not null
#

class EmailDomainBlock < ApplicationRecord
def self.block?(email)
domain = email.gsub(/.+@([^.]+)/, '\1')
where(domain: domain).exists?
end
end
1 change: 1 addition & 0 deletions app/validators/blacklisted_email_validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def blocked_email?(value)
end

def on_blacklist?(value)
return true if EmailDomainBlock.block?(value)
return false if Rails.configuration.x.email_domains_blacklist.blank?

domains = Rails.configuration.x.email_domains_blacklist.gsub('.', '\.')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
%tr
%td.domain
%samp= email_domain_block.domain
%td
= table_link_to 'trash', t('admin.email_domain_blocks.delete'), admin_email_domain_block_path(email_domain_block), method: :delete
13 changes: 13 additions & 0 deletions app/views/admin/email_domain_blocks/index.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
- content_for :page_title do
= t('admin.email_domain_blocks.title')

%table.table
%thead
%tr
%th= t('admin.email_domain_blocks.domain')
%th
%tbody
= render @email_domain_blocks

= paginate @email_domain_blocks
= link_to t('admin.email_domain_blocks.add_new'), new_admin_email_domain_block_path, class: 'button'
10 changes: 10 additions & 0 deletions app/views/admin/email_domain_blocks/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- content_for :page_title do
= t('.title')

= simple_form_for @email_domain_block, url: admin_email_domain_blocks_path do |f|
= render 'shared/error_messages', object: @email_domain_block

= f.input :domain, placeholder: t('admin.email_domain_blocks.domain')

.actions
= f.button :button, t('.create'), type: :submit
10 changes: 10 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ en:
undo: Undo
title: Domain Blocks
undo: Undo
email_domain_blocks:
add_new: Add new
created_msg: Email domain block successfully created
delete: Delete
destroyed_msg: Email domain block successfully deleted
domain: Domain
new:
create: Create block
title: New email domain block
title: Email Domain Block
instances:
account_count: Known accounts
domain_name: Domain
Expand Down
10 changes: 10 additions & 0 deletions config/locales/ja.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ ja:
undo: 元に戻す
title: ドメインブロック
undo: 元に戻す
email_domain_blocks:
add_new: 新規追加
created_msg: 処理を完了しました
delete: 消去
destroyed_msg: 消去しました
domain: ドメイン
new:
create: ブロックを作成
title: 新規メールドメインブロック
title: メールドメインブロック
instances:
account_count: 既知のアカウント数
domain_name: ドメイン名
Expand Down
1 change: 1 addition & 0 deletions config/navigation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
admin.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url, highlights_on: %r{/admin/instances}
admin.item :subscriptions, safe_join([fa_icon('paper-plane-o fw'), t('admin.subscriptions.title')]), admin_subscriptions_url
admin.item :domain_blocks, safe_join([fa_icon('lock fw'), t('admin.domain_blocks.title')]), admin_domain_blocks_url, highlights_on: %r{/admin/domain_blocks}
admin.item :email_domain_blocks, safe_join([fa_icon('envelope fw'), t('admin.email_domain_blocks.title')]), admin_email_domain_blocks_url, highlights_on: %r{/admin/email_domain_blocks}
admin.item :sidekiq, safe_join([fa_icon('diamond fw'), 'Sidekiq']), sidekiq_url, link_html: { target: 'sidekiq' }
admin.item :pghero, safe_join([fa_icon('database fw'), 'PgHero']), pghero_url, link_html: { target: 'pghero' }
admin.item :settings, safe_join([fa_icon('cogs fw'), t('admin.settings.title')]), edit_admin_settings_url
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
namespace :admin do
resources :subscriptions, only: [:index]
resources :domain_blocks, only: [:index, :new, :create, :show, :destroy]
resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
resource :settings, only: [:edit, :update]

resources :instances, only: [:index] do
Expand Down
9 changes: 9 additions & 0 deletions db/migrate/20170928082043_create_email_domain_blocks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class CreateEmailDomainBlocks < ActiveRecord::Migration[5.1]
def change
create_table :email_domain_blocks do |t|
t.string :domain, null: false

t.timestamps
end
end
end
8 changes: 7 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20170927215609) do
ActiveRecord::Schema.define(version: 20170928082043) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -110,6 +110,12 @@
t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true
end

create_table "email_domain_blocks", force: :cascade do |t|
t.string "domain", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "favourites", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
Expand Down
59 changes: 59 additions & 0 deletions spec/controllers/admin/email_domain_blocks_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Admin::EmailDomainBlocksController, type: :controller do
render_views

before do
sign_in Fabricate(:user, admin: true), scope: :user
end

describe 'GET #index' do
around do |example|
default_per_page = EmailDomainBlock.default_per_page
EmailDomainBlock.paginates_per 1
example.run
EmailDomainBlock.paginates_per default_per_page
end

it 'renders email blacks' do
2.times { Fabricate(:email_domain_block) }

get :index, params: { page: 2 }

assigned = assigns(:email_domain_blocks)
expect(assigned.count).to eq 1
expect(assigned.klass).to be EmailDomainBlock
expect(response).to have_http_status(:success)
end
end

describe 'GET #new' do
it 'assigns a new email black' do
get :new

expect(assigns(:email_domain_block)).to be_instance_of(EmailDomainBlock)
expect(response).to have_http_status(:success)
end
end

describe 'POST #create' do
it 'blocks the domain when succeeded to save' do
post :create, params: { email_domain_block: { domain: 'example.com'} }

expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.created_msg')
expect(response).to redirect_to(admin_email_domain_blocks_path)
end
end

describe 'DELETE #destroy' do
it 'unblocks the domain' do
email_domain_block = Fabricate(:email_domain_block)
delete :destroy, params: { id: email_domain_block.id }

expect(flash[:notice]).to eq I18n.t('admin.email_domain_blocks.destroyed_msg')
expect(response).to redirect_to(admin_email_domain_blocks_path)
end
end
end
3 changes: 3 additions & 0 deletions spec/fabricators/email_domain_block_fabricator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fabricator(:email_domain_block) do
domain { sequence(:domain) { |i| "#{i}#{Faker::Internet.domain_name}" } }
end
21 changes: 21 additions & 0 deletions spec/models/email_domain_block_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require 'rails_helper'

RSpec.describe EmailDomainBlock, type: :model do
describe 'validations' do
it 'has a valid fabricator' do
email_domain_block = Fabricate.build(:email_domain_block)
expect(email_domain_block).to be_valid
end
end

describe 'block?' do
it 'returns true if the domain is registed' do
Fabricate(:email_domain_block, domain: 'example.com')
expect(EmailDomainBlock.block?('nyarn@example.com')).to eq true
end
it 'returns true if the domain is not registed' do
Fabricate(:email_domain_block, domain: 'domain')
expect(EmailDomainBlock.block?('example')).to eq false
end
end
end

0 comments on commit b3af3f9

Please sign in to comment.