summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2024-01-24 11:49:19 +0100
committerGitHub <noreply@github.com>2024-01-24 10:49:19 +0000
commitb19ae521b7d28a76e8e1d8da8157e051e9d8de6c (patch)
tree1f00583263bed52b13d502609fac7047174a3b9c
parent7a1f087659204e9d0cbba2de37e45b1921cefe20 (diff)
Add confirmation when redirecting logged-out requests to permalink (#27792)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
-rw-r--r--app/controllers/concerns/web_app_controller_concern.rb15
-rw-r--r--app/controllers/redirect/accounts_controller.rb10
-rw-r--r--app/controllers/redirect/base_controller.rb24
-rw-r--r--app/controllers/redirect/statuses_controller.rb10
-rw-r--r--app/javascript/styles/mastodon/containers.scss56
-rw-r--r--app/lib/permalink_redirector.rb63
-rw-r--r--app/views/redirects/show.html.haml8
-rw-r--r--config/locales/en.yml3
-rw-r--r--config/routes.rb5
9 files changed, 165 insertions, 29 deletions
diff --git a/app/controllers/concerns/web_app_controller_concern.rb b/app/controllers/concerns/web_app_controller_concern.rb
index 5687d6e5b60..b8c909877b6 100644
--- a/app/controllers/concerns/web_app_controller_concern.rb
+++ b/app/controllers/concerns/web_app_controller_concern.rb
@@ -21,10 +21,19 @@ module WebAppControllerConcern
def redirect_unauthenticated_to_permalinks!
return if user_signed_in? && current_account.moved_to_account_id.nil?
- redirect_path = PermalinkRedirector.new(request.path).redirect_path
- return if redirect_path.blank?
+ permalink_redirector = PermalinkRedirector.new(request.path)
+ return if permalink_redirector.redirect_path.blank?
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in?
- redirect_to(redirect_path)
+
+ respond_to do |format|
+ format.html do
+ redirect_to(permalink_redirector.redirect_confirmation_path, allow_other_host: false)
+ end
+
+ format.json do
+ redirect_to(permalink_redirector.redirect_uri, allow_other_host: true)
+ end
+ end
end
end
diff --git a/app/controllers/redirect/accounts_controller.rb b/app/controllers/redirect/accounts_controller.rb
new file mode 100644
index 00000000000..98d2cc2b1f9
--- /dev/null
+++ b/app/controllers/redirect/accounts_controller.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class Redirect::AccountsController < ApplicationController
+ private
+
+ def set_resource
+ @resource = Account.find(params[:id])
+ not_found if @resource.local?
+ end
+end
diff --git a/app/controllers/redirect/base_controller.rb b/app/controllers/redirect/base_controller.rb
new file mode 100644
index 00000000000..90894ec1ed8
--- /dev/null
+++ b/app/controllers/redirect/base_controller.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class Redirect::BaseController < ApplicationController
+ vary_by 'Accept-Language'
+
+ before_action :set_resource
+ before_action :set_app_body_class
+
+ def show
+ @redirect_path = ActivityPub::TagManager.instance.url_for(@resource)
+
+ render 'redirects/show', layout: 'application'
+ end
+
+ private
+
+ def set_app_body_class
+ @body_classes = 'app-body'
+ end
+
+ def set_resource
+ raise NotImplementedError
+ end
+end
diff --git a/app/controllers/redirect/statuses_controller.rb b/app/controllers/redirect/statuses_controller.rb
new file mode 100644
index 00000000000..37a938c651a
--- /dev/null
+++ b/app/controllers/redirect/statuses_controller.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class Redirect::StatusesController < Redirect::BaseController
+ private
+
+ def set_resource
+ @resource = Status.find(params[:id])
+ not_found if @resource.local? || !@resource.distributable?
+ end
+end
diff --git a/app/javascript/styles/mastodon/containers.scss b/app/javascript/styles/mastodon/containers.scss
index 3d646da2391..b6e995787d2 100644
--- a/app/javascript/styles/mastodon/containers.scss
+++ b/app/javascript/styles/mastodon/containers.scss
@@ -104,3 +104,59 @@
margin-inline-start: 10px;
}
}
+
+.redirect {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 100vh;
+ font-size: 14px;
+ line-height: 18px;
+
+ &__logo {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 30px;
+
+ img {
+ height: 48px;
+ }
+ }
+
+ &__message {
+ text-align: center;
+
+ h1 {
+ font-size: 17px;
+ line-height: 22px;
+ font-weight: 700;
+ margin-bottom: 30px;
+ }
+
+ p {
+ margin-bottom: 30px;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ a {
+ color: $highlight-text-color;
+ font-weight: 500;
+ text-decoration: none;
+
+ &:hover,
+ &:focus,
+ &:active {
+ text-decoration: underline;
+ }
+ }
+ }
+
+ &__link {
+ margin-top: 15px;
+ }
+}
diff --git a/app/lib/permalink_redirector.rb b/app/lib/permalink_redirector.rb
index 0dd37483e23..f551f69db85 100644
--- a/app/lib/permalink_redirector.rb
+++ b/app/lib/permalink_redirector.rb
@@ -5,17 +5,46 @@ class PermalinkRedirector
def initialize(path)
@path = path
+ @object = nil
+ end
+
+ def object
+ @object ||= begin
+ if at_username_status_request? || statuses_status_request?
+ status = Status.find_by(id: second_segment)
+ status if status&.distributable? && !status&.local?
+ elsif at_username_request?
+ username, domain = first_segment.delete_prefix('@').split('@')
+ domain = nil if TagManager.instance.local_domain?(domain)
+ account = Account.find_remote(username, domain)
+ account unless account&.local?
+ elsif accounts_request? && record_integer_id_request?
+ account = Account.find_by(id: second_segment)
+ account unless account&.local?
+ end
+ end
end
def redirect_path
- if at_username_status_request? || statuses_status_request?
- find_status_url_by_id(second_segment)
- elsif at_username_request?
- find_account_url_by_name(first_segment)
- elsif accounts_request? && record_integer_id_request?
- find_account_url_by_id(second_segment)
- elsif @path.start_with?('/deck')
- @path.delete_prefix('/deck')
+ return ActivityPub::TagManager.instance.url_for(object) if object.present?
+
+ @path.delete_prefix('/deck') if @path.start_with?('/deck')
+ end
+
+ def redirect_uri
+ return ActivityPub::TagManager.instance.uri_for(object) if object.present?
+
+ @path.delete_prefix('/deck') if @path.start_with?('/deck')
+ end
+
+ def redirect_confirmation_path
+ case object.class.name
+ when 'Account'
+ redirect_account_path(object.id)
+ when 'Status'
+ redirect_status_path(object.id)
+ else
+ @path.delete_prefix('/deck') if @path.start_with?('/deck')
end
end
@@ -56,22 +85,4 @@ class PermalinkRedirector
def path_segments
@path_segments ||= @path.delete_prefix('/deck').delete_prefix('/').split('/')
end
-
- def find_status_url_by_id(id)
- status = Status.find_by(id: id)
- ActivityPub::TagManager.instance.url_for(status) if status&.distributable? && !status.account.local?
- end
-
- def find_account_url_by_id(id)
- account = Account.find_by(id: id)
- ActivityPub::TagManager.instance.url_for(account) if account.present? && !account.local?
- end
-
- def find_account_url_by_name(name)
- username, domain = name.gsub(/\A@/, '').split('@')
- domain = nil if TagManager.instance.local_domain?(domain)
- account = Account.find_remote(username, domain)
-
- ActivityPub::TagManager.instance.url_for(account) if account.present? && !account.local?
- end
end
diff --git a/app/views/redirects/show.html.haml b/app/views/redirects/show.html.haml
new file mode 100644
index 00000000000..0d09387a9c7
--- /dev/null
+++ b/app/views/redirects/show.html.haml
@@ -0,0 +1,8 @@
+.redirect
+ .redirect__logo
+ = link_to render_logo, root_path
+
+ .redirect__message
+ %h1= t('redirects.title', instance: site_hostname)
+ %p= t('redirects.prompt')
+ %p= link_to @redirect_path, @redirect_path, rel: 'noreferrer noopener'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 83eaaa4552c..9d739be07f8 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1547,6 +1547,9 @@ en:
errors:
limit_reached: Limit of different reactions reached
unrecognized_emoji: is not a recognized emoji
+ redirects:
+ prompt: If you trust this link, click it to continue.
+ title: You are leaving %{instance}.
relationships:
activity: Account activity
confirm_follow_selected_followers: Are you sure you want to follow selected followers?
diff --git a/config/routes.rb b/config/routes.rb
index 85c3b18556e..c4f862acafa 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -162,6 +162,11 @@ Rails.application.routes.draw do
end
end
+ namespace :redirect do
+ resources :accounts, only: :show
+ resources :statuses, only: :show
+ end
+
resources :media, only: [:show] do
get :player
end