Skip to content

Commit

Permalink
Merge branch 'dev' into merge-upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
sneakers-the-rat committed Sep 23, 2024
2 parents 02d9f61 + b6b3324 commit 11942f7
Show file tree
Hide file tree
Showing 19 changed files with 137 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .env.vagrant
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ DB_HOST=/var/run/postgresql/

ES_ENABLED=true
ES_HOST=localhost
ES_PORT=9200
ES_PORT=9200
2 changes: 1 addition & 1 deletion app/controllers/settings/profiles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def update
private

def account_params
params.require(:account).permit(:display_name, :note, :avatar, :header, :bot, fields_attributes: [:name, :value])
params.require(:account).permit(:display_name, :note, :avatar, :header, :bot, :account_css, fields_attributes: [:name, :value])
end

def set_account
Expand Down
1 change: 1 addition & 0 deletions app/javascript/flavours/glitch/api_types/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export interface ApiAccountJSON {
limited?: boolean;
memorial?: boolean;
hide_collections: boolean;
account_css?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';

import classNames from 'classnames';
import { Helmet } from 'react-helmet';
import { withRouter } from 'react-router-dom';
import {Helmet} from 'react-helmet';
import {withRouter} from 'react-router-dom';

import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
Expand Down Expand Up @@ -405,6 +405,11 @@ class Header extends ImmutablePureComponent {
<title>{titleFromAccount(account)}</title>
<meta name='robots' content={(isLocal && isIndexable) ? 'all' : 'noindex'} />
<link rel='canonical' href={account.get('url')} />
{account.account_css && (
<style id={"account-css"} nonce={document.querySelector('meta[name=style-nonce]').content}>
{account.account_css}
</style>
)}
</Helmet>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions app/javascript/flavours/glitch/models/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const accountDefaultValues: AccountShape = {
limited: false,
moved: null,
hide_collections: false,
account_css: '',
};

const AccountFactory = ImmutableRecord<AccountShape>(accountDefaultValues);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@import 'latex';
@import 'bigger_collapsed_statuses';
@import 'better_code_blocks';
@import 'myspace';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#account_account_css {
font-family: $font-monospace;
height: 15em;
}
2 changes: 2 additions & 0 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
# requested_review_at :datetime
# indexable :boolean default(FALSE), not null
# attribution_domains :string default([]), is an Array
# account_css :text
#

class Account < ApplicationRecord
Expand Down Expand Up @@ -121,6 +122,7 @@ class Account < ApplicationRecord
end

normalizes :username, with: ->(username) { username.squish }
normalizes :account_css, with: ->(account_css) { Sanitize::CSS.stylesheet(account_css, Sanitize::Config::RELAXED) }

scope :without_internal, -> { where(id: 1...) }
scope :remote, -> { where.not(domain: nil) }
Expand Down
3 changes: 2 additions & 1 deletion app/serializers/rest/account_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ class REST::AccountSerializer < ActiveModel::Serializer

attributes :id, :username, :acct, :display_name, :locked, :bot, :discoverable, :indexable, :group, :created_at,
:note, :url, :uri, :avatar, :avatar_static, :header, :header_static,
:followers_count, :following_count, :statuses_count, :last_status_at, :hide_collections
:followers_count, :following_count, :statuses_count, :last_status_at, :hide_collections,
:account_css

has_one :moved_to_account, key: :moved, serializer: REST::AccountSerializer, if: :moved_and_not_nested?

Expand Down
5 changes: 5 additions & 0 deletions app/views/settings/profiles/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,10 @@
.fields-group
= f.input :bot, as: :boolean, wrapper: :with_label, hint: t('simple_form.hints.defaults.bot')

%h4= t 'edit_profile.myspace_mode'

.fields-group
= f.input :account_css, as: :text, wrapper: :with_block_label, label: I18n.t('simple_form.labels.account.account_css'), hint: I18n.t('simple_form.hints.account.account_css'), neuromatchstodon_only: true

.actions
= f.button :button, t('generic.save_changes'), type: :submit
10 changes: 10 additions & 0 deletions config/initializers/simple_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,20 @@ def glitch_only(_wrapper_options = nil)
end
end

module NeuromatchstodonOnlyComponent
def neuromatchstodon_only(_wrapper_options = nil)
return unless options[:neuromatchstodon_only]

options[:label_text] = ->(raw_label_text, _required_label_text, _label_present) { safe_join([raw_label_text, ' ', content_tag(:span, I18n.t('simple_form.neuromatchstodon_only'), class: 'glitch_only')]) }
nil
end
end

SimpleForm.include_component(AppendComponent)
SimpleForm.include_component(RecommendedComponent)
SimpleForm.include_component(WarningHintComponent)
SimpleForm.include_component(GlitchOnlyComponent)
SimpleForm.include_component(NeuromatchstodonOnlyComponent)

SimpleForm.setup do |config|
# Wrappers are used by the form builder to generate a
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,7 @@ en:
basic_information: Basic information
hint_html: "<strong>Customize what people see on your public profile and next to your posts.</strong> Other people are more likely to follow you back and interact with you when you have a filled out profile and a profile picture."
other: Other
myspace_mode: "MySpace Mode"
errors:
'400': The request you submitted was invalid or malformed.
'403': You don't have permission to view this page.
Expand Down
3 changes: 3 additions & 0 deletions config/locales/simple_form.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ en:
note: 'You can @mention other people or #hashtags.'
show_collections: People will be able to browse through your follows and followers. People that you follow will see that you follow them regardless.
unlocked: People will be able to follow you without requesting approval. Uncheck if you want to review follow requests and chose whether to accept or reject new followers.
account_css: Custom CSS that is applied to your account page
account_alias:
acct: Specify the username@domain of the account you want to move from
account_migration:
Expand Down Expand Up @@ -152,6 +153,7 @@ en:
indexable: Include public posts in search results
show_collections: Show follows and followers on profile
unlocked: Automatically accept new followers
account_css: Account CSS
account_alias:
acct: Handle of the old account
account_migration:
Expand Down Expand Up @@ -341,3 +343,4 @@ en:
sessions:
webauthn: Use one of your security keys to sign in
'yes': 'Yes'
neuromatchstodon_only: "Neuromatchstodon Only"
7 changes: 7 additions & 0 deletions db/migrate/20240828084252_add_account_css_to_account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddAccountCssToAccount < ActiveRecord::Migration[7.1]
def change
add_column :accounts, :account_css, :text, null: true
end
end
1 change: 1 addition & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@
t.datetime "requested_review_at", precision: nil
t.boolean "indexable", default: false, null: false
t.string "attribution_domains", default: [], array: true
t.text "account_css"
t.index "(((setweight(to_tsvector('simple'::regconfig, (display_name)::text), 'A'::\"char\") || setweight(to_tsvector('simple'::regconfig, (username)::text), 'B'::\"char\")) || setweight(to_tsvector('simple'::regconfig, (COALESCE(domain, ''::character varying))::text), 'C'::\"char\")))", name: "search_index", using: :gin
t.index "lower((username)::text), COALESCE(lower((domain)::text), ''::text)", name: "index_accounts_on_username_and_domain_lower", unique: true
t.index ["domain", "id"], name: "index_accounts_on_domain_and_id"
Expand Down
30 changes: 30 additions & 0 deletions public/robots.txt
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ Disallow: /
User-agent: GPTBot
Disallow: /

# AI Data Scraper
# https://darkvisitors.com/agents/meta-externalagent

User-agent: Meta-ExternalAgent
Disallow: /

# AI Assistant
# https://darkvisitors.com/agents/meta-externalfetcher

User-agent: Meta-ExternalFetcher
Disallow: /

# AI Search Crawler
# https://darkvisitors.com/agents/oai-searchbot

User-agent: OAI-SearchBot
Disallow: /

# AI Data Scraper
# https://darkvisitors.com/agents/omgili

Expand All @@ -116,6 +134,18 @@ Disallow: /
User-agent: PerplexityBot
Disallow: /

# AI Data Scraper
# https://darkvisitors.com/agents/timpibot

User-agent: Timpibot
Disallow: /

# AI Data Scraper
# https://darkvisitors.com/agents/webzio-extended

User-agent: Webzio-Extended
Disallow: /

# AI Search Crawler
# https://darkvisitors.com/agents/youbot

Expand Down
27 changes: 27 additions & 0 deletions spec/controllers/settings/profiles_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,31 @@
expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
end
end

describe 'PUT #account_css with custom css' do
it 'hopefully removes malicious css' do
put :update, params: {
account: {
account_css: <<~CSS,
@import url(swear_words.css);
a { text-decoration: none; }
a:hover {
left: expression(alert('xss!'));
text-decoration: underline;
}
CSS
},
}
expect(account.reload.account_css).to eq <<~CSS
a { text-decoration: none; }
a:hover {
text-decoration: underline;
}
CSS
end
end
end
17 changes: 16 additions & 1 deletion spec/support/stories/profile_stories.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

module ProfileStories
attr_reader :bob, :alice, :alice_bio
attr_reader :bob, :alice, :alice_bio, :chupacabra, :chupacabra_css

def fill_in_auth_details(email, password)
fill_in 'user_email', with: email
Expand Down Expand Up @@ -43,6 +43,21 @@ def with_alice_as_local_user
)
end

def with_chupacabras_fancy_profile
@chupacabra_css = <<~CSS
body {
background-color: red !important;
}
CSS

@chupacabra = Fabricate(
:user,
email: '[email protected]', password: password, confirmed_at: confirmed_at,
account: Fabricate(:account, username: 'chupacabra', note: 'I am gonna getcha!', account_css: @chupacabra_css)
)
Web::Setting.where(user: chupacabra).first_or_initialize(user: chupacabra).update!(data: { introductionVersion: 2018_12_16_044202 })
end

def confirmed_at
@confirmed_at ||= Time.zone.now
end
Expand Down
17 changes: 17 additions & 0 deletions spec/system/profile_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,21 @@

expect(subject).to have_content 'Changes successfully saved!'
end

describe 'with JS', :js, :streaming do
before do
with_chupacabras_fancy_profile
end

it 'Can have custom account_css set' do
visit account_path('chupacabra')
# wait for page to load...
page.find '.account__header'
expect(subject.html).to have_content('background-color: red !important')

visit account_path('bob')
page.find '.account__header'
expect(subject.html).to have_no_content('background-color: red !important')
end
end
end

0 comments on commit 11942f7

Please sign in to comment.