about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock8
-rw-r--r--app/controllers/accounts_controller.rb8
-rw-r--r--app/controllers/application_controller.rb5
-rw-r--r--app/controllers/follower_accounts_controller.rb1
-rw-r--r--app/controllers/relationships_controller.rb19
-rw-r--r--app/controllers/statuses_controller.rb4
-rw-r--r--app/helpers/admin/filter_helper.rb2
-rw-r--r--app/javascript/flavours/glitch/actions/notifications.js2
-rw-r--r--app/javascript/flavours/glitch/styles/tables.scss24
-rw-r--r--app/javascript/mastodon/actions/notifications.js2
-rw-r--r--app/javascript/mastodon/locales/defaultMessages.json39
-rw-r--r--app/javascript/mastodon/locales/en.json5
-rw-r--r--app/javascript/mastodon/locales/ja.json2
-rw-r--r--app/javascript/styles/mastodon/tables.scss24
-rw-r--r--app/lib/activitypub/activity/flag.rb7
-rw-r--r--app/models/report.rb11
-rw-r--r--app/models/status.rb2
-rw-r--r--app/serializers/activitypub/flag_serializer.rb1
-rw-r--r--app/services/report_service.rb3
-rw-r--r--app/views/relationships/show.html.haml11
-rw-r--r--config/locales/cs.yml2
-rw-r--r--config/locales/devise.ja.yml3
-rw-r--r--config/locales/en.yml6
-rw-r--r--config/locales/ja.yml15
-rw-r--r--db/migrate/20190317135723_add_uri_to_reports.rb5
-rw-r--r--db/schema.rb3
-rw-r--r--spec/lib/activitypub/activity/announce_spec.rb1
-rw-r--r--spec/lib/activitypub/activity/flag_spec.rb23
-rw-r--r--spec/services/reblog_service_spec.rb21
-rw-r--r--spec/services/report_service_spec.rb5
31 files changed, 208 insertions, 58 deletions
diff --git a/Gemfile b/Gemfile
index 9b08ab780..a00b3f513 100644
--- a/Gemfile
+++ b/Gemfile
@@ -129,7 +129,7 @@ group :development do
   gem 'letter_opener_web', '~> 1.3'
   gem 'memory_profiler'
   gem 'rubocop', '~> 0.65', require: false
-  gem 'brakeman', '~> 4.4', require: false
+  gem 'brakeman', '~> 4.5', require: false
   gem 'bundler-audit', '~> 0.6', require: false
   gem 'scss_lint', '~> 0.57', require: false
 
diff --git a/Gemfile.lock b/Gemfile.lock
index 6ab8ae819..45370d154 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -102,7 +102,7 @@ GEM
       debug_inspector (>= 0.0.1)
     bootsnap (1.4.1)
       msgpack (~> 1.0)
-    brakeman (4.4.0)
+    brakeman (4.5.0)
     browser (2.5.3)
     builder (3.2.3)
     bullet (5.9.0)
@@ -271,7 +271,7 @@ GEM
       domain_name (~> 0.5)
     http-form_data (2.1.1)
     http_accept_language (2.1.1)
-    httplog (1.2.1)
+    httplog (1.2.2)
       rack (>= 1.0)
       rainbow (>= 2.0.0)
     i18n (1.6.0)
@@ -405,7 +405,7 @@ GEM
     pg (1.1.4)
     pghero (2.2.0)
       activerecord
-    pkg-config (1.3.6)
+    pkg-config (1.3.7)
     powerpack (0.1.2)
     premailer (1.11.1)
       addressable
@@ -668,7 +668,7 @@ DEPENDENCIES
   better_errors (~> 2.5)
   binding_of_caller (~> 0.7)
   bootsnap (~> 1.4)
-  brakeman (~> 4.4)
+  brakeman (~> 4.5)
   browser
   bullet (~> 5.9)
   bundler-audit (~> 0.6)
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 157ea8569..fcdebb47f 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -11,6 +11,8 @@ class AccountsController < ApplicationController
     respond_to do |format|
       format.html do
         use_pack 'public'
+        mark_cacheable! unless user_signed_in?
+
         @body_classes      = 'with-modals'
         @pinned_statuses   = []
         @endorsed_accounts = @account.endorsed_accounts.to_a.sample(4)
@@ -31,17 +33,21 @@ class AccountsController < ApplicationController
       end
 
       format.atom do
+        mark_cacheable!
+
         @entries = @account.stream_entries.where(hidden: false).with_includes.paginate_by_max_id(PAGE_SIZE, params[:max_id], params[:since_id])
         render xml: OStatus::AtomSerializer.render(OStatus::AtomSerializer.new.feed(@account, @entries.reject { |entry| entry.status.nil? || entry.status.local_only? }))
       end
 
       format.rss do
