Signed-off-by: Baptiste Lemoine <contact@cipherbliss.com>

# Conflicts:
#	yarn.lock
This commit is contained in:
tykayn 2021-01-13 14:45:58 +01:00 committed by Baptiste Lemoine
commit d96d645e0f
70 changed files with 480 additions and 433 deletions

View File

@ -30,7 +30,7 @@ plugins:
channel: eslint-7
rubocop:
enabled: true
channel: rubocop-0-92
channel: rubocop-1-70
sass-lint:
enabled: true
exclude_patterns:

View File

@ -2,17 +2,18 @@ require:
- rubocop-rails
AllCops:
TargetRubyVersion: 2.4
TargetRubyVersion: 2.5
NewCops: disable
Exclude:
- 'spec/**/*'
- 'db/**/*'
- 'app/views/**/*'
- 'config/**/*'
- 'bin/*'
- 'Rakefile'
- 'node_modules/**/*'
- 'Vagrantfile'
- 'vendor/**/*'
- 'spec/**/*'
- 'db/**/*'
- 'app/views/**/*'
- 'config/**/*'
- 'bin/*'
- 'Rakefile'
- 'node_modules/**/*'
- 'Vagrantfile'
- 'vendor/**/*'
- 'lib/json_ld/*'
- 'lib/templates/**/*'

View File

@ -1,7 +1,7 @@
FROM ubuntu:20.04 as build-dep
# Use bash for the shell
SHELL ["bash", "-c"]
SHELL ["/usr/bin/bash", "-c"]
# Install Node v12 (LTS)
ENV NODE_VER="12.20.0"

View File

@ -64,7 +64,7 @@ gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0'
gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar'
gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b176939f851338d0a4971a532'
gem 'nokogiri', '~> 1.10'
gem 'nokogiri', '~> 1.11'
gem 'nsa', '~> 0.2'
gem 'oj', '~> 3.10'
gem 'ox', '~> 2.14'
@ -80,7 +80,7 @@ gem 'rails-settings-cached', '~> 0.6'
gem 'redis', '~> 4.2', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'rqrcode', '~> 1.2'
gem 'ruby-progressbar', '~> 1.10'
gem 'ruby-progressbar', '~> 1.11'
gem 'sanitize', '~> 5.2'
gem 'scenic', '~> 1.5'
gem 'sidekiq', '~> 6.1'
@ -123,7 +123,7 @@ group :test do
gem 'microformats', '~> 4.2'
gem 'rails-controller-testing', '~> 1.0'
gem 'rspec-sidekiq', '~> 3.1'
gem 'simplecov', '~> 0.20', require: false
gem 'simplecov', '~> 0.21', require: false
gem 'webmock', '~> 3.11'
gem 'parallel_tests', '~> 3.4'
gem 'rspec_junit_formatter', '~> 0.4'
@ -133,7 +133,7 @@ group :development do
gem 'active_record_query_trace', '~> 1.8'
gem 'annotate', '~> 3.1'
gem 'better_errors', '~> 2.9'
gem 'binding_of_caller', '~> 0.7'
gem 'binding_of_caller', '~> 1.0'
gem 'bullet', '~> 6.1'
gem 'letter_opener', '~> 1.7'
gem 'letter_opener_web', '~> 1.4'

View File

@ -100,7 +100,7 @@ GEM
erubi (>= 1.0.0)
rack (>= 0.9.0)
bindata (2.4.8)
binding_of_caller (0.8.0)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
blurhash (0.1.4)
ffi (~> 1.10.0)
@ -165,7 +165,7 @@ GEM
crass (1.0.6)
css_parser (1.7.1)
addressable
debug_inspector (0.0.3)
debug_inspector (1.0.0)
devise (4.7.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@ -184,7 +184,7 @@ GEM
diff-lcs (1.4.4)
discard (1.2.0)
activerecord (>= 4.2, < 7)
docile (1.3.2)
docile (1.3.4)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
doorkeeper (5.4.0)
@ -236,7 +236,7 @@ GEM
fugit (1.3.9)
et-orbi (~> 1.1, >= 1.1.8)
raabro (~> 1.3)
fuubar (2.5.0)
fuubar (2.5.1)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
globalid (0.4.2)
@ -349,7 +349,7 @@ GEM
mime-types-data (3.2020.0512)
mimemagic (0.3.5)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
mini_portile2 (2.5.0)
minitest (5.14.2)
msgpack (1.3.3)
multi_json (1.15.0)
@ -359,8 +359,9 @@ GEM
net-ssh (>= 2.6.5, < 7.0.0)
net-ssh (6.1.0)
nio4r (2.5.4)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
nokogiri (1.11.0)
mini_portile2 (~> 2.5.0)
racc (~> 1.4)
nokogumbo (2.0.2)
nokogiri (~> 1.8, >= 1.8.4)
nsa (0.2.7)
@ -433,6 +434,7 @@ GEM
pundit (2.1.0)
activesupport (>= 3.0.0)
raabro (1.3.3)
racc (1.5.2)
rack (2.2.3)
rack-attack (6.3.1)
rack (>= 1.0, < 3)
@ -551,7 +553,7 @@ GEM
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 0.90.0, < 2.0)
ruby-progressbar (1.10.1)
ruby-progressbar (1.11.0)
ruby-saml (1.11.0)
nokogiri (>= 1.5.10)
rufus-scheduler (3.6.0)
@ -589,7 +591,7 @@ GEM
simple_form (5.0.3)
actionpack (>= 5.0)
activemodel (>= 5.0)
simplecov (0.20.0)
simplecov (0.21.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
@ -639,7 +641,7 @@ GEM
unf (~> 0.1.0)
tzinfo (1.2.9)
thread_safe (~> 0.1)
tzinfo-data (1.2020.5)
tzinfo-data (1.2020.6)
tzinfo (>= 1.0.0)
unf (0.1.4)
unf_ext
@ -688,7 +690,7 @@ DEPENDENCIES
annotate (~> 3.1)
aws-sdk-s3 (~> 1.87)
better_errors (~> 2.9)
binding_of_caller (~> 0.7)
binding_of_caller (~> 1.0)
blurhash (~> 0.1)
bootsnap (~> 1.5)
brakeman (~> 4.10)
@ -745,7 +747,7 @@ DEPENDENCIES
mime-types (~> 3.3.1)
net-ldap (~> 0.17)
nilsimsa!
nokogiri (~> 1.10)
nokogiri (~> 1.11)
nsa (~> 0.2)
oj (~> 3.10)
omniauth (~> 1.9)
@ -786,7 +788,7 @@ DEPENDENCIES
rspec_junit_formatter (~> 0.4)
rubocop (~> 1.7)
rubocop-rails (~> 2.9)
ruby-progressbar (~> 1.10)
ruby-progressbar (~> 1.11)
sanitize (~> 5.2)
scenic (~> 1.5)
sidekiq (~> 6.1)
@ -795,7 +797,7 @@ DEPENDENCIES
sidekiq-unique-jobs (~> 6.0)
simple-navigation (~> 4.1)
simple_form (~> 5.0)
simplecov (~> 0.20)
simplecov (~> 0.21)
sprockets (~> 3.7.2)
sprockets-rails (~> 3.2)
stackprof

View File

@ -1,4 +1,4 @@
web: env PORT=3000 bundle exec puma -C config/puma.rb
sidekiq: env PORT=3000 bundle exec sidekiq
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
stream: env PORT=4000 yarn run start
webpack: ./bin/webpack-dev-server --listen-host 0.0.0.0

View File

@ -5,7 +5,7 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
include JsonLdHelper
include AccountOwnedConcern
before_action :skip_unknown_actor_delete
before_action :skip_unknown_actor_activity
before_action :require_signature!
skip_before_action :authenticate_user!
@ -18,13 +18,13 @@ class ActivityPub::InboxesController < ActivityPub::BaseController
private
def skip_unknown_actor_delete
head 202 if unknown_deleted_account?
def skip_unknown_actor_activity
head 202 if unknown_affected_account?
end
def unknown_deleted_account?
def unknown_affected_account?
json = Oj.load(body, mode: :strict)
json.is_a?(Hash) && json['type'] == 'Delete' && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists?
json.is_a?(Hash) && %w(Delete Update).include?(json['type']) && json['actor'].present? && json['actor'] == value_or_id(json['object']) && !Account.where(uri: json['actor']).exists?
rescue Oj::ParseError
false
end

View File

@ -42,7 +42,7 @@ class Api::V1::AccountsController < Api::BaseController
end
def mute
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration] || 0))
MuteService.new.call(current_user.account, @account, notifications: truthy_param?(:notifications), duration: (params[:duration]&.to_i || 0))
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships
end

View File

