mirror of
https://github.com/glitch-soc/mastodon.git
synced 2026-03-29 03:00:33 +02:00
Merge pull request #3107 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes up to ac039d5f13
This commit is contained in:
16
Gemfile.lock
16
Gemfile.lock
@@ -116,7 +116,7 @@ GEM
|
||||
base64 (0.3.0)
|
||||
bcp47_spec (0.2.1)
|
||||
bcrypt (3.1.20)
|
||||
benchmark (0.4.0)
|
||||
benchmark (0.4.1)
|
||||
better_errors (2.10.1)
|
||||
erubi (>= 1.0.0)
|
||||
rack (>= 0.9.0)
|
||||
@@ -708,7 +708,7 @@ GEM
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdf-normalize (0.7.0)
|
||||
rdf (~> 3.3)
|
||||
rdoc (6.14.0)
|
||||
rdoc (6.14.1)
|
||||
erb
|
||||
psych (>= 4.0.0)
|
||||
redcarpet (3.6.1)
|
||||
@@ -737,17 +737,17 @@ GEM
|
||||
rspec-core (~> 3.13.0)
|
||||
rspec-expectations (~> 3.13.0)
|
||||
rspec-mocks (~> 3.13.0)
|
||||
rspec-core (3.13.3)
|
||||
rspec-core (3.13.4)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-expectations (3.13.4)
|
||||
rspec-expectations (3.13.5)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-github (3.0.0)
|
||||
rspec-core (~> 3.0)
|
||||
rspec-mocks (3.13.4)
|
||||
rspec-mocks (3.13.5)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-rails (8.0.0)
|
||||
rspec-rails (8.0.1)
|
||||
actionpack (>= 7.2)
|
||||
activesupport (>= 7.2)
|
||||
railties (>= 7.2)
|
||||
@@ -760,7 +760,7 @@ GEM
|
||||
rspec-expectations (~> 3.0)
|
||||
rspec-mocks (~> 3.0)
|
||||
sidekiq (>= 5, < 9)
|
||||
rspec-support (3.13.3)
|
||||
rspec-support (3.13.4)
|
||||
rubocop (1.76.2)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
@@ -940,7 +940,7 @@ GEM
|
||||
xorcist (1.1.3)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.7.2)
|
||||
zeitwerk (2.7.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
@@ -15,8 +15,9 @@ class Api::V1::Instances::TermsOfServicesController < Api::V1::Instances::BaseCo
|
||||
if params[:date].present?
|
||||
TermsOfService.published.find_by!(effective_date: params[:date])
|
||||
else
|
||||
TermsOfService.live.first || TermsOfService.published.first! # For the case when none of the published terms have become effective yet
|
||||
TermsOfService.current
|
||||
end
|
||||
end
|
||||
not_found if @terms_of_service.nil?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -377,7 +377,11 @@ class Status extends ImmutablePureComponent {
|
||||
if (newTab) {
|
||||
window.open(path, '_blank', 'noopener');
|
||||
} else {
|
||||
history.push(path);
|
||||
if (history.location.pathname.replace('/deck/', '/') === path) {
|
||||
history.replace(path);
|
||||
} else {
|
||||
history.push(path);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1244,6 +1244,7 @@ body > [data-popper-placement] {
|
||||
line-height: 20px;
|
||||
letter-spacing: 0.25px;
|
||||
display: -webkit-box;
|
||||
line-clamp: 4;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
padding: 0;
|
||||
@@ -1322,6 +1323,7 @@ body > [data-popper-placement] {
|
||||
letter-spacing: 0.25px;
|
||||
padding-top: 0 !important;
|
||||
display: -webkit-box;
|
||||
line-clamp: 4;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
max-height: 4 * 20px;
|
||||
@@ -2166,6 +2168,7 @@ body > [data-popper-placement] {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
line-clamp: 1;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
margin-top: 10px;
|
||||
@@ -3189,7 +3192,7 @@ a.account__display-name {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
$sidebar-width: 285px;
|
||||
|
||||
.columns-area__panels__main {
|
||||
@@ -3389,7 +3392,7 @@ a.account__display-name {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
.columns-area__panels__pane--compositional {
|
||||
display: none;
|
||||
}
|
||||
@@ -3630,19 +3633,19 @@ a.account__display-name {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (height <= 930px - 56px) {
|
||||
@media screen and (height <= (930px - 56px)) {
|
||||
&__portal .trends__item:nth-child(n + 4) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (height <= 930px - (56px * 2)) {
|
||||
@media screen and (height <= (930px - 56px * 2)) {
|
||||
&__portal .trends__item:nth-child(n + 3) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (height <= 930px - (56px * 3)) {
|
||||
@media screen and (height <= (930px - 56px * 3)) {
|
||||
&__portal {
|
||||
display: none;
|
||||
}
|
||||
@@ -4198,6 +4201,7 @@ a.status-card {
|
||||
.status-card.expanded .status-card__title {
|
||||
white-space: normal;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
@@ -6390,6 +6394,7 @@ a.status-card {
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: $dark-text-color;
|
||||
line-clamp: 4;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
max-height: 4 * 22px;
|
||||
@@ -8021,7 +8026,7 @@ img.modal-warning {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
border-right: 0;
|
||||
border-left: 0;
|
||||
}
|
||||
@@ -8429,7 +8434,7 @@ noscript {
|
||||
}
|
||||
|
||||
// Fallback for older browsers with no container queries support
|
||||
@media screen and (max-width: 372px + 55px) {
|
||||
@media screen and (max-width: (372px + 55px)) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -8898,7 +8903,7 @@ noscript {
|
||||
width: 124px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
@media screen and (max-width: 124px + 300px) {
|
||||
@media screen and (max-width: (124px + 300px)) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -8908,7 +8913,7 @@ noscript {
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
|
||||
@media screen and (max-width: 124px + 300px) {
|
||||
@media screen and (max-width: (124px + 300px)) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -9001,7 +9006,6 @@ noscript {
|
||||
height: 100%;
|
||||
min-width: auto;
|
||||
min-height: auto;
|
||||
vertical-align: bottom;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
@@ -9037,6 +9041,7 @@ noscript {
|
||||
}
|
||||
|
||||
.emoji-picker-dropdown {
|
||||
display: flex;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
@@ -9268,7 +9273,7 @@ noscript {
|
||||
.layout-single-column .explore__search-header {
|
||||
display: none;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@@ -9666,7 +9671,7 @@ noscript {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
&__choices {
|
||||
flex-direction: column;
|
||||
|
||||
@@ -11216,6 +11221,7 @@ noscript {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
max-height: 2 * 20px;
|
||||
|
||||
@@ -301,7 +301,11 @@ class Status extends ImmutablePureComponent {
|
||||
if (newTab) {
|
||||
window.open(path, '_blank', 'noopener');
|
||||
} else {
|
||||
history.push(path);
|
||||
if (history.location.pathname.replace('/deck/', '/') === path) {
|
||||
history.replace(path);
|
||||
} else {
|
||||
history.push(path);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1185,6 +1185,7 @@ body > [data-popper-placement] {
|
||||
line-height: 20px;
|
||||
letter-spacing: 0.25px;
|
||||
display: -webkit-box;
|
||||
line-clamp: 4;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
padding: 0;
|
||||
@@ -1263,6 +1264,7 @@ body > [data-popper-placement] {
|
||||
letter-spacing: 0.25px;
|
||||
padding-top: 0 !important;
|
||||
display: -webkit-box;
|
||||
line-clamp: 4;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
max-height: 4 * 20px;
|
||||
@@ -2100,6 +2102,7 @@ body > [data-popper-placement] {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
line-clamp: 1;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
margin-top: 10px;
|
||||
@@ -3124,7 +3127,7 @@ a.account__display-name {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
$sidebar-width: 285px;
|
||||
|
||||
.columns-area__panels__main {
|
||||
@@ -3324,7 +3327,7 @@ a.account__display-name {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
.columns-area__panels__pane--compositional {
|
||||
display: none;
|
||||
}
|
||||
@@ -3565,19 +3568,19 @@ a.account__display-name {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (height <= 930px - 56px) {
|
||||
@media screen and (height <= (930px - 56px)) {
|
||||
&__portal .trends__item:nth-child(n + 4) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (height <= 930px - (56px * 2)) {
|
||||
@media screen and (height <= (930px - 56px * 2)) {
|
||||
&__portal .trends__item:nth-child(n + 3) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (height <= 930px - (56px * 3)) {
|
||||
@media screen and (height <= (930px - 56px * 3)) {
|
||||
&__portal {
|
||||
display: none;
|
||||
}
|
||||
@@ -4110,6 +4113,7 @@ a.status-card {
|
||||
.status-card.expanded .status-card__title {
|
||||
white-space: normal;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
@@ -6153,6 +6157,7 @@ a.status-card {
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
color: $dark-text-color;
|
||||
line-clamp: 4;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
max-height: 4 * 22px;
|
||||
@@ -7717,7 +7722,7 @@ a.status-card {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
border-right: 0;
|
||||
border-left: 0;
|
||||
}
|
||||
@@ -8126,7 +8131,7 @@ noscript {
|
||||
}
|
||||
|
||||
// Fallback for older browsers with no container queries support
|
||||
@media screen and (max-width: 372px + 55px) {
|
||||
@media screen and (max-width: (372px + 55px)) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -8595,7 +8600,7 @@ noscript {
|
||||
width: 124px;
|
||||
flex: 0 0 auto;
|
||||
|
||||
@media screen and (max-width: 124px + 300px) {
|
||||
@media screen and (max-width: (124px + 300px)) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -8605,7 +8610,7 @@ noscript {
|
||||
flex: 0 0 auto;
|
||||
position: relative;
|
||||
|
||||
@media screen and (max-width: 124px + 300px) {
|
||||
@media screen and (max-width: (124px + 300px)) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -8698,7 +8703,6 @@ noscript {
|
||||
height: 100%;
|
||||
min-width: auto;
|
||||
min-height: auto;
|
||||
vertical-align: bottom;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
@@ -8734,6 +8738,7 @@ noscript {
|
||||
}
|
||||
|
||||
.emoji-picker-dropdown {
|
||||
display: flex;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
@@ -8959,7 +8964,7 @@ noscript {
|
||||
.layout-single-column .explore__search-header {
|
||||
display: none;
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@@ -9357,7 +9362,7 @@ noscript {
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $no-gap-breakpoint - 1px) {
|
||||
@media screen and (max-width: ($no-gap-breakpoint - 1px)) {
|
||||
&__choices {
|
||||
flex-direction: column;
|
||||
|
||||
@@ -10902,6 +10907,7 @@ noscript {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
display: -webkit-box;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
max-height: 2 * 20px;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
class TermsOfService < ApplicationRecord
|
||||
scope :published, -> { where.not(published_at: nil).order(Arel.sql('coalesce(effective_date, published_at) DESC')) }
|
||||
scope :live, -> { published.where('effective_date IS NULL OR effective_date < now()').limit(1) }
|
||||
scope :upcoming, -> { published.reorder(effective_date: :asc).where('effective_date IS NOT NULL AND effective_date > now()').limit(1) }
|
||||
scope :draft, -> { where(published_at: nil).order(id: :desc).limit(1) }
|
||||
|
||||
validates :text, presence: true
|
||||
@@ -26,6 +27,10 @@ class TermsOfService < ApplicationRecord
|
||||
|
||||
NOTIFICATION_ACTIVITY_CUTOFF = 1.year.freeze
|
||||
|
||||
def self.current
|
||||
live.first || upcoming.first # For the case when none of the published terms have become effective yet
|
||||
end
|
||||
|
||||
def published?
|
||||
published_at.present?
|
||||
end
|
||||
|
||||
@@ -21,5 +21,5 @@ class WebauthnCredential < ApplicationRecord
|
||||
validates :external_id, uniqueness: true
|
||||
validates :nickname, uniqueness: { scope: :user_id }
|
||||
validates :sign_count,
|
||||
numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: SIGN_COUNT_LIMIT - 1 }
|
||||
numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than: SIGN_COUNT_LIMIT }
|
||||
end
|
||||
|
||||
@@ -25,12 +25,15 @@ class Webhook < ApplicationRecord
|
||||
status.updated
|
||||
).freeze
|
||||
|
||||
SECRET_LENGTH_MIN = 12
|
||||
SECRET_SIZE = 20
|
||||
|
||||
attr_writer :current_account
|
||||
|
||||
scope :enabled, -> { where(enabled: true) }
|
||||
|
||||
validates :url, presence: true, url: true
|
||||
validates :secret, presence: true, length: { minimum: 12 }
|
||||
validates :secret, presence: true, length: { minimum: SECRET_LENGTH_MIN }
|
||||
validates :events, presence: true
|
||||
|
||||
validate :events_validation_error, if: :invalid_events?
|
||||
@@ -41,7 +44,7 @@ class Webhook < ApplicationRecord
|
||||
before_validation :generate_secret
|
||||
|
||||
def rotate_secret!
|
||||
update!(secret: SecureRandom.hex(20))
|
||||
update!(secret: random_secret)
|
||||
end
|
||||
|
||||
def enable!
|
||||
@@ -93,6 +96,10 @@ class Webhook < ApplicationRecord
|
||||
end
|
||||
|
||||
def generate_secret
|
||||
self.secret = SecureRandom.hex(20) if secret.blank?
|
||||
self.secret = random_secret if secret.blank?
|
||||
end
|
||||
|
||||
def random_secret
|
||||
SecureRandom.hex(SECRET_SIZE)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -127,7 +127,7 @@ class InitialStateSerializer < ActiveModel::Serializer
|
||||
trends_as_landing_page: Setting.trends_as_landing_page,
|
||||
trends_enabled: Setting.trends,
|
||||
version: instance_presenter.version,
|
||||
terms_of_service_enabled: TermsOfService.live.exists?,
|
||||
terms_of_service_enabled: TermsOfService.current.present?,
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer
|
||||
status: object.status_page_url,
|
||||
about: about_url,
|
||||
privacy_policy: privacy_policy_url,
|
||||
terms_of_service: TermsOfService.live.exists? ? terms_of_service_url : nil,
|
||||
terms_of_service: TermsOfService.current.present? ? terms_of_service_url : nil,
|
||||
},
|
||||
|
||||
vapid: {
|
||||
|
||||
@@ -24,4 +24,55 @@ RSpec.describe TermsOfService do
|
||||
expect(subject.pluck(:id)).to match_array(user_before.id)
|
||||
end
|
||||
end
|
||||
|
||||
describe '::current' do
|
||||
context 'when no terms exist' do
|
||||
it 'returns nil' do
|
||||
expect(described_class.current).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only unpublished terms exist' do
|
||||
before do
|
||||
yesterday = Date.yesterday
|
||||
travel_to yesterday do
|
||||
Fabricate(:terms_of_service, published_at: nil, effective_date: yesterday)
|
||||
end
|
||||
Fabricate(:terms_of_service, published_at: nil, effective_date: Date.tomorrow)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(described_class.current).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when both effective and future terms exist' do
|
||||
let!(:effective_terms) do
|
||||
yesterday = Date.yesterday
|
||||
travel_to yesterday do
|
||||
Fabricate(:terms_of_service, effective_date: yesterday)
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
Fabricate(:terms_of_service, effective_date: Date.tomorrow)
|
||||
end
|
||||
|
||||
it 'returns the effective terms' do
|
||||
expect(described_class.current).to eq effective_terms
|
||||
end
|
||||
end
|
||||
|
||||
context 'when only future terms exist' do
|
||||
let!(:upcoming_terms) { Fabricate(:terms_of_service, effective_date: Date.tomorrow) }
|
||||
|
||||
before do
|
||||
Fabricate(:terms_of_service, effective_date: 10.days.since)
|
||||
end
|
||||
|
||||
it 'returns the terms that are upcoming next' do
|
||||
expect(described_class.current).to eq upcoming_terms
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,6 +14,6 @@ RSpec.describe WebauthnCredential do
|
||||
it { is_expected.to validate_uniqueness_of(:external_id) }
|
||||
it { is_expected.to validate_uniqueness_of(:nickname).scoped_to(:user_id) }
|
||||
|
||||
it { is_expected.to validate_numericality_of(:sign_count).only_integer.is_greater_than_or_equal_to(0).is_less_than_or_equal_to(described_class::SIGN_COUNT_LIMIT - 1) }
|
||||
it { is_expected.to validate_numericality_of(:sign_count).only_integer.is_greater_than_or_equal_to(0).is_less_than(described_class::SIGN_COUNT_LIMIT) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,6 +8,8 @@ RSpec.describe Webhook do
|
||||
describe 'Validations' do
|
||||
subject { Fabricate.build :webhook }
|
||||
|
||||
it { is_expected.to validate_length_of(:secret).is_at_least(described_class::SECRET_LENGTH_MIN) }
|
||||
|
||||
it { is_expected.to validate_presence_of(:events) }
|
||||
|
||||
it { is_expected.to_not allow_values([], %w(account.invalid)).for(:events) }
|
||||
|
||||
Reference in New Issue
Block a user