+        mark_cacheable!
+
         @statuses = cache_collection(default_statuses.without_reblogs.without_replies.limit(PAGE_SIZE), Status)
         render xml: RSS::AccountSerializer.render(@account, @statuses)
       end
 
       format.json do
-        skip_session!
+        mark_cacheable!
 
         render_cached_json(['activitypub', 'actor', @account], content_type: 'application/activity+json') do
           ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter)
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0209805d0..5401b9d59 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -227,6 +227,11 @@ class ApplicationController < ActionController::Base
     response.headers['Vary'] = 'Accept'
   end
 
+  def mark_cacheable!
+    skip_session!
+    expires_in 0, public: true
+  end
+
   def skip_session!
     request.session_options[:skip] = true
   end
diff --git a/app/controllers/follower_accounts_controller.rb b/app/controllers/follower_accounts_controller.rb
index f985f0eff..213c209ab 100644
--- a/app/controllers/follower_accounts_controller.rb
+++ b/app/controllers/follower_accounts_controller.rb
@@ -7,6 +7,7 @@ class FollowerAccountsController < ApplicationController
     respond_to do |format|
       format.html do
         use_pack 'public'
+        mark_cacheable! unless user_signed_in?
 
         next if @account.user_hides_network?
 
diff --git a/app/controllers/relationships_controller.rb b/app/controllers/relationships_controller.rb
index af91cb658..a0b9c77df 100644
--- a/app/controllers/relationships_controller.rb
+++ b/app/controllers/relationships_controller.rb
@@ -32,17 +32,18 @@ class RelationshipsController < ApplicationController
   def relationships_scope
     scope = begin
       if following_relationship?
-        current_account.following.includes(:account_stat)
+        current_account.following.joins(:account_stat)
       else
-        current_account.followers.includes(:account_stat)
+        current_account.followers.joins(:account_stat)
       end
     end
 
     scope.merge!(Follow.recent)
     scope.merge!(mutual_relationship_scope) if mutual_relationship?
-    scope.merge!(abandoned_account_scope)   if params[:status] == 'abandoned'
-    scope.merge!(active_account_scope)      if params[:status] == 'active'
+    scope.merge!(moved_account_scope)       if params[:status] == 'moved'
+    scope.merge!(primary_account_scope)     if params[:status] == 'primary'
     scope.merge!(by_domain_scope)           if params[:by_domain].present?
+    scope.merge!(dormant_account_scope)     if params[:activity] == 'dormant'
 
     scope
   end
@@ -51,14 +52,18 @@ class RelationshipsController < ApplicationController
     Account.where(id: current_account.following)
   end
 
-  def abandoned_account_scope
+  def moved_account_scope
     Account.where.not(moved_to_account_id: nil)
   end
 
-  def active_account_scope
+  def primary_account_scope
     Account.where(moved_to_account_id: nil)
   end
 
+  def dormant_account_scope
+    AccountStat.where(last_status_at: nil).or(AccountStat.where(AccountStat.arel_table[:last_status_at].lt(1.month.ago)))
+  end
+
   def by_domain_scope
     Account.where(domain: params[:by_domain])
   end
@@ -80,7 +85,7 @@ class RelationshipsController < ApplicationController
   end
 
   def current_params
-    params.slice(:page, :status, :relationship, :by_domain).permit(:page, :status, :relationship, :by_domain)
+    params.slice(:page, :status, :relationship, :by_domain, :activity).permit(:page, :status, :relationship, :by_domain, :activity)
   end
 
   def action_from_button
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index 6f56a67ba..53cf1c4ca 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -28,6 +28,8 @@ class StatusesController < ApplicationController
     respond_to do |format|
       format.html do
         use_pack 'public'
+        mark_cacheable! unless user_signed_in?
+
         @body_classes = 'with-modals'
 
         set_ancestors
@@ -37,7 +39,7 @@ class StatusesController < ApplicationController
       end
 
       format.json do
-        skip_session! unless @stream_entry.hidden?
+        mark_cacheable! unless @stream_entry.hidden?
 
         render_cached_json(['activitypub', 'note', @status], content_type: 'application/activity+json', public: !@stream_entry.hidden?) do
           ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter)
diff --git a/app/helpers/admin/filter_helper.rb b/app/helpers/admin/filter_helper.rb
index 09a356296..4fd36ef42 100644
--- a/app/helpers/admin/filter_helper.rb
+++ b/app/helpers/admin/filter_helper.rb
@@ -7,7 +7,7 @@ module Admin::FilterHelper
   CUSTOM_EMOJI_FILTERS = %i(local remote by_domain shortcode).freeze
   TAGS_FILTERS         = %i(hidden).freeze
   INSTANCES_FILTERS    = %i(limited by_domain).freeze