@ -12,7 +12,7 @@ class Api::V1::Crypto::Keys::ClaimsController < Api::BaseController
private
def set_claim_results
@claim_results = devices.map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }.compact
@claim_results = devices.filter_map { |device_params| ::Keys::ClaimService.new.call(current_account, device_params[:account_id], device_params[:device_id]) }
end
def resource_params

View File

@ -17,7 +17,7 @@ class Api::V1::Crypto::Keys::QueriesController < Api::BaseController
end
def set_query_results
@query_results = @accounts.map { |account| ::Keys::QueryService.new.call(account) }.compact
@query_results = @accounts.filter_map { |account| ::Keys::QueryService.new.call(account) }
end
def account_ids

View File

@ -7,7 +7,7 @@ class Api::V1::MarkersController < Api::BaseController
before_action :require_user!
def index
@markers = current_user.markers.where(timeline: Array(params[:timeline])).each_with_object({}) { |marker, h| h[marker.timeline] = marker }
@markers = current_user.markers.where(timeline: Array(params[:timeline])).index_by(&:timeline)
render json: serialize_map(@markers)
end

View File

@ -38,14 +38,14 @@ module CacheConcern
klass.reload_stale_associations!(cached_keys_with_value.values) if klass.respond_to?(:reload_stale_associations!)
unless uncached_ids.empty?
uncached = klass.where(id: uncached_ids).with_includes.each_with_object({}) { |item, h| h[item.id] = item }
uncached = klass.where(id: uncached_ids).with_includes.index_by(&:id)
uncached.each_value do |item|
Rails.cache.write(item, item)
end
end
raw.map { |item| cached_keys_with_value[item.id] || uncached[item.id] }.compact
raw.filter_map { |item| cached_keys_with_value[item.id] || uncached[item.id] }
end
def cache_collection_paginated_by_id(raw, klass, limit, options)

View File

@ -7,8 +7,12 @@ module Settings
def destroy
if valid_picture?
msg = I18n.t('generic.changes_saved_msg') if UpdateAccountService.new.call(@account, { @picture => nil, "#{@picture}_remote_url" => '' })
redirect_to settings_profile_path, notice: msg, status: 303
if UpdateAccountService.new.call(@account, { @picture => nil, "#{@picture}_remote_url" => '' })
ActivityPub::UpdateDistributionWorker.perform_async(@account.id)
redirect_to settings_profile_path, notice: I18n.t('generic.changes_saved_msg'), status: 303
else
redirect_to settings_profile_path
end
else
bad_request
end

View File

