Skip to content

Commit

Permalink
Merge branch 'glitch-soc:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Ember-ruby authored Nov 26, 2023
2 parents 6a62caa + b3581d1 commit 3c103a6
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 117 deletions.
36 changes: 4 additions & 32 deletions app/javascript/flavours/glitch/components/account.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { RelativeTimestamp } from './relative_timestamp';
const messages = defineMessages({
follow: { id: 'account.follow', defaultMessage: 'Follow' },
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' },
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' },
Expand All @@ -38,7 +38,6 @@ class Account extends ImmutablePureComponent {
onMuteNotifications: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
hidden: PropTypes.bool,
small: PropTypes.bool,
actionIcon: PropTypes.string,
actionTitle: PropTypes.string,
defaultAction: PropTypes.string,
Expand Down Expand Up @@ -74,17 +73,7 @@ class Account extends ImmutablePureComponent {
};

render () {
const {
account,
hidden,
intl,
small,
onActionClick,
actionIcon,
actionTitle,
defaultAction,
size,
} = this.props;
const { account, intl, hidden, onActionClick, actionIcon, actionTitle, defaultAction, size } = this.props;

if (!account) {
return (
Expand Down Expand Up @@ -114,7 +103,7 @@ class Account extends ImmutablePureComponent {
if (actionIcon) {
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />;
}
} else if (account.get('id') !== me && !small && account.get('relationship', null) !== null) {
} else if (account.get('id') !== me && account.get('relationship', null) !== null) {
const following = account.getIn(['relationship', 'following']);
const requested = account.getIn(['relationship', 'requested']);
const blocking = account.getIn(['relationship', 'blocking']);
Expand Down Expand Up @@ -151,24 +140,7 @@ class Account extends ImmutablePureComponent {
mute_expires_at = <div><RelativeTimestamp timestamp={account.get('mute_expires_at')} futureDate /></div>;
}

return small ? (
<Permalink
className='account small'
href={account.get('url')}
to={`/@${account.get('acct')}`}
>
<div className='account__avatar-wrapper'>
<Avatar
account={account}
size={24}
/>
</div>
<DisplayName
account={account}
inline
/>
</Permalink>
) : (
return (
<div className='account'>
<div className='account__wrapper'>
<Permalink key={account.get('id')} className='account__display-name' title={account.get('acct')} href={account.get('url')} to={`/@${account.get('acct')}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';

import AttachmentList from 'flavours/glitch/components/attachment_list';
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router';

import { Avatar } from '../../../components/avatar';
import { DisplayName } from '../../../components/display_name';
import { IconButton } from '../../../components/icon_button';
import AccountContainer from '../../../containers/account_container';

const messages = defineMessages({
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
Expand All @@ -18,14 +20,19 @@ class ReplyIndicator extends ImmutablePureComponent {

static propTypes = {
status: ImmutablePropTypes.map,
onCancel: PropTypes.func,
onCancel: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
...WithOptionalRouterPropTypes,
};

handleClick = () => {
const { onCancel } = this.props;
if (onCancel) {
onCancel();
this.props.onCancel();
};

handleAccountClick = (e) => {
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.props.history?.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
}
};

Expand All @@ -38,19 +45,15 @@ class ReplyIndicator extends ImmutablePureComponent {

const content = { __html: status.get('contentHtml') };

const account = status.get('account');

return (
<div className='reply-indicator'>
<div className='reply-indicator__header'>
<div className='reply-indicator__cancel'><IconButton title={intl.formatMessage(messages.cancel)} icon='times' onClick={this.handleClick} inverted /></div>

{account && (
<AccountContainer
id={account}
small
/>
)}
<a href={status.getIn(['account', 'url'])} onClick={this.handleAccountClick} className='reply-indicator__display-name' target='_blank' rel='noopener noreferrer'>
<div className='reply-indicator__display-avatar'><Avatar account={status.get('account')} size={24} /></div>
<DisplayName account={status.get('account')} inline />
</a>
</div>

<div className='reply-indicator__content translate' dangerouslySetInnerHTML={content} />
Expand All @@ -67,4 +70,4 @@ class ReplyIndicator extends ImmutablePureComponent {

}

export default injectIntl(ReplyIndicator);
export default withOptionalRouter(injectIntl(ReplyIndicator));
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { connect } from 'react-redux';

import { cancelReplyCompose } from '../../../actions/compose';
import { makeGetStatus } from '../../../selectors';
import ReplyIndicator from '../components/reply_indicator';

const makeMapStateToProps = () => {
const getStatus = makeGetStatus();

const mapStateToProps = state => {
let statusId = state.getIn(['compose', 'id'], null);
let editing = true;
Expand All @@ -14,7 +17,7 @@ const makeMapStateToProps = () => {
}

return {
status: state.getIn(['statuses', statusId]),
status: getStatus(state, { id: statusId }),
editing,
};
};
Expand Down
15 changes: 0 additions & 15 deletions app/javascript/flavours/glitch/styles/components/accounts.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,6 @@
-webkit-box-orient: vertical;
color: $ui-secondary-color;
}

&.small {
border: 0;
padding: 0;

& > .account__avatar-wrapper {
margin: 0;
margin-inline-end: 8px;
}

& > .display-name {
height: 24px;
line-height: 24px;
}
}
}

.follow-recommendations-account {
Expand Down
23 changes: 19 additions & 4 deletions app/javascript/flavours/glitch/styles/components/compose_form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -141,17 +141,32 @@
.reply-indicator__header {
margin-bottom: 5px;
overflow: hidden;

& > .account.small {
color: $inverted-text-color;
}
}

.reply-indicator__cancel {
float: right;
line-height: 24px;
}

.reply-indicator__display-name {
color: $inverted-text-color;
display: block;
max-width: 100%;
line-height: 24px;
overflow: hidden;
text-decoration: none;

& > .display-name {
line-height: unset;
height: unset;
}
}

.reply-indicator__display-avatar {
float: left;
margin-inline-end: 5px;
}

.reply-indicator__content {
position: relative;
font-size: 14px;
Expand Down
18 changes: 9 additions & 9 deletions app/javascript/packs/public.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createRoot } from 'react-dom/client';
import { IntlMessageFormat } from 'intl-messageformat';
import { defineMessages } from 'react-intl';

import delegate from '@rails/ujs';
import Rails from '@rails/ujs';
import axios from 'axios';
import { throttle } from 'lodash';

Expand Down Expand Up @@ -129,7 +129,7 @@ function loaded() {
});
}

delegate(document, '#user_account_attributes_username', 'input', throttle(({ target }) => {
Rails.delegate(document, '#user_account_attributes_username', 'input', throttle(({ target }) => {
if (target.value && target.value.length > 0) {
axios.get('/api/v1/accounts/lookup', { params: { acct: target.value } }).then(() => {
target.setCustomValidity(formatMessage(messages.usernameTaken));
Expand All @@ -141,7 +141,7 @@ function loaded() {
}
}, 500, { leading: false, trailing: true }));

delegate(document, '#user_password,#user_password_confirmation', 'input', () => {
Rails.delegate(document, '#user_password,#user_password_confirmation', 'input', () => {
const password = document.getElementById('user_password');
const confirmation = document.getElementById('user_password_confirmation');
if (!confirmation) return;
Expand All @@ -155,7 +155,7 @@ function loaded() {
}
});

delegate(document, '.status__content__spoiler-link', 'click', function() {
Rails.delegate(document, '.status__content__spoiler-link', 'click', function() {
const statusEl = this.parentNode.parentNode;

if (statusEl.dataset.spoiler === 'expanded') {
Expand Down Expand Up @@ -192,23 +192,23 @@ const toggleSidebar = () => {
sidebar.classList.toggle('visible');
};

delegate(document, '.sidebar__toggle__icon', 'click', () => {
Rails.delegate(document, '.sidebar__toggle__icon', 'click', () => {
toggleSidebar();
});

delegate(document, '.sidebar__toggle__icon', 'keydown', e => {
Rails.delegate(document, '.sidebar__toggle__icon', 'keydown', e => {
if (e.key === ' ' || e.key === 'Enter') {
e.preventDefault();
toggleSidebar();
}
});

delegate(document, '.custom-emoji', 'mouseover', ({ target }) => target.src = target.getAttribute('data-original'));
delegate(document, '.custom-emoji', 'mouseout', ({ target }) => target.src = target.getAttribute('data-static'));
Rails.delegate(document, '.custom-emoji', 'mouseover', ({ target }) => target.src = target.getAttribute('data-original'));
Rails.delegate(document, '.custom-emoji', 'mouseout', ({ target }) => target.src = target.getAttribute('data-static'));

// Empty the honeypot fields in JS in case something like an extension
// automatically filled them.
delegate(document, '#registration_new_user,#new_user', 'submit', () => {
Rails.delegate(document, '#registration_new_user,#new_user', 'submit', () => {
['user_website', 'user_confirm_password', 'registration_user_website', 'registration_user_confirm_password'].forEach(id => {
const field = document.getElementById(id);
if (field) {
Expand Down
74 changes: 35 additions & 39 deletions config/initializers/content_security_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ def host_to_url(str)
uri.to_s
end

base_host = Rails.configuration.x.web_domain

assets_host = Rails.configuration.action_controller.asset_host
assets_host ||= host_to_url(base_host)

media_host = host_to_url(ENV['S3_ALIAS_HOST'])
media_host ||= host_to_url(ENV['S3_CLOUDFRONT_HOST'])
media_host ||= host_to_url(ENV['AZURE_ALIAS_HOST'])
media_host ||= host_to_url(ENV['S3_HOSTNAME']) if ENV['S3_ENABLED'] == 'true'
media_host ||= assets_host

def sso_host
return unless ENV['ONE_CLICK_SSO_LOGIN'] == 'true'
return unless ENV['OMNIAUTH_ONLY'] == 'true'
Expand All @@ -32,50 +43,35 @@ def sso_host
end
end

unless Rails.env.development?
assets_host = Rails.configuration.action_controller.asset_host || "https://#{ENV['WEB_DOMAIN'] || ENV['LOCAL_DOMAIN']}"
data_hosts = [assets_host]

if ENV['S3_ENABLED'] == 'true' || ENV['AZURE_ENABLED'] == 'true'
attachments_host = host_to_url(ENV['S3_ALIAS_HOST'] || ENV['S3_CLOUDFRONT_HOST'] || ENV['AZURE_ALIAS_HOST'] || ENV['S3_HOSTNAME'] || "s3-#{ENV['S3_REGION'] || 'us-east-1'}.amazonaws.com")
elsif ENV['SWIFT_ENABLED'] == 'true'
attachments_host = ENV['SWIFT_OBJECT_URL']
attachments_host = "https://#{Addressable::URI.parse(attachments_host).host}"
Rails.application.config.content_security_policy do |p|
p.base_uri :none
p.default_src :none
p.frame_ancestors :none
p.font_src :self, assets_host
p.img_src :self, :data, :blob, assets_host, media_host
p.style_src :self, assets_host
p.media_src :self, :data, assets_host, media_host
p.frame_src :self, :https
p.manifest_src :self, assets_host

if sso_host.present?
p.form_action :self, sso_host
else
attachments_host = nil
p.form_action :self
end

data_hosts << attachments_host unless attachments_host.nil?
p.child_src :self, :blob, assets_host
p.worker_src :self, :blob, assets_host

if ENV['PAPERCLIP_ROOT_URL']
url = Addressable::URI.parse(assets_host) + ENV['PAPERCLIP_ROOT_URL']
data_hosts << "https://#{url.host}"
end
if Rails.env.development?
webpacker_public_host = ENV.fetch('WEBPACKER_DEV_SERVER_PUBLIC', Webpacker.config.dev_server[:public])
webpacker_urls = %w(ws http).map { |protocol| "#{protocol}#{Webpacker.dev_server.https? ? 's' : ''}://#{webpacker_public_host}" }

data_hosts.concat(ENV['EXTRA_DATA_HOSTS'].split('|')) if ENV['EXTRA_DATA_HOSTS']

data_hosts.uniq!

Rails.application.config.content_security_policy do |p|
p.base_uri :none
p.default_src :none
p.frame_ancestors :none
p.script_src :self, assets_host, "'wasm-unsafe-eval'"
p.font_src :self, assets_host
p.img_src :self, :data, :blob, *data_hosts
p.style_src :self, assets_host
p.media_src :self, :data, *data_hosts
p.frame_src :self, :https
p.child_src :self, :blob, assets_host
p.worker_src :self, :blob, assets_host
p.connect_src :self, :blob, :data, Rails.configuration.x.streaming_api_base_url, *data_hosts
p.manifest_src :self, assets_host

if sso_host.present?
p.form_action :self, sso_host
else
p.form_action :self
end
p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url, *webpacker_urls
p.script_src :self, :unsafe_inline, :unsafe_eval, assets_host
else
p.connect_src :self, :data, :blob, assets_host, media_host, Rails.configuration.x.streaming_api_base_url
p.script_src :self, assets_host, "'wasm-unsafe-eval'"
end
end

Expand Down
6 changes: 3 additions & 3 deletions spec/requests/content_security_policy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
"default-src 'none'",
"frame-ancestors 'none'",
"font-src 'self' https://cb6e6126.ngrok.io",
"img-src 'self' data: blob: https://cb6e6126.ngrok.io",
"img-src 'self' data: blob: https://cb6e6126.ngrok.io https://cb6e6126.ngrok.io",
"style-src 'self' https://cb6e6126.ngrok.io 'nonce-ZbA+JmE7+bK8F5qvADZHuQ=='",
"media-src 'self' data: https://cb6e6126.ngrok.io",
"media-src 'self' data: https://cb6e6126.ngrok.io https://cb6e6126.ngrok.io",
"frame-src 'self' https:",
"manifest-src 'self' https://cb6e6126.ngrok.io",
"form-action 'self'",
"child-src 'self' blob: https://cb6e6126.ngrok.io",
"worker-src 'self' blob: https://cb6e6126.ngrok.io",
"connect-src 'self' blob: data: ws://localhost:4000 https://cb6e6126.ngrok.io",
"connect-src 'self' data: blob: https://cb6e6126.ngrok.io https://cb6e6126.ngrok.io ws://localhost:4000",
"script-src 'self' https://cb6e6126.ngrok.io 'wasm-unsafe-eval'"
)
end
Expand Down

0 comments on commit 3c103a6

Please sign in to comment.