-  FOLLOWERS_FILTERS    = %i(relationship status by_domain).freeze
+  FOLLOWERS_FILTERS    = %i(relationship status by_domain activity).freeze
 
   FILTERS = ACCOUNT_FILTERS + REPORT_FILTERS + INVITE_FILTER + CUSTOM_EMOJI_FILTERS + TAGS_FILTERS + INSTANCES_FILTERS + FOLLOWERS_FILTERS
 
diff --git a/app/javascript/flavours/glitch/actions/notifications.js b/app/javascript/flavours/glitch/actions/notifications.js
index dd4f5fd44..57fecf63d 100644
--- a/app/javascript/flavours/glitch/actions/notifications.js
+++ b/app/javascript/flavours/glitch/actions/notifications.js
@@ -7,6 +7,7 @@ import {
   importFetchedStatus,
   importFetchedStatuses,
 } from './importer';
+import { saveSettings } from './settings';
 import { defineMessages } from 'react-intl';
 import { List as ImmutableList } from 'immutable';
 import { unescapeHTML } from 'flavours/glitch/util/html';
@@ -286,5 +287,6 @@ export function setFilter (filterType) {
       value: filterType,
     });
     dispatch(expandNotifications());
+    dispatch(saveSettings());
   };
 };
diff --git a/app/javascript/flavours/glitch/styles/tables.scss b/app/javascript/flavours/glitch/styles/tables.scss
index 11845fb17..154844665 100644
--- a/app/javascript/flavours/glitch/styles/tables.scss
+++ b/app/javascript/flavours/glitch/styles/tables.scss
@@ -149,6 +149,10 @@ a.table-action-link {
           margin-top: 0;
         }
       }
+
+      @media screen and (max-width: $no-gap-breakpoint) {
+        display: none;
+      }
     }
 
     &__actions,
@@ -170,6 +174,10 @@ a.table-action-link {
       text-align: right;
       padding-right: 16px - 5px;
     }
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      display: none;
+    }
   }
 
   &__row {
@@ -177,6 +185,12 @@ a.table-action-link {
     border-top: 0;
     background: darken($ui-base-color, 4%);
 
+    @media screen and (max-width: $no-gap-breakpoint) {
+      &:first-child {
+        border-top: 1px solid darken($ui-base-color, 8%);
+      }
+    }
+
     &:hover {
       background: darken($ui-base-color, 2%);
     }
@@ -211,5 +225,15 @@ a.table-action-link {
     border: 1px solid darken($ui-base-color, 8%);
     border-top: 0;
     box-shadow: none;
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      border-top: 1px solid darken($ui-base-color, 8%);
+    }
+  }
+
+  @media screen and (max-width: 870px) {
+    .accounts-table tbody td.optional {
+      display: none;
+    }
   }
 }
diff --git a/app/javascript/mastodon/actions/notifications.js b/app/javascript/mastodon/actions/notifications.js
index 61fef19e9..b0861fc6b 100644
--- a/app/javascript/mastodon/actions/notifications.js
+++ b/app/javascript/mastodon/actions/notifications.js
@@ -7,6 +7,7 @@ import {
   importFetchedStatus,
   importFetchedStatuses,
 } from './importer';
+import { saveSettings } from './settings';
 import { defineMessages } from 'react-intl';
 import { List as ImmutableList } from 'immutable';
 import { unescapeHTML } from '../utils/html';
@@ -187,5 +188,6 @@ export function setFilter (filterType) {
       value: filterType,
     });
     dispatch(expandNotifications());
+    dispatch(saveSettings());
   };
 };
diff --git a/app/javascript/mastodon/locales/defaultMessages.json b/app/javascript/mastodon/locales/defaultMessages.json
index 094f401b1..8261ce578 100644
--- a/app/javascript/mastodon/locales/defaultMessages.json
+++ b/app/javascript/mastodon/locales/defaultMessages.json
@@ -134,15 +134,6 @@
   {
     "descriptors": [
       {
-        "defaultMessage": "It crashed!",
-        "id": "error_boundary.it_crashed"
-      }
-    ],
-    "path": "app/javascript/mastodon/components/error_boundary.json"
-  },
-  {
-    "descriptors": [
-      {
         "defaultMessage": "{count} {rawCount, plural, one {person} other {people}} talking",
         "id": "trends.count_by_accounts"
       }
@@ -1870,6 +1861,10 @@
       {
         "defaultMessage": "Boosts:",
         "id": "notifications.column_settings.reblog"
+      },
+      {
+        "defaultMessage": "Poll results:",
+        "id": "notifications.column_settings.poll"
       }
     ],
     "path": "app/javascript/mastodon/features/notifications/components/column_settings.json"
@@ -1889,6 +1884,10 @@
         "id": "notifications.filter.boosts"
       },
       {
+        "defaultMessage": "Poll results",
+        "id": "notifications.filter.polls"
+      },
+      {
         "defaultMessage": "Follows",
         "id": "notifications.filter.follows"
       },
