Add confirmation when redirecting logged-out requests to permalink (#27792)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>th-new
parent
7a1f087659
commit
b19ae521b7
app
controllers
javascript/styles/mastodon
views/redirects
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue