Added LinkBlock functionality in admin

• Added:
- LinkBlock functionality in admin
This commit is contained in:
mgabdev 2020-12-08 23:19:10 -05:00
parent 95d326936b
commit c18991f174
16 changed files with 190 additions and 2 deletions

@ -0,0 +1,47 @@
# frozen_string_literal: true
module Admin
class LinkBlocksController < BaseController
before_action :set_link_block, only: [:show, :destroy]
def index
authorize :link_block, :index?
@link_blocks = LinkBlock.page(params[:page])
end
def new
authorize :link_block, :create?
@link_block = LinkBlock.new
end
def create
authorize :link_block, :create?
@link_block = LinkBlock.new(resource_params)
if @link_block.save
log_action :create, @link_block
redirect_to admin_link_blocks_path, notice: I18n.t('admin.link_blocks.created_msg')
else
render :new
end
end
def destroy
authorize @link_block, :destroy?
@link_block.destroy!
log_action :destroy, @link_block
redirect_to admin_link_blocks_path, notice: I18n.t('admin.link_blocks.destroyed_msg')
end
private
def set_link_block
@link_block = LinkBlock.find(params[:id])
end
def resource_params
params.require(:link_block).permit(:link)
end
end
end

@ -22,6 +22,12 @@ class TagManager
uri.normalized_host
end
def normalize_link(link)
return if link.nil?
uri = Addressable::URI.parse(link)
return "#{uri.normalized_host}#{uri.normalized_path}"
end
def same_acct?(canonical, needle)
return true if canonical.casecmp(needle).zero?
username, domain = needle.split('@')

@ -0,0 +1,15 @@
# frozen_string_literal: true
module LinkNormalizable
extend ActiveSupport::Concern
included do
before_validation :normalize_link
end
private
def normalize_link
self.link = TagManager.instance.normalize_link(link&.strip)
end
end

26
app/models/link_block.rb Normal file

@ -0,0 +1,26 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: link_blocks
#
# id :bigint(8) not null, primary key
# link :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
#
class LinkBlock < ApplicationRecord
include LinkNormalizable
validates :link, presence: true, uniqueness: true
def self.block?(text)
return false if text.nil?
return false if text.length < 1
urls = text.scan(FetchLinkCardService::URL_PATTERN).map { |array| Addressable::URI.parse(array[0]).normalize }
url = urls.first
link_for_fetch = TagManager.instance.normalize_link(url)
where(link: link_for_fetch).exists?
end
end

@ -0,0 +1,15 @@
# frozen_string_literal: true
class LinkBlockPolicy < ApplicationPolicy
def index?
admin?
end
def create?
admin?
end
def destroy?
admin?
end
end

@ -25,6 +25,7 @@ class EditStatusService < BaseService
return idempotency_duplicate if idempotency_given? && idempotency_duplicate?
validate_links!
validate_media!
preprocess_attributes!
revision_text = prepare_revision_text
@ -89,6 +90,10 @@ class EditStatusService < BaseService
raise GabSocial::ValidationError, I18n.t('media_attachments.validations.images_and_video') if @media.size > 1 && hasVideoOrGif
end
def validate_links!
raise GabSocial::NotPermittedError if LinkBlock.block?(@text)
end
def language_from_option(str)
ISO_639.find(str)&.alpha2
end

@ -34,6 +34,7 @@ class PostStatusService < BaseService
return idempotency_duplicate if idempotency_given? && idempotency_duplicate?
validate_links!
validate_media!
validate_group!
preprocess_attributes!
@ -98,7 +99,7 @@ class PostStatusService < BaseService
end
def postprocess_status!
LinkCrawlWorker.perform_async(@status.id) unless @status.spoiler_text?
LinkCrawlWorker.perform_async(@status.id)
DistributionWorker.perform_async(@status.id)
# Pubsubhubbub::DistributionWorker.perform_async(@status.stream_entry.id)
# ActivityPub::DistributionWorker.perform_async(@status.id)
@ -127,6 +128,10 @@ class PostStatusService < BaseService
raise GabSocial::ValidationError, I18n.t('media_attachments.validations.images_and_video') if @media.size > 1 && hasVideoOrGif
end
def validate_links!
raise GabSocial::NotPermittedError if LinkBlock.block?(@text)
end
def language_from_option(str)
ISO_639.find(str)&.alpha2
end

