mirror of
https://github.com/mastodon/mastodon.git
synced 2024-12-28 22:15:06 +01:00
Change referrer policy to be controlled by header in web UI (#33214)
This commit is contained in:
parent
2e35b15b4d
commit
425311e1d9
@ -109,7 +109,7 @@ module.exports = defineConfig({
|
|||||||
'react/jsx-equals-spacing': 'error',
|
'react/jsx-equals-spacing': 'error',
|
||||||
'react/jsx-no-bind': 'error',
|
'react/jsx-no-bind': 'error',
|
||||||
'react/jsx-no-useless-fragment': 'error',
|
'react/jsx-no-useless-fragment': 'error',
|
||||||
'react/jsx-no-target-blank': 'off',
|
'react/jsx-no-target-blank': ['error', { allowReferrer: true }],
|
||||||
'react/jsx-tag-spacing': 'error',
|
'react/jsx-tag-spacing': 'error',
|
||||||
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
'react/jsx-uses-react': 'off', // not needed with new JSX transform
|
||||||
'react/jsx-wrap-multilines': 'error',
|
'react/jsx-wrap-multilines': 'error',
|
||||||
|
@ -8,6 +8,7 @@ module Admin
|
|||||||
layout 'admin'
|
layout 'admin'
|
||||||
|
|
||||||
before_action :set_cache_headers
|
before_action :set_cache_headers
|
||||||
|
before_action :set_referrer_policy_header
|
||||||
|
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
@ -17,6 +18,10 @@ module Admin
|
|||||||
response.cache_control.replace(private: true, no_store: true)
|
response.cache_control.replace(private: true, no_store: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_referrer_policy_header
|
||||||
|
response.headers['Referrer-Policy'] = 'same-origin'
|
||||||
|
end
|
||||||
|
|
||||||
def set_user
|
def set_user
|
||||||
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
@user = Account.find(params[:account_id]).user || raise(ActiveRecord::RecordNotFound)
|
||||||
end
|
end
|
||||||
|
@ -36,7 +36,7 @@ export default class AttachmentList extends ImmutablePureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={attachment.get('id')}>
|
<li key={attachment.get('id')}>
|
||||||
<a href={displayUrl} target='_blank' rel='noopener noreferrer'>
|
<a href={displayUrl} target='_blank' rel='noopener'>
|
||||||
{compact && <Icon id='link' icon={LinkIcon} />}
|
{compact && <Icon id='link' icon={LinkIcon} />}
|
||||||
{compact && ' ' }
|
{compact && ' ' }
|
||||||
{displayUrl ? filename(displayUrl) : <FormattedMessage id='attachments_list.unprocessed' defaultMessage='(unprocessed)' />}
|
{displayUrl ? filename(displayUrl) : <FormattedMessage id='attachments_list.unprocessed' defaultMessage='(unprocessed)' />}
|
||||||
|
@ -124,7 +124,7 @@ class DropdownMenu extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={classNames('dropdown-menu__item', { 'dropdown-menu__item--dangerous': dangerous })} key={`${text}-${i}`}>
|
<li className={classNames('dropdown-menu__item', { 'dropdown-menu__item--dangerous': dangerous })} key={`${text}-${i}`}>
|
||||||
<a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
|
<a href={href} target={target} data-method={method} rel='noopener' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
|
||||||
{text}
|
{text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -98,7 +98,7 @@ export default class ErrorBoundary extends PureComponent {
|
|||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener noreferrer' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
|
<p className='error-boundary__footer'>Mastodon v{version} · <a href={source_url} rel='noopener' target='_blank'><FormattedMessage id='errors.unexpected_crash.report_issue' defaultMessage='Report issue' /></a> · <button onClick={this.handleCopyStackTrace} className={copied ? 'copied' : ''}><FormattedMessage id='errors.unexpected_crash.copy_stacktrace' defaultMessage='Copy stacktrace to clipboard' /></button></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Helmet>
|
<Helmet>
|
||||||
|
@ -88,7 +88,7 @@ export const FollowButton: React.FC<{
|
|||||||
<a
|
<a
|
||||||
href='/settings/profile'
|
href='/settings/profile'
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noreferrer noopener'
|
rel='noopener'
|
||||||
className='button button-secondary'
|
className='button button-secondary'
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
@ -106,7 +106,7 @@ class Item extends PureComponent {
|
|||||||
if (attachment.get('type') === 'unknown') {
|
if (attachment.get('type') === 'unknown') {
|
||||||
return (
|
return (
|
||||||
<div className={classNames('media-gallery__item', { standalone, 'media-gallery__item--tall': height === 100, 'media-gallery__item--wide': width === 100 })} key={attachment.get('id')}>
|
<div className={classNames('media-gallery__item', { standalone, 'media-gallery__item--tall': height === 100, 'media-gallery__item--wide': width === 100 })} key={attachment.get('id')}>
|
||||||
<a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={description} lang={lang} target='_blank' rel='noopener noreferrer'>
|
<a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={description} lang={lang} target='_blank' rel='noopener'>
|
||||||
<Blurhash
|
<Blurhash
|
||||||
hash={attachment.get('blurhash')}
|
hash={attachment.get('blurhash')}
|
||||||
className='media-gallery__preview'
|
className='media-gallery__preview'
|
||||||
@ -138,7 +138,7 @@ class Item extends PureComponent {
|
|||||||
href={attachment.get('remote_url') || originalUrl}
|
href={attachment.get('remote_url') || originalUrl}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noopener noreferrer'
|
rel='noopener'
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={previewUrl}
|
src={previewUrl}
|
||||||
|
@ -42,7 +42,7 @@ class ServerBanner extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<div className='server-banner'>
|
<div className='server-banner'>
|
||||||
<div className='server-banner__introduction'>
|
<div className='server-banner__introduction'>
|
||||||
<FormattedMessage id='server_banner.is_one_of_many' defaultMessage='{domain} is one of the many independent Mastodon servers you can use to participate in the fediverse.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank'>Mastodon</a> }} />
|
<FormattedMessage id='server_banner.is_one_of_many' defaultMessage='{domain} is one of the many independent Mastodon servers you can use to participate in the fediverse.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank' rel='noopener'>Mastodon</a> }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Link to='/about'>
|
<Link to='/about'>
|
||||||
|
@ -293,7 +293,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
if (e?.button === 0 && !(e?.ctrlKey || e?.metaKey)) {
|
if (e?.button === 0 && !(e?.ctrlKey || e?.metaKey)) {
|
||||||
history.push(path);
|
history.push(path);
|
||||||
} else if (e?.button === 1 || (e?.button === 0 && (e?.ctrlKey || e?.metaKey))) {
|
} else if (e?.button === 1 || (e?.button === 0 && (e?.ctrlKey || e?.metaKey))) {
|
||||||
window.open(path, '_blank', 'noreferrer noopener');
|
window.open(path, '_blank', 'noopener');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ class About extends PureComponent {
|
|||||||
<div className='about__header'>
|
<div className='about__header'>
|
||||||
<ServerHeroImage blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' />
|
<ServerHeroImage blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' />
|
||||||
<h1>{isLoading ? <Skeleton width='10ch' /> : server.get('domain')}</h1>
|
<h1>{isLoading ? <Skeleton width='10ch' /> : server.get('domain')}</h1>
|
||||||
<p><FormattedMessage id='about.powered_by' defaultMessage='Decentralized social media powered by {mastodon}' values={{ mastodon: <a href='https://joinmastodon.org' className='about__mail' target='_blank'>Mastodon</a> }} /></p>
|
<p><FormattedMessage id='about.powered_by' defaultMessage='Decentralized social media powered by {mastodon}' values={{ mastodon: <a href='https://joinmastodon.org' className='about__mail' target='_blank' rel='noopener'>Mastodon</a> }} /></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='about__meta'>
|
<div className='about__meta'>
|
||||||
|
@ -421,7 +421,7 @@ class Header extends ImmutablePureComponent {
|
|||||||
|
|
||||||
<div className='account__header__bar'>
|
<div className='account__header__bar'>
|
||||||
<div className='account__header__tabs'>
|
<div className='account__header__tabs'>
|
||||||
<a className='avatar' href={account.get('avatar')} rel='noopener noreferrer' target='_blank' onClick={this.handleAvatarClick}>
|
<a className='avatar' href={account.get('avatar')} rel='noopener' target='_blank' onClick={this.handleAvatarClick}>
|
||||||
<Avatar account={suspended || hidden ? undefined : account} size={90} />
|
<Avatar account={suspended || hidden ? undefined : account} size={90} />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ describe('emoji', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('keeps ordering as expected (issue fixed by PR 20677)', () => {
|
it('keeps ordering as expected (issue fixed by PR 20677)', () => {
|
||||||
expect(emojify('<p>💕 <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener noreferrer" target="_blank">#<span>foo</span></a> test: foo.</p>'))
|
expect(emojify('<p>💕 <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener" target="_blank">#<span>foo</span></a> test: foo.</p>'))
|
||||||
.toEqual('<p><picture><img draggable="false" class="emojione" alt="💕" title=":two_hearts:" src="/emoji/1f495.svg"></picture> <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener noreferrer" target="_blank">#<span>foo</span></a> test: foo.</p>');
|
.toEqual('<p><picture><img draggable="false" class="emojione" alt="💕" title=":two_hearts:" src="/emoji/1f495.svg"></picture> <a class="hashtag" href="https://example.com/tags/foo" rel="nofollow noopener" target="_blank">#<span>foo</span></a> test: foo.</p>');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -85,7 +85,7 @@ class ContentWithRouter extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
link.setAttribute('target', '_blank');
|
link.setAttribute('target', '_blank');
|
||||||
link.setAttribute('rel', 'noopener noreferrer');
|
link.setAttribute('rel', 'noopener');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export const RelationshipsSeveranceEvent = ({ type, target, followingCount, foll
|
|||||||
|
|
||||||
<div className='notification-group__main'>
|
<div className='notification-group__main'>
|
||||||
<p>{intl.formatMessage(messages[type], { from: <strong>{domain}</strong>, target: <strong>{target}</strong>, followingCount, followersCount })}</p>
|
<p>{intl.formatMessage(messages[type], { from: <strong>{domain}</strong>, target: <strong>{target}</strong>, followingCount, followersCount })}</p>
|
||||||
<a href='/severed_relationships' target='_blank' rel='noopener noreferrer' className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></a>
|
<a href='/severed_relationships' target='_blank' rel='noopener' className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -55,7 +55,7 @@ class Report extends ImmutablePureComponent {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='notification__report__actions'>
|
<div className='notification__report__actions'>
|
||||||
<a href={`/admin/reports/${report.get('id')}`} className='button' target='_blank' rel='noopener noreferrer'>{intl.formatMessage(messages.openReport)}</a>
|
<a href={`/admin/reports/${report.get('id')}`} className='button' target='_blank' rel='noopener'>{intl.formatMessage(messages.openReport)}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,7 +70,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
|
|||||||
if (button === 0 && !(ctrlKey || metaKey)) {
|
if (button === 0 && !(ctrlKey || metaKey)) {
|
||||||
history.push(path);
|
history.push(path);
|
||||||
} else if (button === 1 || (button === 0 && (ctrlKey || metaKey))) {
|
} else if (button === 1 || (button === 0 && (ctrlKey || metaKey))) {
|
||||||
window.open(path, '_blank', 'noreferrer noopener');
|
window.open(path, '_blank', 'noopener');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ const Embed: React.FC<{ id: string }> = ({ id }) => {
|
|||||||
className='embed__overlay'
|
className='embed__overlay'
|
||||||
href={permalink}
|
href={permalink}
|
||||||
target='_blank'
|
target='_blank'
|
||||||
rel='noreferrer noopener'
|
rel='noopener'
|
||||||
aria-label=''
|
aria-label=''
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -208,7 +208,7 @@ export default class Card extends PureComponent {
|
|||||||
<div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
|
<div className='status-card__actions' onClick={this.handleEmbedClick} role='none'>
|
||||||
<div>
|
<div>
|
||||||
<button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button>
|
<button type='button' onClick={this.handleEmbedClick}><Icon id='play' icon={PlayArrowIcon} /></button>
|
||||||
<a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener noreferrer'><Icon id='external-link' icon={OpenInNewIcon} /></a>
|
<a href={card.get('url')} onClick={this.handleExternalLinkClick} target='_blank' rel='noopener'><Icon id='external-link' icon={OpenInNewIcon} /></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : spoilerButton}
|
) : spoilerButton}
|
||||||
@ -219,7 +219,7 @@ export default class Card extends PureComponent {
|
|||||||
return (
|
return (
|
||||||
<div className={classNames('status-card', { expanded: largeImage })} ref={this.setRef} onClick={revealed ? null : this.handleReveal} role={revealed ? 'button' : null}>
|
<div className={classNames('status-card', { expanded: largeImage })} ref={this.setRef} onClick={revealed ? null : this.handleReveal} role={revealed ? 'button' : null}>
|
||||||
{embed}
|
{embed}
|
||||||
<a href={card.get('url')} target='_blank' rel='noopener noreferrer'>{description}</a>
|
<a href={card.get('url')} target='_blank' rel='noopener'>{description}</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (card.get('image')) {
|
} else if (card.get('image')) {
|
||||||
@ -239,7 +239,7 @@ export default class Card extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<a href={card.get('url')} className={classNames('status-card', { expanded: largeImage, bottomless: showAuthor })} target='_blank' rel='noopener noreferrer' ref={this.setRef}>
|
<a href={card.get('url')} className={classNames('status-card', { expanded: largeImage, bottomless: showAuthor })} target='_blank' rel='noopener' ref={this.setRef}>
|
||||||
{embed}
|
{embed}
|
||||||
{description}
|
{description}
|
||||||
</a>
|
</a>
|
||||||
|
@ -24,7 +24,7 @@ export default class ActionsModal extends ImmutablePureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={`${text}-${i}`}>
|
<li key={`${text}-${i}`}>
|
||||||
<a href={href} target='_blank' rel='noopener noreferrer' onClick={this.props.onClick} data-index={i} className={classNames({ active })}>
|
<a href={href} target='_blank' rel='noopener' onClick={this.props.onClick} data-index={i} className={classNames({ active })}>
|
||||||
{icon && <IconButton title={text} icon={icon} iconComponent={iconComponent} role='presentation' tabIndex={-1} inverted />}
|
{icon && <IconButton title={text} icon={icon} iconComponent={iconComponent} role='presentation' tabIndex={-1} inverted />}
|
||||||
<div>
|
<div>
|
||||||
<div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div>
|
<div className={classNames({ 'actions-modal__item-label': !!meta })}>{text}</div>
|
||||||
|
@ -26,7 +26,7 @@ export const LinkFooter: React.FC<{
|
|||||||
{statusPageUrl && (
|
{statusPageUrl && (
|
||||||
<>
|
<>
|
||||||
<DividingCircle />
|
<DividingCircle />
|
||||||
<a href={statusPageUrl} target='_blank' rel='noopener noreferrer'>
|
<a href={statusPageUrl} target='_blank' rel='noopener'>
|
||||||
<FormattedMessage id='footer.status' defaultMessage='Status' />
|
<FormattedMessage id='footer.status' defaultMessage='Status' />
|
||||||
</a>
|
</a>
|
||||||
</>
|
</>
|
||||||
@ -72,15 +72,11 @@ export const LinkFooter: React.FC<{
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
<strong>Mastodon</strong>:{' '}
|
<strong>Mastodon</strong>:{' '}
|
||||||
<a href='https://joinmastodon.org' target='_blank' rel='noreferrer'>
|
<a href='https://joinmastodon.org' target='_blank' rel='noopener'>
|
||||||
<FormattedMessage id='footer.about' defaultMessage='About' />
|
<FormattedMessage id='footer.about' defaultMessage='About' />
|
||||||
</a>
|
</a>
|
||||||
<DividingCircle />
|
<DividingCircle />
|
||||||
<a
|
<a href='https://joinmastodon.org/apps' target='_blank' rel='noopener'>
|
||||||
href='https://joinmastodon.org/apps'
|
|
||||||
target='_blank'
|
|
||||||
rel='noreferrer'
|
|
||||||
>
|
|
||||||
<FormattedMessage id='footer.get_app' defaultMessage='Get the app' />
|
<FormattedMessage id='footer.get_app' defaultMessage='Get the app' />
|
||||||
</a>
|
</a>
|
||||||
<DividingCircle />
|
<DividingCircle />
|
||||||
@ -91,7 +87,7 @@ export const LinkFooter: React.FC<{
|
|||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<DividingCircle />
|
<DividingCircle />
|
||||||
<a href={source_url} rel='noopener noreferrer' target='_blank'>
|
<a href={source_url} rel='noopener' target='_blank'>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='footer.source_code'
|
id='footer.source_code'
|
||||||
defaultMessage='View source code'
|
defaultMessage='View source code'
|
||||||
|
@ -7,7 +7,7 @@ class TextFormatter
|
|||||||
|
|
||||||
URL_PREFIX_REGEX = %r{\A(https?://(www\.)?|xmpp:)}
|
URL_PREFIX_REGEX = %r{\A(https?://(www\.)?|xmpp:)}
|
||||||
|
|
||||||
DEFAULT_REL = %w(nofollow noopener noreferrer).freeze
|
DEFAULT_REL = %w(nofollow noopener).freeze
|
||||||
|
|
||||||
DEFAULT_OPTIONS = {
|
DEFAULT_OPTIONS = {
|
||||||
multiline: true,
|
multiline: true,
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
= t("statuses.visibilities.#{status.visibility}")
|
= t("statuses.visibilities.#{status.visibility}")
|
||||||
·
|
·
|
||||||
|
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status.proper), class: 'detailed-status__link', rel: 'noopener' do
|
||||||
= t('admin.statuses.view_publicly')
|
= t('admin.statuses.view_publicly')
|
||||||
|
|
||||||
- if status.proper.sensitive?
|
- if status.proper.sensitive?
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
= material_symbol 'link'
|
= material_symbol 'link'
|
||||||
= media_attachment.file_file_name
|
= media_attachment.file_file_name
|
||||||
.strike-card__statuses-list__item__meta
|
.strike-card__statuses-list__item__meta
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener' do
|
||||||
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||||
- unless status.application.nil?
|
- unless status.application.nil?
|
||||||
·
|
·
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
data: { confirm: t('admin.reports.are_you_sure') },
|
data: { confirm: t('admin.reports.are_you_sure') },
|
||||||
name: :report,
|
name: :report,
|
||||||
type: :submit
|
type: :submit
|
||||||
= link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener noreferrer'
|
= link_to t('admin.statuses.open'), ActivityPub::TagManager.instance.url_for(@status), class: 'button', target: '_blank', rel: 'noopener'
|
||||||
|
|
||||||
%h3= t('admin.statuses.metadata')
|
%h3= t('admin.statuses.metadata')
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
.time-period
|
.time-period
|
||||||
= date_range(@time_period)
|
= date_range(@time_period)
|
||||||
|
|
||||||
= link_to t('admin.tags.open'), tag_url(@tag), class: 'button', target: '_blank', rel: 'noopener noreferrer'
|
= link_to t('admin.tags.open'), tag_url(@tag), class: 'button', target: '_blank', rel: 'noopener'
|
||||||
|
|
||||||
- if current_user.can?(:view_dashboard)
|
- if current_user.can?(:view_dashboard)
|
||||||
.dashboard
|
.dashboard
|
||||||
@ -17,7 +17,7 @@
|
|||||||
label: t('admin.trends.tags.dashboard.tag_accounts_measure'),
|
label: t('admin.trends.tags.dashboard.tag_accounts_measure'),
|
||||||
measure: 'tag_accounts',
|
measure: 'tag_accounts',
|
||||||
params: { id: @tag.id },
|
params: { id: @tag.id },
|
||||||
rel: 'noopener noreferrer',
|
rel: 'noopener',
|
||||||
start_at: @time_period.first,
|
start_at: @time_period.first,
|
||||||
target: '_blank'
|
target: '_blank'
|
||||||
.dashboard__item
|
.dashboard__item
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
.one-liner
|
.one-liner
|
||||||
= admin_account_link_to status.account
|
= admin_account_link_to status.account
|
||||||
|
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', class: 'emojify', rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', class: 'emojify', rel: 'noopener' do
|
||||||
= one_line_preview(status)
|
= one_line_preview(status)
|
||||||
|
|
||||||
- status.ordered_media_attachments.each do |media_attachment|
|
- status.ordered_media_attachments.each do |media_attachment|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
%br/
|
%br/
|
||||||
|
|
||||||
= link_to tag_path(tag), target: '_blank', rel: 'noopener noreferrer' do
|
= link_to tag_path(tag), target: '_blank', rel: 'noopener' do
|
||||||
= t('admin.trends.tags.used_by_over_week', count: tag.history.reduce(0) { |sum, day| sum + day.accounts })
|
= t('admin.trends.tags.used_by_over_week', count: tag.history.reduce(0) { |sum, day| sum + day.accounts })
|
||||||
|
|
||||||
- if tag.trendable?
|
- if tag.trendable?
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
- compact ||= false
|
- compact ||= false
|
||||||
|
|
||||||
.card.h-card
|
.card.h-card
|
||||||
= link_to account_url, target: '_blank', rel: 'noopener noreferrer' do
|
= link_to account_url, target: '_blank', rel: 'noopener' do
|
||||||
- unless compact
|
- unless compact
|
||||||
.card__img
|
.card__img
|
||||||
= image_tag account.header.url, alt: ''
|
= image_tag account.header.url, alt: ''
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
= material_symbol 'link'
|
= material_symbol 'link'
|
||||||
= media_attachment.file_file_name
|
= media_attachment.file_file_name
|
||||||
.strike-card__statuses-list__item__meta
|
.strike-card__statuses-list__item__meta
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status), target: '_blank', rel: 'noopener' do
|
||||||
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||||
- unless status.application.nil?
|
- unless status.application.nil?
|
||||||
·
|
·
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
= media_attachment.file_file_name
|
= media_attachment.file_file_name
|
||||||
|
|
||||||
.detailed-status__meta
|
.detailed-status__meta
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'name-tag', target: '_blank', rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status.account), class: 'name-tag', target: '_blank', rel: 'noopener' do
|
||||||
= image_tag(status.account.avatar.url, width: 15, height: 15, alt: '', class: 'avatar')
|
= image_tag(status.account.avatar.url, width: 15, height: 15, alt: '', class: 'avatar')
|
||||||
.username= status.account.acct
|
.username= status.account.acct
|
||||||
·
|
·
|
||||||
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener noreferrer' do
|
= link_to ActivityPub::TagManager.instance.url_for(status), class: 'detailed-status__datetime', rel: 'noopener' do
|
||||||
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
%time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at)
|
||||||
- if status.edited?
|
- if status.edited?
|
||||||
·
|
·
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
- @applications.each do |application|
|
- @applications.each do |application|
|
||||||
.applications-list__item{ id: dom_id(application) }
|
.applications-list__item{ id: dom_id(application) }
|
||||||
- if application.website.present?
|
- if application.website.present?
|
||||||
= link_to application.name, application.website, target: '_blank', rel: 'noopener noreferrer', class: 'announcements-list__item__title'
|
= link_to application.name, application.website, target: '_blank', rel: 'noopener', class: 'announcements-list__item__title'
|
||||||
- else
|
- else
|
||||||
%strong.announcements-list__item__title
|
%strong.announcements-list__item__title
|
||||||
= application.name
|
= application.name
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
.redirect__message
|
.redirect__message
|
||||||
%h1= t('redirects.title', instance: site_hostname)
|
%h1= t('redirects.title', instance: site_hostname)
|
||||||
%p= t('redirects.prompt')
|
%p= t('redirects.prompt')
|
||||||
%p= link_to @redirect_path, @redirect_path, rel: 'noreferrer noopener'
|
%p= link_to @redirect_path, @redirect_path, rel: 'noopener'
|
||||||
|
@ -153,7 +153,7 @@ Rails.application.configure do
|
|||||||
'X-Frame-Options' => 'DENY',
|
'X-Frame-Options' => 'DENY',
|
||||||
'X-Content-Type-Options' => 'nosniff',
|
'X-Content-Type-Options' => 'nosniff',
|
||||||
'X-XSS-Protection' => '0',
|
'X-XSS-Protection' => '0',
|
||||||
'Referrer-Policy' => 'same-origin',
|
'Referrer-Policy' => ENV['ALLOW_REFERRER_ORIGIN'] == 'true' ? 'origin' : 'same-origin',
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO: Remove once devise-two-factor data migration complete
|
# TODO: Remove once devise-two-factor data migration complete
|
||||||
|
@ -114,7 +114,7 @@ class Sanitize
|
|||||||
|
|
||||||
add_attributes: {
|
add_attributes: {
|
||||||
'a' => {
|
'a' => {
|
||||||
'rel' => 'nofollow noopener noreferrer',
|
'rel' => 'nofollow noopener',
|
||||||
'target' => '_blank',
|
'target' => '_blank',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -39,15 +39,15 @@ RSpec.describe Sanitize::Config do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'keeps a with href' do
|
it 'keeps a with href' do
|
||||||
expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
expect(Sanitize.fragment('<a href="http://example.com">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener" target="_blank">Test</a>'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'keeps a with translate="no"' do
|
it 'keeps a with translate="no"' do
|
||||||
expect(Sanitize.fragment('<a href="http://example.com" translate="no">Test</a>', subject)).to eq '<a href="http://example.com" translate="no" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
expect(Sanitize.fragment('<a href="http://example.com" translate="no">Test</a>', subject)).to eq '<a href="http://example.com" translate="no" rel="nofollow noopener" target="_blank">Test</a>'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes "translate" attribute with invalid value' do
|
it 'removes "translate" attribute with invalid value' do
|
||||||
expect(Sanitize.fragment('<a href="http://example.com" translate="foo">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
expect(Sanitize.fragment('<a href="http://example.com" translate="foo">Test</a>', subject)).to eq '<a href="http://example.com" rel="nofollow noopener" target="_blank">Test</a>'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes a with unparsable href' do
|
it 'removes a with unparsable href' do
|
||||||
@ -55,7 +55,7 @@ RSpec.describe Sanitize::Config do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it 'keeps a with supported scheme and no host' do
|
it 'keeps a with supported scheme and no host' do
|
||||||
expect(Sanitize.fragment('<a href="dweb:/a/foo">Test</a>', subject)).to eq '<a href="dweb:/a/foo" rel="nofollow noopener noreferrer" target="_blank">Test</a>'
|
expect(Sanitize.fragment('<a href="dweb:/a/foo">Test</a>', subject)).to eq '<a href="dweb:/a/foo" rel="nofollow noopener" target="_blank">Test</a>'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sanitizes math to LaTeX' do
|
it 'sanitizes math to LaTeX' do
|
||||||
|
Loading…
Reference in New Issue
Block a user