1
0
Fork 0
forked from gitea/nas

Merge branch 'master' into master

This commit is contained in:
JantsoP 2017-04-04 08:41:46 +02:00 committed by GitHub
commit db4a41cf58
46 changed files with 565 additions and 75 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 59 KiB

Before After
Before After

View file

@ -43,7 +43,7 @@ const GettingStarted = ({ intl, me }) => {
<div className='scrollable optionally-scrollable' style={{ display: 'flex', flexDirection: 'column' }}>
<div className='static-content getting-started'>
<p><FormattedMessage id='getting_started.open_source_notice' defaultMessage='Mastodon is open source software. You can contribute or report issues on github at {github}. {apps}.' values={{ github: <a href="https://github.com/tootsuite/mastodon" target="_blank">tootsuite/mastodon</a>, apps: <a href="https://github.com/tootsuite/mastodon/blob/master/docs/Using-Mastodon/Apps.md" target="_blank"><FormattedMessage id='getting_started.apps' defaultMessage='Various apps are available' /></a> }} /></p>
<p><FormattedMessage id='getting_started.open_source_notice' defaultMessage='Mastodon is open source software. You can contribute or report issues on GitHub at {github}. {apps}.' values={{ github: <a href="https://github.com/tootsuite/mastodon" target="_blank">tootsuite/mastodon</a>, apps: <a href="https://github.com/tootsuite/mastodon/blob/master/docs/Using-Mastodon/Apps.md" target="_blank"><FormattedMessage id='getting_started.apps' defaultMessage='Various apps are available' /></a> }} /></p>
</div>
</div>
</Column>

View file

@ -25,7 +25,7 @@ const en = {
"getting_started.heading": "Getting started",
"getting_started.about_addressing": "You can follow people if you know their username and the domain they are on by entering an e-mail-esque address into the search form.",
"getting_started.about_shortcuts": "If the target user is on the same domain as you, just the username will work. The same rule applies to mentioning people in statuses.",
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on github at {github}. {apps}.",
"getting_started.open_source_notice": "Mastodon is open source software. You can contribute or report issues on GitHub at {github}. {apps}.",
"column.home": "Home",
"column.community": "Local timeline",
"column.public": "Federated timeline",

View file

@ -9,6 +9,24 @@ class Admin::DomainBlocksController < ApplicationController
@blocks = DomainBlock.paginate(page: params[:page], per_page: 40)
end
def new
@domain_block = DomainBlock.new
end
def create
@domain_block = DomainBlock.new(resource_params)
if @domain_block.save
DomainBlockWorker.perform_async(@domain_block.id)
redirect_to admin_domain_blocks_path, notice: 'Domain block is now being processed'
else
render action: :new
end
end
private
def resource_params
params.require(:domain_block).permit(:domain, :severity)
end
end

View file

@ -16,19 +16,19 @@ class Admin::ReportsController < ApplicationController
end
def resolve
@report.update(action_taken: true)
@report.update(action_taken: true, action_taken_by_account_id: current_account.id)
redirect_to admin_report_path(@report)
end
def suspend
Admin::SuspensionWorker.perform_async(@report.target_account.id)
@report.update(action_taken: true)
Report.unresolved.where(target_account: @report.target_account).update_all(action_taken: true, action_taken_by_account_id: current_account.id)
redirect_to admin_report_path(@report)
end
def silence
@report.target_account.update(silenced: true)
@report.update(action_taken: true)
Report.unresolved.where(target_account: @report.target_account).update_all(action_taken: true, action_taken_by_account_id: current_account.id)
redirect_to admin_report_path(@report)
end

View file

@ -4,6 +4,12 @@ class Api::V1::AppsController < ApiController
respond_to :json
def create
@app = Doorkeeper::Application.create!(name: params[:client_name], redirect_uri: params[:redirect_uris], scopes: (params[:scopes] || Doorkeeper.configuration.default_scopes), website: params[:website])
@app = Doorkeeper::Application.create!(name: app_params[:client_name], redirect_uri: app_params[:redirect_uris], scopes: (app_params[:scopes] || Doorkeeper.configuration.default_scopes), website: app_params[:website])
end
private
def app_params
params.permit(:client_name, :redirect_uris, :scopes, :website)
end
end

View file

@ -7,7 +7,7 @@ class Api::V1::FollowsController < ApiController
respond_to :json
def create
raise ActiveRecord::RecordNotFound if params[:uri].blank?
raise ActiveRecord::RecordNotFound if follow_params[:uri].blank?
@account = FollowService.new.call(current_user.account, target_uri).try(:target_account)
render action: :show
@ -16,6 +16,10 @@ class Api::V1::FollowsController < ApiController
private
def target_uri
params[:uri].strip.gsub(/\A@/, '')
follow_params[:uri].strip.gsub(/\A@/, '')
end
def follow_params
params.permit(:uri)
end
end

View file

@ -10,10 +10,16 @@ class Api::V1::MediaController < ApiController
respond_to :json
def create
@media = MediaAttachment.create!(account: current_user.account, file: params[:file])
@media = MediaAttachment.create!(account: current_user.account, file: media_params[:file])
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
render json: { error: 'File type of uploaded media could not be verified' }, status: 422
rescue Paperclip::Error
render json: { error: 'Error processing thumbnail for uploaded media' }, status: 500
end
private
def media_params
params.permit(:file)
end
end

View file

@ -12,13 +12,19 @@ class Api::V1::ReportsController < ApiController
end
def create
status_ids = params[:status_ids].is_a?(Enumerable) ? params[:status_ids] : [params[:status_ids]]
status_ids = report_params[:status_ids].is_a?(Enumerable) ? report_params[:status_ids] : [report_params[:status_ids]]
@report = Report.create!(account: current_account,
target_account: Account.find(params[:account_id]),
target_account: Account.find(report_params[:account_id]),
status_ids: Status.find(status_ids).pluck(:id),
comment: params[:comment])
comment: report_params[:comment])
render :show
end
private
def report_params
params.permit(:account_id, :comment, status_ids: [])
end
end

View file

@ -62,11 +62,11 @@ class Api::V1::StatusesController < ApiController
end
def create
@status = PostStatusService.new.call(current_user.account, params[:status], params[:in_reply_to_id].blank? ? nil : Status.find(params[:in_reply_to_id]), media_ids: params[:media_ids],
sensitive: params[:sensitive],
spoiler_text: params[:spoiler_text],
visibility: params[:visibility],
application: doorkeeper_token.application)
@status = PostStatusService.new.call(current_user.account, status_params[:status], status_params[:in_reply_to_id].blank? ? nil : Status.find(status_params[:in_reply_to_id]), media_ids: status_params[:media_ids],
sensitive: status_params[:sensitive],
spoiler_text: status_params[:spoiler_text],
visibility: status_params[:visibility],
application: doorkeeper_token.application)
render action: :show
end
@ -111,4 +111,8 @@ class Api::V1::StatusesController < ApiController
@status = Status.find(params[:id])
raise ActiveRecord::RecordNotFound unless @status.permitted?(current_account)
end
def status_params
params.permit(:status, :in_reply_to_id, :sensitive, :spoiler_text, :visibility, media_ids: [])
end
end

View file

@ -39,7 +39,14 @@ class ApplicationController < ActionController::Base
end
def set_user_activity
current_user.touch(:current_sign_in_at) if !current_user.nil? && (current_user.current_sign_in_at.nil? || current_user.current_sign_in_at < 24.hours.ago)
return unless !current_user.nil? && (current_user.current_sign_in_at.nil? || current_user.current_sign_in_at < 24.hours.ago)
# Mark user as signed-in today
current_user.update_tracked_fields(request)
# If the sign in is after a two week break, we need to regenerate their feed
RegenerationWorker.perform_async(current_user.account_id) if current_user.last_sign_in_at < 14.days.ago
return
end
def check_suspension

View file

@ -3,6 +3,7 @@
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
skip_before_action :authenticate_resource_owner!
before_action :set_locale
before_action :store_current_location
before_action :authenticate_resource_owner!
@ -11,4 +12,10 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
def store_current_location
store_location_for(:user, request.url)
end
def set_locale
I18n.locale = current_user.try(:locale) || I18n.default_locale
rescue I18n::InvalidLocale
I18n.locale = I18n.default_locale
end
end

View file

@ -4,4 +4,5 @@ module Mastodon
class Error < StandardError; end
class NotPermittedError < Error; end
class ValidationError < Error; end
class RaceConditionError < Error; end
end

View file

@ -10,17 +10,9 @@ class Feed
max_id = '+inf' if max_id.blank?
since_id = '-inf' if since_id.blank?
unhydrated = redis.zrevrangebyscore(key, "(#{max_id}", "(#{since_id}", limit: [0, limit], with_scores: true).map(&:last).map(&:to_i)
status_map = Status.where(id: unhydrated).cache_ids.map { |s| [s.id, s] }.to_h
# If we're after most recent items and none are there, we need to precompute the feed
if unhydrated.empty? && max_id == '+inf' && since_id == '-inf'
RegenerationWorker.perform_async(@account.id, @type)
@statuses = Status.send("as_#{@type}_timeline", @account).cache_ids.paginate_by_max_id(limit, nil, nil)
else
status_map = Status.where(id: unhydrated).cache_ids.map { |s| [s.id, s] }.to_h
@statuses = unhydrated.map { |id| status_map[id] }.compact
end
@statuses
unhydrated.map { |id| status_map[id] }.compact
end
private

View file

@ -3,6 +3,7 @@
class Report < ApplicationRecord
belongs_to :account
belongs_to :target_account, class_name: 'Account'
belongs_to :action_taken_by_account, class_name: 'Account'
scope :unresolved, -> { where(action_taken: false) }
scope :resolved, -> { where(action_taken: true) }

View file

@ -188,7 +188,7 @@ class Status < ApplicationRecord
end
before_validation do
text.strip!
text&.strip!
spoiler_text&.strip!
self.reply = !(in_reply_to_id.nil? && thread.nil?) unless reply

View file

@ -1,13 +1,11 @@
# frozen_string_literal: true
class BlockDomainService < BaseService
def call(domain, severity)
DomainBlock.where(domain: domain).first_or_create!(domain: domain, severity: severity)
if severity == :silence
Account.where(domain: domain).update_all(silenced: true)
def call(domain_block)
if domain_block.silence?
Account.where(domain: domain_block.domain).update_all(silenced: true)
else
Account.where(domain: domain).find_each do |account|
Account.where(domain: domain_block.domain).find_each do |account|
account.subscription(api_subscription_url(account.id)).unsubscribe if account.subscribed?
SuspendAccountService.new.call(account)
end

View file

@ -4,6 +4,8 @@ class FanOutOnWriteService < BaseService
# Push a status into home and mentions feeds
# @param [Status] status
def call(status)
raise Mastodon::RaceConditionError if status.visibility.nil?
deliver_to_self(status) if status.account.local?
if status.direct_visibility?

View file

@ -14,3 +14,4 @@
%td= block.severity
= will_paginate @blocks, pagination_options
= link_to 'Add new', new_admin_domain_block_path, class: 'button'

View file

@ -0,0 +1,18 @@
- content_for :page_title do
New domain block
= simple_form_for @domain_block, url: admin_domain_blocks_path do |f|
= render 'shared/error_messages', object: @domain_block
%p.hint The domain block will not prevent creation of account entries in the database, but will retroactively and automatically apply specific moderation methods on those accounts.
= f.input :domain, placeholder: 'Domain'
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false
%p.hint
%strong Silence
will make the account's posts invisible to anyone who isn't following them.
%strong Suspend
will remove all of the account's content, media, and profile data.
.actions
= f.button :button, 'Create block', type: :submit

View file

@ -8,20 +8,25 @@
%li= filter_link_to 'Unresolved', action_taken: nil
%li= filter_link_to 'Resolved', action_taken: '1'
%table.table
%thead
%tr
%th ID
%th Target
%th Reported by
%th Comment
%th
%tbody
- @reports.each do |report|
= form_tag do
%table.table
%thead
%tr
%td= "##{report.id}"
%td= link_to report.target_account.acct, admin_account_path(report.target_account.id)
%td= link_to report.account.acct, admin_account_path(report.account.id)
%td= truncate(report.comment, length: 30, separator: ' ')
%td= table_link_to 'circle', 'View', admin_report_path(report)
%th
%th ID
%th Target
%th Reported by
%th Comment
%th
%tbody
- @reports.each do |report|
%tr
%td= check_box_tag 'select', report.id
%td= "##{report.id}"
%td= link_to report.target_account.acct, admin_account_path(report.target_account.id)
%td= link_to report.account.acct, admin_account_path(report.account.id)
%td= truncate(report.comment, length: 30, separator: ' ')
%td= table_link_to 'circle', 'View', admin_report_path(report)
= will_paginate @reports, pagination_options

View file

@ -27,7 +27,7 @@
= link_to remove_admin_report_path(@report, status_id: status.id), method: :post, class: 'icon-button', style: 'font-size: 24px; width: 24px; height: 24px', title: 'Delete' do
= fa_icon 'trash'
- unless @report.action_taken?
- if !@report.action_taken?
%hr/
%div{ style: 'overflow: hidden' }
@ -36,3 +36,9 @@
= link_to 'Suspend account', suspend_admin_report_path(@report), method: :post, class: 'button'
%div{ style: 'float: left' }
= link_to 'Mark as resolved', resolve_admin_report_path(@report), method: :post, class: 'button'
- elsif !@report.action_taken_by_account.nil?
%hr/
%p
%strong Action taken by:
= @report.action_taken_by_account.acct

View file

@ -3,7 +3,7 @@
class AfterRemoteFollowRequestWorker
include Sidekiq::Worker
sidekiq_options retry: 5
sidekiq_options queue: 'pull', retry: 5
def perform(follow_request_id)
follow_request = FollowRequest.find(follow_request_id)

View file

@ -3,7 +3,7 @@
class AfterRemoteFollowWorker
include Sidekiq::Worker
sidekiq_options retry: 5
sidekiq_options queue: 'pull', retry: 5
def perform(follow_id)
follow = Follow.find(follow_id)

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
class DomainBlockWorker
include Sidekiq::Worker
def perform(domain_block_id)
BlockDomainService.new.call(DomainBlock.find(domain_block_id))
rescue ActiveRecord::RecordNotFound
true
end
end

View file

@ -5,7 +5,7 @@ require 'csv'
class ImportWorker
include Sidekiq::Worker
sidekiq_options retry: false
sidekiq_options queue: 'pull', retry: false
def perform(import_id)
import = Import.find(import_id)

View file

@ -3,7 +3,7 @@
class LinkCrawlWorker
include Sidekiq::Worker
sidekiq_options retry: false
sidekiq_options queue: 'pull', retry: false
def perform(status_id)
FetchLinkCardService.new.call(Status.find(status_id))

View file

@ -3,6 +3,8 @@
class MergeWorker
include Sidekiq::Worker
sidekiq_options queue: 'pull'
def perform(from_account_id, into_account_id)
FeedManager.instance.merge_into_timeline(Account.find(from_account_id), Account.find(into_account_id))
end

View file

@ -3,7 +3,7 @@
class NotificationWorker
include Sidekiq::Worker
sidekiq_options retry: 5
sidekiq_options queue: 'push', retry: 5
def perform(xml, source_account_id, target_account_id)
SendInteractionService.new.call(xml, Account.find(source_account_id), Account.find(target_account_id))

View file

@ -3,7 +3,7 @@
class ProcessingWorker
include Sidekiq::Worker
sidekiq_options backtrace: true
sidekiq_options queue: 'pull', backtrace: true
def perform(account_id, body)
ProcessFeedService.new.call(body, Account.find(account_id))

View file

@ -3,7 +3,9 @@
class RegenerationWorker
include Sidekiq::Worker
def perform(account_id, timeline_type)
PrecomputeFeedService.new.call(timeline_type, Account.find(account_id))
sidekiq_options queue: 'pull', backtrace: true
def perform(account_id, _ = :home)
PrecomputeFeedService.new.call(:home, Account.find(account_id))
end
end

View file

@ -3,7 +3,7 @@
class SalmonWorker
include Sidekiq::Worker
sidekiq_options backtrace: true
sidekiq_options queue: 'pull', backtrace: true
def perform(account_id, body)
ProcessInteractionService.new.call(body, Account.find(account_id))

View file

@ -3,7 +3,7 @@
class ThreadResolveWorker
include Sidekiq::Worker
sidekiq_options retry: false
sidekiq_options queue: 'pull', retry: false
def perform(child_status_id, parent_url)
child_status = Status.find(child_status_id)

View file

@ -3,6 +3,8 @@
class UnmergeWorker
include Sidekiq::Worker
sidekiq_options queue: 'pull'
def perform(from_account_id, into_account_id)
FeedManager.instance.unmerge_from_timeline(Account.find(from_account_id), Account.find(into_account_id))
end