@@ -1912,6 +1911,10 @@
       {
         "defaultMessage": "{name} boosted your status",
         "id": "notification.reblog"
+      },
+      {
+        "defaultMessage": "A poll you have voted in has ended",
+        "id": "notification.poll"
       }
     ],
     "path": "app/javascript/mastodon/features/notifications/components/notification.json"
@@ -1976,24 +1979,6 @@
   {
     "descriptors": [
       {
-        "defaultMessage": "A look inside...",
-        "id": "standalone.public_title"
-      }
-    ],
-    "path": "app/javascript/mastodon/features/standalone/community_timeline/index.json"
-  },
-  {
-    "descriptors": [
-      {
-        "defaultMessage": "A look inside...",
-        "id": "standalone.public_title"
-      }
-    ],
-    "path": "app/javascript/mastodon/features/standalone/public_timeline/index.json"
-  },
-  {
-    "descriptors": [
-      {
         "defaultMessage": "Delete",
         "id": "status.delete"
       },
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 4d1b02098..1c45d6f20 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -137,7 +137,6 @@
   "empty_column.mutes": "You haven't muted any users yet.",
   "empty_column.notifications": "You don't have any notifications yet. Interact with others to start the conversation.",
   "empty_column.public": "There is nothing here! Write something publicly, or manually follow users from other servers to fill it up",
-  "error_boundary.it_crashed": "It crashed!",
   "follow_request.authorize": "Authorize",
   "follow_request.reject": "Reject",
   "getting_started.developers": "Developers",
@@ -253,6 +252,7 @@
   "notification.favourite": "{name} favourited your status",
   "notification.follow": "{name} followed you",
   "notification.mention": "{name} mentioned you",
+  "notification.poll": "A poll you have voted in has ended",
   "notification.reblog": "{name} boosted your status",
   "notifications.clear": "Clear notifications",
   "notifications.clear_confirmation": "Are you sure you want to permanently clear all your notifications?",
@@ -263,6 +263,7 @@
   "notifications.column_settings.filter_bar.show": "Show",
   "notifications.column_settings.follow": "New followers:",
   "notifications.column_settings.mention": "Mentions:",
+  "notifications.column_settings.poll": "Poll results:",
   "notifications.column_settings.push": "Push notifications",
   "notifications.column_settings.reblog": "Boosts:",
   "notifications.column_settings.show": "Show in column",
@@ -272,6 +273,7 @@
   "notifications.filter.favourites": "Favourites",
   "notifications.filter.follows": "Follows",
   "notifications.filter.mentions": "Mentions",
+  "notifications.filter.polls": "Poll results",
   "notifications.group": "{count} notifications",
   "poll.closed": "Closed",
   "poll.refresh": "Refresh",
@@ -313,7 +315,6 @@
   "search_results.hashtags": "Hashtags",
   "search_results.statuses": "Toots",
   "search_results.total": "{count, number} {count, plural, one {result} other {results}}",
-  "standalone.public_title": "A look inside...",
   "status.admin_account": "Open moderation interface for @{name}",
   "status.admin_status": "Open this status in the moderation interface",
   "status.block": "Block @{name}",
diff --git a/app/javascript/mastodon/locales/ja.json b/app/javascript/mastodon/locales/ja.json
index 9213b2a48..ca66fbf2a 100644
--- a/app/javascript/mastodon/locales/ja.json
+++ b/app/javascript/mastodon/locales/ja.json
@@ -137,7 +137,6 @@
   "empty_column.mutes": "まだ誰もミュートしていません。",
   "empty_column.notifications": "まだ通知がありません。他の人とふれ合って会話を始めましょう。",
   "empty_column.public": "ここにはまだ何もありません! 公開で何かを投稿したり、他のサーバーのユーザーをフォローしたりしていっぱいにしましょう",
-  "error_boundary.it_crashed": "It crashed!",
   "follow_request.authorize": "許可",
   "follow_request.reject": "拒否",
   "getting_started.developers": "開発",
@@ -313,7 +312,6 @@
   "search_results.hashtags": "ハッシュタグ",
   "search_results.statuses": "トゥート",
   "search_results.total": "{count, number}件の結果",
-  "standalone.public_title": "A look inside...",
   "status.admin_account": "@{name} のモデレーション画面を開く",
   "status.admin_status": "このトゥートをモデレーション画面で開く",
   "status.block": "@{name}さんをブロック",
diff --git a/app/javascript/styles/mastodon/tables.scss b/app/javascript/styles/mastodon/tables.scss
index d3a0ea03d..11ac6dfeb 100644
--- a/app/javascript/styles/mastodon/tables.scss
+++ b/app/javascript/styles/mastodon/tables.scss
@@ -149,6 +149,10 @@ a.table-action-link {
           margin-top: 0;
         }
       }
+
+      @media screen and (max-width: $no-gap-breakpoint) {
+        display: none;
+      }
     }
 
     &__actions,
@@ -170,6 +174,10 @@ a.table-action-link {
       text-align: right;
       padding-right: 16px - 5px;
     }
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      display: none;
+    }
   }
 
   &__row {
@@ -177,6 +185,12 @@ a.table-action-link {
     border-top: 0;
     background: darken($ui-base-color, 4%);
 
+    @media screen and (max-width: $no-gap-breakpoint) {
+      &:first-child {
+        border-top: 1px solid darken($ui-base-color, 8%);
+      }
+    }
+
     &:hover {
       background: darken($ui-base-color, 2%);
     }
@@ -215,5 +229,15 @@ a.table-action-link {
     border: 1px solid darken($ui-base-color, 8%);
     border-top: 0;
     box-shadow: none;
+
+    @media screen and (max-width: $no-gap-breakpoint) {
+      border-top: 1px solid darken($ui-base-color, 8%);
+    }
+  }
+
+  @media screen and (max-width: 870px) {
+    .accounts-table tbody td.optional {
+      display: none;
+    }
   }
 }
diff --git a/app/lib/activitypub/activity/flag.rb b/app/lib/activitypub/activity/flag.rb
index 0d10d6c3c..f73b93058 100644
--- a/app/lib/activitypub/activity/flag.rb
+++ b/app/lib/activitypub/activity/flag.rb
@@ -14,7 +14,8 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity
         @account,
         target_account,
         status_ids: target_statuses.nil? ? [] : target_statuses.map(&:id),
-        comment: @json['content'] || ''
+        comment: @json['content'] || '',
+        uri: report_uri
       )
     end
   end
@@ -28,4 +29,8 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity
   def object_uris
     @object_uris ||= Array(@object.is_a?(Array) ? @object.map { |item| value_or_id(item) } : value_or_id(@object))
   end
+
+  def report_uri
+    @json['id'] unless @json['id'].nil? || invalid_origin?(@json['id'])
+  end
 end
diff --git a/app/models/report.rb b/app/models/report.rb
index 2804020f5..86c303798 100644
--- a/app/models/report.rb
+++ b/app/models/report.rb
@@ -13,6 +13,7 @@
 #  action_taken_by_account_id :bigint(8)
 #  target_account_id          :bigint(8)        not null
 #  assigned_account_id        :bigint(8)
+#  uri                        :string
 #
 
 class Report < ApplicationRecord
@@ -28,6 +29,12 @@ class Report < ApplicationRecord
 
   validates :comment, length: { maximum: 1000 }
 
+  def local?
+    false # Force uri_for to use uri attribute
+  end
+
+  before_validation :set_uri, only: :create
+
   def object_type
     :flag
   end
@@ -89,4 +96,8 @@ class Report < ApplicationRecord
 
     Admin::ActionLog.from("(#{sql}) AS admin_action_logs")
   end
+
+  def set_uri
+    self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil? && account.local?
+  end
 end
diff --git a/app/models/status.rb b/app/models/status.rb
index 440d7cc63..95f336820 100644
--- a/app/models/status.rb
+++ b/app/models/status.rb
@@ -473,8 +473,8 @@ class Status < ApplicationRecord
   end
 
   def set_visibility
+    self.visibility = reblog.visibility if reblog? && visibility.nil?
     self.visibility = (account.locked? ? :private : :public) if visibility.nil?
-    self.visibility = reblog.visibility if reblog?
     self.sensitive  = false if sensitive.nil?
   end
 
diff --git a/app/serializers/activitypub/flag_serializer.rb b/app/serializers/activitypub/flag_serializer.rb
index 53e8f726d..1e7a46dd9 100644
--- a/app/serializers/activitypub/flag_serializer.rb
+++ b/app/serializers/activitypub/flag_serializer.rb
@@ -5,7 +5,6 @@ class ActivityPub::FlagSerializer < ActiveModel::Serializer
   attribute :virtual_object, key: :object
 
   def id
-    # This is nil for now
     ActivityPub::TagManager.instance.uri_for(object)
   end
 
diff --git a/app/services/report_service.rb b/app/services/report_service.rb
index 1bcc1c0d5..73bd6694f 100644
--- a/app/services/report_service.rb
+++ b/app/services/report_service.rb
@@ -21,7 +21,8 @@ class ReportService < BaseService
     @report = @source_account.reports.create!(
       target_account: @target_account,
       status_ids: @status_ids,
-      comment: @comment
+      comment: @comment,
+      uri: @options[:uri]
     )
   end
 
diff --git a/app/views/relationships/show.html.haml b/app/views/relationships/show.html.haml
index 94972026a..fc9613731 100644
--- a/app/views/relationships/show.html.haml
+++ b/app/views/relationships/show.html.haml
@@ -13,13 +13,20 @@
     %strong= t 'relationships.status'
     %ul
       %li= filter_link_to t('generic.all'), status: nil
-      %li= filter_link_to t('relationships.active'), status: 'active'
-      %li= filter_link_to t('relationships.abandoned'), status: 'abandoned'
+      %li= filter_link_to t('relationships.primary'), status: 'primary'
+      %li= filter_link_to t('relationships.moved'), status: 'moved'
+
+  .filter-subset
+    %strong= t 'relationships.activity'
+    %ul
+      %li= filter_link_to t('generic.all'), activity: nil
+      %li= filter_link_to t('relationships.dormant'), activity: 'dormant'
 
 = form_for(@form, url: relationships_path, method: :patch) do |f|
   = hidden_field_tag :page, params[:page] || 1
   = hidden_field_tag :relationship, params[:relationship]
   = hidden_field_tag :status, params[:status]
+  = hidden_field_tag :activity, params[:activity]
 
   .batch-table
     .batch-table__toolbar
diff --git a/config/locales/cs.yml b/config/locales/cs.yml
index 6e7afecf5..e455a27fd 100644
--- a/config/locales/cs.yml
+++ b/config/locales/cs.yml
@@ -37,7 +37,7 @@ cs:
     tagline: Sledujte své přátele a objevujte nové
     terms: Podmínky používání
     user_count_after:
-      few: uživatelů
+      few: uživatelé
       one: uživatel
       other: uživatelů
     user_count_before: Domov
diff --git a/config/locales/devise.ja.yml b/config/locales/devise.ja.yml
index bd2bb71bb..b4772d8d6 100644
--- a/config/locales/devise.ja.yml
+++ b/config/locales/devise.ja.yml
@@ -12,6 +12,7 @@ ja:
       last_attempt: あと1回失敗するとアカウントがロックされます。
       locked: アカウントはロックされました。
       not_found_in_database: "%{authentication_keys}かパスワードが誤っています。"
+      pending: あなたのアカウントはまだ審査中です。
       timeout: セッションの有効期限が切れました。続行するには再度ログインしてください。
       unauthenticated: 続行するにはログインするか、アカウントを作成してください。
       unconfirmed: 続行するにはメールアドレスを確認する必要があります。
@@ -20,6 +21,7 @@ ja:
         action: メールアドレスの確認
         action_with_app: 確認し %{app} に戻る
         explanation: このメールアドレスで%{host}にアカウントを作成しました。有効にするまであと一歩です。もし心当たりがない場合、申し訳ありませんがこのメールを無視してください。
+        explanation_when_pending: このメールアドレスで%{host}への招待を申請しました。メールアドレスを確認したら、サーバー管理者が申請を審査します。それまでログインできません。申請が却下された場合、あなたのデータは削除されますので以降の操作は必要ありません。もし心当たりがない場合、申し訳ありませんがこのメールを無視してください。
         extra_html: また <a href="%{terms_path}">サーバーのルール</a> と <a href="%{policy_path}">利用規約</a> もお読みください。
         subject: 'Mastodon: メールアドレスの確認 %{instance}'
         title: メールアドレスの確認
@@ -60,6 +62,7 @@ ja:
       signed_up: アカウントの作成が完了しました。Mastodonへようこそ。
       signed_up_but_inactive: アカウントの作成が完了しました。しかし、アカウントが有効化されていないためログインできませんでした。
       signed_up_but_locked: アカウントの作成が完了しました。しかし、アカウントがロックされているためログインできませんでした。