@ -0,0 +1,5 @@
%tr
%td
%samp= link_block.link
%td
= table_link_to 'trash', t('admin.link_blocks.delete'), admin_link_block_path(link_block), method: :delete

@ -0,0 +1,14 @@
- content_for :page_title do
= t('admin.link_blocks.title')
.table-wrapper
%table.table
%thead
%tr
%th= t('admin.link_blocks.link')
%th
%tbody
= render @link_blocks
= paginate @link_blocks
= link_to t('admin.link_blocks.add_new'), new_admin_link_block_path, class: 'button'

@ -0,0 +1,11 @@
- content_for :page_title do
= t('.title')
= simple_form_for @link_block, url: admin_link_blocks_path do |f|
= render 'shared/error_messages', object: @link_block
.fields-group
= f.input :link, wrapper: :with_label, label: t('admin.link_blocks.link')
.actions
= f.button :button, t('.create'), type: :submit

@ -325,6 +325,16 @@ en:
title: Undo domain block for %{domain}
undo: Undo
undo: Undo domain block
link_blocks:
add_new: Add new
created_msg: Successfully added link to blacklist
delete: Delete
destroyed_msg: Successfully deleted link from blacklist
link: Link
new:
create: Add link
title: New link blacklist entry
title: Link blacklist
email_domain_blocks:
add_new: Add new
created_msg: Successfully added e-mail domain to blacklist

@ -292,6 +292,16 @@ en_GB:
title: Undo domain block for %{domain}
undo: Undo
undo: Undo domain block
link_blocks:
add_new: Add new
created_msg: Successfully added link to blacklist
delete: Delete
destroyed_msg: Successfully deleted link from blacklist
link: Link
new:
create: Add link
title: New link blacklist entry
title: Link blacklist
email_domain_blocks:
add_new: Add new
created_msg: Successfully added e-mail domain to blacklist

@ -37,6 +37,7 @@ SimpleNavigation::Configuration.run do |navigation|
s.item :tags, safe_join([fa_icon('tag fw'), t('admin.tags.title')]), admin_tags_path
s.item :instances, safe_join([fa_icon('cloud fw'), t('admin.instances.title')]), admin_instances_url(limited: '1'), highlights_on: %r{/admin/instances|/admin/domain_blocks}, if: -> { current_user.admin? }
s.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}, if: -> { current_user.admin? }
s.item :link_blocks, safe_join([fa_icon('link fw'), t('admin.link_blocks.title')]), admin_link_blocks_url, highlights_on: %r{/admin/link_blocks}, if: -> { current_user.admin? }
end
n.item :admin, safe_join([fa_icon('cogs fw'), t('admin.title')]), admin_dashboard_url, if: proc { current_user.staff? } do |s|

@ -153,6 +153,7 @@ Rails.application.routes.draw do
resources :subscriptions, only: [:index]
resources :domain_blocks, only: [:new, :create, :show, :destroy]
resources :email_domain_blocks, only: [:index, :new, :create, :destroy]
resources :link_blocks, only: [:index, :new, :create, :destroy]
resources :action_logs, only: [:index]
resources :warning_presets, except: [:new]
resource :settings, only: [:edit, :update]

@ -0,0 +1,10 @@
class CreateLinkBlocks < ActiveRecord::Migration[5.2]
def change
create_table :link_blocks do |t|
t.string :link, null: false, default: ''
t.timestamps null: false
end
add_index :link_blocks, :link, unique: true
end
end

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2020_09_08_210104) do
ActiveRecord::Schema.define(version: 2020_12_06_060226) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
@ -432,6 +432,13 @@ ActiveRecord::Schema.define(version: 2020_09_08_210104) do
t.index ["user_id"], name: "index_invites_on_user_id"
end
create_table "link_blocks", force: :cascade do |t|
t.string "link", default: "", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["link"], name: "index_link_blocks_on_link", unique: true
end
create_table "list_accounts", force: :cascade do |t|
t.bigint "list_id", null: false
t.bigint "account_id", null: false