Jay Logan 2020-03-05 03:05:55 -06:00
commit f21382798c
28 changed files with 354 additions and 208 deletions

View File

@ -3,6 +3,32 @@ Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [v3.1.2] - 2020-02-27
### Added
- Add `--reset-password` option to `tootctl accounts modify` ([ThibG](https://github.com/tootsuite/mastodon/pull/13126))
- Add source-mapped stacktrace to error message in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13082))
### Fixed
- Fix dismissing an announcement twice raising an obscure error ([ThibG](https://github.com/tootsuite/mastodon/pull/13124))
- Fix misleading error when attempting to re-send a pending follow request ([ThibG](https://github.com/tootsuite/mastodon/pull/13133))
- Fix backups failing when files are missing from media attachments ([ThibG](https://github.com/tootsuite/mastodon/pull/13146))
- Fix duplicate accounts being created when fetching an account for its key only ([ThibG](https://github.com/tootsuite/mastodon/pull/13147))
- Fix `/web` redirecting to `/web/web` in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13128))
- Fix previously OStatus-based accounts not being detected as ActivityPub ([ThibG](https://github.com/tootsuite/mastodon/pull/13129))
- Fix account JSON/RSS not being cacheable due to wrong mime type comparison ([ThibG](https://github.com/tootsuite/mastodon/pull/13116))
- Fix old browsers crashing because of missing `finally` polyfill in web UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13115))
- Fix account's bio not being shown if there are no proofs/fields in admin UI ([ThibG](https://github.com/tootsuite/mastodon/pull/13075))
- Fix sign-ups without checked user agreement being accepted through the web form ([ThibG](https://github.com/tootsuite/mastodon/pull/13088))
- Fix non-x64 architectures not being able to build Docker image because of hardcoded Node.js architecture ([SaraSmiseth](https://github.com/tootsuite/mastodon/pull/13081))
- Fix invite request input not being shown on sign-up error if left empty ([ThibG](https://github.com/tootsuite/mastodon/pull/13089))
- Fix some migration hints mentioning GitLab instead of Mastodon ([saper](https://github.com/tootsuite/mastodon/pull/13084))
### Security
- Fix leak of arbitrary statuses through unfavourite action in REST API ([Gargron](https://github.com/tootsuite/mastodon/pull/13161))
## [3.1.1] - 2020-02-10 ## [3.1.1] - 2020-02-10
### Fixed ### Fixed

View File

@ -9,7 +9,7 @@ gem 'puma', '~> 4.3'
gem 'rails', '~> 5.2.4' gem 'rails', '~> 5.2.4'
gem 'sprockets', '~> 3.7.2' gem 'sprockets', '~> 3.7.2'
gem 'thor', '~> 0.20' gem 'thor', '~> 0.20'
gem 'rack', '~> 2.1.2' gem 'rack', '~> 2.2.2'
gem 'thwait', '~> 0.1.0' gem 'thwait', '~> 0.1.0'
gem 'e2mmap', '~> 0.1.0' gem 'e2mmap', '~> 0.1.0'
@ -56,7 +56,6 @@ gem 'goldfinger', '~> 2.1'
gem 'hiredis', '~> 0.6' gem 'hiredis', '~> 0.6'
gem 'redis-namespace', '~> 1.7' gem 'redis-namespace', '~> 1.7'
gem 'health_check', git: 'https://github.com/ianheggie/health_check', ref: '0b799ead604f900ed50685e9b2d469cd2befba5b' gem 'health_check', git: 'https://github.com/ianheggie/health_check', ref: '0b799ead604f900ed50685e9b2d469cd2befba5b'
gem 'html2text'
gem 'htmlentities', '~> 4.3' gem 'htmlentities', '~> 4.3'
gem 'http', '~> 4.3' gem 'http', '~> 4.3'
gem 'http_accept_language', '~> 2.1' gem 'http_accept_language', '~> 2.1'

View File

@ -202,14 +202,14 @@ GEM
dotenv (= 2.7.5) dotenv (= 2.7.5)
railties (>= 3.2, < 6.1) railties (>= 3.2, < 6.1)
e2mmap (0.1.0) e2mmap (0.1.0)
elasticsearch (7.3.0) elasticsearch (7.5.0)
elasticsearch-api (= 7.3.0) elasticsearch-api (= 7.5.0)
elasticsearch-transport (= 7.3.0) elasticsearch-transport (= 7.5.0)
elasticsearch-api (7.3.0) elasticsearch-api (7.5.0)
multi_json multi_json
elasticsearch-dsl (0.1.8) elasticsearch-dsl (0.1.8)
elasticsearch-transport (7.3.0) elasticsearch-transport (7.5.0)
faraday faraday (>= 0.14, < 1)
multi_json multi_json
encryptor (3.0.0) encryptor (3.0.0)
equatable (0.6.1) equatable (0.6.1)
@ -220,7 +220,7 @@ GEM
fabrication (2.21.0) fabrication (2.21.0)
faker (2.10.1) faker (2.10.1)
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
faraday (1.0.0) faraday (0.17.3)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
fast_blank (1.0.0) fast_blank (1.0.0)
fastimage (2.1.7) fastimage (2.1.7)
@ -270,8 +270,6 @@ GEM
highline (2.0.3) highline (2.0.3)
hiredis (0.6.3) hiredis (0.6.3)
hkdf (0.3.0) hkdf (0.3.0)
html2text (0.2.1)
nokogiri (~> 1.6)
htmlentities (4.3.4) htmlentities (4.3.4)
http (4.3.0) http (4.3.0)
addressable (~> 2.3) addressable (~> 2.3)
@ -437,12 +435,12 @@ GEM
pry-rails (0.3.9) pry-rails (0.3.9)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (4.0.3) public_suffix (4.0.3)
puma (4.3.1) puma (4.3.3)
nio4r (~> 2.0) nio4r (~> 2.0)
pundit (2.1.0) pundit (2.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
raabro (1.1.6) raabro (1.1.6)
rack (2.1.2) rack (2.2.2)
rack-attack (6.2.2) rack-attack (6.2.2)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rack-cors (1.1.1) rack-cors (1.1.1)
@ -493,7 +491,7 @@ GEM
link_header (~> 0.0, >= 0.0.8) link_header (~> 0.0, >= 0.0.8)
rdf-normalize (0.4.0) rdf-normalize (0.4.0)
rdf (~> 3.1) rdf (~> 3.1)
redcarpet (3.4.0) redcarpet (3.5.0)
redis (4.1.3) redis (4.1.3)
redis-actionpack (5.0.2) redis-actionpack (5.0.2)
actionpack (>= 4.0, < 6) actionpack (>= 4.0, < 6)
@ -706,7 +704,6 @@ DEPENDENCIES
hamlit-rails (~> 0.2) hamlit-rails (~> 0.2)
health_check! health_check!
hiredis (~> 0.6) hiredis (~> 0.6)
html2text
htmlentities (~> 4.3) htmlentities (~> 4.3)
http (~> 4.3) http (~> 4.3)
http_accept_language (~> 2.1) http_accept_language (~> 2.1)
@ -751,7 +748,7 @@ DEPENDENCIES
pry-rails (~> 0.3) pry-rails (~> 0.3)
puma (~> 4.3) puma (~> 4.3)
pundit (~> 2.1) pundit (~> 2.1)
rack (~> 2.1.2) rack (~> 2.2.2)
rack-attack (~> 6.2) rack-attack (~> 6.2)
rack-cors (~> 1.1) rack-cors (~> 1.1)
rails (~> 5.2.4) rails (~> 5.2.4)

View File

@ -11,7 +11,7 @@ class Api::V1::AnnouncementsController < Api::BaseController
end end
def dismiss def dismiss
AnnouncementMute.create!(account: current_account, announcement: @announcement) AnnouncementMute.find_or_create_by!(account: current_account, announcement: @announcement)
render_empty render_empty
end end

View File

@ -5,35 +5,28 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' } before_action -> { doorkeeper_authorize! :write, :'write:bookmarks' }
before_action :require_user! before_action :require_user!
before_action :set_status
respond_to :json respond_to :json
def create def create
@status = bookmarked_status current_account.bookmarks.find_or_create_by!(account: current_account, status: @status)
render json: @status, serializer: REST::StatusSerializer render json: @status, serializer: REST::StatusSerializer
end end
def destroy def destroy
@status = requested_status bookmark = current_account.bookmarks.find_by(status: @status)
@bookmarks_map = { @status.id => false } bookmark&.destroy!
bookmark = Bookmark.find_by!(account: current_user.account, status: @status) render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, bookmarks_map: { @status.id => false })
bookmark.destroy!
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, bookmarks_map: @bookmarks_map)
end end
private private
def bookmarked_status def set_status
authorize_with current_user.account, requested_status, :show? @status = Status.find(params[:status_id])
authorize @status, :show?
bookmark = Bookmark.find_or_create_by!(account: current_user.account, status: requested_status) rescue Mastodon::NotPermittedError
not_found
bookmark.status.reload
end
def requested_status
Status.find(params[:status_id])
end end
end end

View File

@ -69,8 +69,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
@status = Status.find(params[:status_id]) @status = Status.find(params[:status_id])
authorize @status, :show? authorize @status, :show?
rescue Mastodon::NotPermittedError rescue Mastodon::NotPermittedError
# Reraise in order to get a 404 instead of a 403 error code not_found
raise ActiveRecord::RecordNotFound
end end
def pagination_params(core_params) def pagination_params(core_params)

View File

@ -5,34 +5,26 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:favourites' } before_action -> { doorkeeper_authorize! :write, :'write:favourites' }
before_action :require_user! before_action :require_user!
before_action :set_status
respond_to :json respond_to :json
def create def create
@status = favourited_status FavouriteService.new.call(current_account, @status)
render json: @status, serializer: REST::StatusSerializer render json: @status, serializer: REST::StatusSerializer
end end
def destroy def destroy
@status = requested_status UnfavouriteWorker.perform_async(current_account.id, @status.id)
@favourites_map = { @status.id => false } render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, favourites_map: { @status.id => false })
UnfavouriteWorker.perform_async(current_user.account_id, @status.id)
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, favourites_map: @favourites_map)
end end
private private
def favourited_status def set_status
service_result.status.reload @status = Status.find(params[:status_id])
end authorize @status, :show?
rescue Mastodon::NotPermittedError
def service_result not_found
FavouriteService.new.call(current_user.account, requested_status)
end
def requested_status
Status.find(params[:status_id])
end end
end end

View File

@ -66,8 +66,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
@status = Status.find(params[:status_id]) @status = Status.find(params[:status_id])
authorize @status, :show? authorize @status, :show?
rescue Mastodon::NotPermittedError rescue Mastodon::NotPermittedError
# Reraise in order to get a 404 instead of a 403 error code not_found
raise ActiveRecord::RecordNotFound
end end
def pagination_params(core_params) def pagination_params(core_params)

View File

@ -5,33 +5,34 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:statuses' } before_action -> { doorkeeper_authorize! :write, :'write:statuses' }
before_action :require_user! before_action :require_user!
before_action :set_reblog
respond_to :json respond_to :json
def create def create
@status = ReblogService.new.call(current_user.account, status_for_reblog, reblog_params) @status = ReblogService.new.call(current_account, @reblog, reblog_params)
render json: @status, serializer: REST::StatusSerializer render json: @status, serializer: REST::StatusSerializer
end end
def destroy def destroy
@status = status_for_destroy.reblog @status = current_account.statuses.find_by(reblog_of_id: @reblog.id)
@reblogs_map = { @status.id => false }
authorize status_for_destroy, :unreblog? if @status
status_for_destroy.discard authorize @status, :unreblog?
RemovalWorker.perform_async(status_for_destroy.id) @status.discard
RemovalWorker.perform_async(@status.id)
end
render json: @status, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_user&.account_id, reblogs_map: @reblogs_map) render json: @reblog, serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new([@status], current_account.id, reblogs_map: { @reblog.id => false })
end end
private private
def status_for_reblog def set_reblog
Status.find params[:status_id] @reblog = Status.find(params[:status_id])
end authorize @reblog, :show?
rescue Mastodon::NotPermittedError
def status_for_destroy not_found
@status_for_destroy ||= current_user.account.statuses.where(reblog_of_id: params[:status_id]).first!
end end
def reblog_params def reblog_params

View File

@ -113,6 +113,10 @@ class KeyboardShortcuts extends ImmutablePureComponent {
<td><kbd>s</kbd></td> <td><kbd>s</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.search' defaultMessage='to focus search' /></td> <td><FormattedMessage id='keyboard_shortcuts.search' defaultMessage='to focus search' /></td>
</tr> </tr>
<tr>
<td><kbd>alt</kbd>+<kbd>enter</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.secondary_toot' defaultMessage='to send toot using secondary privacy setting' /></td>
</tr>
<tr> <tr>
<td><kbd>esc</kbd></td> <td><kbd>esc</kbd></td>
<td><FormattedMessage id='keyboard_shortcuts.unfocus' defaultMessage='to un-focus compose textarea/search' /></td> <td><FormattedMessage id='keyboard_shortcuts.unfocus' defaultMessage='to un-focus compose textarea/search' /></td>

View File

@ -12,7 +12,7 @@ function main() {
if (window.history && history.replaceState) { if (window.history && history.replaceState) {
const { pathname, search, hash } = window.location; const { pathname, search, hash } = window.location;
const path = pathname + search + hash; const path = pathname + search + hash;
if (!(/^\/web[$/]/).test(path)) { if (!(/^\/web($|\/)/).test(path)) {
history.replaceState(null, document.title, `/web${path}`); history.replaceState(null, document.title, `/web${path}`);
} }
} }

View File

@ -12,7 +12,7 @@ function main() {
if (window.history && history.replaceState) { if (window.history && history.replaceState) {
const { pathname, search, hash } = window.location; const { pathname, search, hash } = window.location;
const path = pathname + search + hash; const path = pathname + search + hash;
if (!(/^\/web[$/]/).test(path)) { if (!(/^\/web($|\/)/).test(path)) {
history.replaceState(null, document.title, `/web${path}`); history.replaceState(null, document.title, `/web${path}`);
} }
} }

View File

@ -480,7 +480,16 @@ class Account < ApplicationRecord
def from_text(text) def from_text(text)
return [] if text.blank? return [] if text.blank?
text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.map { |(username, domain)| EntityCache.instance.mention(username, domain) } text.scan(MENTION_RE).map { |match| match.first.split('@', 2) }.uniq.map do |(username, domain)|
domain = begin
if TagManager.instance.local_domain?(domain)
nil
else
TagManager.instance.normalize_domain(domain)
end
end
EntityCache.instance.mention(username, domain)
end.compact
end end
private private

View File

@ -18,9 +18,10 @@ class ActivityPub::ProcessAccountService < BaseService
RedisLock.acquire(lock_options) do |lock| RedisLock.acquire(lock_options) do |lock|
if lock.acquired? if lock.acquired?
@account = Account.find_remote(@username, @domain) @account = Account.remote.find_by(uri: @uri) if @options[:only_key]
@old_public_key = @account&.public_key @account ||= Account.find_remote(@username, @domain)
@old_protocol = @account&.protocol @old_public_key = @account&.public_key
@old_protocol = @account&.protocol
create_account if @account.nil? create_account if @account.nil?
update_account update_account

View File

@ -66,6 +66,8 @@ class BackupService < BaseService
def dump_media_attachments!(tar) def dump_media_attachments!(tar)
MediaAttachment.attached.where(account: account).reorder(nil).find_in_batches do |media_attachments| MediaAttachment.attached.where(account: account).reorder(nil).find_in_batches do |media_attachments|
media_attachments.each do |m| media_attachments.each do |m|
next unless m.file&.path
download_to_tar(tar, m.file, m.file.path) download_to_tar(tar, m.file, m.file.path)
end end

View File

@ -18,14 +18,13 @@ class FollowService < BaseService
if source_account.following?(target_account) if source_account.following?(target_account)
# We're already following this account, but we'll call follow! again to # We're already following this account, but we'll call follow! again to
# make sure the reblogs status is set correctly. # make sure the reblogs status is set correctly.
source_account.follow!(target_account, reblogs: reblogs) return source_account.follow!(target_account, reblogs: reblogs)
return
elsif source_account.requested?(target_account) elsif source_account.requested?(target_account)
# This isn't managed by a method in AccountInteractions, so we modify it # This isn't managed by a method in AccountInteractions, so we modify it
# ourselves if necessary. # ourselves if necessary.
req = source_account.follow_requests.find_by(target_account: target_account) req = source_account.follow_requests.find_by(target_account: target_account)
req.update!(show_reblogs: reblogs) req.update!(show_reblogs: reblogs)
return return req
end end
ActivityTracker.increment('activity:interactions') ActivityTracker.increment('activity:interactions')

View File

@ -99,7 +99,7 @@ class ResolveAccountService < BaseService
if lock.acquired? if lock.acquired?
@account = Account.find_remote(@username, @domain) @account = Account.find_remote(@username, @domain)
next if (@account.present? && !@account.activitypub?) || actor_json.nil? next if actor_json.nil?
@account = ActivityPub::ProcessAccountService.new.call(@username, @domain, actor_json) @account = ActivityPub::ProcessAccountService.new.call(@username, @domain, actor_json)
else else

View File

@ -10,6 +10,12 @@
%strong %strong
= t('authorize_follow.already_following') = t('authorize_follow.already_following')
= render 'post_follow_actions'
- elsif current_account.requested?(@resource)
.flash-message
%strong
= t('authorize_follow.already_requested')
= render 'post_follow_actions' = render 'post_follow_actions'
- else - else
= form_tag authorize_interaction_path, method: :post, class: 'simple_form' do = form_tag authorize_interaction_path, method: :post, class: 'simple_form' do

View File

@ -674,6 +674,7 @@ en:
trouble_logging_in: Trouble logging in? trouble_logging_in: Trouble logging in?
authorize_follow: authorize_follow:
already_following: You are already following this account already_following: You are already following this account
already_requested: You have already sent a follow request to that account
error: Unfortunately, there was an error looking up the remote account error: Unfortunately, there was an error looking up the remote account
follow: Follow follow: Follow
follow_request: 'You have sent a follow request to:' follow_request: 'You have sent a follow request to:'

View File

@ -120,6 +120,7 @@ module Mastodon
option :disable, type: :boolean option :disable, type: :boolean
option :disable_2fa, type: :boolean option :disable_2fa, type: :boolean
option :approve, type: :boolean option :approve, type: :boolean
option :reset_password, type: :boolean
desc 'modify USERNAME', 'Modify a user' desc 'modify USERNAME', 'Modify a user'
long_desc <<-LONG_DESC long_desc <<-LONG_DESC
Modify a user account. Modify a user account.
@ -138,6 +139,9 @@ module Mastodon
With the --disable-2fa option, the two-factor authentication With the --disable-2fa option, the two-factor authentication
requirement for the user can be removed. requirement for the user can be removed.
With the --reset-password option, the user's password is replaced by
a randomly-generated one, printed in the output.
LONG_DESC LONG_DESC
def modify(username) def modify(username)
user = Account.find_local(username)&.user user = Account.find_local(username)&.user
@ -152,6 +156,8 @@ module Mastodon
user.moderator = options[:role] == 'moderator' user.moderator = options[:role] == 'moderator'
end end
password = SecureRandom.hex if options[:reset_password]
user.password = password if options[:reset_password]
user.email = options[:email] if options[:email] user.email = options[:email] if options[:email]
user.disabled = false if options[:enable] user.disabled = false if options[:enable]
user.disabled = true if options[:disable] user.disabled = true if options[:disable]
@ -161,6 +167,7 @@ module Mastodon
if user.save if user.save
say('OK', :green) say('OK', :green)
say("New password: #{password}") if options[:reset_password]
else else
user.errors.to_h.each do |key, error| user.errors.to_h.each do |key, error|
say('Failure/Error: ', :red) say('Failure/Error: ', :red)

View File

@ -14,7 +14,9 @@ def setup_redis_env_url(prefix = nil, defaults = true)
ENV[prefix + 'REDIS_URL'] = if [password, host, port, db].all?(&:nil?) ENV[prefix + 'REDIS_URL'] = if [password, host, port, db].all?(&:nil?)
ENV['REDIS_URL'] ENV['REDIS_URL']
else else
"redis://#{password.blank? ? '' : ":#{password}@"}#{host}:#{port}/#{db}" Addressable::URI.parse("redis://#{host}:#{port}/#{db}").tap do |uri|
uri.password = password if password.present?
end.normalize.to_str
end end
end end

View File

@ -13,7 +13,7 @@ module Mastodon
end end
def patch def patch
1 2
end end
def flags def flags

View File

@ -336,7 +336,20 @@ namespace :mastodon do
if prompt.yes?('Save configuration?') if prompt.yes?('Save configuration?')
cmd = TTY::Command.new(printer: :quiet) cmd = TTY::Command.new(printer: :quiet)
File.write(Rails.root.join('.env.production'), "# Generated with mastodon:setup on #{Time.now.utc}\n\n" + env.each_pair.map { |key, value| "#{key}=#{value}" }.join("\n") + "\n") env_contents = env.each_pair.map do |key, value|
if value.is_a?(String) && value =~ /[\s\#\\"]/
if value =~ /[']/
value = value.to_s.gsub(/[\\"\$]/) { |x| "\\#{x}" }
"#{key}=\"#{value}\""
else
"#{key}='#{value}'"
end
else
"#{key}=#{value}"
end
end.join("\n")
File.write(Rails.root.join('.env.production'), "# Generated with mastodon:setup on #{Time.now.utc}\n\n" + env_contents + "\n")
if using_docker if using_docker
prompt.ok 'Below is your configuration, save it to an .env.production file outside Docker:' prompt.ok 'Below is your configuration, save it to an .env.production file outside Docker:'

View File

@ -60,7 +60,7 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@babel/core": "^7.8.3", "@babel/core": "^7.8.4",
"@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-decorators": "^7.8.3", "@babel/plugin-proposal-decorators": "^7.8.3",
"@babel/plugin-transform-react-inline-elements": "^7.8.3", "@babel/plugin-transform-react-inline-elements": "^7.8.3",
@ -71,8 +71,8 @@
"@clusterws/cws": "^0.17.3", "@clusterws/cws": "^0.17.3",
"@gamestdio/websocket": "^0.3.2", "@gamestdio/websocket": "^0.3.2",
"array-includes": "^3.1.1", "array-includes": "^3.1.1",
"atrament": "^0.2.3",
"arrow-key-navigation": "^1.1.0", "arrow-key-navigation": "^1.1.0",
"atrament": "0.2.4",
"autoprefixer": "^9.7.4", "autoprefixer": "^9.7.4",
"axios": "^0.19.2", "axios": "^0.19.2",
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
@ -95,8 +95,8 @@
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"exif-js": "^2.3.0", "exif-js": "^2.3.0",
"express": "^4.17.1", "express": "^4.17.1",
"file-loader": "^5.0.2",
"favico.js": "^0.3.10", "favico.js": "^0.3.10",
"file-loader": "^5.0.2",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"glob": "^7.1.6", "glob": "^7.1.6",
"history": "^4.10.1", "history": "^4.10.1",
@ -137,7 +137,7 @@
"react-motion": "^0.5.2", "react-motion": "^0.5.2",
"react-notification": "^6.8.5", "react-notification": "^6.8.5",
"react-overlays": "^0.9.1", "react-overlays": "^0.9.1",
"react-redux": "^7.1.3", "react-redux": "^7.2.0",
"react-redux-loading-bar": "^4.0.8", "react-redux-loading-bar": "^4.0.8",
"react-router-dom": "^4.1.1", "react-router-dom": "^4.1.1",
"react-router-scroll-4": "^1.0.0-beta.1", "react-router-scroll-4": "^1.0.0-beta.1",
@ -150,7 +150,7 @@
"redux": "^4.0.5", "redux": "^4.0.5",
"redux-immutable": "^4.0.0", "redux-immutable": "^4.0.0",
"redux-thunk": "^2.2.0", "redux-thunk": "^2.2.0",
"rellax": "^1.10.0", "rellax": "^1.12.1",
"requestidlecallback": "^0.3.0", "requestidlecallback": "^0.3.0",
"reselect": "^4.0.0", "reselect": "^4.0.0",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
@ -168,7 +168,7 @@
"webpack": "^4.41.5", "webpack": "^4.41.5",
"webpack-assets-manifest": "^3.1.1", "webpack-assets-manifest": "^3.1.1",
"webpack-bundle-analyzer": "^3.6.0", "webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.10", "webpack-cli": "^3.3.11",
"webpack-merge": "^4.2.1", "webpack-merge": "^4.2.1",
"wicg-inert": "^3.0.0" "wicg-inert": "^3.0.0"
}, },

View File

@ -21,36 +21,67 @@ describe Api::V1::Statuses::BookmarksController do
post :create, params: { status_id: status.id } post :create, params: { status_id: status.id }
end end
it 'returns http success' do context 'with public status' do
expect(response).to have_http_status(:success) it 'returns http success' do
expect(response).to have_http_status(:success)
end
it 'updates the bookmarked attribute' do
expect(user.account.bookmarked?(status)).to be true
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
expect(hash_body[:bookmarked]).to be true
end
end end
it 'updates the bookmarked attribute' do context 'with private status of not-followed account' do
expect(user.account.bookmarked?(status)).to be true let(:status) { Fabricate(:status, visibility: :private) }
end
it 'return json with updated attributes' do it 'returns http not found' do
hash_body = body_as_json expect(response).to have_http_status(404)
end
expect(hash_body[:id]).to eq status.id.to_s
expect(hash_body[:bookmarked]).to be true
end end
end end
describe 'POST #destroy' do describe 'POST #destroy' do
let(:status) { Fabricate(:status, account: user.account) } context 'with public status' do
let(:status) { Fabricate(:status, account: user.account) }
before do before do
Bookmark.find_or_create_by!(account: user.account, status: status) Bookmark.find_or_create_by!(account: user.account, status: status)
post :destroy, params: { status_id: status.id } post :destroy, params: { status_id: status.id }
end
it 'returns http success' do
expect(response).to have_http_status(:success)
end
it 'updates the bookmarked attribute' do
expect(user.account.bookmarked?(status)).to be false
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
expect(hash_body[:bookmarked]).to be false
end
end end
it 'returns http success' do context 'with private status that was not bookmarked' do
expect(response).to have_http_status(:success) let(:status) { Fabricate(:status, visibility: :private) }
end
it 'updates the bookmarked attribute' do before do
expect(user.account.bookmarked?(status)).to be false post :destroy, params: { status_id: status.id }
end
it 'returns http not found' do
expect(response).to have_http_status(404)
end
end end
end end
end end

View File

@ -21,45 +21,77 @@ describe Api::V1::Statuses::FavouritesController do
post :create, params: { status_id: status.id } post :create, params: { status_id: status.id }
end end
it 'returns http success' do context 'with public status' do
expect(response).to have_http_status(200) it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'updates the favourites count' do
expect(status.favourites.count).to eq 1
end
it 'updates the favourited attribute' do
expect(user.account.favourited?(status)).to be true
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
expect(hash_body[:favourites_count]).to eq 1
expect(hash_body[:favourited]).to be true
end
end end
it 'updates the favourites count' do context 'with private status of not-followed account' do
expect(status.favourites.count).to eq 1 let(:status) { Fabricate(:status, visibility: :private) }
end
it 'updates the favourited attribute' do it 'returns http not found' do
expect(user.account.favourited?(status)).to be true expect(response).to have_http_status(404)
end end
it 'return json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
expect(hash_body[:favourites_count]).to eq 1
expect(hash_body[:favourited]).to be true
end end
end end
describe 'POST #destroy' do describe 'POST #destroy' do
let(:status) { Fabricate(:status, account: user.account) } context 'with public status' do
let(:status) { Fabricate(:status, account: user.account) }
before do before do
FavouriteService.new.call(user.account, status) FavouriteService.new.call(user.account, status)
post :destroy, params: { status_id: status.id } post :destroy, params: { status_id: status.id }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'updates the favourites count' do
expect(status.favourites.count).to eq 0
end
it 'updates the favourited attribute' do
expect(user.account.favourited?(status)).to be false
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
expect(hash_body[:favourites_count]).to eq 0
expect(hash_body[:favourited]).to be false
end
end end
it 'returns http success' do context 'with private status that was not favourited' do
expect(response).to have_http_status(200) let(:status) { Fabricate(:status, visibility: :private) }
end
it 'updates the favourites count' do before do
expect(status.favourites.count).to eq 0 post :destroy, params: { status_id: status.id }
end end
it 'updates the favourited attribute' do it 'returns http not found' do
expect(user.account.favourited?(status)).to be false expect(response).to have_http_status(404)
end
end end
end end
end end

View File

@ -21,45 +21,77 @@ describe Api::V1::Statuses::ReblogsController do
post :create, params: { status_id: status.id } post :create, params: { status_id: status.id }
end end
it 'returns http success' do context 'with public status' do
expect(response).to have_http_status(200) it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 1
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be true
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:reblog][:id]).to eq status.id.to_s
expect(hash_body[:reblog][:reblogs_count]).to eq 1
expect(hash_body[:reblog][:reblogged]).to be true
end
end end
it 'updates the reblogs count' do context 'with private status of not-followed account' do
expect(status.reblogs.count).to eq 1 let(:status) { Fabricate(:status, visibility: :private) }
end
it 'updates the reblogged attribute' do it 'returns http not found' do
expect(user.account.reblogged?(status)).to be true expect(response).to have_http_status(404)
end end
it 'return json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:reblog][:id]).to eq status.id.to_s
expect(hash_body[:reblog][:reblogs_count]).to eq 1
expect(hash_body[:reblog][:reblogged]).to be true
end end
end end
describe 'POST #destroy' do describe 'POST #destroy' do
let(:status) { Fabricate(:status, account: user.account) } context 'with public status' do
let(:status) { Fabricate(:status, account: user.account) }
before do before do
ReblogService.new.call(user.account, status) ReblogService.new.call(user.account, status)
post :destroy, params: { status_id: status.id } post :destroy, params: { status_id: status.id }
end
it 'returns http success' do
expect(response).to have_http_status(200)
end
it 'updates the reblogs count' do
expect(status.reblogs.count).to eq 0
end
it 'updates the reblogged attribute' do
expect(user.account.reblogged?(status)).to be false
end
it 'returns json with updated attributes' do
hash_body = body_as_json
expect(hash_body[:id]).to eq status.id.to_s
expect(hash_body[:reblogs_count]).to eq 0
expect(hash_body[:reblogged]).to be false
end
end end
it 'returns http success' do context 'with private status that was not reblogged' do
expect(response).to have_http_status(200) let(:status) { Fabricate(:status, visibility: :private) }
end
it 'updates the reblogs count' do before do
expect(status.reblogs.count).to eq 0 post :destroy, params: { status_id: status.id }
end end
it 'updates the reblogged attribute' do it 'returns http not found' do
expect(user.account.reblogged?(status)).to be false expect(response).to have_http_status(404)
end
end end
end end
end end

View File

@ -18,17 +18,17 @@
invariant "^2.2.4" invariant "^2.2.4"
semver "^5.5.0" semver "^5.5.0"
"@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.8.3": "@babel/core@^7.1.0", "@babel/core@^7.4.5", "@babel/core@^7.8.4":
version "7.8.3" version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e"
integrity sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA== integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==
dependencies: dependencies:
"@babel/code-frame" "^7.8.3" "@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.8.3" "@babel/generator" "^7.8.4"
"@babel/helpers" "^7.8.3" "@babel/helpers" "^7.8.4"
"@babel/parser" "^7.8.3" "@babel/parser" "^7.8.4"
"@babel/template" "^7.8.3" "@babel/template" "^7.8.3"
"@babel/traverse" "^7.8.3" "@babel/traverse" "^7.8.4"
"@babel/types" "^7.8.3" "@babel/types" "^7.8.3"
convert-source-map "^1.7.0" convert-source-map "^1.7.0"
debug "^4.1.0" debug "^4.1.0"
@ -39,10 +39,10 @@
semver "^5.4.1" semver "^5.4.1"
source-map "^0.5.0" source-map "^0.5.0"
"@babel/generator@^7.0.0", "@babel/generator@^7.8.3": "@babel/generator@^7.0.0", "@babel/generator@^7.8.4":
version "7.8.3" version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.3.tgz#0e22c005b0a94c1c74eafe19ef78ce53a4d45c03" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e"
integrity sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug== integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==
dependencies: dependencies:
"@babel/types" "^7.8.3" "@babel/types" "^7.8.3"
jsesc "^2.5.1" jsesc "^2.5.1"
@ -243,13 +243,13 @@
"@babel/traverse" "^7.8.3" "@babel/traverse" "^7.8.3"
"@babel/types" "^7.8.3" "@babel/types" "^7.8.3"
"@babel/helpers@^7.8.3": "@babel/helpers@^7.8.4":
version "7.8.3" version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.3.tgz#382fbb0382ce7c4ce905945ab9641d688336ce85" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73"
integrity sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ== integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==
dependencies: dependencies:
"@babel/template" "^7.8.3" "@babel/template" "^7.8.3"
"@babel/traverse" "^7.8.3" "@babel/traverse" "^7.8.4"
"@babel/types" "^7.8.3" "@babel/types" "^7.8.3"
"@babel/highlight@^7.8.3": "@babel/highlight@^7.8.3":
@ -261,10 +261,10 @@
esutils "^2.0.2" esutils "^2.0.2"
js-tokens "^4.0.0" js-tokens "^4.0.0"
"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.8.3": "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4":
version "7.8.3" version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.3.tgz#790874091d2001c9be6ec426c2eed47bc7679081" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8"
integrity sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ== integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==
"@babel/plugin-proposal-async-generator-functions@^7.8.3": "@babel/plugin-proposal-async-generator-functions@^7.8.3":
version "7.8.3" version "7.8.3"
@ -817,16 +817,16 @@
"@babel/parser" "^7.8.3" "@babel/parser" "^7.8.3"
"@babel/types" "^7.8.3" "@babel/types" "^7.8.3"
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.8.3": "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4":
version "7.8.3" version "7.8.4"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.3.tgz#a826215b011c9b4f73f3a893afbc05151358bf9a" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c"
integrity sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg== integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==
dependencies: dependencies:
"@babel/code-frame" "^7.8.3" "@babel/code-frame" "^7.8.3"
"@babel/generator" "^7.8.3" "@babel/generator" "^7.8.4"
"@babel/helper-function-name" "^7.8.3" "@babel/helper-function-name" "^7.8.3"
"@babel/helper-split-export-declaration" "^7.8.3" "@babel/helper-split-export-declaration" "^7.8.3"
"@babel/parser" "^7.8.3" "@babel/parser" "^7.8.4"
"@babel/types" "^7.8.3" "@babel/types" "^7.8.3"
debug "^4.1.0" debug "^4.1.0"
globals "^11.1.0" globals "^11.1.0"
@ -1773,9 +1773,10 @@ atob@^2.1.1:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
atrament@^0.2.3: atrament@0.2.4:
version "0.2.3" version "0.2.4"
resolved "https://registry.yarnpkg.com/atrament/-/atrament-0.2.3.tgz#6ccbc0daa6d3f25e5aeaeb31befeb78e86980348" resolved "https://registry.yarnpkg.com/atrament/-/atrament-0.2.4.tgz#6f78196edfcd194e568b7c0b9c88201ec371ac66"
integrity sha512-hSA9VwW6COMwvRhSEO4uZweZ91YGOdHqwvslNyrJZG+8mzc4qx/qMsDZBuAeXFeWZO/QKtRjIXguOUy1aNMl3A==
autoprefixer@^9.7.4: autoprefixer@^9.7.4:
version "9.7.4" version "9.7.4"
@ -4300,6 +4301,7 @@ fast-levenshtein@~2.0.6:
favico.js@^0.3.10: favico.js@^0.3.10:
version "0.3.10" version "0.3.10"
resolved "https://registry.yarnpkg.com/favico.js/-/favico.js-0.3.10.tgz#80586e27a117f24a8d51c18a99bdc714d4339301" resolved "https://registry.yarnpkg.com/favico.js/-/favico.js-0.3.10.tgz#80586e27a117f24a8d51c18a99bdc714d4339301"
integrity sha1-gFhuJ6EX8kqNUcGKmb3HFNQzkwE=
faye-websocket@^0.10.0: faye-websocket@^0.10.0:
version "0.10.0" version "0.10.0"
@ -8732,14 +8734,13 @@ react-redux-loading-bar@^4.0.8:
prop-types "^15.6.2" prop-types "^15.6.2"
react-lifecycles-compat "^3.0.2" react-lifecycles-compat "^3.0.2"
react-redux@^7.1.3: react-redux@^7.2.0:
version "7.1.3" version "7.2.0"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.3.tgz#717a3d7bbe3a1b2d535c94885ce04cdc5a33fc79" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d"
integrity sha512-uI1wca+ECG9RoVkWQFF4jDMqmaw0/qnvaSvOoL/GA4dNxf6LoV8sUAcNDvE5NWKs4hFpn0t6wswNQnY3f7HT3w== integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA==
dependencies: dependencies:
"@babel/runtime" "^7.5.5" "@babel/runtime" "^7.5.5"
hoist-non-react-statics "^3.3.0" hoist-non-react-statics "^3.3.0"
invariant "^2.2.4"
loose-envify "^1.4.0" loose-envify "^1.4.0"
prop-types "^15.7.2" prop-types "^15.7.2"
react-is "^16.9.0" react-is "^16.9.0"
@ -9081,10 +9082,10 @@ regjsparser@^0.6.0:
dependencies: dependencies:
jsesc "~0.5.0" jsesc "~0.5.0"
rellax@^1.10.0: rellax@^1.12.1:
version "1.10.0" version "1.12.1"
resolved "https://registry.yarnpkg.com/rellax/-/rellax-1.10.0.tgz#0308b813b458f9175d37ffb4272e1f616eab1341" resolved "https://registry.yarnpkg.com/rellax/-/rellax-1.12.1.tgz#1b433ef7ac4aa3573449a33efab391c112f6b34d"
integrity sha512-BtxD9b8cAQcTs6iat1fqKvHMjIZ8CaxjsC5U/cIIVHC4LjkIsr0ZmeqxUm5ZvBvyjLwfPbU8Wcryp77sR5C8QA== integrity sha512-XBIi0CDpW5FLTujYjYBn1CIbK2CJL6TsAg/w409KghP2LucjjzBjsujXDAjyBLWgsfupfUcL5WzdnIPcGfK7XA==
remove-trailing-separator@^1.0.1: remove-trailing-separator@^1.0.1:
version "1.1.0" version "1.1.0"
@ -9738,11 +9739,6 @@ source-list-map@^2.0.0:
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
source-map@0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
source-map-resolve@^0.5.0: source-map-resolve@^0.5.0:
version "0.5.2" version "0.5.2"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259"
@ -9775,6 +9771,11 @@ source-map-url@^0.4.0:
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
source-map@0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
integrity sha1-dc449SvwczxafwwRjYEzSiu19BI=
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7:
version "0.5.7" version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
@ -10841,10 +10842,10 @@ webpack-bundle-analyzer@^3.6.0:
opener "^1.5.1" opener "^1.5.1"
ws "^6.0.0" ws "^6.0.0"
webpack-cli@^3.3.10: webpack-cli@^3.3.11:
version "3.3.10" version "3.3.11"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631"
integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg== integrity sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g==
dependencies: dependencies:
chalk "2.4.2" chalk "2.4.2"
cross-spawn "6.0.5" cross-spawn "6.0.5"