Merge branch 'main' of https://github.com/glitch-soc/mastodon into main
commit
ecc8e19071
1055 changed files with 31110 additions and 15962 deletions
@ -0,0 +1,7 @@ |
||||
[production] |
||||
defaults |
||||
not IE 11 |
||||
not dead |
||||
|
||||
[development] |
||||
supports es6-module |
@ -0,0 +1,21 @@ |
||||
{ |
||||
"problemMatcher": [ |
||||
{ |
||||
"owner": "stylelint", |
||||
"pattern": [ |
||||
{ |
||||
"regexp": "^([^\\s].*)$", |
||||
"file": 1 |
||||
}, |
||||
{ |
||||
"regexp": "^\\s+((\\d+):(\\d+))?\\s+(✖|×)\\s+(.*)\\s{2,}(.*)$", |
||||
"line": 2, |
||||
"column": 3, |
||||
"message": 5, |
||||
"code": 6, |
||||
"loop": true |
||||
} |
||||
] |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,83 @@ |
||||
--- |
||||
################################# |
||||
################################# |
||||
## Super Linter GitHub Actions ## |
||||
################################# |
||||
################################# |
||||
name: Lint Code Base |
||||
|
||||
# |
||||
# Documentation: |
||||
# https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions |
||||
# |
||||
|
||||
############################# |
||||
# Start the job on all push # |
||||
############################# |
||||
on: |
||||
push: |
||||
branches-ignore: [main] |
||||
# Remove the line above to run when pushing to master |
||||
pull_request: |
||||
branches: [main] |
||||
|
||||
############### |
||||
# Set the Job # |
||||
############### |
||||
permissions: |
||||
checks: write |
||||
contents: read |
||||
pull-requests: write |
||||
statuses: write |
||||
|
||||
jobs: |
||||
build: |
||||
# Name the Job |
||||
name: Lint Code Base |
||||
# Set the agent to run on |
||||
runs-on: ubuntu-latest |
||||
|
||||
################## |
||||
# Load all steps # |
||||
################## |
||||
steps: |
||||
########################## |
||||
# Checkout the code base # |
||||
########################## |
||||
- name: Checkout Code |
||||
uses: actions/checkout@v3 |
||||
with: |
||||
# Full git history is needed to get a proper list of changed files within `super-linter` |
||||
fetch-depth: 0 |
||||
|
||||
- name: Set-up Node.js |
||||
uses: actions/setup-node@v3 |
||||
with: |
||||
node-version: 16.x |
||||
cache: yarn |
||||
- name: Intall dependencies |
||||
run: yarn install --frozen-lockfile |
||||
- name: Set-up RuboCop Problem Mathcher |
||||
uses: r7kamura/rubocop-problem-matchers-action@v1 |
||||
- name: Set-up Stylelint Problem Matcher |
||||
uses: xt0rted/stylelint-problem-matcher@v1 |
||||
# https://github.com/xt0rted/stylelint-problem-matcher/issues/360 |
||||
- run: echo "::add-matcher::.github/stylelint-matcher.json" |
||||
|
||||
################################ |
||||
# Run Linter against code base # |
||||
################################ |
||||
- name: Lint Code Base |
||||
uses: github/super-linter@v4 |
||||
env: |
||||
CSS_FILE_NAME: stylelint.config.js |
||||
DEFAULT_BRANCH: main |
||||
NO_COLOR: 1 # https://github.com/xt0rted/stylelint-problem-matcher/issues/360 |
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
||||
JAVASCRIPT_ES_CONFIG_FILE: .eslintrc.js |
||||
LINTER_RULES_PATH: . |
||||
RUBY_CONFIG_FILE: .rubocop.yml |
||||
VALIDATE_ALL_CODEBASE: false |
||||
VALIDATE_CSS: true |
||||
VALIDATE_JAVASCRIPT_ES: true |
||||
VALIDATE_RUBY: true |
@ -1,37 +0,0 @@ |
||||
# Linter Documentation: |
||||
# https://github.com/sasstools/sass-lint/tree/v1.13.1/docs/options |
||||
|
||||
files: |
||||
include: app/javascript/styles/**/*.scss |
||||
ignore: |
||||
- app/javascript/styles/mastodon/reset.scss |
||||
|
||||
rules: |
||||
# Disallows |
||||
no-color-literals: 0 |
||||
no-css-comments: 0 |
||||
no-duplicate-properties: 0 |
||||
no-ids: 0 |
||||
no-important: 0 |
||||
no-mergeable-selectors: 0 |
||||
no-misspelled-properties: 0 |
||||
no-qualifying-elements: 0 |
||||
no-transition-all: 0 |
||||
no-vendor-prefixes: 0 |
||||
|
||||
# Nesting |
||||
force-element-nesting: 0 |
||||
force-attribute-nesting: 0 |
||||
force-pseudo-nesting: 0 |
||||
|
||||
# Name Formats |
||||
class-name-format: 0 |
||||
leading-zero: 0 |
||||
|
||||
# Style Guide |
||||
attribute-quotes: 0 |
||||
hex-length: 0 |
||||
indentation: 0 |
||||
nesting-depth: 0 |
||||
property-sort-order: 0 |
||||
quotes: 0 |
@ -0,0 +1,60 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
require 'csv' |
||||
|
||||
module Admin |
||||
class ExportDomainAllowsController < BaseController |
||||
include AdminExportControllerConcern |
||||
|
||||
before_action :set_dummy_import!, only: [:new] |
||||
|
||||
ROWS_PROCESSING_LIMIT = 20_000 |
||||
|
||||
def new |
||||
authorize :domain_allow, :create? |
||||
end |
||||
|
||||
def export |
||||
authorize :instance, :index? |
||||
send_export_file |
||||
end |
||||
|
||||
def import |
||||
authorize :domain_allow, :create? |
||||
begin |
||||
@import = Admin::Import.new(import_params) |
||||
parse_import_data!(export_headers) |
||||
|
||||
@data.take(ROWS_PROCESSING_LIMIT).each do |row| |
||||
domain = row['#domain'].strip |
||||
next if DomainAllow.allowed?(domain) |
||||
|
||||
domain_allow = DomainAllow.new(domain: domain) |
||||
log_action :create, domain_allow if domain_allow.save |
||||
end |
||||
flash[:notice] = I18n.t('admin.domain_allows.created_msg') |
||||
rescue ActionController::ParameterMissing |
||||
flash[:error] = I18n.t('admin.export_domain_allows.no_file') |
||||
end |
||||
redirect_to admin_instances_path |
||||
end |
||||
|
||||
private |
||||
|
||||
def export_filename |
||||
'domain_allows.csv' |
||||
end |
||||
|
||||
def export_headers |
||||
%w(#domain) |
||||
end |
||||
|
||||
def export_data |
||||
CSV.generate(headers: export_headers, write_headers: true) do |content| |
||||
DomainAllow.allowed_domains.each do |instance| |
||||
content << [instance.domain] |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,71 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
require 'csv' |
||||
|
||||
module Admin |
||||
class ExportDomainBlocksController < BaseController |
||||
include AdminExportControllerConcern |
||||
|
||||
before_action :set_dummy_import!, only: [:new] |
||||
|
||||
ROWS_PROCESSING_LIMIT = 20_000 |
||||
|
||||
def new |
||||
authorize :domain_block, :create? |
||||
end |
||||
|
||||
def export |
||||
authorize :instance, :index? |
||||
send_export_file |
||||
end |
||||
|
||||
def import |
||||
authorize :domain_block, :create? |
||||
|
||||
@import = Admin::Import.new(import_params) |
||||
parse_import_data!(export_headers) |
||||
|
||||
@global_private_comment = I18n.t('admin.export_domain_blocks.import.private_comment_template', source: @import.data_file_name, date: I18n.l(Time.now.utc)) |
||||
|
||||
@form = Form::DomainBlockBatch.new |
||||
@domain_blocks = @data.take(ROWS_PROCESSING_LIMIT).filter_map do |row| |
||||
domain = row['#domain'].strip |
||||
next if DomainBlock.rule_for(domain).present? |
||||
|
||||
domain_block = DomainBlock.new(domain: domain, |
||||
severity: row['#severity'].strip, |
||||
reject_media: row['#reject_media'].strip, |
||||
reject_reports: row['#reject_reports'].strip, |
||||
private_comment: @global_private_comment, |
||||
public_comment: row['#public_comment']&.strip, |
||||
obfuscate: row['#obfuscate'].strip) |
||||
|
||||
domain_block if domain_block.valid? |
||||
end |
||||
|
||||
@warning_domains = Instance.where(domain: @domain_blocks.map(&:domain)).where('EXISTS (SELECT 1 FROM follows JOIN accounts ON follows.account_id = accounts.id OR follows.target_account_id = accounts.id WHERE accounts.domain = instances.domain)').pluck(:domain) |
||||
rescue ActionController::ParameterMissing |
||||
flash.now[:alert] = I18n.t('admin.export_domain_blocks.no_file') |
||||
set_dummy_import! |
||||
render :new |
||||
end |
||||
|
||||
private |
||||
|
||||
def export_filename |
||||
'domain_blocks.csv' |
||||
end |
||||
|
||||
def export_headers |
||||
%w(#domain #severity #reject_media #reject_reports #public_comment #obfuscate) |
||||
end |
||||
|
||||
def export_data |
||||
CSV.generate(headers: export_headers, write_headers: true) do |content| |
||||
DomainBlock.with_user_facing_limitations.each do |instance| |
||||
content << [instance.domain, instance.severity, instance.reject_media, instance.reject_reports, instance.public_comment, instance.obfuscate] |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -1,27 +0,0 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
module Admin |
||||
class SignInTokenAuthenticationsController < BaseController |
||||
before_action :set_target_user |
||||
|
||||
def create |
||||
authorize @user, :enable_sign_in_token_auth? |
||||
@user.update(skip_sign_in_token: false) |
||||
log_action :enable_sign_in_token_auth, @user |
||||
redirect_to admin_account_path(@user.account_id) |
||||
end |
||||
|
||||
def destroy |
||||
authorize @user, :disable_sign_in_token_auth? |
||||
@user.update(skip_sign_in_token: true) |
||||
log_action :disable_sign_in_token_auth, @user |
||||
redirect_to admin_account_path(@user.account_id) |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_target_user |
||||
@user = User.find(params[:user_id]) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,19 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
module Admin |
||||
class Webhooks::SecretsController < BaseController |
||||
before_action :set_webhook |
||||
|
||||
def rotate |
||||
authorize @webhook, :rotate_secret? |
||||
@webhook.rotate_secret! |
||||
redirect_to admin_webhook_path(@webhook) |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_webhook |
||||
@webhook = Webhook.find(params[:webhook_id]) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,77 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
module Admin |
||||
class WebhooksController < BaseController |
||||
before_action :set_webhook, except: [:index, :new, :create] |
||||
|
||||
def index |
||||
authorize :webhook, :index? |
||||
|
||||
@webhooks = Webhook.page(params[:page]) |
||||
end |
||||
|
||||
def new |
||||
authorize :webhook, :create? |
||||
|
||||
@webhook = Webhook.new |
||||
end |
||||
|
||||
def create |
||||
authorize :webhook, :create? |
||||
|
||||
@webhook = Webhook.new(resource_params) |
||||
|
||||
if @webhook.save |
||||
redirect_to admin_webhook_path(@webhook) |
||||
else |
||||
render :new |
||||
end |
||||
end |
||||
|
||||
def show |
||||
authorize @webhook, :show? |
||||
end |
||||
|
||||
def edit |
||||
authorize @webhook, :update? |
||||
end |
||||
|
||||
def update |
||||
authorize @webhook, :update? |
||||
|
||||
if @webhook.update(resource_params) |
||||
redirect_to admin_webhook_path(@webhook) |
||||
else |
||||
render :show |
||||
end |
||||
end |
||||
|
||||
def enable |
||||
authorize @webhook, :enable? |
||||
@webhook.enable! |
||||
redirect_to admin_webhook_path(@webhook) |
||||
end |
||||
|
||||
def disable |
||||
authorize @webhook, :disable? |
||||
@webhook.disable! |
||||
redirect_to admin_webhook_path(@webhook) |
||||
end |
||||
|
||||
def destroy |
||||
authorize @webhook, :destroy? |
||||
@webhook.destroy! |
||||
redirect_to admin_webhooks_path |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_webhook |
||||
@webhook = Webhook.find(params[:id]) |
||||
end |
||||
|
||||
def resource_params |
||||
params.require(:webhook).permit(:url, events: []) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,95 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::DomainAllowsController < Api::BaseController |
||||
include Authorization |
||||
include AccountableConcern |
||||
|
||||
LIMIT = 100 |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_allows' }, only: [:index, :show] |
||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_allows' }, except: [:index, :show] |
||||
before_action :require_staff! |
||||
before_action :set_domain_allows, only: :index |
||||
before_action :set_domain_allow, only: [:show, :destroy] |
||||
|
||||
after_action :insert_pagination_headers, only: :index |
||||
|
||||
PAGINATION_PARAMS = %i(limit).freeze |
||||
|
||||
def create |
||||
authorize :domain_allow, :create? |
||||
|
||||
@domain_allow = DomainAllow.find_by(resource_params) |
||||
|
||||
if @domain_allow.nil? |
||||
@domain_allow = DomainAllow.create!(resource_params) |
||||
log_action :create, @domain_allow |
||||
end |
||||
|
||||
render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer |
||||
end |
||||
|
||||
def index |
||||
authorize :domain_allow, :index? |
||||
render json: @domain_allows, each_serializer: REST::Admin::DomainAllowSerializer |
||||
end |
||||
|
||||
def show |
||||
authorize @domain_allow, :show? |
||||
render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer |
||||
end |
||||
|
||||
def destroy |
||||
authorize @domain_allow, :destroy? |
||||
UnallowDomainService.new.call(@domain_allow) |
||||
log_action :destroy, @domain_allow |
||||
render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_domain_allows |
||||
@domain_allows = filtered_domain_allows.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) |
||||
end |
||||
|
||||
def set_domain_allow |
||||
@domain_allow = DomainAllow.find(params[:id]) |
||||
end |
||||
|
||||
def filtered_domain_allows |
||||
# TODO: no filtering yet |
||||
DomainAllow.all |
||||
end |
||||
|
||||
def insert_pagination_headers |
||||
set_pagination_headers(next_path, prev_path) |
||||
end |
||||
|
||||
def next_path |
||||
api_v1_admin_domain_allows_url(pagination_params(max_id: pagination_max_id)) if records_continue? |
||||
end |
||||
|
||||
def prev_path |
||||
api_v1_admin_domain_allows_url(pagination_params(min_id: pagination_since_id)) unless @domain_allows.empty? |
||||
end |
||||
|
||||
def pagination_max_id |
||||
@domain_allows.last.id |
||||
end |
||||
|
||||
def pagination_since_id |
||||
@domain_allows.first.id |
||||
end |
||||
|
||||
def records_continue? |
||||
@domain_allows.size == limit_param(LIMIT) |
||||
end |
||||
|
||||
def pagination_params(core_params) |
||||
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params) |
||||
end |
||||
|
||||
def resource_params |
||||
params.permit(:domain) |
||||
end |
||||
end |
@ -0,0 +1,109 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Admin::DomainBlocksController < Api::BaseController |
||||
include Authorization |
||||
include AccountableConcern |
||||
|
||||
LIMIT = 100 |
||||
|
||||
before_action -> { authorize_if_got_token! :'admin:read', :'admin:read:domain_blocks' }, only: [:index, :show] |
||||
before_action -> { authorize_if_got_token! :'admin:write', :'admin:write:domain_blocks' }, except: [:index, :show] |
||||
before_action :require_staff! |
||||
before_action :set_domain_blocks, only: :index |
||||
before_action :set_domain_block, only: [:show, :update, :destroy] |
||||
|
||||
after_action :insert_pagination_headers, only: :index |
||||
|
||||
PAGINATION_PARAMS = %i(limit).freeze |
||||
|
||||
def create |
||||
authorize :domain_block, :create? |
||||
|
||||
existing_domain_block = resource_params[:domain].present? ? DomainBlock.rule_for(resource_params[:domain]) : nil |
||||
return render json: existing_domain_block, serializer: REST::Admin::ExistingDomainBlockErrorSerializer, status: 422 if existing_domain_block.present? |
||||
|
||||
@domain_block = DomainBlock.create!(resource_params) |
||||
DomainBlockWorker.perform_async(@domain_block.id) |
||||
log_action :create, @domain_block |
||||
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer |
||||
end |
||||
|
||||
def index |
||||
authorize :domain_block, :index? |
||||
render json: @domain_blocks, each_serializer: REST::Admin::DomainBlockSerializer |
||||
end |
||||
|
||||
def show |
||||
authorize @domain_block, :show? |
||||
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer |
||||
end |
||||
|
||||
def update |
||||
authorize @domain_block, :update? |
||||
|
||||
@domain_block.update(domain_block_params) |
||||
severity_changed = @domain_block.severity_changed? |
||||
@domain_block.save! |
||||
DomainBlockWorker.perform_async(@domain_block.id, severity_changed) |
||||
log_action :update, @domain_block |
||||
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer |
||||
end |
||||
|
||||
def destroy |
||||
authorize @domain_block, :destroy? |
||||
UnblockDomainService.new.call(@domain_block) |
||||
log_action :destroy, @domain_block |
||||
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_domain_blocks |
||||
@domain_blocks = filtered_domain_blocks.order(id: :desc).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id)) |
||||
end |
||||
|
||||
def set_domain_block |
||||
@domain_block = DomainBlock.find(params[:id]) |
||||
end |
||||
|
||||
def filtered_domain_blocks |
||||
# TODO: no filtering yet |
||||
DomainBlock.all |
||||
end |
||||
|
||||
def domain_block_params |
||||
params.permit(:severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate) |
||||
end |
||||
|
||||
def insert_pagination_headers |
||||
set_pagination_headers(next_path, prev_path) |
||||
end |
||||
|
||||
def next_path |
||||
api_v1_admin_domain_blocks_url(pagination_params(max_id: pagination_max_id)) if records_continue? |
||||
end |
||||
|
||||
def prev_path |
||||
api_v1_admin_domain_blocks_url(pagination_params(min_id: pagination_since_id)) unless @domain_blocks.empty? |
||||
end |
||||
|
||||
def pagination_max_id |
||||
@domain_blocks.last.id |
||||
end |
||||
|
||||
def pagination_since_id |
||||
@domain_blocks.first.id |
||||
end |
||||
|
||||
def records_continue? |
||||
@domain_blocks.size == limit_param(LIMIT) |
||||
end |
||||
|
||||
def pagination_params(core_params) |
||||
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params) |
||||
end |
||||
|
||||
def resource_params |
||||
params.permit(:domain, :severity, :reject_media, :reject_reports, :private_comment, :public_comment, :obfuscate) |
||||
end |
||||
end |
@ -0,0 +1,50 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V1::Filters::KeywordsController < Api::BaseController |
||||
before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show] |
||||
before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show] |
||||
before_action :require_user! |
||||
|
||||
before_action :set_keywords, only: :index |
||||
before_action :set_keyword, only: [:show, :update, :destroy] |
||||
|
||||
def index |
||||
render json: @keywords, each_serializer: REST::FilterKeywordSerializer |
||||
end |
||||
|
||||
def create |
||||
@keyword = current_account.custom_filters.find(params[:filter_id]).keywords.create!(resource_params) |
||||
|
||||
render json: @keyword, serializer: REST::FilterKeywordSerializer |
||||
end |
||||
|
||||
def show |
||||
render json: @keyword, serializer: REST::FilterKeywordSerializer |
||||
end |
||||
|
||||
def update |
||||
@keyword.update!(resource_params) |
||||
|
||||
render json: @keyword, serializer: REST::FilterKeywordSerializer |
||||
end |
||||
|
||||
def destroy |
||||
@keyword.destroy! |
||||
render_empty |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_keywords |
||||
filter = current_account.custom_filters.includes(:keywords).find(params[:filter_id]) |
||||
@keywords = filter.keywords |
||||
end |
||||
|
||||
def set_keyword |
||||
@keyword = CustomFilterKeyword.includes(:custom_filter).where(custom_filter: { account: current_account }).find(params[:id]) |
||||
end |
||||
|
||||
def resource_params |
||||
params.permit(:keyword, :whole_word) |
||||
end |
||||
end |
@ -0,0 +1,31 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController |
||||
FILTER_PARAMS = %i( |
||||
origin |
||||
status |
||||
permissions |
||||
username |
||||
by_domain |
||||
display_name |
||||
email |
||||
ip |
||||
invited_by |
||||
).freeze |
||||
|
||||
PAGINATION_PARAMS = (%i(limit) + FILTER_PARAMS).freeze |
||||
|
||||
private |
||||
|
||||
def filtered_accounts |
||||
AccountFilter.new(filter_params).results |
||||
end |
||||
|
||||
def filter_params |
||||
params.permit(*FILTER_PARAMS) |
||||
end |
||||
|
||||
def pagination_params(core_params) |
||||
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params) |
||||
end |
||||
end |
@ -0,0 +1,48 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
class Api::V2::FiltersController < Api::BaseController |
||||
before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show] |
||||
before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show] |
||||
before_action :require_user! |
||||
before_action :set_filters, only: :index |
||||
before_action :set_filter, only: [:show, :update, :destroy] |
||||
|
||||
def index |
||||
render json: @filters, each_serializer: REST::FilterSerializer, rules_requested: true |
||||
end |
||||
|
||||
def create |
||||
@filter = current_account.custom_filters.create!(resource_params) |
||||
|
||||
render json: @filter, serializer: REST::FilterSerializer, rules_requested: true |
||||
end |
||||
|
||||
def show |
||||
render json: @filter, serializer: REST::FilterSerializer, rules_requested: true |
||||
end |
||||
|
||||
def update |
||||
@filter.update!(resource_params) |
||||
|
||||
render json: @filter, serializer: REST::FilterSerializer, rules_requested: true |
||||
end |
||||
|
||||
def destroy |
||||
@filter.destroy! |
||||
render_empty |
||||
end |
||||
|
||||
private |
||||
|
||||
def set_filters |
||||
@filters = current_account.custom_filters.includes(:keywords) |
||||
end |
||||
|
||||
def set_filter |
||||
@filter = current_account.custom_filters.find(params[:id]) |
||||
end |
||||
|
||||
def resource_params |
||||
params.permit(:title, :expires_in, :filter_action, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy]) |
||||
end |
||||
end |
@ -0,0 +1,39 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
module AdminExportControllerConcern |
||||
extend ActiveSupport::Concern |
||||
|
||||
private |
||||
|
||||
def send_export_file |
||||
respond_to do |format| |
||||
format.csv { send_data export_data, filename: export_filename } |
||||
end |
||||
end |
||||
|
||||
def export_data |
||||
raise 'Override in controller' |
||||
end |
||||
|
||||
def export_filename |
||||
raise 'Override in controller' |
||||
end |
||||
|
||||
def set_dummy_import! |
||||
@import = Admin::Import.new |
||||
end |
||||
|
||||
def import_params |
||||
params.require(:admin_import).permit(:data) |
||||
end |
||||
|
||||
def import_data |
||||
Paperclip.io_adapters.for(@import.data).read |
||||
end |
||||
|
||||
def parse_import_data!(default_headers) |
||||
data = CSV.parse(import_data, headers: true) |
||||
data = CSV.parse(import_data, headers: default_headers) unless data.headers&.first&.strip&.include?(default_headers[0]) |
||||
@data = data.reject(&:blank?) |
||||
end |
||||
end |
@ -1,57 +0,0 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
module SignInTokenAuthenticationConcern |
||||
extend ActiveSupport::Concern |
||||
|
||||
included do |
||||
prepend_before_action :authenticate_with_sign_in_token, if: :sign_in_token_required?, only: [:create] |
||||
end |
||||
|
||||
def sign_in_token_required? |
||||
find_user&.suspicious_sign_in?(request.remote_ip) |
||||
end |
||||
|
||||
def valid_sign_in_token_attempt?(user) |
||||
Devise.secure_compare(user.sign_in_token, user_params[:sign_in_token_attempt]) |
||||
end |
||||
|
||||
def authenticate_with_sign_in_token |
||||
if user_params[:email].present? |
||||
user = self.resource = find_user_from_params |
||||
prompt_for_sign_in_token(user) if user&.external_or_valid_password?(user_params[:password]) |
||||
elsif session[:attempt_user_id] |
||||
user = self.resource = User.find_by(id: session[:attempt_user_id]) |
||||
return if user.nil? |
||||
|
||||
if session[:attempt_user_updated_at] != user.updated_at.to_s |
||||
restart_session |
||||
elsif user_params.key?(:sign_in_token_attempt) |
||||
authenticate_with_sign_in_token_attempt(user) |
||||
end |
||||
end |
||||
end |
||||
|
||||
def authenticate_with_sign_in_token_attempt(user) |
||||
if valid_sign_in_token_attempt?(user) |
||||
on_authentication_success(user, :sign_in_token) |
||||
else |
||||
on_authentication_failure(user, :sign_in_token, :invalid_sign_in_token) |
||||
flash.now[:alert] = I18n.t('users.invalid_sign_in_token') |
||||
prompt_for_sign_in_token(user) |
||||
end |
||||
end |
||||
|
||||
def prompt_for_sign_in_token(user) |
||||
if user.sign_in_token_expired? |
||||
user.generate_sign_in_token && user.save |
||||
UserMailer.sign_in_token(user, request.remote_ip, request.user_agent, Time.now.utc.to_s).deliver_later! |
||||
end |
||||
|
||||
set_attempt_session(user) |
||||
use_pack 'auth' |
||||
|
||||
@body_classes = 'lighter' |
||||
|
||||
set_locale { render :sign_in_token } |
||||
end |
||||
end |
@ -0,0 +1,37 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
module BrandingHelper |
||||
def logo_as_symbol(version = :icon) |
||||
case version |
||||
when :icon |
||||
_logo_as_symbol_icon |
||||
when :wordmark |
||||
_logo_as_symbol_wordmark |
||||
end |
||||
end |
||||
|
||||
def _logo_as_symbol_wordmark |
||||
content_tag(:svg, tag(:use, href: '#logo-symbol-wordmark'), viewBox: '0 0 261 66', class: 'logo logo--wordmark') |
||||
end |
||||
|
||||
def _logo_as_symbol_icon |
||||
content_tag(:svg, tag(:use, href: '#logo-symbol-icon'), viewBox: '0 0 79 79', class: 'logo logo--icon') |
||||
end |
||||
|
||||
def render_logo |
||||
image_pack_tag('logo.svg', alt: 'Mastodon', class: 'logo logo--icon') |
||||
end |
||||
|
||||
def render_symbol(version = :icon) |
||||
path = begin |
||||
case version |
||||
when :icon |
||||
'logo-symbol-icon.svg' |
||||
when :wordmark |
||||
'logo-symbol-wordmark.svg' |
||||
end |
||||
end |
||||
|
||||
render(file: Rails.root.join('app', 'javascript', 'images', path)).html_safe # rubocop:disable Rails/OutputSafety |
||||
end |
||||
end |
@ -0,0 +1,54 @@ |
||||
# frozen_string_literal: true |
||||
|
||||
module FormattingHelper |
||||
def html_aware_format(text, local, options = {}) |
||||
HtmlAwareFormatter.new(text, local, options).to_s |
||||
end |
||||
|
||||
def linkify(text, options = {}) |
||||
TextFormatter.new(text, options).to_s |
||||
end |
||||
|
||||
def extract_status_plain_text(status) |
||||
PlainTextFormatter.new(status.text, status.local?).to_s |
||||
end |
||||
module_function :extract_status_plain_text |
||||
|
||||
def status_content_format(status) |
||||
html_aware_format(status.text, status.local?, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []), content_type: status.content_type) |
||||
end |
||||
|
||||
def rss_status_content_format(status) |
||||
html = status_content_format(status) |
||||
|
||||
before_html = begin |
||||
if status.spoiler_text? |
||||
"<p><strong>#{I18n.t('rss.content_warning', locale: available_locale_or_nil(status.language) || I18n.default_locale)}</strong> #{h(status.spoiler_text)}</p><hr />" |
||||
else |
||||
'' |
||||
end |
||||
end.html_safe # rubocop:disable Rails/OutputSafety |
||||
|
||||
after_html = begin |
||||
if status.preloadable_poll |
||||
"<p>#{status.preloadable_poll.options.map { |o| "<input type=#{status.preloadable_poll.multiple? ? 'checkbox' : 'radio'} disabled /> #{h(o)}" }.join('<br />')}</p>" |
||||
else |
||||
'' |
||||
end |
||||
end.html_safe # rubocop:disable Rails/OutputSafety |
||||
|
||||
prerender_custom_emojis( |
||||
safe_join([before_html, html, after_html]), |
||||
status.emojis, |
||||
style: 'width: 1.1em; height: 1.1em; object-fit: contain; vertical-align: middle; margin: -.2ex .15em .2ex' |
||||
).to_str |
||||
end |
||||
|
||||
def account_bio_format(account) |
||||
html_aware_format(account.note, account.local?) |
||||
end |
||||
|
||||
def account_field_value_format(field, with_rel_me: true) |
||||
html_aware_format(field.value, field.account.local?, with_rel_me: with_rel_me, with_domains: true, multiline: false) |
||||
end |
||||
end |
@ -1,2 +0,0 @@ |
||||
module Settings::KeywordMutesHelper |
||||
end |
@ -1 +1,3 @@ |
||||
import 'styles/mailer.scss'; |
||||
require('../styles/mailer.scss'); |
||||
|
||||
require.context('../icons'); |
||||
|
@ -0,0 +1,12 @@ |
||||
import { saveSettings } from './settings'; |
||||
|
||||
export const LANGUAGE_USE = 'LANGUAGE_USE'; |
||||
|
||||
export const useLanguage = language => dispatch => { |
||||
dispatch({ |
||||
type: LANGUAGE_USE, |
||||
language, |
||||
}); |
||||
|
||||
dispatch(saveSettings()); |
||||
}; |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue