about summary refs log tree commit diff
diff options
context:
space:
mode:
authorutam0k <k0ma@utam0k.jp>2017-10-04 22:16:10 +0900
committerEugen Rochko <eugen@zeonfederated.com>2017-10-04 15:16:10 +0200
commitb3af3f9f8cd5ed9c7ee06452e981b1b7734e1d89 (patch)
tree8ea106d91d77f83a1c0b368d8657203c544e7eca
parentd5091387c6ddbe03b118b0cfb6d74cf821b84fb2 (diff)
Implement EmailBlackList (#5109)
* 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
-rw-r--r--app/controllers/admin/email_domain_blocks_controller.rb40
-rw-r--r--app/models/email_domain_block.rb17
-rw-r--r--app/validators/blacklisted_email_validator.rb1
-rw-r--r--app/views/admin/email_domain_blocks/_email_domain_block.html.haml5
-rw-r--r--app/views/admin/email_domain_blocks/index.html.haml13
-rw-r--r--app/views/admin/email_domain_blocks/new.html.haml10
-rw-r--r--config/locales/en.yml10
-rw-r--r--config/locales/ja.yml10
-rw-r--r--config/navigation.rb1
-rw-r--r--config/routes.rb1
-rw-r--r--db/migrate/20170928082043_create_email_domain_blocks.rb9
-rw-r--r--db/schema.rb8
-rw-r--r--spec/controllers/admin/email_domain_blocks_controller_spec.rb59
-rw-r--r--spec/fabricators/email_domain_block_fabricator.rb3
-rw-r--r--spec/models/email_domain_block_spec.rb21
15 files changed, 207 insertions, 1 deletions
diff --git a/app/controllers/admin/email_domain_blocks_controller.rb b/app/controllers/admin/email_domain_blocks_controller.rb
new file mode 100644
index 000000000..09275d5dc
--- /dev/null
+++ b/app/controllers/admin/email_domain_blocks_controller.rb
@@ -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
diff --git a/app/models/email_domain_block.rb b/app/models/email_domain_block.rb
new file mode 100644
index 000000000..839038bea
--- /dev/null
+++ b/app/models/email_domain_block.rb
@@ -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
diff --git a/app/validators/blacklisted_email_validator.rb b/app/validators/blacklisted_email_validator.rb
index 0ba79694b..3f203f49a 100644
--- a/app/validators/blacklisted_email_validator.rb
+++ b/app/validators/blacklisted_email_validator.rb
@@ -12,6 +12,7 @@ class BlacklistedEmailValidator < ActiveModel::Validator
   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('.', '\.')
diff --git a/app/views/admin/email_domain_blocks/_email_domain_block.html.haml b/app/views/admin/email_domain_blocks/_email_domain_block.html.haml
new file mode 100644
index 000000000..61cff9395
--- /dev/null
+++ b/app/views/admin/email_domain_blocks/_email_domain_block.html.haml
@@ -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
diff --git a/app/views/admin/email_domain_blocks/index.html.haml b/app/views/admin/email_domain_blocks/index.html.haml
new file mode 100644
index 000000000..fbdb3b80b
--- /dev/null
+++ b/app/views/admin/email_domain_blocks/index.html.haml
@@ -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'
diff --git a/app/views/admin/email_domain_blocks/new.html.haml b/app/views/admin/email_domain_blocks/new.html.haml
new file mode 100644
index 000000000..bcae867d9
--- /dev/null
+++ b/app/views/admin/email_domain_blocks/new.html.haml
@@ -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
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 4a6df8cb2..5d9557535 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -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
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index d637a99ea..3d6f2fd0b 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -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: ドメイン名
diff --git a/config/navigation.rb b/config/navigation.rb
index 215d843b9..50bfbd480 100644
--- a/config/navigation.rb
+++ b/config/navigation.rb
@@ -26,6 +26,7 @@ SimpleNavigation::Configuration.run do |navigation|
       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
diff --git a/config/routes.rb b/config/routes.rb
index 8e80e1510..959afc23f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -108,6 +108,7 @@ Rails.application.routes.draw do
   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
diff --git a/db/migrate/20170928082043_create_email_domain_blocks.rb b/db/migrate/20170928082043_create_email_domain_blocks.rb
new file mode 100644
index 000000000..1f0fb7587
--- /dev/null
+++ b/db/migrate/20170928082043_create_email_domain_blocks.rb
@@ -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
diff --git a/db/schema.rb b/db/schema.rb
index 00cc24bae..337678c67 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -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"
@@ -110,6 +110,12 @@ ActiveRecord::Schema.define(version: 20170927215609) do
     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
diff --git a/spec/controllers/admin/email_domain_blocks_controller_spec.rb b/spec/controllers/admin/email_domain_blocks_controller_spec.rb
new file mode 100644
index 000000000..295de9073
--- /dev/null
+++ b/spec/controllers/admin/email_domain_blocks_controller_spec.rb
@@ -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
diff --git a/spec/fabricators/email_domain_block_fabricator.rb b/spec/fabricators/email_domain_block_fabricator.rb
new file mode 100644
index 000000000..d18af6433
--- /dev/null
+++ b/spec/fabricators/email_domain_block_fabricator.rb
@@ -0,0 +1,3 @@
+Fabricator(:email_domain_block) do
+  domain { sequence(:domain) { |i| "#{i}#{Faker::Internet.domain_name}" } }
+end
diff --git a/spec/models/email_domain_block_spec.rb b/spec/models/email_domain_block_spec.rb
new file mode 100644
index 000000000..5f5d189d9
--- /dev/null
+++ b/spec/models/email_domain_block_spec.rb
@@ -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