+      signed_up_but_pending: メールアドレスの確認用のリンクが入力したメールアドレスに送信されました。リンクをクリックした後、あなたの申請を審査します。承認されると通知されます。
       signed_up_but_unconfirmed: メールアドレスの確認用のリンクが入力したメールアドレスに送信されました。メール内のリンクをクリックしてアカウントを有効化してください。
       update_needs_confirmation: アカウント情報の更新に成功しました。しかし、メールアドレスの確認が必要です。送信されたメール内のリンクをクリックしてメールアドレスを確認してください。
       updated: アカウント情報の更新に成功しました。
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 8a17d88e0..81059b163 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -755,9 +755,11 @@ en:
     publishing: Publishing
     web: Web
   relationships:
-    abandoned: Abandoned
-    active: Active
+    activity: Account activity
+    dormant: Dormant
+    moved: Moved
     mutual: Mutual
+    primary: Primary
     relationship: Relationship
     remove_selected_domains: Remove all followers from the selected domains
     remove_selected_followers: Remove selected followers
diff --git a/config/locales/ja.yml b/config/locales/ja.yml
index 0c5631d3d..985d4f100 100644
--- a/config/locales/ja.yml
+++ b/config/locales/ja.yml
@@ -79,6 +79,7 @@ ja:
       delete: 削除
       destroyed_msg: モデレーションメモを削除しました!
     accounts:
+      approve: 承認
       are_you_sure: 本当に実行しますか?
       avatar: アイコン
       by_domain: ドメイン
@@ -124,6 +125,7 @@ ja:
       moderation:
         active: アクティブ
         all: すべて
+        pending: 保留中
         silenced: サイレンス済み
         suspended: 停止済み
         title: モデレーション
@@ -133,6 +135,7 @@ ja:
       no_limits_imposed: 制限なし
       not_subscribed: 購読していない
       outbox_url: Outbox URL
+      pending: 審査待ち
       perform_full_suspension: 活動を完全に停止させる
       profile_url: プロフィールURL
       promote: 昇格
@@ -140,6 +143,7 @@ ja:
       public: パブリック
       push_subscription_expires: PuSH購読期限
       redownload: プロフィールを更新
+      reject: 却下
       remove_avatar: アイコンを削除
       remove_header: ヘッダーを削除
       resend_confirmation:
@@ -411,6 +415,12 @@ ja:
         min_invite_role:
           disabled: 誰も許可しない
           title: 招待の作成を許可
+      registrations_mode:
+        modes:
+          approved: 登録には承認が必要
+          none: 誰も許可しない
+          open: 誰でも登録可
+        title: 新規登録
       show_known_fediverse_at_about_page:
         desc_html: チェックを入れるとプレビュー欄に既知の連合先全てのトゥートを表示します。外すとローカルのトゥートだけ表示します。
         title: タイムラインプレビューに連合タイムラインを表示する
@@ -473,6 +483,9 @@ ja:
       edit_preset: プリセット警告文を編集
       title: プリセット警告文を管理
   admin_mailer:
+    new_pending_account:
+      body: 新しいアカウントの詳細は以下の通りです。この申請を承認または却下することができます。
+      subject: "%{instance} で新しいアカウント (%{username}) が審査待ちです"
     new_report:
       body: "%{reporter} が %{target} を通報しました"
       body_remote: "%{domain} の誰かが %{target} を通報しました"
@@ -494,6 +507,7 @@ ja:
     your_token: アクセストークン
   auth:
     agreement_html: 登録するをクリックすると <a href="%{rules_path}">サーバーのルール</a> と <a href="%{terms_path}">プライバシーポリシー</a> に従うことに同意したことになります。
+    apply_for_account: 登録を申請する
     change_password: パスワード
     checkbox_agreement_html: <a href="%{rules_path}" target="_blank">サーバーのルール</a> と <a href="%{terms_path}" target="_blank">プライバシーポリシー</a> に同意します
     confirm_email: メールアドレスの確認
@@ -612,6 +626,7 @@ ja:
     more: さらに…
     resources: リソース
   generic:
+    all: すべて
     changes_saved_msg: 正常に変更されました!
     copy: コピー
     save_changes: 変更を保存
diff --git a/db/migrate/20190317135723_add_uri_to_reports.rb b/db/migrate/20190317135723_add_uri_to_reports.rb
new file mode 100644
index 000000000..47c0f2a21
--- /dev/null
+++ b/db/migrate/20190317135723_add_uri_to_reports.rb
@@ -0,0 +1,5 @@
+class AddUriToReports < ActiveRecord::Migration[5.2]
+  def change
+    add_column :reports, :uri, :string
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index ad8b56d2e..32758da1c 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: 2019_03_14_181829) do
+ActiveRecord::Schema.define(version: 2019_03_17_135723) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -536,6 +536,7 @@ ActiveRecord::Schema.define(version: 2019_03_14_181829) do
     t.bigint "action_taken_by_account_id"
     t.bigint "target_account_id", null: false
     t.bigint "assigned_account_id"