@ -1,8 +1,8 @@
import React, { PureComponent, Fragment } from 'react';
import React, { Fragment, PureComponent } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import { IntlProvider, addLocaleData } from 'react-intl';
import { List as ImmutableList, fromJS } from 'immutable';
import { addLocaleData, IntlProvider } from 'react-intl';
import { fromJS } from 'immutable';
import { getLocale } from 'mastodon/locales';
import { getScrollbarWidth } from 'mastodon/utils/scrollbar';
import MediaGallery from 'mastodon/components/media_gallery';
@ -27,10 +27,11 @@ export default class MediaContainer extends PureComponent {
};
state = {
media: null,
index: null,
time: null,
media : null,
index : null,
time : null,
backgroundColor: null,
options : null,
};
handleOpenMedia = (media, index) => {
@ -38,26 +39,29 @@ export default class MediaContainer extends PureComponent {
document.documentElement.style.marginRight = `${getScrollbarWidth()}px`;
this.setState({ media, index });
}
};
handleOpenVideo = (video, time) => {
const media = ImmutableList([video]);
handleOpenVideo = (options) => {
const { components } = this.props;
const { media } = JSON.parse(components[options.componetIndex].getAttribute('data-props'));
const mediaList = fromJS(media);
document.body.classList.add('with-modals--active');
document.documentElement.style.marginRight = `${getScrollbarWidth()}px`;
this.setState({ media, time });
}
this.setState({ media: mediaList, options });
};
handleCloseMedia = () => {
document.body.classList.remove('with-modals--active');
document.documentElement.style.marginRight = 0;
this.setState({
media: null,
index: null,
time: null,
media : null,
index : null,
time : null,
backgroundColor: null,
options : null,
});
}
@ -83,7 +87,8 @@ export default class MediaContainer extends PureComponent {
...(hashtag ? { hashtag: fromJS(hashtag) } : {}),
...(componentName === 'Video' ? {
onOpenVideo: this.handleOpenVideo,
componetIndex: i,
onOpenVideo : this.handleOpenVideo,
} : {
onOpenMedia: this.handleOpenMedia,
}),
@ -100,7 +105,9 @@ export default class MediaContainer extends PureComponent {
<MediaModal
media={this.state.media}
index={this.state.index || 0}
time={this.state.time}
currentTime={this.state.options?.startTime}
autoPlay={this.state.options?.autoPlay}
volume={this.state.options?.defaultVolume}
onClose={this.handleCloseMedia}
onChangeBackgroundColor={this.setBackgroundColor}
/>

View File

@ -92,7 +92,7 @@ class ComposeForm extends ImmutablePureComponent {
const fulltext = this.getFulltextForCharacterCounting();
const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0;
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 500 || (isOnlyWhitespace && !anyMedia));
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > this.props.maxTootCharsLimit || (isOnlyWhitespace && !anyMedia));
}
handleSubmit = () => {
@ -258,8 +258,11 @@ class ComposeForm extends ImmutablePureComponent {
<PollButtonContainer />
<PrivacyDropdownContainer />
<SpoilerButtonContainer />
</div>
<div className='character-counter__wrapper'><CharacterCounter max={7777} text={this.getFulltextForCharacterCounting()} /></div>
</div >
<div className='character-counter__wrapper'><CharacterCounter
max={this.props.maxTootCharsLimit}
text={this.getFulltextForCharacterCounting()}
/></div >
</div>
<div className='compose-form__publish'>

View File

@ -6,11 +6,11 @@ import StatusListContainer from '../ui/containers/status_list_container';
import Column from '../../components/column';
import ColumnBackButton from '../../components/column_back_button';
import ColumnHeader from '../../components/column_header';
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import { addColumn, moveColumn, removeColumn } from '../../actions/columns';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { connectListStream } from '../../actions/streaming';
import { expandListTimeline } from '../../actions/timelines';
import { fetchList, deleteList, updateList } from '../../actions/lists';
import { deleteList, fetchList, updateList } from '../../actions/lists';
import { openModal } from '../../actions/modal';
import MissingIndicator from '../../components/missing_indicator';
import LoadingIndicator from '../../components/loading_indicator';
@ -194,7 +194,14 @@ class ListTimeline extends React.PureComponent {
</span>
<div className='column-settings__row'>
{ ['none', 'list', 'followed'].map(policy => (
<RadioButton name='order' value={policy} label={intl.formatMessage(messages[policy])} checked={replies_policy === policy} onChange={this.handleRepliesPolicyChange} />
<RadioButton
name='order'
key={policy}
value={policy}
label={intl.formatMessage(messages[policy])}
checked={replies_policy === policy}
onChange={this.handleRepliesPolicyChange}
/>
))}
</div>
</div>

View File

@ -6,7 +6,7 @@ import { connect } from 'react-redux';
import classNames from 'classnames';
import { changeUploadCompose, uploadThumbnail } from '../../../actions/compose';
import { getPointerPosition } from '../../video';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import IconButton from 'mastodon/components/icon_button';
import Button from 'mastodon/components/button';
import Video from 'mastodon/features/video';
@ -226,9 +226,9 @@ class FocalPointModal extends ImmutablePureComponent {
fetchTesseract().then(({ createWorker }) => {
const worker = createWorker({
workerPath: tesseractWorkerPath,
corePath: tesseractCorePath,
langPath: assetHost,
logger: ({ status, progress }) => {
corePath : tesseractCorePath,
langPath : `${assetHost}/ocr/lang-data/`,
logger : ({ status, progress }) => {
if (status === 'recognizing text') {
this.setState({ ocrStatus: 'detecting', progress });
} else {

View File

@ -26,12 +26,15 @@ export default @injectIntl
class MediaModal extends ImmutablePureComponent {
static propTypes = {
media: ImmutablePropTypes.list.isRequired,
statusId: PropTypes.string,
index: PropTypes.number.isRequired,
onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
media : ImmutablePropTypes.list.isRequired,
statusId : PropTypes.string,
index : PropTypes.number.isRequired,
onClose : PropTypes.func.isRequired,
intl : PropTypes.object.isRequired,
onChangeBackgroundColor: PropTypes.func.isRequired,
currentTime : PropTypes.number,
autoPlay : PropTypes.bool,
volume : PropTypes.number,
};
static contextTypes = {
@ -183,7 +186,7 @@ class MediaModal extends ImmutablePureComponent {
/>
);
} else if (image.get('type') === 'video') {
const { time } = this.props;
const { currentTime, autoPlay, volume } = this.props;
return (
<Video
@ -192,7 +195,10 @@ class MediaModal extends ImmutablePureComponent {
src={image.get('url')}
width={image.get('width')}
height={image.get('height')}
currentTime={time || 0}
frameRate={image.getIn(['meta', 'original', 'frame_rate'])}
currentTime={currentTime || 0}
autoPlay={autoPlay || false}
volume={volume || 1}
onCloseVideo={onClose}
detailed
alt={image.get('description')}

View File

@ -1,10 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import { is } from 'immutable';
import { throttle, debounce } from 'lodash';
import { debounce, throttle } from 'lodash';
import classNames from 'classnames';
import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen';
import { exitFullscreen, isFullscreen, requestFullscreen } from '../ui/util/fullscreen';
import { displayMedia, useBlurhash } from '../../initial_state';
import Icon from 'mastodon/components/icon';
import Blurhash from 'mastodon/components/blurhash';
@ -101,30 +101,31 @@ class Video extends React.PureComponent {
preview: PropTypes.string,
frameRate: PropTypes.string,
src: PropTypes.string.isRequired,
alt: PropTypes.string,
width: PropTypes.number,
height: PropTypes.number,
sensitive: PropTypes.bool,
currentTime: PropTypes.number,
onOpenVideo: PropTypes.func,
onCloseVideo: PropTypes.func,
detailed: PropTypes.bool,
inline: PropTypes.bool,
editable: PropTypes.bool,
alwaysVisible: PropTypes.bool,
cacheWidth: PropTypes.func,
visible: PropTypes.bool,
onToggleVisibility: PropTypes.func,
alt : PropTypes.string,
width : PropTypes.number,
height : PropTypes.number,
sensitive : PropTypes.bool,
currentTime : PropTypes.number,
onOpenVideo : PropTypes.func,
onCloseVideo : PropTypes.func,
detailed : PropTypes.bool,
inline : PropTypes.bool,
editable : PropTypes.bool,
alwaysVisible : PropTypes.bool,
cacheWidth : PropTypes.func,
visible : PropTypes.bool,
onToggleVisibility : PropTypes.func,
deployPictureInPicture: PropTypes.func,
intl: PropTypes.object.isRequired,
blurhash: PropTypes.string,
autoPlay: PropTypes.bool,
volume: PropTypes.number,
muted: PropTypes.bool,
intl : PropTypes.object.isRequired,
blurhash : PropTypes.string,
autoPlay : PropTypes.bool,
volume : PropTypes.number,
muted : PropTypes.bool,
componetIndex : PropTypes.number,
};
static defaultProps = {
frameRate: 25,
frameRate: '25',
};
state = {
@ -498,9 +499,10 @@ class Video extends React.PureComponent {
this.video.pause();
this.props.onOpenVideo({
startTime: this.video.currentTime,
autoPlay: !this.state.paused,
startTime : this.video.currentTime,
autoPlay : !this.state.paused,
defaultVolume: this.state.volume,
componetIndex: this.props.componetIndex,
});
}

View File

@ -80,10 +80,6 @@
// custom bliss
.navigation-panel{
.column-link{
span{
opacity: 0 ;
}
&:hover span{
opacity: 1;
transition: opacity ease 0.1s;

View File

@ -2884,6 +2884,7 @@ a.account__display-name {
flex: 0 0 auto;
padding: 10px;
padding-top: 20px;
z-index: 1;
ul {
margin-bottom: 10px;

View File

@ -445,7 +445,6 @@
}
.logo-button {
line-height: 36px;
padding: 3px 15px;
}

View File

@ -83,7 +83,7 @@
background: $ui-highlight-color;
color: $primary-text-color;
text-transform: none;
line-height: 16px;
line-height: 1.2;
height: auto;
min-height: 36px;
min-width: 88px;
@ -131,6 +131,12 @@
}
}
a.button.logo-button {
display: inline-flex;
align-items: center;
justify-content: center;
}
.embed,
.public-layout {
.status__content[data-spoiler=folded] {

View File

@ -11,8 +11,13 @@ class ActivityPub::Activity::Block < ActivityPub::Activity
return
end
UnfollowService.new.call(@account, target_account) if @account.following?(target_account)
UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
RejectFollowService.new.call(target_account, @account) if target_account.requested?(@account)
@account.block!(target_account, uri: @json['id']) unless delete_arrived_first?(@json['id'])
unless delete_arrived_first?(@json['id'])
BlockWorker.perform_async(@account.id, target_account.id)
@account.block!(target_account, uri: @json['id'])
end
end
end

View File

@ -4,8 +4,8 @@ class ActivityPub::Activity::Flag < ActivityPub::Activity
def perform
return if skip_reports?
target_accounts = object_uris.map { |uri| account_from_uri(uri) }.compact.select(&:local?)
target_statuses_by_account = object_uris.map { |uri| status_from_uri(uri) }.compact.select(&:local?).group_by(&:account_id)
target_accounts = object_uris.filter_map { |uri| account_from_uri(uri) }.select(&:local?)
target_statuses_by_account = object_uris.filter_map { |uri| status_from_uri(uri) }.select(&:local?).group_by(&:account_id)
target_accounts.each do |target_account|
target_statuses = target_statuses_by_account[target_account.id]

View File

@ -25,11 +25,11 @@ class EntityCache
end
unless uncached_ids.empty?
uncached = CustomEmoji.where(shortcode: shortcodes, domain: domain, disabled: false).each_with_object({}) { |item, h| h[item.shortcode] = item }
uncached = CustomEmoji.where(shortcode: shortcodes, domain: domain, disabled: false).index_by(&:shortcode)
uncached.each_value { |item| Rails.cache.write(to_key(:emoji, item.shortcode, domain), item, expires_in: MAX_EXPIRATION) }
end
shortcodes.map { |shortcode| cached[to_key(:emoji, shortcode, domain)] || uncached[shortcode] }.compact
shortcodes.filter_map { |shortcode| cached[to_key(:emoji, shortcode, domain)] || uncached[shortcode] }
end
def to_key(type, *ids)

View File

@ -30,7 +30,7 @@ module Settings
def all_as_records
vars = thing_scoped
records = vars.each_with_object({}) { |r, h| h[r.var] = r }
records = vars.index_by(&:var)
Setting.default_settings.each do |key, default_value|
next if records.key?(key) || default_value.is_a?(Hash)

View File

@ -186,9 +186,9 @@ class SpamCheck
def matching_status_ids
if nilsimsa?
other_digests.select { |record| record.start_with?('nilsimsa') && nilsimsa_compare_value(digest, record.split(':')[1]) >= NILSIMSA_COMPARE_THRESHOLD }.map { |record| record.split(':')[2] }.compact
other_digests.select { |record| record.start_with?('nilsimsa') && nilsimsa_compare_value(digest, record.split(':')[1]) >= NILSIMSA_COMPARE_THRESHOLD }.filter_map { |record| record.split(':')[2] }
else
other_digests.select { |record| record.start_with?('md5') && record.split(':')[1] == digest }.map { |record| record.split(':')[2] }.compact
other_digests.select { |record| record.start_with?('md5') && record.split(':')[1] == digest }.filter_map { |record| record.split(':')[2] }
end
end

View File

@ -21,7 +21,7 @@ class Webfinger
private
def links
@links ||= @json['links'].map { |link| [link['rel'], link] }.to_h
@links ||= @json['links'].index_by { |link| link['rel'] }
end
end

View File

@ -273,7 +273,7 @@ class Account < ApplicationRecord
end
def tags_as_strings=(tag_names)
hashtags_map = Tag.find_or_create_by_names(tag_names).each_with_object({}) { |tag, h| h[tag.name] = tag }
hashtags_map = Tag.find_or_create_by_names(tag_names).index_by(&:name)
# Remove hashtags that are to be deleted
tags.each do |tag|
@ -385,15 +385,17 @@ class Account < ApplicationRecord
end
class Field < ActiveModelSerializers::Model
attributes :name, :value, :verified_at, :account, :errors
attributes :name, :value, :verified_at, :account
def initialize(account, attributes)
@account = account
@attributes = attributes
@name = attributes['name'].strip[0, string_limit]
@value = attributes['value'].strip[0, string_limit]
@verified_at = attributes['verified_at']&.to_datetime
@errors = {}
@original_field = attributes
string_limit = account.local? ? 255 : 2047
super(
account: account,
name: attributes['name'].strip[0, string_limit],
value: attributes['value'].strip[0, string_limit],
verified_at: attributes['verified_at']&.to_datetime,
)
end
def verified?
@ -415,22 +417,12 @@ class Account < ApplicationRecord
end
def mark_verified!
@verified_at = Time.now.utc
@attributes['verified_at'] = @verified_at
self.verified_at = Time.now.utc
@original_field['verified_at'] = verified_at
end
def to_h
{ name: @name, value: @value, verified_at: @verified_at }
end
private
def string_limit
if account.local?
255
else
2047
end
{ name: name, value: value, verified_at: verified_at }
end
end
@ -516,7 +508,7 @@ class Account < ApplicationRecord
def from_text(text)
return [] if text.blank?
text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.map do |(username, domain)|
text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.filter_map do |(username, domain)|
domain = begin
if TagManager.instance.local_domain?(domain)
nil
@ -525,7 +517,7 @@ class Account < ApplicationRecord
end
end
EntityCache.instance.mention(username, domain)
end.compact
end
end
private

View File

@ -83,7 +83,7 @@ module StatusThreadingConcern
def find_statuses_from_tree_path(ids, account, promote: false)
statuses = Status.with_accounts(ids).to_a
account_ids = statuses.map(&:account_id).uniq
domains = statuses.map(&:account_domain).compact.uniq
domains = statuses.filter_map(&:account_domain).uniq
relations = relations_map_for_account(account, account_ids, domains)
statuses.reject! { |status| StatusFilter.new(status, account, relations).filtered? }

View File

@ -46,7 +46,7 @@ class CustomFilter < ApplicationRecord
private
def clean_up_contexts
self.context = Array(context).map(&:strip).map(&:presence).compact
self.context = Array(context).map(&:strip).filter_map(&:presence)
end
def remove_cache

View File

@ -2,12 +2,11 @@
class HomeFeed < Feed
def initialize(account)
@type = :home
@id = account.id
@account = account
super(:home, account.id)
end
def regenerating?
redis.exists?("account:#{@id}:regeneration")
redis.exists?("account:#{@account.id}:regeneration")
end
end

View File

@ -2,7 +2,6 @@
class ListFeed < Feed
def initialize(list)
@type = :list
@id = list.id
super(:list, list.id)
end
end

View File

@ -92,11 +92,11 @@ class Notification < ApplicationRecord
end
def reload_stale_associations!(cached_items)
account_ids = (cached_items.map(&:from_account_id) + cached_items.map { |item| item.target_status&.account_id }.compact).uniq
account_ids = (cached_items.map(&:from_account_id) + cached_items.filter_map { |item| item.target_status&.account_id }).uniq
return if account_ids.empty?
accounts = Account.where(id: account_ids).includes(:account_stat).each_with_object({}) { |a, h| h[a.id] = a }
accounts = Account.where(id: account_ids).includes(:account_stat).index_by(&:id)
cached_items.each do |item|
item.from_account = accounts[item.from_account_id]

View File

@ -73,10 +73,12 @@ class Poll < ApplicationRecord
attributes :id, :title, :votes_count, :poll
def initialize(poll, id, title, votes_count)
@poll = poll
@id = id
@title = title
@votes_count = votes_count
super(
poll: poll,
id: id,
title: title,
votes_count: votes_count,
)
end
end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
class PublicFeed < Feed
class PublicFeed
# @param [Account] account
# @param [Hash] options
# @option [Boolean] :with_replies
@ -33,28 +33,30 @@ class PublicFeed < Feed
private
attr_reader :account, :options
def with_reblogs?
@options[:with_reblogs]
options[:with_reblogs]
end
def with_replies?
@options[:with_replies]
options[:with_replies]
end
def local_only?
@options[:local]
options[:local]
end
def remote_only?
@options[:remote]
options[:remote]
end
def account?
@account.present?
account.present?
end
def media_only?
@options[:only_media]
options[:only_media]
end
def public_scope
@ -82,9 +84,9 @@ class PublicFeed < Feed
end
def account_filters_scope
Status.not_excluded_by_account(@account).tap do |scope|
scope.merge!(Status.not_domain_blocked_by_account(@account)) unless local_only?
scope.merge!(Status.in_chosen_languages(@account)) if @account.chosen_languages.present?
Status.not_excluded_by_account(account).tap do |scope|
scope.merge!(Status.not_domain_blocked_by_account(account)) unless local_only?
scope.merge!(Status.in_chosen_languages(account)) if account.chosen_languages.present?
end
end
end

View File

@ -40,7 +40,7 @@ class Setting < RailsSettings::Base
def all_as_records
vars = thing_scoped
records = vars.each_with_object({}) { |r, h| h[r.var] = r }
records = vars.index_by(&:var)
default_settings.each do |key, default_value|
next if records.key?(key) || default_value.is_a?(Hash)

View File

@ -301,7 +301,7 @@ class Status < ApplicationRecord
return if account_ids.empty?
accounts = Account.where(id: account_ids).includes(:account_stat).each_with_object({}) { |a, h| h[a.id] = a }
accounts = Account.where(id: account_ids).includes(:account_stat).index_by(&:id)
cached_items.each do |item|
item.account = accounts[item.account_id]
@ -334,7 +334,7 @@ class Status < ApplicationRecord
def from_text(text)
return [] if text.blank?
text.scan(FetchLinkCardService::URL_PATTERN).map(&:first).uniq.map do |url|
text.scan(FetchLinkCardService::URL_PATTERN).map(&:first).uniq.filter_map do |url|
status = begin
if TagManager.instance.local_url?(url)
ActivityPub::TagManager.instance.uri_to_resource(url, Status)
@ -343,7 +343,7 @@ class Status < ApplicationRecord
end
end
status&.distributable? ? status : nil
end.compact
end
end
end

View File

@ -13,9 +13,8 @@ class TagFeed < PublicFeed
# @option [Boolean] :remote
# @option [Boolean] :only_media
def initialize(tag, account, options = {})
@tag = tag
@account = account
@options = options
@tag = tag
super(account, options)
end
# @param [Integer] limit
@ -40,15 +39,15 @@ class TagFeed < PublicFeed
private
def tagged_with_any_scope
Status.group(:id).tagged_with(tags_for(Array(@tag.name) | Array(@options[:any])))
Status.group(:id).tagged_with(tags_for(Array(@tag.name) | Array(options[:any])))
end
def tagged_with_all_scope
Status.group(:id).tagged_with_all(tags_for(@options[:all]))
Status.group(:id).tagged_with_all(tags_for(options[:all]))
end
def tagged_with_none_scope
Status.group(:id).tagged_with_none(tags_for(@options[:none]))
Status.group(:id).tagged_with_none(tags_for(options[:none]))
end
def tags_for(names)

View File

@ -91,7 +91,7 @@ class TrendingTags
tags = Tag.where(id: tag_ids)
tags = tags.trendable if filtered
tags = tags.each_with_object({}) { |tag, h| h[tag.id] = tag }
tags = tags.index_by(&:id)
tag_ids.map { |tag_id| tags[tag_id] }.compact.take(limit)
end

View File

@ -14,7 +14,7 @@ class StatusRelationshipsPresenter
else
statuses = statuses.compact
status_ids = statuses.flat_map { |s| [s.id, s.reblog_of_id] }.uniq.compact
conversation_ids = statuses.map(&:conversation_id).compact.uniq
conversation_ids = statuses.filter_map(&:conversation_id).uniq
pinnable_status_ids = statuses.map(&:proper).select { |s| s.account_id == current_account_id && %w(public unlisted).include?(s.visibility) }.map(&:id)
@reblogs_map = Status.reblogs_map(status_ids, current_account_id).merge(options[:reblogs_map] || {})

View File

@ -24,8 +24,7 @@ class ActivityPub::FetchFeaturedCollectionService < BaseService
def process_items(items)
status_ids = items.map { |item| value_or_id(item) }
.reject { |uri| ActivityPub::TagManager.instance.local_uri?(uri) }
.map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) }
.compact
.filter_map { |uri| ActivityPub::FetchRemoteStatusService.new.call(uri) }
.select { |status| status.account_id == @account.id }
.map(&:id)

View File

@ -37,7 +37,7 @@ class ActivityPub::ProcessCollectionService < BaseService
end
def process_items(items)
items.reverse_each.map { |item| process_item(item) }.compact
items.reverse_each.filter_map { |item| process_item(item) }
end
def supported_context?

View File

@ -30,7 +30,7 @@ class ActivityPub::ProcessPollService < BaseService
voters_count = @json['votersCount']
latest_options = items.map { |item| item['name'].presence || item['content'] }.compact
latest_options = items.filter_map { |item| item['name'].presence || item['content'] }
# If for some reasons the options were changed, it invalidates all previous
# votes, so we need to remove them

View File

@ -14,7 +14,7 @@ class ActivityPub::SynchronizeFollowersService < BaseService
# should never happen in practice, since in almost all cases we keep an
# Account record, and should we not do that, we should have sent a Delete.
# In any case there is not much we can do if that occurs.
@expected_followers = items.map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) }.compact
@expected_followers = items.filter_map { |uri| ActivityPub::TagManager.instance.uri_to_resource(uri, Account) }
remove_unexpected_local_followers!
handle_unexpected_outgoing_follows!

View File

@ -67,7 +67,7 @@ class FetchLinkCardService < BaseService
else
html = Nokogiri::HTML(@status.text)
links = html.css('a')
urls = links.map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.compact.map(&:normalize).compact
urls = links.filter_map { |a| Addressable::URI.parse(a['href']) unless skip_link?(a) }.filter_map(&:normalize)
end
urls.reject { |uri| bad_url?(uri) }.first

View File

@ -107,12 +107,12 @@ class ImportService < BaseService
end
end
statuses = items.map do |uri|
statuses = items.filter_map do |uri|
status = ActivityPub::TagManager.instance.uri_to_resource(uri, Status)
next if status.nil? && ActivityPub::TagManager.instance.local_uri?(uri)
status || ActivityPub::FetchRemoteStatusService.new.call(uri)
end.compact
end
account_ids = statuses.map(&:account_id)
preloaded_relations = relations_map_for_account(@account, account_ids)

View File

@ -8,11 +8,13 @@ class Keys::ClaimService < BaseService
:key, :signature
def initialize(account, device_id, key_attributes = {})
@account = account
@device_id = device_id
@key_id = key_attributes[:key_id]
@key = key_attributes[:key]
@signature = key_attributes[:signature]
super(
account: account,
device_id: device_id,
key_id: key_attributes[:key_id],
key: key_attributes[:key],
signature: key_attributes[:signature],
)
end
end

View File

@ -7,8 +7,10 @@ class Keys::QueryService < BaseService
attributes :account, :devices
def initialize(account, devices)
@account = account
@devices = devices || []
super(
account: account,
devices: devices || [],
)
end
def find(device_id)
@ -20,11 +22,13 @@ class Keys::QueryService < BaseService
attributes :device_id, :name, :identity_key, :fingerprint_key
def initialize(attributes = {})
@device_id = attributes[:device_id]
@name = attributes[:name]
@identity_key = attributes[:identity_key]
@fingerprint_key = attributes[:fingerprint_key]
@claim_url = attributes[:claim_url]
super(
device_id: attributes[:device_id],
name: attributes[:name],
identity_key: attributes[:identity_key],
fingerprint_key: attributes[:fingerprint_key],
)
@claim_url = attributes[:claim_url]
end
def valid_claim_url?

View File

@ -5,7 +5,7 @@ class ExistingUsernameValidator < ActiveModel::EachValidator
return if value.blank?
if options[:multiple]
missing_usernames = value.split(',').map { |username| username.strip.gsub(/\A@/, '') }.map { |username| username unless Account.find_local(username) }.compact
missing_usernames = value.split(',').map { |username| username.strip.gsub(/\A@/, '') }.filter_map { |username| username unless Account.find_local(username) }
record.errors.add(attribute, I18n.t('existing_username_validator.not_found_multiple', usernames: missing_usernames.join(', '))) if missing_usernames.any?
else
record.errors.add(attribute, I18n.t('existing_username_validator.not_found')) unless Account.find_local(value.strip.gsub(/\A@/, ''))

View File

@ -14,7 +14,7 @@
- unless status.proper.media_attachments.empty?
- if status.proper.media_attachments.first.video?
- video = status.proper.media_attachments.first
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), blurhash: video.blurhash, sensitive: status.proper.sensitive?, visible: false, width: 610, height: 343, inline: true, alt: video.description
= react_component :video, src: video.file.url(:original), preview: video.file.url(:small), frameRate: video.file.meta.dig('original', 'frame_rate'), blurhash: video.blurhash, sensitive: status.proper.sensitive?, visible: false, width: 610, height: 343, inline: true, alt: video.description, media: [ActiveModelSerializers::SerializableResource.new(video, serializer: REST::MediaAttachmentSerializer)].as_json
- elsif status.proper.media_attachments.first.audio?
- audio = status.proper.media_attachments.first
= react_component :audio, src: audio.file.url(:original), height: 110, alt: audio.description, duration: audio.file.meta.dig(:original, :duration)

View File

@ -3,7 +3,7 @@
= javascript_pack_tag 'public', crossorigin: 'anonymous'
- if @media_attachment.video?
= react_component :video, src: @media_attachment.file.url(:original), preview: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.file.url(:small), blurhash: @media_attachment.blurhash, width: 670, height: 380, editable: true, detailed: true, inline: true, alt: @media_attachment.description do
= react_component :video, src: @media_attachment.file.url(:original), preview: @media_attachment.thumbnail.present? ? @media_attachment.thumbnail.url : @media_attachment.file.url(:small), frameRate: @media_attachment.file.meta.dig('original', 'frame_rate'), blurhash: @media_attachment.blurhash, width: 670, height: 380, editable: true, detailed: true, inline: true, alt: @media_attachment.description, media: [ActiveModelSerializers::SerializableResource.new(@media_attachment, serializer: REST::MediaAttachmentSerializer)].as_json do
%video{ controls: 'controls' }
%source{ src: @media_attachment.file.url(:original) }
- elsif @media_attachment.gifv?

View File

@ -29,7 +29,7 @@
- if !status.media_attachments.empty?
- if status.media_attachments.first.video?
- video = status.media_attachments.first
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 670, height: 380, detailed: true, inline: true, alt: video.description do
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), frameRate: video.file.meta.dig('original', 'frame_rate'), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 670, height: 380, detailed: true, inline: true, alt: video.description, media: [ActiveModelSerializers::SerializableResource.new(video, serializer: REST::MediaAttachmentSerializer)].as_json do
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
- elsif status.media_attachments.first.audio?
- audio = status.media_attachments.first

View File

@ -38,7 +38,7 @@
- if !status.media_attachments.empty?
- if status.media_attachments.first.video?
- video = status.media_attachments.first
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 610, height: 343, inline: true, alt: video.description do
= react_component :video, src: full_asset_url(video.file.url(:original)), preview: full_asset_url(video.thumbnail.present? ? video.thumbnail.url : video.file.url(:small)), frameRate: video.file.meta.dig('original', 'frame_rate'), blurhash: video.blurhash, sensitive: sensitized?(status, current_account), width: 610, height: 343, inline: true, alt: video.description, media: [ActiveModelSerializers::SerializableResource.new(video, serializer: REST::MediaAttachmentSerializer)].as_json do
= render partial: 'statuses/attachment_list', locals: { attachments: status.media_attachments }
- elsif status.media_attachments.first.audio?
- audio = status.media_attachments.first

View File

@ -7,6 +7,7 @@ require 'rails/all'
Bundler.require(*Rails.groups)
require_relative '../app/lib/exceptions'
require_relative '../lib/enumerable'
require_relative '../lib/redis/namespace_extensions'
require_relative '../lib/paperclip/url_generator_extensions'
require_relative '../lib/paperclip/attachment_extensions'

View File

@ -60,6 +60,7 @@ Devise.setup do |config|
saml_options[:attribute_statements][:verified] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED']
saml_options[:attribute_statements][:verified_email] = [ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']] if ENV['SAML_ATTRIBUTES_STATEMENTS_VERIFIED_EMAIL']
saml_options[:uid_attribute] = ENV['SAML_UID_ATTRIBUTE'] if ENV['SAML_UID_ATTRIBUTE']
saml_options[:allowed_clock_drift] = ENV['SAML_ALLOWED_CLOCK_DRIFT'] if ENV['SAML_ALLOWED_CLOCK_DRIFT']
config.omniauth :saml, saml_options
end
end

View File

@ -68,7 +68,7 @@ en:
deleted:
explanation: The following security key has been deleted from your account
subject: 'Mastodon: Security key deleted'
title: One of you security keys has been deleted
title: One of your security keys has been deleted
webauthn_disabled:
explanation: Authentication with security keys has been disabled for your account. Login is now possible using only the token generated by the paired TOTP app.
subject: 'Mastodon: Authentication with security keys disabled'

View File

@ -2,14 +2,14 @@
const { resolve } = require('path');
const { env } = require('process');
const { safeLoad } = require('js-yaml');
const { load } = require('js-yaml');
const { readFileSync } = require('fs');
const configPath = resolve('config', 'webpacker.yml');
const settings = safeLoad(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV];
const settings = load(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV];
const themePath = resolve('config', 'themes.yml');
const themes = safeLoad(readFileSync(themePath), 'utf8');
const themes = load(readFileSync(themePath), 'utf8');
const output = {
path: resolve('public', settings.public_output_path),

4
dist/nginx.conf vendored
View File

@ -73,7 +73,7 @@ server {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
proxy_pass_header Server;
@ -98,7 +98,7 @@ server {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Proxy "";
proxy_pass http://streaming;

26
lib/enumerable.rb Normal file
View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
module Enumerable
# TODO: Remove this once stop to support Ruby 2.6
if RUBY_VERSION < '2.7.0'
def filter_map
if block_given?
result = []
each do |element|
res = yield element
result << res if res
end
result
else
Enumerator.new do |yielder|
result = []
each do |element|
res = yielder.yield element
result << res if res
end
result
end
end
end
end
end

View File

@ -43,7 +43,12 @@ module Mastodon
tar.each do |entry|
next unless entry.file? && entry.full_name.end_with?('.png')
shortcode = [options[:prefix], File.basename(entry.full_name, '.*'), options[:suffix]].compact.join
filename = File.basename(entry.full_name, '.*')
# Skip macOS shadow files
next if filename.start_with?('._')
shortcode = [options[:prefix], filename, options[:suffix]].compact.join
custom_emoji = CustomEmoji.local.find_by(shortcode: shortcode)
if custom_emoji && !options[:overwrite]

View File

@ -160,6 +160,7 @@ module Mastodon
deduplicate_tags!
deduplicate_webauthn_credentials!
Scenic.database.refresh_materialized_view('instances', concurrently: true, cascade: false) if ActiveRecord::Migrator.current_version >= 2020_12_06_004238
Rails.cache.clear
@prompt.say 'Finished!'
@ -188,6 +189,11 @@ module Mastodon
else
ActiveRecord::Base.connection.add_index :accounts, "lower (username), COALESCE(lower(domain), '')", name: 'index_accounts_on_username_and_domain_lower', unique: true
end
@prompt.say 'Reindexing textual indexes on accounts…'
ActiveRecord::Base.connection.execute('REINDEX INDEX search_index;')
ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_uri;')
ActiveRecord::Base.connection.execute('REINDEX INDEX index_accounts_on_url;')
end
def deduplicate_users!

View File

@ -326,7 +326,7 @@ module Mastodon
end
preload_map.each_with_object({}) do |(model_name, record_ids), model_map|
model_map[model_name] = model_name.constantize.where(id: record_ids).each_with_object({}) { |record, record_map| record_map[record.id] = record }
model_map[model_name] = model_name.constantize.where(id: record_ids).index_by(&:id)
end
end
end

View File

@ -27,7 +27,7 @@ module Paperclip
return true if original_filename == other_filename
return false if original_filename.nil?
formats = styles.values.map(&:format).compact
formats = styles.values.filter_map(&:format)
return false if formats.empty?

View File

@ -142,7 +142,7 @@ module Paperclip
g = 0.0
b = 0.0
if s == 0.0
if s.zero?
r = l.to_f
g = l.to_f
b = l.to_f # achromatic

View File

@ -107,7 +107,7 @@
"intl-messageformat": "^2.2.0",
"intl-relativeformat": "^6.4.3",
"is-nan": "^1.3.2",
"js-yaml": "^3.14.1",
"js-yaml": "^4.0.0",
"lodash": "^4.17.19",
"mark-loader": "^0.1.6",
"marky": "^1.2.1",
@ -157,7 +157,7 @@
"requestidlecallback": "^0.3.0",
"reselect": "^4.0.0",
"rimraf": "^3.0.2",
"sass": "^1.30.0",
"sass": "^1.32.0",
"sass-loader": "^10.1.0",
"stacktrace-js": "^2.0.2",
"stringz": "^2.1.0",
@ -168,28 +168,28 @@
"tiny-queue": "^0.2.1",
"uuid": "^8.3.1",
"webpack": "^4.44.2",
"webpack-assets-manifest": "^3.1.1",
"webpack-assets-manifest": "^4.0.0",
"webpack-bundle-analyzer": "^4.3.0",
"webpack-cli": "^3.3.12",
"webpack-merge": "^5.7.3",
"wicg-inert": "^3.1.0"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/jest-dom": "^5.11.8",
"@testing-library/react": "^11.2.2",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"eslint": "^7.16.0",
"eslint": "^7.17.0",
"eslint-plugin-import": "~2.22.1",
"eslint-plugin-jsx-a11y": "~6.4.1",
"eslint-plugin-promise": "~4.2.1",
"eslint-plugin-react": "~7.21.5",
"eslint-plugin-react": "~7.22.0",
"jest": "^26.6.3",
"raf": "^3.4.1",
"react-intl-translations-manager": "^5.0.3",
"react-test-renderer": "^16.14.0",
"sass-lint": "^1.13.1",
"webpack-dev-server": "^3.11.0",
"webpack-dev-server": "^3.11.1",
"yargs": "^16.2.0"
},
"resolutions": {

View File

@ -268,6 +268,34 @@ RSpec.describe Api::V1::AccountsController, type: :controller do
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
end
describe 'POST #mute with nonzero duration set' do
let(:scopes) { 'write:mutes' }
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }
before do
user.account.follow!(other_account)
post :mute, params: { id: other_account.id, duration: 300 }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'does not remove the following relation between user and target user' do
expect(user.account.following?(other_account)).to be true
end
it 'creates a muting relation' do
expect(user.account.muting?(other_account)).to be true
end
it 'mutes notifications' do
expect(user.account.muting_notifications?(other_account)).to be true
end
it_behaves_like 'forbidden for wrong scope', 'read:accounts'
end
describe 'POST #unmute' do
let(:scopes) { 'write:mutes' }
let(:other_account) { Fabricate(:user, email: 'bob@example.com', account: Fabricate(:account, username: 'bob')).account }

View File

@ -71,7 +71,7 @@ RSpec.describe Notification, type: :model do
before do
allow(accounts_with_ids).to receive(:[]).with(stale_account1.id).and_return(account1)
allow(accounts_with_ids).to receive(:[]).with(stale_account2.id).and_return(account2)
allow(Account).to receive_message_chain(:where, :includes, :each_with_object).and_return(accounts_with_ids)
allow(Account).to receive_message_chain(:where, :includes, :index_by).and_return(accounts_with_ids)
end
let(:cached_items) do

369
yarn.lock
View File

@ -2,14 +2,7 @@
# yarn lockfile v1
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==
dependencies:
"@babel/highlight" "^7.10.4"
"@babel/code-frame@^7.12.11":
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
@ -21,29 +14,7 @@
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41"
integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw==
"@babel/core@^7.1.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
version "7.12.7"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.7.tgz#bf55363c08c8352a37691f7216ec30090bf7e3bf"
integrity sha512-tRKx9B53kJe8NCGGIxEQb2Bkr0riUIEuN7Sc1fxhs5H8lKlCWUvQCSNMVIB0Meva7hcbCRJ76de15KoLltdoqw==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.12.5"
"@babel/helper-module-transforms" "^7.12.1"
"@babel/helpers" "^7.12.5"
"@babel/parser" "^7.12.7"
"@babel/template" "^7.12.7"
"@babel/traverse" "^7.12.7"
"@babel/types" "^7.12.7"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.1"
json5 "^2.1.2"
lodash "^4.17.19"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
"@babel/core@^7.12.10":
"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.7.2", "@babel/core@^7.7.5":
version "7.12.10"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd"
integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w==
@ -73,15 +44,6 @@
jsesc "^2.5.1"
source-map "^0.5.0"
"@babel/generator@^7.12.5":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.5.tgz#a2c50de5c8b6d708ab95be5e6053936c1884a4de"
integrity sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==
dependencies:
"@babel/types" "^7.12.5"
jsesc "^2.5.1"
source-map "^0.5.0"
"@babel/helper-annotate-as-pure@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3"
@ -104,6 +66,15 @@
"@babel/helper-explode-assignable-expression" "^7.10.4"
"@babel/types" "^7.10.4"
"@babel/helper-builder-react-jsx-experimental@^7.12.10":
version "7.12.10"
resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.10.tgz#a58cb96a793dc0fcd5c9ed3bb36d62fdc60534c2"
integrity sha512-3Kcr2LGpL7CTRDTTYm1bzeor9qZbxbvU2AxsLA6mUG9gYarSfIKMK0UlU+azLWI+s0+BH768bwyaziWB2NOJlQ==
dependencies:
"@babel/helper-annotate-as-pure" "^7.12.10"
"@babel/helper-module-imports" "^7.12.5"
"@babel/types" "^7.12.10"
"@babel/helper-builder-react-jsx-experimental@^7.12.4":
version "7.12.4"
resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.12.4.tgz#55fc1ead5242caa0ca2875dcb8eed6d311e50f48"
@ -319,12 +290,7 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
"@babel/helper-validator-option@^7.12.1":
version "7.12.1"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.1.tgz#175567380c3e77d60ff98a54bb015fe78f2178d9"
integrity sha512-YpJabsXlJVWP0USHjnC/AQDTLlZERbON577YUVO/wLpqyj6HAtVYnWaQaN0iUN+1/tWn3c+uKKXjRut5115Y2A==
"@babel/helper-validator-option@^7.12.11":
"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f"
integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw==
@ -357,12 +323,7 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.12.7", "@babel/parser@^7.7.0":
version "7.12.7"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056"
integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==
"@babel/parser@^7.12.10", "@babel/parser@^7.12.11":
"@babel/parser@^7.1.0", "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.7.0":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79"
integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg==
@ -804,15 +765,14 @@
"@babel/plugin-syntax-jsx" "^7.12.1"
"@babel/plugin-transform-react-jsx@^7.12.10":
version "7.12.12"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e"
integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw==
version "7.12.10"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.10.tgz#a7af3097c73479123594c8c8fe39545abebd44e3"
integrity sha512-MM7/BC8QdHXM7Qc1wdnuk73R4gbuOpfrSUgfV/nODGc86sPY1tgmY2M9E9uAnf2e4DOIp8aKGWqgZfQxnTNGuw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.12.10"
"@babel/helper-module-imports" "^7.12.5"
"@babel/helper-builder-react-jsx" "^7.10.4"
"@babel/helper-builder-react-jsx-experimental" "^7.12.10"
"@babel/helper-plugin-utils" "^7.10.4"
"@babel/plugin-syntax-jsx" "^7.12.1"
"@babel/types" "^7.12.12"
"@babel/plugin-transform-react-pure-annotations@^7.12.1":
version "7.12.1"
@ -1021,22 +981,7 @@
"@babel/parser" "^7.12.7"
"@babel/types" "^7.12.7"
"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.7", "@babel/traverse@^7.7.0":
version "7.12.7"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.7.tgz#572a722408681cef17d6b0bef69ef2e728ca69f1"
integrity sha512-nMWaqsQEeSvMNypswUDzjqQ+0rR6pqCtoQpsqGJC4/Khm9cISwPTSpai57F6/jDaOoEGz8yE/WxcO3PV6tKSmQ==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.12.5"
"@babel/helper-function-name" "^7.10.4"
"@babel/helper-split-export-declaration" "^7.11.0"
"@babel/parser" "^7.12.7"
"@babel/types" "^7.12.7"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.19"
"@babel/traverse@^7.12.10":
"@babel/traverse@^7.1.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5", "@babel/traverse@^7.7.0":
version "7.12.12"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376"
integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==
@ -1051,16 +996,7 @@
globals "^11.1.0"
lodash "^4.17.19"
"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
version "7.12.7"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.7.tgz#6039ff1e242640a29452c9ae572162ec9a8f5d13"
integrity sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
lodash "^4.17.19"
to-fast-properties "^2.0.0"
"@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12":
"@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0":
version "7.12.12"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299"
integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==
@ -1454,10 +1390,10 @@
lz-string "^1.4.4"
pretty-format "^26.6.2"
"@testing-library/jest-dom@^5.11.6":
version "5.11.6"
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.6.tgz#782940e82e5cd17bc0a36f15156ba16f3570ac81"
integrity sha512-cVZyUNRWwUKI0++yepYpYX7uhrP398I+tGz4zOlLVlUYnZS+Svuxv4fwLeCIy7TnBYKXUaOlQr3vopxL8ZfEnA==
"@testing-library/jest-dom@^5.11.8":
version "5.11.8"
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.8.tgz#433a84d6f9a089485101b9e112ef03e5c30bcbfc"
integrity sha512-ScyKrWQM5xNcr79PkSewnA79CLaoxVskE+f7knTOhDD9ftZSA1Jw8mj+pneqhEu3x37ncNfW84NUr7lqK+mXjA==
dependencies:
"@babel/runtime" "^7.9.2"
"@types/testing-library__jest-dom" "^5.9.1"
@ -1834,11 +1770,6 @@ acorn-jsx@^3.0.0:
dependencies:
acorn "^3.0.4"
acorn-jsx@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
acorn-jsx@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
@ -2028,6 +1959,11 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
aria-query@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
@ -2061,16 +1997,7 @@ array-flatten@^2.1.0:
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
array-includes@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348"
integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.0"
is-string "^1.0.5"
array-includes@^3.1.2:
array-includes@^3.1.1, array-includes@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8"
integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==
@ -2637,7 +2564,7 @@ browserslist@^4.0.0, browserslist@^4.12.0:
escalade "^3.1.0"
node-releases "^1.1.61"
browserslist@^4.14.5, browserslist@^4.6.4:
browserslist@^4.14.5:
version "4.14.7"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.7.tgz#c071c1b3622c1c2e790799a37bb09473a4351cb6"
integrity sha512-BSVRLCeG3Xt/j/1cCGj1019Wbty0H+Yvu2AOuZSuoaUWn3RatbL33Cxk+Q4jRMRAbOm0p7SLravLjpnT6s0vzQ==
@ -2659,6 +2586,17 @@ browserslist@^4.15.0:
escalade "^3.1.1"
node-releases "^1.1.67"
browserslist@^4.6.4:
version "4.16.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766"
integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA==
dependencies:
caniuse-lite "^1.0.30001173"
colorette "^1.2.1"
electron-to-chromium "^1.3.634"
escalade "^3.1.1"
node-releases "^1.1.69"
bser@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
@ -2838,10 +2776,10 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001135:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001143.tgz#560f2cfb9f313d1d7e52eb8dac0e4e36c8821c0d"
integrity sha512-p/PO5YbwmCpBJPxjOiKBvAlUPgF8dExhfEpnsH+ys4N/791WHrYrGg0cyHiAURl5hSbx5vIcjKmQAP6sHDYH3w==
caniuse-lite@^1.0.30000981:
version "1.0.30001161"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001161.tgz#64f7ffe79ee780b8c92843ff34feb36cea4651e0"
integrity sha512-JharrCDxOqPLBULF9/SPa6yMcBRTjZARJ6sc3cuKrPfyIk64JN6kuMINWqA99Xc8uElMFcROliwtz0n9pYej+g==
caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001173:
version "1.0.30001176"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001176.tgz#e44bac506d4656bae4944a1417f41597bd307335"
integrity sha512-VWdkYmqdkDLRe0lvfJlZQ43rnjKqIGKHWhWWRbkqMsJIUaYDNf/K/sdZZcVO6YKQklubokdkJY+ujArsuJ5cag==
caniuse-lite@^1.0.30001157:
version "1.0.30001159"
@ -2876,7 +2814,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.0, chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
@ -2893,7 +2831,7 @@ chalk@^3.0.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.0.0, chalk@^4.1.0:
chalk@^4.0, chalk@^4.0.0, chalk@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a"
integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==
@ -3686,10 +3624,10 @@ debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"
debug@^3.1.1, debug@^3.2.5:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
debug@^3.1.1, debug@^3.2.6:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
dependencies:
ms "^2.1.1"
@ -4024,6 +3962,11 @@ electron-to-chromium@^1.3.621:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz#16dd5aec9de03894e8d14a1db4cda8a369b9b7fe"
integrity sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA==
electron-to-chromium@^1.3.634:
version "1.3.637"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.637.tgz#be46f77acc217cdecf633bbd25292f6a36cc689b"
integrity sha512-924WXYMYquYybc+7pNApGlhY2RWg3MY3he4BrZ5BUmM2n1MGBsrS+PZxrlo6UAsWuNl4NE66fqFdwsWkBUGgkA==
elliptic@^6.5.3:
version "6.5.3"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
@ -4335,10 +4278,10 @@ eslint-plugin-promise@~4.2.1:
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a"
integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==
eslint-plugin-react@~7.21.5:
version "7.21.5"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz#50b21a412b9574bfe05b21db176e8b7b3b15bff3"
integrity sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==
eslint-plugin-react@~7.22.0:
version "7.22.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269"
integrity sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA==
dependencies:
array-includes "^3.1.1"
array.prototype.flatmap "^1.2.3"
@ -4424,10 +4367,10 @@ eslint@^2.7.0:
text-table "~0.2.0"
user-home "^2.0.0"
eslint@^7.16.0:
version "7.16.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.16.0.tgz#a761605bf9a7b32d24bb7cde59aeb0fd76f06092"
integrity sha512-iVWPS785RuDA4dWuhhgXTNrGxHHK3a8HLSMBgbbU59ruJDubUraXN8N5rn7kb8tG6sjg74eE0RA3YWT51eusEw==
eslint@^7.17.0:
version "7.17.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.17.0.tgz#4ccda5bf12572ad3bf760e6f195886f50569adb0"
integrity sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==
dependencies:
"@babel/code-frame" "^7.0.0"
"@eslint/eslintrc" "^0.2.2"
@ -4475,16 +4418,7 @@ espree@^3.1.6:
acorn "^5.5.0"
acorn-jsx "^3.0.0"
espree@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348"
integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==
dependencies:
acorn "^7.4.0"
acorn-jsx "^5.2.0"
eslint-visitor-keys "^1.3.0"
espree@^7.3.1:
espree@^7.3.0, espree@^7.3.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
@ -4747,14 +4681,7 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
faye-websocket@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=
dependencies:
websocket-driver ">=0.5.1"
faye-websocket@~0.11.1:
faye-websocket@^0.11.3:
version "0.11.3"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e"
integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==
@ -5103,9 +5030,9 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-intrinsic@^1.0.0, get-intrinsic@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49"
integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.1.tgz#94a9768fcbdd0595a1c9273aacf4c89d075631be"
integrity sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
@ -5521,6 +5448,11 @@ http-link-header@^1.0.3:
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4"
integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=
http-parser-js@>=0.5.1:
version "0.5.3"
resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9"
integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==
http-proxy-middleware@0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a"
@ -6646,14 +6578,6 @@ js-string-escape@1.0.1:
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
js-yaml@^3.13.1, js-yaml@^3.4.6, js-yaml@^3.5.1, js-yaml@^3.5.4:
version "3.14.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^3.14.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
@ -6661,6 +6585,13 @@ js-yaml@^3.14.1:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f"
integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==
dependencies:
argparse "^2.0.1"
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@ -6740,7 +6671,7 @@ json-stringify-safe@~5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
json3@^3.3.2:
json3@^3.3.3:
version "3.3.3"
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==
@ -6953,6 +6884,13 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
lockfile@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609"
integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==
dependencies:
signal-exit "^3.0.2"
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@ -6968,6 +6906,11 @@ lodash.defaults@^4.0.1:
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
lodash.escaperegexp@^4.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
lodash.get@^4.0:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
@ -7341,14 +7284,14 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
mkdirp@^0.5, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
dependencies:
minimist "^1.2.5"
mkdirp@^1.0.3, mkdirp@^1.0.4:
mkdirp@^1.0, mkdirp@^1.0.3, mkdirp@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
@ -7526,6 +7469,11 @@ node-releases@^1.1.66, node-releases@^1.1.67:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12"
integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg==
node-releases@^1.1.69:
version "1.1.69"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.69.tgz#3149dbde53b781610cd8b486d62d86e26c3725f6"
integrity sha512-DGIjo79VDEyAnRlfSqYTsy+yoHd2IOjJiKUozD2MV2D85Vso6Bug56mb9tT/fY5Urt0iqk01H7x+llAruDR2zA==
normalize-package-data@^2.3.2, normalize-package-data@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@ -7702,17 +7650,7 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
object.values@^1.1.0, object.values@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e"
integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.17.0-next.1"
function-bind "^1.1.1"
has "^1.0.3"
object.values@^1.1.2:
object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731"
integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==
@ -8784,9 +8722,9 @@ postcss-selector-matches@^4.0.0:
postcss "^7.0.2"
postcss-selector-not@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0"
integrity sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz#263016eef1cf219e0ade9a913780fc1f48204cbf"
integrity sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==
dependencies:
balanced-match "^1.0.0"
postcss "^7.0.2"
@ -9829,7 +9767,7 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2:
resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1:
version "1.19.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
@ -9986,7 +9924,7 @@ sass-loader@^10.1.0:
schema-utils "^3.0.0"
semver "^7.3.2"
sass@^1.30.0:
sass@^1.32.0:
version "1.32.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.0.tgz#10101a026c13080b14e2b374d4e15ee24400a4d3"
integrity sha512-fhyqEbMIycQA4blrz/C0pYhv2o4x2y6FYYAH0CshBw3DXh5D5wyERgxw0ptdau1orc/GhNrhF7DFN2etyOCEng==
@ -10031,7 +9969,7 @@ schema-utils@^2.2.0, schema-utils@^2.6.5:
ajv "^6.12.4"
ajv-keywords "^3.5.2"
schema-utils@^3.0.0:
schema-utils@^3.0, schema-utils@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
@ -10053,7 +9991,7 @@ select-hose@^2.0.0:
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
selfsigned@^1.10.7:
selfsigned@^1.10.8:
version "1.10.8"
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30"
integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==
@ -10313,26 +10251,26 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.0"
use "^3.1.0"
sockjs-client@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5"
integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g==
sockjs-client@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.0.tgz#2f8ff5d4b659e0d092f7aba0b7c386bd2aa20add"
integrity sha512-8Dt3BDi4FYNrCFGTL/HtwVzkARrENdwOUf1ZoW/9p3M8lZdFT35jVdrHza+qgxuG9H3/shR4cuX/X9umUrjP8Q==
dependencies:
debug "^3.2.5"
debug "^3.2.6"
eventsource "^1.0.7"
faye-websocket "~0.11.1"
inherits "^2.0.3"
json3 "^3.3.2"
url-parse "^1.4.3"
faye-websocket "^0.11.3"
inherits "^2.0.4"
json3 "^3.3.3"
url-parse "^1.4.7"
sockjs@0.3.20:
version "0.3.20"
resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855"
integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==
sockjs@^0.3.21:
version "0.3.21"
resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417"
integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==
dependencies:
faye-websocket "^0.10.0"
faye-websocket "^0.11.3"
uuid "^3.4.0"
websocket-driver "0.6.5"
websocket-driver "^0.7.4"
source-list-map@^2.0.0:
version "2.0.1"
@ -10847,7 +10785,7 @@ table@^6.0.4:
slice-ansi "^4.0.0"
string-width "^4.2.0"
tapable@^1.0.0, tapable@^1.1.3:
tapable@^1.0, tapable@^1.0.0, tapable@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
@ -11297,7 +11235,7 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
url-parse@^1.4.3:
url-parse@^1.4.3, url-parse@^1.4.7:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
@ -11521,18 +11459,21 @@ webidl-conversions@^6.1.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-assets-manifest@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-3.1.1.tgz#39bbc3bf2ee57fcd8ba07cda51c9ba4a3c6ae1de"
integrity sha512-JV9V2QKc5wEWQptdIjvXDUL1ucbPLH2f27toAY3SNdGZp+xSaStAgpoMcvMZmqtFrBc9a5pTS1058vxyMPOzRQ==
webpack-assets-manifest@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/webpack-assets-manifest/-/webpack-assets-manifest-4.0.0.tgz#6c906f6a77945aa326822e158f22d172ccc59f0f"
integrity sha512-zbozd1Cr6gS5XMWWHfISusocOO2bO05ktpJXWdoYtv12/FSXsNqyVjNwLE9ehBXDsEOwRtqd3kPDdTZKFjjD/w==
dependencies:
chalk "^2.0"
chalk "^4.0"
deepmerge "^4.2.2"
lockfile "^1.0.4"
lodash.escaperegexp "^4.0"
lodash.get "^4.0"
lodash.has "^4.0"
mkdirp "^0.5"
schema-utils "^1.0.0"
tapable "^1.0.0"
webpack-sources "^1.0.0"
mkdirp "^1.0"
schema-utils "^3.0"
tapable "^1.0"
webpack-sources "^1.0"
webpack-bundle-analyzer@^4.3.0:
version "4.3.0"
@ -11577,10 +11518,10 @@ webpack-dev-middleware@^3.7.2:
range-parser "^1.2.1"
webpack-log "^2.0.0"
webpack-dev-server@^3.11.0:
version "3.11.0"
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c"
integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==
webpack-dev-server@^3.11.1:
version "3.11.1"
resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.1.tgz#c74028bf5ba8885aaf230e48a20e8936ab8511f0"
integrity sha512-u4R3mRzZkbxQVa+MBWi2uVpB5W59H3ekZAJsQlKUTdl7Elcah2EhygTPLmeFXybQkf9i2+L0kn7ik9SnXa6ihQ==
dependencies:
ansi-html "0.0.7"
bonjour "^3.5.0"
@ -11602,11 +11543,11 @@ webpack-dev-server@^3.11.0:
p-retry "^3.0.1"
portfinder "^1.0.26"
schema-utils "^1.0.0"
selfsigned "^1.10.7"
selfsigned "^1.10.8"
semver "^6.3.0"
serve-index "^1.9.1"
sockjs "0.3.20"
sockjs-client "1.4.0"
sockjs "^0.3.21"
sockjs-client "^1.5.0"
spdy "^4.0.2"
strip-ansi "^3.0.1"
supports-color "^6.1.0"
@ -11632,7 +11573,7 @@ webpack-merge@^5.7.3:
clone-deep "^4.0.1"
wildcard "^2.0.0"
webpack-sources@^1.0.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
webpack-sources@^1.0, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
@ -11669,13 +11610,6 @@ webpack@^4.44.2:
watchpack "^1.7.4"
webpack-sources "^1.4.1"
websocket-driver@0.6.5:
version "0.6.5"
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36"
integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=
dependencies:
websocket-extensions ">=0.1.1"
websocket-driver@>=0.5.1:
version "0.7.3"
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9"
@ -11685,6 +11619,15 @@ websocket-driver@>=0.5.1:
safe-buffer ">=5.1.0"
websocket-extensions ">=0.1.1"
websocket-driver@^0.7.4:
version "0.7.4"
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
dependencies:
http-parser-js ">=0.5.1"
safe-buffer ">=5.1.0"
websocket-extensions ">=0.1.1"
websocket-extensions@>=0.1.1:
version "0.1.4"
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"