+    t.string "uri"
     t.index ["account_id"], name: "index_reports_on_account_id"
     t.index ["target_account_id"], name: "index_reports_on_target_account_id"
   end
diff --git a/spec/lib/activitypub/activity/announce_spec.rb b/spec/lib/activitypub/activity/announce_spec.rb
index aa58d9e23..926083a4f 100644
--- a/spec/lib/activitypub/activity/announce_spec.rb
+++ b/spec/lib/activitypub/activity/announce_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe ActivityPub::Activity::Announce do
       type: 'Announce',
       actor: 'https://example.com/actor',
       object: object_json,
+      to: 'http://example.com/followers',
     }.with_indifferent_access
   end
 
diff --git a/spec/lib/activitypub/activity/flag_spec.rb b/spec/lib/activitypub/activity/flag_spec.rb
index 3f082a813..ec7359f2f 100644
--- a/spec/lib/activitypub/activity/flag_spec.rb
+++ b/spec/lib/activitypub/activity/flag_spec.rb
@@ -1,14 +1,15 @@
 require 'rails_helper'
 
 RSpec.describe ActivityPub::Activity::Flag do
-  let(:sender)  { Fabricate(:account, domain: 'example.com') }
+  let(:sender)  { Fabricate(:account, domain: 'example.com', uri: 'http://example.com/account') }
   let(:flagged) { Fabricate(:account) }
   let(:status)  { Fabricate(:status, account: flagged, uri: 'foobar') }
+  let(:flag_id) { nil }
 
   let(:json) do
     {
       '@context': 'https://www.w3.org/ns/activitystreams',
-      id: nil,
+      id: flag_id,
       type: 'Flag',
       content: 'Boo!!',
       actor: ActivityPub::TagManager.instance.uri_for(sender),
@@ -34,4 +35,22 @@ RSpec.describe ActivityPub::Activity::Flag do
       expect(report.status_ids).to eq [status.id]
     end
   end
+
+  describe '#perform with a defined uri' do
+    subject { described_class.new(json, sender) }
+    let (:flag_id) { 'http://example.com/reports/1' }
+
+    before do
+      subject.perform
+    end
+
+    it 'creates a report' do
+      report = Report.find_by(account: sender, target_account: flagged)
+
+      expect(report).to_not be_nil
+      expect(report.comment).to eq 'Boo!!'
+      expect(report.status_ids).to eq [status.id]
+      expect(report.uri).to eq flag_id
+    end
+  end
 end
diff --git a/spec/services/reblog_service_spec.rb b/spec/services/reblog_service_spec.rb
index 2755da772..9e66c6643 100644
--- a/spec/services/reblog_service_spec.rb
+++ b/spec/services/reblog_service_spec.rb
@@ -3,6 +3,27 @@ require 'rails_helper'
 RSpec.describe ReblogService, type: :service do
   let(:alice)  { Fabricate(:account, username: 'alice') }
 
+  context 'creates a reblog with appropriate visibility' do
+    let(:bob)               { Fabricate(:account, username: 'bob') }
+    let(:visibility)        { :public }
+    let(:reblog_visibility) { :public }
+    let(:status)            { Fabricate(:status, account: bob, visibility: visibility) }
+
+    subject { ReblogService.new }
+
+    before do
+      subject.call(alice, status, visibility: reblog_visibility)
+    end
+
+    describe 'boosting privately' do
+      let(:reblog_visibility) { :private }
+
+      it 'reblogs privately' do
+        expect(status.reblogs.first.visibility).to eq 'private'
+      end
+    end
+  end
+
   context 'OStatus' do
     let(:bob)    { Fabricate(:account, username: 'bob', domain: 'example.com', salmon_url: 'http://salmon.example.com') }
     let(:status) { Fabricate(:status, account: bob, uri: 'tag:example.com;something:something') }
diff --git a/spec/services/report_service_spec.rb b/spec/services/report_service_spec.rb
index e8b094c89..454e4d896 100644
--- a/spec/services/report_service_spec.rb
+++ b/spec/services/report_service_spec.rb
@@ -21,6 +21,11 @@ RSpec.describe ReportService, type: :service do
       subject.call(source_account, remote_account, forward: false)
       expect(a_request(:post, 'http://example.com/inbox')).to_not have_been_made
     end
+
+    it 'has an uri' do
+      report = subject.call(source_account, remote_account, forward: true)
+      expect(report.uri).to_not be_nil
+    end
   end
 
   context 'when other reports already exist for the same target' do