Merge remote-tracking branch 'parent/main' into kb_migration
This commit is contained in:
commit
a56a732dd2
57 changed files with 986 additions and 605 deletions
24
.github/renovate.json5
vendored
24
.github/renovate.json5
vendored
|
@ -9,7 +9,9 @@
|
||||||
],
|
],
|
||||||
stabilityDays: 3, // Wait 3 days after the package has been published before upgrading it
|
stabilityDays: 3, // Wait 3 days after the package has been published before upgrading it
|
||||||
// packageRules order is important, they are applied from top to bottom and are merged,
|
// packageRules order is important, they are applied from top to bottom and are merged,
|
||||||
// so for example grouping rules needs to be at the bottom
|
// meaning the most important ones must be at the bottom, for example grouping rules
|
||||||
|
// If we do not want a package to be grouped with others, we need to set its groupName
|
||||||
|
// to `null` after any other rule set it to something.
|
||||||
packageRules: [
|
packageRules: [
|
||||||
{
|
{
|
||||||
// Ignore major version bumps for these node packages
|
// Ignore major version bumps for these node packages
|
||||||
|
@ -45,6 +47,7 @@
|
||||||
// Ignore major version bumps for these Ruby packages
|
// Ignore major version bumps for these Ruby packages
|
||||||
matchManagers: ['bundler'],
|
matchManagers: ['bundler'],
|
||||||
matchPackageNames: [
|
matchPackageNames: [
|
||||||
|
'rack', // Needs to be synced with Rails version
|
||||||
'sprockets', // Requires manual upgrade https://github.com/rails/sprockets/blob/master/UPGRADING.md#guide-to-upgrading-from-sprockets-3x-to-4x
|
'sprockets', // Requires manual upgrade https://github.com/rails/sprockets/blob/master/UPGRADING.md#guide-to-upgrading-from-sprockets-3x-to-4x
|
||||||
'strong_migrations', // Requires manual upgrade
|
'strong_migrations', // Requires manual upgrade
|
||||||
'sidekiq', // Requires manual upgrade
|
'sidekiq', // Requires manual upgrade
|
||||||
|
@ -84,12 +87,17 @@
|
||||||
// Update devDependencies every week, with one grouped PR
|
// Update devDependencies every week, with one grouped PR
|
||||||
matchDepTypes: 'devDependencies',
|
matchDepTypes: 'devDependencies',
|
||||||
matchUpdateTypes: ['patch', 'minor'],
|
matchUpdateTypes: ['patch', 'minor'],
|
||||||
excludePackageNames: [
|
|
||||||
'typescript', // Typescript has many changes in minor versions, needs to be checked every time
|
|
||||||
],
|
|
||||||
groupName: 'devDependencies (non-major)',
|
groupName: 'devDependencies (non-major)',
|
||||||
extends: ['schedule:weekly'],
|
extends: ['schedule:weekly'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Group all eslint-related packages with `eslint` in the same PR
|
||||||
|
matchManagers: ['npm'],
|
||||||
|
matchPackageNames: ['eslint'],
|
||||||
|
matchPackagePrefixes: ['eslint-', '@typescript-eslint/'],
|
||||||
|
matchUpdateTypes: ['patch', 'minor'],
|
||||||
|
groupName: 'eslint (non-major)',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// Update @types/* packages every week, with one grouped PR
|
// Update @types/* packages every week, with one grouped PR
|
||||||
matchPackagePrefixes: '@types/',
|
matchPackagePrefixes: '@types/',
|
||||||
|
@ -98,6 +106,14 @@
|
||||||
extends: ['schedule:weekly'],
|
extends: ['schedule:weekly'],
|
||||||
addLabels: ['typescript'],
|
addLabels: ['typescript'],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// We want those packages to always have their own PR
|
||||||
|
matchManagers: ['npm'],
|
||||||
|
matchPackageNames: [
|
||||||
|
'typescript', // Typescript has code-impacting changes in minor versions
|
||||||
|
],
|
||||||
|
groupName: null, // We dont want them to belong to any group
|
||||||
|
},
|
||||||
// Add labels depending on package manager
|
// Add labels depending on package manager
|
||||||
{ matchManagers: ['npm', 'nvm'], addLabels: ['javascript'] },
|
{ matchManagers: ['npm', 'nvm'], addLabels: ['javascript'] },
|
||||||
{ matchManagers: ['bundler', 'ruby-version'], addLabels: ['ruby'] },
|
{ matchManagers: ['bundler', 'ruby-version'], addLabels: ['ruby'] },
|
||||||
|
|
2
.github/workflows/rebase-needed.yml
vendored
2
.github/workflows/rebase-needed.yml
vendored
|
@ -23,5 +23,5 @@ jobs:
|
||||||
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
commentOnClean: This pull request has resolved merge conflicts and is ready for review.
|
commentOnClean: This pull request has resolved merge conflicts and is ready for review.
|
||||||
commentOnDirty: This pull request has merge conflicts that must be resolved before it can be merged.
|
commentOnDirty: This pull request has merge conflicts that must be resolved before it can be merged.
|
||||||
retryMax: 10
|
retryMax: 30
|
||||||
continueOnMissingPermissions: false
|
continueOnMissingPermissions: false
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `haml-lint --auto-gen-config`
|
# `haml-lint --auto-gen-config`
|
||||||
# on 2023-07-11 23:58:05 +0200 using Haml-Lint version 0.48.0.
|
# on 2023-07-17 12:00:21 -0400 using Haml-Lint version 0.48.0.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the lints are removed from the code base.
|
# one by one as the lints are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
# versions of Haml-Lint, may require this file to be generated again.
|
# versions of Haml-Lint, may require this file to be generated again.
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
# Offense count: 94
|
# Offense count: 959
|
||||||
RuboCop:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
# Offense count: 960
|
|
||||||
LineLength:
|
LineLength:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
@ -19,6 +15,10 @@ linters:
|
||||||
UnnecessaryStringOutput:
|
UnnecessaryStringOutput:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
||||||
|
# Offense count: 67
|
||||||
|
RuboCop:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
# Offense count: 3
|
# Offense count: 3
|
||||||
ViewLength:
|
ViewLength:
|
||||||
exclude:
|
exclude:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This configuration was generated by
|
# This configuration was generated by
|
||||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
|
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp`
|
||||||
# using RuboCop version 1.54.1.
|
# using RuboCop version 1.54.2.
|
||||||
# The point is for the user to remove these configuration records
|
# The point is for the user to remove these configuration records
|
||||||
# one by one as the offenses are removed from the code base.
|
# one by one as the offenses are removed from the code base.
|
||||||
# Note that changes in the inspected code, or installation of new
|
# Note that changes in the inspected code, or installation of new
|
||||||
|
@ -194,7 +194,6 @@ RSpec/AnyInstance:
|
||||||
- 'spec/models/account_spec.rb'
|
- 'spec/models/account_spec.rb'
|
||||||
- 'spec/models/setting_spec.rb'
|
- 'spec/models/setting_spec.rb'
|
||||||
- 'spec/services/activitypub/process_collection_service_spec.rb'
|
- 'spec/services/activitypub/process_collection_service_spec.rb'
|
||||||
- 'spec/validators/blacklisted_email_validator_spec.rb'
|
|
||||||
- 'spec/validators/follow_limit_validator_spec.rb'
|
- 'spec/validators/follow_limit_validator_spec.rb'
|
||||||
- 'spec/workers/activitypub/delivery_worker_spec.rb'
|
- 'spec/workers/activitypub/delivery_worker_spec.rb'
|
||||||
- 'spec/workers/web/push_notification_worker_spec.rb'
|
- 'spec/workers/web/push_notification_worker_spec.rb'
|
||||||
|
@ -333,11 +332,7 @@ RSpec/MessageChain:
|
||||||
RSpec/MessageSpies:
|
RSpec/MessageSpies:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'spec/controllers/admin/accounts_controller_spec.rb'
|
- 'spec/controllers/admin/accounts_controller_spec.rb'
|
||||||
- 'spec/controllers/api/base_controller_spec.rb'
|
|
||||||
- 'spec/controllers/auth/registrations_controller_spec.rb'
|
|
||||||
- 'spec/helpers/admin/account_moderation_notes_helper_spec.rb'
|
- 'spec/helpers/admin/account_moderation_notes_helper_spec.rb'
|
||||||
- 'spec/helpers/application_helper_spec.rb'
|
|
||||||
- 'spec/lib/status_finder_spec.rb'
|
|
||||||
- 'spec/lib/webfinger_resource_spec.rb'
|
- 'spec/lib/webfinger_resource_spec.rb'
|
||||||
- 'spec/models/admin/account_action_spec.rb'
|
- 'spec/models/admin/account_action_spec.rb'
|
||||||
- 'spec/models/concerns/remotable_spec.rb'
|
- 'spec/models/concerns/remotable_spec.rb'
|
||||||
|
@ -372,7 +367,7 @@ Rails/ApplicationController:
|
||||||
|
|
||||||
# Configuration parameters: Database, Include.
|
# Configuration parameters: Database, Include.
|
||||||
# SupportedDatabases: mysql, postgresql
|
# SupportedDatabases: mysql, postgresql
|
||||||
# Include: db/migrate/*.rb
|
# Include: db/**/*.rb
|
||||||
Rails/BulkChangeTable:
|
Rails/BulkChangeTable:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'db/migrate/20160222143943_add_profile_fields_to_accounts.rb'
|
- 'db/migrate/20160222143943_add_profile_fields_to_accounts.rb'
|
||||||
|
@ -408,7 +403,7 @@ Rails/BulkChangeTable:
|
||||||
- 'db/migrate/20220824164433_add_human_identifier_to_admin_action_logs.rb'
|
- 'db/migrate/20220824164433_add_human_identifier_to_admin_action_logs.rb'
|
||||||
|
|
||||||
# Configuration parameters: Include.
|
# Configuration parameters: Include.
|
||||||
# Include: db/migrate/*.rb
|
# Include: db/**/*.rb
|
||||||
Rails/CreateTableWithTimestamps:
|
Rails/CreateTableWithTimestamps:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'db/migrate/20170508230434_create_conversation_mutes.rb'
|
- 'db/migrate/20170508230434_create_conversation_mutes.rb'
|
||||||
|
@ -808,7 +803,6 @@ Style/MutableConstant:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'app/models/tag.rb'
|
- 'app/models/tag.rb'
|
||||||
- 'app/services/delete_account_service.rb'
|
- 'app/services/delete_account_service.rb'
|
||||||
- 'config/initializers/twitter_regex.rb'
|
|
||||||
- 'lib/mastodon/migration_warning.rb'
|
- 'lib/mastodon/migration_warning.rb'
|
||||||
|
|
||||||
# This cop supports safe autocorrection (--autocorrect).
|
# This cop supports safe autocorrection (--autocorrect).
|
||||||
|
|
20
Gemfile.lock
20
Gemfile.lock
|
@ -103,20 +103,20 @@ GEM
|
||||||
attr_required (1.0.1)
|
attr_required (1.0.1)
|
||||||
awrence (1.2.1)
|
awrence (1.2.1)
|
||||||
aws-eventstream (1.2.0)
|
aws-eventstream (1.2.0)
|
||||||
aws-partitions (1.780.0)
|
aws-partitions (1.786.0)
|
||||||
aws-sdk-core (3.175.0)
|
aws-sdk-core (3.178.0)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
aws-partitions (~> 1, >= 1.651.0)
|
aws-partitions (~> 1, >= 1.651.0)
|
||||||
aws-sigv4 (~> 1.5)
|
aws-sigv4 (~> 1.5)
|
||||||
jmespath (~> 1, >= 1.6.1)
|
jmespath (~> 1, >= 1.6.1)
|
||||||
aws-sdk-kms (1.67.0)
|
aws-sdk-kms (1.71.0)
|
||||||
aws-sdk-core (~> 3, >= 3.174.0)
|
aws-sdk-core (~> 3, >= 3.177.0)
|
||||||
aws-sigv4 (~> 1.1)
|
aws-sigv4 (~> 1.1)
|
||||||
aws-sdk-s3 (1.126.0)
|
aws-sdk-s3 (1.130.0)
|
||||||
aws-sdk-core (~> 3, >= 3.174.0)
|
aws-sdk-core (~> 3, >= 3.177.0)
|
||||||
aws-sdk-kms (~> 1)
|
aws-sdk-kms (~> 1)
|
||||||
aws-sigv4 (~> 1.4)
|
aws-sigv4 (~> 1.6)
|
||||||
aws-sigv4 (1.5.2)
|
aws-sigv4 (1.6.0)
|
||||||
aws-eventstream (~> 1, >= 1.0.2)
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
bcrypt (3.1.18)
|
bcrypt (3.1.18)
|
||||||
better_errors (2.10.1)
|
better_errors (2.10.1)
|
||||||
|
@ -493,7 +493,7 @@ GEM
|
||||||
net-smtp
|
net-smtp
|
||||||
premailer (~> 1.7, >= 1.7.9)
|
premailer (~> 1.7, >= 1.7.9)
|
||||||
private_address_check (0.5.0)
|
private_address_check (0.5.0)
|
||||||
public_suffix (5.0.1)
|
public_suffix (5.0.3)
|
||||||
puma (6.3.0)
|
puma (6.3.0)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
pundit (2.3.0)
|
pundit (2.3.0)
|
||||||
|
@ -596,7 +596,7 @@ GEM
|
||||||
sidekiq (>= 2.4.0)
|
sidekiq (>= 2.4.0)
|
||||||
rspec-support (3.12.0)
|
rspec-support (3.12.0)
|
||||||
rspec_chunked (0.6)
|
rspec_chunked (0.6)
|
||||||
rubocop (1.54.1)
|
rubocop (1.54.2)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (>= 3.17.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
|
|
|
@ -19,6 +19,7 @@ class Api::V1::TagsController < Api::BaseController
|
||||||
|
|
||||||
def unfollow
|
def unfollow
|
||||||
TagFollow.find_by(account: current_account, tag: @tag)&.destroy!
|
TagFollow.find_by(account: current_account, tag: @tag)&.destroy!
|
||||||
|
TagUnmergeWorker.perform_async(@tag.id, current_account.id)
|
||||||
render json: @tag, serializer: REST::TagSerializer
|
render json: @tag, serializer: REST::TagSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
module DatabaseHelper
|
module DatabaseHelper
|
||||||
def with_read_replica(&block)
|
def with_read_replica(&block)
|
||||||
ApplicationRecord.connected_to(role: :read, prevent_writes: true, &block)
|
ApplicationRecord.connected_to(role: :reading, prevent_writes: true, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_primary(&block)
|
def with_primary(&block)
|
||||||
ApplicationRecord.connected_to(role: :primary, &block)
|
ApplicationRecord.connected_to(role: :writing, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,9 +23,7 @@ export default class ColumnBackButton extends PureComponent {
|
||||||
|
|
||||||
if (onClick) {
|
if (onClick) {
|
||||||
onClick();
|
onClick();
|
||||||
// Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201
|
} else if (router.history.location?.state?.fromMastodon) {
|
||||||
// When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location
|
|
||||||
} else if (router.route.location.key) {
|
|
||||||
router.history.goBack();
|
router.history.goBack();
|
||||||
} else {
|
} else {
|
||||||
router.history.push('/');
|
router.history.push('/');
|
||||||
|
|
|
@ -63,10 +63,12 @@ class ColumnHeader extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleBackClick = () => {
|
handleBackClick = () => {
|
||||||
if (window.history && window.history.state) {
|
const { router } = this.context;
|
||||||
this.context.router.history.goBack();
|
|
||||||
|
if (router.history.location?.state?.fromMastodon) {
|
||||||
|
router.history.goBack();
|
||||||
} else {
|
} else {
|
||||||
this.context.router.history.push('/');
|
router.history.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +85,7 @@ class ColumnHeader extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
const { router } = this.context;
|
||||||
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props;
|
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props;
|
||||||
const { collapsed, animating } = this.state;
|
const { collapsed, animating } = this.state;
|
||||||
|
|
||||||
|
@ -126,7 +129,7 @@ class ColumnHeader extends PureComponent {
|
||||||
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
|
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pinned && (multiColumn || showBackButton)) {
|
if (!pinned && ((multiColumn && router.history.location?.state?.fromMastodon) || showBackButton)) {
|
||||||
backButton = (
|
backButton = (
|
||||||
<button onClick={this.handleBackClick} className='column-header__back-button'>
|
<button onClick={this.handleBackClick} className='column-header__back-button'>
|
||||||
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
|
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
|
||||||
|
|
|
@ -1,16 +1,26 @@
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { PropsWithChildren } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import type { History } from 'history';
|
|
||||||
import { createBrowserHistory } from 'history';
|
import { createBrowserHistory } from 'history';
|
||||||
import { Router as OriginalRouter } from 'react-router';
|
import { Router as OriginalRouter } from 'react-router';
|
||||||
|
|
||||||
import { layoutFromWindow } from 'mastodon/is_mobile';
|
import { layoutFromWindow } from 'mastodon/is_mobile';
|
||||||
|
|
||||||
const browserHistory = createBrowserHistory();
|
interface MastodonLocationState {
|
||||||
const originalPush = browserHistory.push.bind(browserHistory);
|
fromMastodon?: boolean;
|
||||||
|
mastodonModalKey?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const browserHistory = createBrowserHistory<
|
||||||
|
MastodonLocationState | undefined
|
||||||
|
>();
|
||||||
|
const originalPush = browserHistory.push.bind(browserHistory);
|
||||||
|
const originalReplace = browserHistory.replace.bind(browserHistory);
|
||||||
|
|
||||||
|
browserHistory.push = (path: string, state?: MastodonLocationState) => {
|
||||||
|
state = state ?? {};
|
||||||
|
state.fromMastodon = true;
|
||||||
|
|
||||||
browserHistory.push = (path: string, state: History.LocationState) => {
|
|
||||||
if (layoutFromWindow() === 'multi-column' && !path.startsWith('/deck')) {
|
if (layoutFromWindow() === 'multi-column' && !path.startsWith('/deck')) {
|
||||||
originalPush(`/deck${path}`, state);
|
originalPush(`/deck${path}`, state);
|
||||||
} else {
|
} else {
|
||||||
|
@ -18,6 +28,19 @@ browserHistory.push = (path: string, state: History.LocationState) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
browserHistory.replace = (path: string, state?: MastodonLocationState) => {
|
||||||
|
if (browserHistory.location.state?.fromMastodon) {
|
||||||
|
state = state ?? {};
|
||||||
|
state.fromMastodon = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layoutFromWindow() === 'multi-column' && !path.startsWith('/deck')) {
|
||||||
|
originalReplace(`/deck${path}`, state);
|
||||||
|
} else {
|
||||||
|
originalReplace(path, state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const Router: React.FC<PropsWithChildren> = ({ children }) => {
|
export const Router: React.FC<PropsWithChildren> = ({ children }) => {
|
||||||
return <OriginalRouter history={browserHistory}>{children}</OriginalRouter>;
|
return <OriginalRouter history={browserHistory}>{children}</OriginalRouter>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -493,10 +493,12 @@ class UI extends PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleHotkeyBack = () => {
|
handleHotkeyBack = () => {
|
||||||
if (window.history && window.history.state) {
|
const { router } = this.context;
|
||||||
this.context.router.history.goBack();
|
|
||||||
|
if (router.history.location?.state?.fromMastodon) {
|
||||||
|
router.history.goBack();
|
||||||
} else {
|
} else {
|
||||||
this.context.router.history.push('/');
|
router.history.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1478,6 +1478,7 @@ body > [data-popper-placement] {
|
||||||
.detailed-status__link {
|
.detailed-status__link {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detailed-status__favorites,
|
.detailed-status__favorites,
|
||||||
|
@ -4456,7 +4457,7 @@ a.status-card.compact:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.relationship-tag {
|
.relationship-tag {
|
||||||
color: $primary-text-color;
|
color: $white;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
display: block;
|
display: block;
|
||||||
background-color: rgba($black, 0.45);
|
background-color: rgba($black, 0.45);
|
||||||
|
|
|
@ -180,6 +180,26 @@ class FeedManager
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Remove a tag's statuses from a home feed
|
||||||
|
# @param [Tag] from_tag
|
||||||
|
# @param [Account] into_account
|
||||||
|
# @return [void]
|
||||||
|
def unmerge_tag_from_home(from_tag, into_account)
|
||||||
|
timeline_key = key(:home, into_account.id)
|
||||||
|
timeline_status_ids = redis.zrange(timeline_key, 0, -1)
|
||||||
|
|
||||||
|
# This is a bit tricky because we need posts tagged with this hashtag that are not
|
||||||
|
# also tagged with another followed hashtag or from a followed user
|
||||||
|
scope = from_tag.statuses
|
||||||
|
.where(id: timeline_status_ids)
|
||||||
|
.where.not(account: into_account.following)
|
||||||
|
.tagged_with_none(TagFollow.where(account: into_account).pluck(:tag_id))
|
||||||
|
|
||||||
|
scope.select('id, reblog_of_id').reorder(nil).find_each do |status|
|
||||||
|
remove_from_feed(:home, into_account.id, status, aggregate_reblogs: into_account.user&.aggregates_reblogs?)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Clear all statuses from or mentioning target_account from a home feed
|
# Clear all statuses from or mentioning target_account from a home feed
|
||||||
# @param [Account] account
|
# @param [Account] account
|
||||||
# @param [Account] target_account
|
# @param [Account] target_account
|
||||||
|
|
|
@ -5,6 +5,8 @@ class ApplicationRecord < ActiveRecord::Base
|
||||||
|
|
||||||
include Remotable
|
include Remotable
|
||||||
|
|
||||||
|
connects_to database: { writing: :primary, reading: :read }
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def update_index(_type_name, *_args, &_block)
|
def update_index(_type_name, *_args, &_block)
|
||||||
super if Chewy.enabled?
|
super if Chewy.enabled?
|
||||||
|
|
|
@ -8,6 +8,8 @@ class ActivityPub::ProcessCollectionService < BaseService
|
||||||
@json = original_json = Oj.load(body, mode: :strict)
|
@json = original_json = Oj.load(body, mode: :strict)
|
||||||
@options = options
|
@options = options
|
||||||
|
|
||||||
|
return unless @json.is_a?(Hash)
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@json = compact(@json) if @json['signature'].is_a?(Hash)
|
@json = compact(@json) if @json['signature'].is_a?(Hash)
|
||||||
rescue JSON::LD::JsonLdError => e
|
rescue JSON::LD::JsonLdError => e
|
||||||
|
|
|
@ -10,4 +10,4 @@
|
||||||
= opengraph 'og:image:width', '400'
|
= opengraph 'og:image:width', '400'
|
||||||
= opengraph 'og:image:height', '400'
|
= opengraph 'og:image:height', '400'
|
||||||
= opengraph 'twitter:card', 'summary'
|
= opengraph 'twitter:card', 'summary'
|
||||||
= opengraph 'profile:username', acct(account)[1..-1]
|
= opengraph 'profile:username', acct(account)[1..]
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
= f.input :domain, wrapper: :with_label, label: t('admin.domain_blocks.domain'), hint: t('admin.domain_blocks.new.hint'), required: true, readonly: true, disabled: true
|
= f.input :domain, wrapper: :with_label, label: t('admin.domain_blocks.domain'), hint: t('admin.domain_blocks.new.hint'), required: true, readonly: true, disabled: true
|
||||||
|
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| t("admin.domain_blocks.new.severity.#{type}") }, hint: t('admin.domain_blocks.new.severity.desc_html')
|
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: ->(type) { t("admin.domain_blocks.new.severity.#{type}") }, hint: t('admin.domain_blocks.new.severity.desc_html')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
|
= f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
= f.input :domain, wrapper: :with_label, label: t('admin.domain_blocks.domain'), hint: t('.hint'), required: true
|
= f.input :domain, wrapper: :with_label, label: t('admin.domain_blocks.domain'), hint: t('.hint'), required: true
|
||||||
|
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: lambda { |type| t(".severity.#{type}") }, hint: t('.severity.desc_html')
|
= f.input :severity, collection: DomainBlock.severities.keys, wrapper: :with_label, include_blank: false, label_method: ->(type) { t(".severity.#{type}") }, hint: t('.severity.desc_html')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
|
= f.input :reject_media, as: :boolean, wrapper: :with_label, label: I18n.t('admin.domain_blocks.reject_media'), hint: I18n.t('admin.domain_blocks.reject_media_hint')
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
= f.input :ip, as: :string, wrapper: :with_block_label, input_html: { placeholder: '192.0.2.0/24' }
|
= f.input :ip, as: :string, wrapper: :with_block_label, input_html: { placeholder: '192.0.2.0/24' }
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :expires_in, wrapper: :with_block_label, collection: [1.day, 2.weeks, 1.month, 6.months, 1.year, 3.years].map(&:to_i), label_method: lambda { |i| I18n.t("admin.ip_blocks.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
|
= f.input :expires_in, wrapper: :with_block_label, collection: [1.day, 2.weeks, 1.month, 6.months, 1.year, 3.years].map(&:to_i), label_method: ->(i) { I18n.t("admin.ip_blocks.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :severity, as: :radio_buttons, collection: IpBlock.severities.keys, include_blank: false, wrapper: :with_block_label, label_method: lambda { |severity| safe_join([I18n.t("simple_form.labels.ip_block.severities.#{severity}"), content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint')]) }
|
= f.input :severity, as: :radio_buttons, collection: IpBlock.severities.keys, include_blank: false, wrapper: :with_block_label, label_method: ->(severity) { safe_join([I18n.t("simple_form.labels.ip_block.severities.#{severity}"), content_tag(:span, I18n.t("simple_form.hints.ip_block.severities.#{severity}"), class: 'hint')]) }
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :comment, as: :string, wrapper: :with_block_label
|
= f.input :comment, as: :string, wrapper: :with_block_label
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
- (@role.everyone? ? UserRole::Flags::CATEGORIES.slice(:invites) : UserRole::Flags::CATEGORIES).each do |category, permissions|
|
- (@role.everyone? ? UserRole::Flags::CATEGORIES.slice(:invites) : UserRole::Flags::CATEGORIES).each do |category, permissions|
|
||||||
%h4= t(category, scope: 'admin.roles.categories')
|
%h4= t(category, scope: 'admin.roles.categories')
|
||||||
|
|
||||||
= f.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: lambda { |privilege| safe_join([t("admin.roles.privileges.#{privilege}"), content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint')]) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: permissions.filter { |privilege| UserRole::FLAGS[privilege] & current_user.role.computed_permissions == 0 }
|
= f.input :permissions_as_keys, collection: permissions, wrapper: :with_block_label, include_blank: false, label_method: ->(privilege) { safe_join([t("admin.roles.privileges.#{privilege}"), content_tag(:span, t("admin.roles.privileges.#{privilege}_description"), class: 'hint')]) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label: false, hint: false, disabled: permissions.filter { |privilege| UserRole::FLAGS[privilege] & current_user.role.computed_permissions == 0 }
|
||||||
|
|
||||||
%hr.spacer/
|
%hr.spacer/
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
|
|
||||||
.fields-row
|
.fields-row
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :show_domain_blocks, wrapper: :with_label, collection: %i(disabled users all), label_method: lambda { |value| t("admin.settings.domain_blocks.#{value}") }, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
= f.input :show_domain_blocks, wrapper: :with_label, collection: %i(disabled users all), label_method: ->(value) { t("admin.settings.domain_blocks.#{value}") }, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :show_domain_blocks_rationale, wrapper: :with_label, collection: %i(disabled users all), label_method: lambda { |value| t("admin.settings.domain_blocks.#{value}") }, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
= f.input :show_domain_blocks_rationale, wrapper: :with_label, collection: %i(disabled users all), label_method: ->(value) { t("admin.settings.domain_blocks.#{value}") }, include_blank: false, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :status_page_url, wrapper: :with_block_label, input_html: { placeholder: "https://status.#{Rails.configuration.x.local_domain}" }
|
= f.input :status_page_url, wrapper: :with_block_label, input_html: { placeholder: "https://status.#{Rails.configuration.x.local_domain}" }
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
%p.lead= t('admin.settings.appearance.preamble')
|
%p.lead= t('admin.settings.appearance.preamble')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false
|
= f.input :theme, collection: Themes.instance.names, label_method: ->(theme) { I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, include_blank: false
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :custom_css, wrapper: :with_block_label, as: :text, input_html: { rows: 8 }
|
= f.input :custom_css, wrapper: :with_block_label, as: :text, input_html: { rows: 8 }
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
.fields-row
|
.fields-row
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :registrations_mode, collection: %w(open approved none), wrapper: :with_label, include_blank: false, label_method: lambda { |mode| I18n.t("admin.settings.registrations_mode.modes.#{mode}") }
|
= f.input :registrations_mode, collection: %w(open approved none), wrapper: :with_label, include_blank: false, label_method: ->(mode) { I18n.t("admin.settings.registrations_mode.modes.#{mode}") }
|
||||||
|
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :require_invite_text, as: :boolean, wrapper: :with_label, disabled: !approved_registrations?
|
= f.input :require_invite_text, as: :boolean, wrapper: :with_label, disabled: !approved_registrations?
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :title, as: :string, wrapper: :with_label, hint: false
|
= f.input :title, as: :string, wrapper: :with_label, hint: false
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, include_blank: I18n.t('invites.expires_in_prompt')
|
= f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: ->(i) { I18n.t("invites.expires_in.#{i}") }, include_blank: I18n.t('invites.expires_in_prompt')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :context, wrapper: :with_block_label, collection: CustomFilter::VALID_CONTEXTS, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label_method: lambda { |context| I18n.t("filters.contexts.#{context}") }, include_blank: false
|
= f.input :context, wrapper: :with_block_label, collection: CustomFilter::VALID_CONTEXTS, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', label_method: ->(context) { I18n.t("filters.contexts.#{context}") }, include_blank: false
|
||||||
|
|
||||||
%hr.spacer/
|
%hr.spacer/
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
|
|
||||||
.fields-row
|
.fields-row
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :max_uses, wrapper: :with_label, collection: [1, 5, 10, 25, 50, 100], label_method: lambda { |num| I18n.t('invites.max_uses', count: num) }, prompt: I18n.t('invites.max_uses_prompt')
|
= f.input :max_uses, wrapper: :with_label, collection: [1, 5, 10, 25, 50, 100], label_method: ->(num) { I18n.t('invites.max_uses', count: num) }, prompt: I18n.t('invites.max_uses_prompt')
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: lambda { |i| I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
|
= f.input :expires_in, wrapper: :with_label, collection: [30.minutes, 1.hour, 6.hours, 12.hours, 1.day, 1.week].map(&:to_i), label_method: ->(i) { I18n.t("invites.expires_in.#{i}") }, prompt: I18n.t('invites.expires_in_prompt')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :autofollow, wrapper: :with_label
|
= f.input :autofollow, wrapper: :with_label
|
||||||
|
|
|
@ -42,4 +42,4 @@
|
||||||
= link_to a.remote_url, a.remote_url
|
= link_to a.remote_url, a.remote_url
|
||||||
|
|
||||||
%p.status-footer
|
%p.status-footer
|
||||||
= link_to l(status.created_at.in_time_zone(time_zone)), web_url("@#{status.account.pretty_acct}/#{status.id}")
|
= link_to l(status.created_at.in_time_zone(time_zone.presence)), web_url("@#{status.account.pretty_acct}/#{status.id}")
|
||||||
|
|
|
@ -15,4 +15,4 @@
|
||||||
%span.hint= t('simple_form.hints.defaults.scopes')
|
%span.hint= t('simple_form.hints.defaults.scopes')
|
||||||
|
|
||||||
- Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each do |k, v|
|
- Doorkeeper.configuration.scopes.group_by { |s| s.split(':').first }.each do |k, v|
|
||||||
= f.input :scopes, label: false, hint: false, collection: v.sort, wrapper: :with_block_label, include_blank: false, label_method: lambda { |scope| safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) }, selected: f.object.scopes.all, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
= f.input :scopes, label: false, hint: false, collection: v.sort, wrapper: :with_block_label, include_blank: false, label_method: ->(scope) { safe_join([content_tag(:samp, scope, class: class_for_scope(scope)), content_tag(:span, t("doorkeeper.scopes.#{scope}"), class: 'hint')]) }, selected: f.object.scopes.all, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
- content_for :page_title do
|
- content_for :page_title do
|
||||||
= t("imports.titles.#{@bulk_import.type.to_s}")
|
= t("imports.titles.#{@bulk_import.type}")
|
||||||
|
|
||||||
- if @bulk_import.likely_mismatched?
|
- if @bulk_import.likely_mismatched?
|
||||||
.flash-message.warning= t("imports.mismatched_types_warning")
|
.flash-message.warning= t('imports.mismatched_types_warning')
|
||||||
|
|
||||||
- if @bulk_import.overwrite?
|
- if @bulk_import.overwrite?
|
||||||
%p.hint= t("imports.overwrite_preambles.#{@bulk_import.type.to_s}_html", filename: @bulk_import.original_filename, total_items: @bulk_import.total_items)
|
%p.hint= t("imports.overwrite_preambles.#{@bulk_import.type}_html", filename: @bulk_import.original_filename, total_items: @bulk_import.total_items)
|
||||||
- else
|
- else
|
||||||
%p.hint= t("imports.preambles.#{@bulk_import.type.to_s}_html", filename: @bulk_import.original_filename, total_items: @bulk_import.total_items)
|
%p.hint= t("imports.preambles.#{@bulk_import.type}_html", filename: @bulk_import.original_filename, total_items: @bulk_import.total_items)
|
||||||
|
|
||||||
.simple_form
|
.simple_form
|
||||||
.actions
|
.actions
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
= simple_form_for current_user, url: settings_preferences_appearance_path, html: { method: :put, id: 'edit_user' } do |f|
|
= simple_form_for current_user, url: settings_preferences_appearance_path, html: { method: :put, id: 'edit_user' } do |f|
|
||||||
.fields-row
|
.fields-row
|
||||||
.fields-group.fields-row__column.fields-row__column-6
|
.fields-group.fields-row__column.fields-row__column-6
|
||||||
= f.input :locale, collection: I18n.available_locales, wrapper: :with_label, include_blank: false, label_method: lambda { |locale| native_locale_name(locale) }, selected: I18n.locale, hint: false
|
= f.input :locale, collection: I18n.available_locales, wrapper: :with_label, include_blank: false, label_method: ->(locale) { native_locale_name(locale) }, selected: I18n.locale, hint: false
|
||||||
.fields-group.fields-row__column.fields-row__column-6
|
.fields-group.fields-row__column.fields-row__column-6
|
||||||
= f.input :time_zone, wrapper: :with_label, collection: ActiveSupport::TimeZone.all.map { |tz| ["(GMT#{tz.formatted_offset}) #{tz.name}", tz.tzinfo.name] }, hint: false
|
= f.input :time_zone, wrapper: :with_label, collection: ActiveSupport::TimeZone.all.map { |tz| ["(GMT#{tz.formatted_offset}) #{tz.name}", tz.tzinfo.name] }, hint: false
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.simple_fields_for :settings, current_user.settings do |ff|
|
= f.simple_fields_for :settings, current_user.settings do |ff|
|
||||||
= ff.input :theme, collection: Themes.instance.names, label_method: lambda { |theme| I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_theme'), include_blank: false, hint: false
|
= ff.input :theme, collection: Themes.instance.names, label_method: ->(theme) { I18n.t("themes.#{theme}", default: theme) }, wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_theme'), include_blank: false, hint: false
|
||||||
|
|
||||||
- unless I18n.locale == :en
|
- unless I18n.locale == :en
|
||||||
.flash-message.translation-prompt
|
.flash-message.translation-prompt
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
%h4= t 'appearance.sensitive_content'
|
%h4= t 'appearance.sensitive_content'
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= ff.input :'web.display_media', collection: ['default', 'show_all', 'hide_all'],label_method: lambda { |item| t("simple_form.hints.defaults.setting_display_media_#{item}") }, hint: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label, label: I18n.t('simple_form.labels.defaults.setting_display_media')
|
= ff.input :'web.display_media', collection: ['default', 'show_all', 'hide_all'], label_method: ->(item) { t("simple_form.hints.defaults.setting_display_media_#{item}") }, hint: false, as: :radio_buttons, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li', wrapper: :with_floating_label, label: I18n.t('simple_form.labels.defaults.setting_display_media')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= ff.input :'web.display_media_expand', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_display_media_expand'), hint: I18n.t('simple_form.hints.defaults.setting_display_media_expand')
|
= ff.input :'web.display_media_expand', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_display_media_expand'), hint: I18n.t('simple_form.hints.defaults.setting_display_media_expand')
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
.fields-row
|
.fields-row
|
||||||
.fields-group.fields-row__column.fields-row__column-6
|
.fields-group.fields-row__column.fields-row__column-6
|
||||||
= ff.input :default_privacy, collection: Status.selectable_visibilities, wrapper: :with_label, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_privacy')
|
= ff.input :default_privacy, collection: Status.selectable_visibilities, wrapper: :with_label, include_blank: false, label_method: ->(visibility) { safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_privacy')
|
||||||
|
|
||||||
.fields-group.fields-row__column.fields-row__column-6
|
.fields-group.fields-row__column.fields-row__column-6
|
||||||
= ff.input :default_reblog_privacy, collection: Status.selectable_reblog_visibilities, wrapper: :with_label, kmyblue: true, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_reblog_privacy')
|
= ff.input :default_reblog_privacy, collection: Status.selectable_reblog_visibilities, wrapper: :with_label, kmyblue: true, include_blank: false, label_method: lambda { |visibility| safe_join([I18n.t("statuses.visibilities.#{visibility}"), I18n.t("statuses.visibilities.#{visibility}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_reblog_privacy')
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
= ff.input :default_searchability, collection: Status.selectable_searchabilities, wrapper: :with_label, kmyblue: true, include_blank: false, label_method: lambda { |searchability| safe_join([I18n.t("statuses.searchabilities.#{searchability}"), I18n.t("statuses.searchabilities.#{searchability}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_searchability')
|
= ff.input :default_searchability, collection: Status.selectable_searchabilities, wrapper: :with_label, kmyblue: true, include_blank: false, label_method: lambda { |searchability| safe_join([I18n.t("statuses.searchabilities.#{searchability}"), I18n.t("statuses.searchabilities.#{searchability}_long")], ' - ') }, required: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_searchability')
|
||||||
|
|
||||||
.fields-group.fields-row__column.fields-row__column-6
|
.fields-group.fields-row__column.fields-row__column-6
|
||||||
= ff.input :default_language, collection: [nil] + filterable_languages, wrapper: :with_label, label_method: lambda { |locale| locale.nil? ? I18n.t('statuses.default_language') : native_locale_name(locale) }, required: false, include_blank: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_language')
|
= ff.input :default_language, collection: [nil] + filterable_languages, wrapper: :with_label, label_method: ->(locale) { locale.nil? ? I18n.t('statuses.default_language') : native_locale_name(locale) }, required: false, include_blank: false, hint: false, label: I18n.t('simple_form.labels.defaults.setting_default_language')
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= ff.input :'web.enable_login_privacy', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_enable_login_privacy'), hint: false
|
= ff.input :'web.enable_login_privacy', wrapper: :with_label, kmyblue: true, label: I18n.t('simple_form.labels.defaults.setting_enable_login_privacy'), hint: false
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
%h4= t 'preferences.public_timelines'
|
%h4= t 'preferences.public_timelines'
|
||||||
|
|
||||||
.fields-group
|
.fields-group
|
||||||
= f.input :chosen_languages, collection: filterable_languages, wrapper: :with_block_label, include_blank: false, label_method: lambda { |locale| native_locale_name(locale) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
= f.input :chosen_languages, collection: filterable_languages, wrapper: :with_block_label, include_blank: false, label_method: ->(locale) { native_locale_name(locale) }, required: false, as: :check_boxes, collection_wrapper_tag: 'ul', item_wrapper_tag: 'li'
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
= f.button :button, t('generic.save_changes'), type: :submit
|
= f.button :button, t('generic.save_changes'), type: :submit
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
%span.poll__voted
|
%span.poll__voted
|
||||||
%i.poll__voted__mark.fa.fa-check
|
%i.poll__voted__mark.fa.fa-check
|
||||||
|
|
||||||
%progress{ max: 100, value: percent < 1 ? 1 : percent, 'aria-hidden': 'true' }
|
%progress{ max: 100, value: [percent, 1].max, 'aria-hidden': 'true' }
|
||||||
%span.poll__chart
|
%span.poll__chart
|
||||||
- else
|
- else
|
||||||
%label.poll__option><
|
%label.poll__option><
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
= opengraph 'og:title', "#{display_name(@account)} (#{acct(@account)})"
|
= opengraph 'og:title', "#{display_name(@account)} (#{acct(@account)})"
|
||||||
= opengraph 'og:url', short_account_status_url(@account, @status)
|
= opengraph 'og:url', short_account_status_url(@account, @status)
|
||||||
= opengraph 'og:published_time', @status.created_at.iso8601
|
= opengraph 'og:published_time', @status.created_at.iso8601
|
||||||
= opengraph 'profile:username', acct(@account)[1..-1]
|
= opengraph 'profile:username', acct(@account)[1..]
|
||||||
|
|
||||||
= render 'og_description', activity: @status
|
= render 'og_description', activity: @status
|
||||||
= render 'og_image', activity: @status, account: @account
|
= render 'og_image', activity: @status, account: @account
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :enabled, as: :boolean, wrapper: :with_label, label: t('statuses_cleanup.enabled'), hint: t('statuses_cleanup.enabled_hint')
|
= f.input :enabled, as: :boolean, wrapper: :with_label, label: t('statuses_cleanup.enabled'), hint: t('statuses_cleanup.enabled_hint')
|
||||||
.fields-row__column.fields-row__column-6.fields-group
|
.fields-row__column.fields-row__column-6.fields-group
|
||||||
= f.input :min_status_age, wrapper: :with_label, label: t('statuses_cleanup.min_age_label'), collection: AccountStatusesCleanupPolicy::ALLOWED_MIN_STATUS_AGE.map(&:to_i), label_method: lambda { |i| t("statuses_cleanup.min_age.#{i}") }, include_blank: false, hint: false
|
= f.input :min_status_age, wrapper: :with_label, label: t('statuses_cleanup.min_age_label'), collection: AccountStatusesCleanupPolicy::ALLOWED_MIN_STATUS_AGE.map(&:to_i), label_method: ->(i) { t("statuses_cleanup.min_age.#{i}") }, include_blank: false, hint: false
|
||||||
|
|
||||||
.flash-message= t('statuses_cleanup.explanation')
|
.flash-message= t('statuses_cleanup.explanation')
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td.column-cell.text-center
|
%td.column-cell.text-center
|
||||||
%p= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone))
|
%p= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence))
|
||||||
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
===
|
===
|
||||||
|
|
||||||
<%= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone)) %>
|
<%= t 'user_mailer.appeal_approved.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence)) %>
|
||||||
|
|
||||||
=> <%= root_url %>
|
=> <%= root_url %>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
%tr
|
||||||
%td.column-cell.text-center
|
%td.column-cell.text-center
|
||||||
%p= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone))
|
%p= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence))
|
||||||
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
===
|
===
|
||||||
|
|
||||||
<%= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone)) %>
|
<%= t 'user_mailer.appeal_rejected.explanation', appeal_date: l(@appeal.created_at.in_time_zone(@resource.time_zone.presence)), strike_date: l(@appeal.strike.created_at.in_time_zone(@resource.time_zone.presence)) %>
|
||||||
|
|
||||||
=> <%= root_url %>
|
=> <%= root_url %>
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
%strong= "#{t('sessions.browser')}:"
|
%strong= "#{t('sessions.browser')}:"
|
||||||
%span{ title: @user_agent }= t 'sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: @detection.id.to_s), platform: t("sessions.platforms.#{@detection.platform.id}", default: @detection.platform.id.to_s)
|
%span{ title: @user_agent }= t 'sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: @detection.id.to_s), platform: t("sessions.platforms.#{@detection.platform.id}", default: @detection.platform.id.to_s)
|
||||||
%br/
|
%br/
|
||||||
= l(@timestamp.in_time_zone(@resource.time_zone))
|
= l(@timestamp.in_time_zone(@resource.time_zone.presence))
|
||||||
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
||||||
%tbody
|
%tbody
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
<%= t('sessions.ip') %>: <%= @remote_ip %>
|
<%= t('sessions.ip') %>: <%= @remote_ip %>
|
||||||
<%= t('sessions.browser') %>: <%= t('sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: "#{@detection.id}"), platform: t("sessions.platforms.#{@detection.platform.id}", default: "#{@detection.platform.id}")) %>
|
<%= t('sessions.browser') %>: <%= t('sessions.description', browser: t("sessions.browsers.#{@detection.id}", default: "#{@detection.id}"), platform: t("sessions.platforms.#{@detection.platform.id}", default: "#{@detection.platform.id}")) %>
|
||||||
<%= l(@timestamp.in_time_zone(@resource.time_zone)) %>
|
<%= l(@timestamp.in_time_zone(@resource.time_zone.presence)) %>
|
||||||
|
|
||||||
<%= t 'user_mailer.suspicious_sign_in.further_actions_html', action: t('user_mailer.suspicious_sign_in.change_password') %>
|
<%= t 'user_mailer.suspicious_sign_in.further_actions_html', action: t('user_mailer.suspicious_sign_in.change_password') %>
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
- unless @statuses.empty?
|
- unless @statuses.empty?
|
||||||
- @statuses.each_with_index do |status, i|
|
- @statuses.each_with_index do |status, i|
|
||||||
= render 'notification_mailer/status', status: status, i: i + 1, highlighted: true, time_zone: @resource.time_zone
|
= render 'notification_mailer/status', status: status, i: i + 1, highlighted: true, time_zone: @resource.time_zone.presence
|
||||||
|
|
||||||
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
%table.email-table{ cellspacing: 0, cellpadding: 0 }
|
||||||
%tbody
|
%tbody
|
||||||
|
|
21
app/workers/tag_unmerge_worker.rb
Normal file
21
app/workers/tag_unmerge_worker.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class TagUnmergeWorker
|
||||||
|
include Sidekiq::Worker
|
||||||
|
include DatabaseHelper
|
||||||
|
|
||||||
|
sidekiq_options queue: 'pull'
|
||||||
|
|
||||||
|
def perform(from_tag_id, into_account_id)
|
||||||
|
with_primary do
|
||||||
|
@from_tag = Tag.find(from_tag_id)
|
||||||
|
@into_account = Account.find(into_account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
with_read_replica do
|
||||||
|
FeedManager.instance.unmerge_tag_from_home(@from_tag, @into_account)
|
||||||
|
end
|
||||||
|
rescue ActiveRecord::RecordNotFound
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,23 +8,41 @@ default: &default
|
||||||
application_name: ''
|
application_name: ''
|
||||||
|
|
||||||
development:
|
development:
|
||||||
|
primary:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: <%= ENV['DB_NAME'] || 'mastodon_development' %>
|
database: <%= ENV['DB_NAME'] || 'mastodon_development' %>
|
||||||
username: <%= ENV['DB_USER'] %>
|
username: <%= ENV['DB_USER'] %>
|
||||||
password: <%= (ENV['DB_PASS'] || '').to_json %>
|
password: <%= (ENV['DB_PASS'] || '').to_json %>
|
||||||
host: <%= ENV['DB_HOST'] %>
|
host: <%= ENV['DB_HOST'] %>
|
||||||
port: <%= ENV['DB_PORT'] %>
|
port: <%= ENV['DB_PORT'] %>
|
||||||
|
read:
|
||||||
|
<<: *default
|
||||||
|
database: <%= ENV['DB_NAME'] || 'mastodon_development' %>
|
||||||
|
username: <%= ENV['DB_USER'] %>
|
||||||
|
password: <%= (ENV['DB_PASS'] || '').to_json %>
|
||||||
|
host: <%= ENV['DB_HOST'] %>
|
||||||
|
port: <%= ENV['DB_PORT'] %>
|
||||||
|
replica: true
|
||||||
|
|
||||||
# Warning: The database defined as "test" will be erased and
|
# Warning: The database defined as "test" will be erased and
|
||||||
# re-generated from your development database when you run "rake".
|
# re-generated from your development database when you run "rake".
|
||||||
# Do not set this db to the same as development or production.
|
# Do not set this db to the same as development or production.
|
||||||
test:
|
test:
|
||||||
|
primary:
|
||||||
<<: *default
|
<<: *default
|
||||||
database: <%= ENV['DB_NAME'] || 'mastodon' %>_test<%= ENV['TEST_ENV_NUMBER'] %>
|
database: <%= ENV['DB_NAME'] || 'mastodon' %>_test<%= ENV['TEST_ENV_NUMBER'] %>
|
||||||
username: <%= ENV['DB_USER'] %>
|
username: <%= ENV['DB_USER'] %>
|
||||||
password: <%= (ENV['DB_PASS'] || '').to_json %>
|
password: <%= (ENV['DB_PASS'] || '').to_json %>
|
||||||
host: <%= ENV['DB_HOST'] %>
|
host: <%= ENV['DB_HOST'] %>
|
||||||
port: <%= ENV['DB_PORT'] %>
|
port: <%= ENV['DB_PORT'] %>
|
||||||
|
read:
|
||||||
|
<<: *default
|
||||||
|
database: <%= ENV['DB_NAME'] || 'mastodon' %>_test<%= ENV['TEST_ENV_NUMBER'] %>
|
||||||
|
username: <%= ENV['DB_USER'] %>
|
||||||
|
password: <%= (ENV['DB_PASS'] || '').to_json %>
|
||||||
|
host: <%= ENV['DB_HOST'] %>
|
||||||
|
port: <%= ENV['DB_PORT'] %>
|
||||||
|
replica: true
|
||||||
|
|
||||||
production:
|
production:
|
||||||
primary:
|
primary:
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
RSpec.describe Api::V1::PollsController do
|
|
||||||
render_views
|
|
||||||
|
|
||||||
let(:user) { Fabricate(:user) }
|
|
||||||
let(:scopes) { 'read:statuses' }
|
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
|
||||||
|
|
||||||
before { allow(controller).to receive(:doorkeeper_token) { token } }
|
|
||||||
|
|
||||||
describe 'GET #show' do
|
|
||||||
let(:poll) { Fabricate(:poll, status: Fabricate(:status, visibility: visibility)) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
get :show, params: { id: poll.id }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when parent status is public' do
|
|
||||||
let(:visibility) { 'public' }
|
|
||||||
|
|
||||||
it 'returns http success' do
|
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when parent status is private' do
|
|
||||||
let(:visibility) { 'private' }
|
|
||||||
|
|
||||||
it 'returns http not found' do
|
|
||||||
expect(response).to have_http_status(404)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,113 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
describe Api::V1::Statuses::BookmarksController do
|
|
||||||
render_views
|
|
||||||
|
|
||||||
let(:user) { Fabricate(:user) }
|
|
||||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:bookmarks', application: app) }
|
|
||||||
|
|
||||||
context 'with an oauth token' do
|
|
||||||
before do
|
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'POST #create' do
|
|
||||||
let(:status) { Fabricate(:status, account: user.account) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
post :create, params: { status_id: status.id }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with public status' do
|
|
||||||
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
|
|
||||||
|
|
||||||
context 'with private status of not-followed account' do
|
|
||||||
let(:status) { Fabricate(:status, visibility: :private) }
|
|
||||||
|
|
||||||
it 'returns http not found' do
|
|
||||||
expect(response).to have_http_status(404)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'POST #destroy' do
|
|
||||||
context 'with public status' do
|
|
||||||
let(:status) { Fabricate(:status, account: user.account) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
Bookmark.find_or_create_by!(account: user.account, status: status)
|
|
||||||
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
|
|
||||||
|
|
||||||
context 'with public status when blocked by its author' do
|
|
||||||
let(:status) { Fabricate(:status) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
Bookmark.find_or_create_by!(account: user.account, status: status)
|
|
||||||
status.account.block!(user.account)
|
|
||||||
post :destroy, params: { status_id: status.id }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns http success' do
|
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
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
|
|
||||||
|
|
||||||
context 'with private status that was not bookmarked' do
|
|
||||||
let(:status) { Fabricate(:status, visibility: :private) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
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
|
|
|
@ -1,123 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
describe Api::V1::Statuses::FavouritesController do
|
|
||||||
render_views
|
|
||||||
|
|
||||||
let(:user) { Fabricate(:user) }
|
|
||||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:favourites', application: app) }
|
|
||||||
|
|
||||||
context 'with an oauth token' do
|
|
||||||
before do
|
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'POST #create' do
|
|
||||||
let(:status) { Fabricate(:status, account: user.account) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
post :create, params: { status_id: status.id }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with public status' do
|
|
||||||
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
|
|
||||||
|
|
||||||
context 'with private status of not-followed account' do
|
|
||||||
let(:status) { Fabricate(:status, visibility: :private) }
|
|
||||||
|
|
||||||
it 'returns http not found' do
|
|
||||||
expect(response).to have_http_status(404)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'POST #destroy' do
|
|
||||||
context 'with public status' do
|
|
||||||
let(:status) { Fabricate(:status, account: user.account) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
FavouriteService.new.call(user.account, status)
|
|
||||||
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
|
|
||||||
|
|
||||||
context 'with public status when blocked by its author' do
|
|
||||||
let(:status) { Fabricate(:status) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
FavouriteService.new.call(user.account, status)
|
|
||||||
status.account.block!(user.account)
|
|
||||||
post :destroy, params: { status_id: status.id }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns http success' do
|
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'updates the favourite 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[:favourited]).to be false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with private status that was not favourited' do
|
|
||||||
let(:status) { Fabricate(:status, visibility: :private) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
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
|
|
|
@ -1,57 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
describe Api::V1::Statuses::PinsController do
|
|
||||||
render_views
|
|
||||||
|
|
||||||
let(:user) { Fabricate(:user) }
|
|
||||||
let(:app) { Fabricate(:application, name: 'Test app', website: 'http://testapp.com') }
|
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'write:accounts', application: app) }
|
|
||||||
|
|
||||||
context 'with an oauth token' do
|
|
||||||
before do
|
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'POST #create' do
|
|
||||||
let(:status) { Fabricate(:status, account: user.account) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
post :create, params: { status_id: status.id }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns http success' do
|
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'updates the pinned attribute' do
|
|
||||||
expect(user.account.pinned?(status)).to be true
|
|
||||||
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[:pinned]).to be true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe 'POST #destroy' do
|
|
||||||
let(:status) { Fabricate(:status, account: user.account) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
Fabricate(:status_pin, status: status, account: user.account)
|
|
||||||
post :destroy, params: { status_id: status.id }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns http success' do
|
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'updates the pinned attribute' do
|
|
||||||
expect(user.account.pinned?(status)).to be false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,44 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
describe Api::V1::Timelines::HomeController do
|
|
||||||
render_views
|
|
||||||
|
|
||||||
let(:user) { Fabricate(:user, current_sign_in_at: 1.day.ago) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'with a user context' do
|
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: 'read:statuses') }
|
|
||||||
|
|
||||||
describe 'GET #show' do
|
|
||||||
before do
|
|
||||||
follow = Fabricate(:follow, account: user.account)
|
|
||||||
PostStatusService.new.call(follow.target_account, text: 'New status for user home timeline.')
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns http success' do
|
|
||||||
get :show
|
|
||||||
|
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
expect(response.headers['Link'].links.size).to eq(2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'without a user context' do
|
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: 'read') }
|
|
||||||
|
|
||||||
describe 'GET #show' do
|
|
||||||
it 'returns http unprocessable entity' do
|
|
||||||
get :show
|
|
||||||
|
|
||||||
expect(response).to have_http_status(422)
|
|
||||||
expect(response.headers['Link']).to be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -2,27 +2,34 @@
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Api::V1::Emails::ConfirmationsController do
|
RSpec.describe 'Confirmations' do
|
||||||
let(:confirmed_at) { nil }
|
let(:confirmed_at) { nil }
|
||||||
let(:user) { Fabricate(:user, confirmed_at: confirmed_at) }
|
let(:user) { Fabricate(:user, confirmed_at: confirmed_at) }
|
||||||
let(:app) { Fabricate(:application) }
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes, application: app) }
|
let(:scopes) { 'read:accounts write:accounts' }
|
||||||
let(:scopes) { 'write' }
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
describe '#create' do
|
describe 'POST /api/v1/emails/confirmations' do
|
||||||
context 'with an oauth token' do
|
subject do
|
||||||
before do
|
post '/api/v1/emails/confirmations', headers: headers, params: params
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when from a random app' do
|
let(:params) { {} }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read read:accounts'
|
||||||
|
|
||||||
|
context 'with an oauth token' do
|
||||||
|
context 'when user was created by a different application' do
|
||||||
|
let(:user) { Fabricate(:user, confirmed_at: confirmed_at, created_by_application: Fabricate(:application)) }
|
||||||
|
|
||||||
it 'returns http forbidden' do
|
it 'returns http forbidden' do
|
||||||
post :create
|
subject
|
||||||
|
|
||||||
expect(response).to have_http_status(403)
|
expect(response).to have_http_status(403)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when from an app that created the account' do
|
context 'when user was created by the same application' do
|
||||||
before do
|
before do
|
||||||
user.update(created_by_application: token.application)
|
user.update(created_by_application: token.application)
|
||||||
end
|
end
|
||||||
|
@ -31,55 +38,79 @@ RSpec.describe Api::V1::Emails::ConfirmationsController do
|
||||||
let(:confirmed_at) { Time.now.utc }
|
let(:confirmed_at) { Time.now.utc }
|
||||||
|
|
||||||
it 'returns http forbidden' do
|
it 'returns http forbidden' do
|
||||||
post :create
|
subject
|
||||||
|
|
||||||
expect(response).to have_http_status(403)
|
expect(response).to have_http_status(403)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with user changed e-mail and has not confirmed it' do
|
context 'when user changed e-mail and has not confirmed it' do
|
||||||
before do
|
before do
|
||||||
user.update(email: 'foo@bar.com')
|
user.update(email: 'foo@bar.com')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
post :create
|
subject
|
||||||
expect(response).to have_http_status(:success)
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the account is unconfirmed' do
|
context 'when the account is unconfirmed' do
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
post :create
|
subject
|
||||||
expect(response).to have_http_status(:success)
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with email param' do
|
||||||
|
let(:params) { { email: 'foo@bar.com' } }
|
||||||
|
|
||||||
|
it "updates the user's e-mail address", :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.reload.unconfirmed_email).to eq('foo@bar.com')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with invalid email param' do
|
||||||
|
let(:params) { { email: 'invalid' } }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'without an oauth token' do
|
context 'without an oauth token' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
it 'returns http unauthorized' do
|
it 'returns http unauthorized' do
|
||||||
post :create
|
subject
|
||||||
|
|
||||||
expect(response).to have_http_status(401)
|
expect(response).to have_http_status(401)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#check' do
|
describe 'GET /api/v1/emails/check_confirmation' do
|
||||||
let(:scopes) { 'read' }
|
subject do
|
||||||
|
get '/api/v1/emails/check_confirmation', headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write'
|
||||||
|
|
||||||
context 'with an oauth token' do
|
context 'with an oauth token' do
|
||||||
before do
|
|
||||||
allow(controller).to receive(:doorkeeper_token) { token }
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when the account is not confirmed' do
|
context 'when the account is not confirmed' do
|
||||||
it 'returns http success' do
|
it 'returns the confirmation status successfully', :aggregate_failures do
|
||||||
get :check
|
subject
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false' do
|
expect(response).to have_http_status(200)
|
||||||
get :check
|
|
||||||
expect(body_as_json).to be false
|
expect(body_as_json).to be false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -87,31 +118,27 @@ RSpec.describe Api::V1::Emails::ConfirmationsController do
|
||||||
context 'when the account is confirmed' do
|
context 'when the account is confirmed' do
|
||||||
let(:confirmed_at) { Time.now.utc }
|
let(:confirmed_at) { Time.now.utc }
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns the confirmation status successfully', :aggregate_failures do
|
||||||
get :check
|
subject
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true' do
|
expect(response).to have_http_status(200)
|
||||||
get :check
|
|
||||||
expect(body_as_json).to be true
|
expect(body_as_json).to be true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'with an authentication cookie' do
|
context 'with an authentication cookie' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in user, scope: :user
|
sign_in user, scope: :user
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the account is not confirmed' do
|
context 'when the account is not confirmed' do
|
||||||
it 'returns http success' do
|
it 'returns the confirmation status successfully', :aggregate_failures do
|
||||||
get :check
|
subject
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns false' do
|
expect(response).to have_http_status(200)
|
||||||
get :check
|
|
||||||
expect(body_as_json).to be false
|
expect(body_as_json).to be false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -119,21 +146,20 @@ RSpec.describe Api::V1::Emails::ConfirmationsController do
|
||||||
context 'when the account is confirmed' do
|
context 'when the account is confirmed' do
|
||||||
let(:confirmed_at) { Time.now.utc }
|
let(:confirmed_at) { Time.now.utc }
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns the confirmation status successfully', :aggregate_failures do
|
||||||
get :check
|
subject
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'returns true' do
|
expect(response).to have_http_status(200)
|
||||||
get :check
|
|
||||||
expect(body_as_json).to be true
|
expect(body_as_json).to be true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'without an oauth token and an authentication cookie' do
|
context 'without an oauth token and an authentication cookie' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
it 'returns http unauthorized' do
|
it 'returns http unauthorized' do
|
||||||
get :check
|
subject
|
||||||
|
|
||||||
expect(response).to have_http_status(401)
|
expect(response).to have_http_status(401)
|
||||||
end
|
end
|
47
spec/requests/api/v1/polls_spec.rb
Normal file
47
spec/requests/api/v1/polls_spec.rb
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'Polls' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
let(:scopes) { 'read:statuses' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
|
describe 'GET /api/v1/polls/:id' do
|
||||||
|
subject do
|
||||||
|
get "/api/v1/polls/#{poll.id}", headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:poll) { Fabricate(:poll, status: Fabricate(:status, visibility: visibility)) }
|
||||||
|
let(:visibility) { 'public' }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write write:statuses'
|
||||||
|
|
||||||
|
context 'when parent status is public' do
|
||||||
|
it 'returns the poll data successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(
|
||||||
|
id: poll.id.to_s,
|
||||||
|
voted: false,
|
||||||
|
voters_count: poll.voters_count,
|
||||||
|
votes_count: poll.votes_count
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when parent status is private' do
|
||||||
|
let(:visibility) { 'private' }
|
||||||
|
|
||||||
|
it 'returns http not found' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
155
spec/requests/api/v1/statuses/bookmarks_spec.rb
Normal file
155
spec/requests/api/v1/statuses/bookmarks_spec.rb
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'Bookmarks' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
let(:scopes) { 'write:bookmarks' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
|
describe 'POST /api/v1/statuses/:status_id/bookmark' do
|
||||||
|
subject do
|
||||||
|
post "/api/v1/statuses/#{status.id}/bookmark", headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read'
|
||||||
|
|
||||||
|
context 'with public status' do
|
||||||
|
it 'bookmarks the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.bookmarked?(status)).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, bookmarked: true)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with private status of not-followed account' do
|
||||||
|
let(:status) { Fabricate(:status, visibility: :private) }
|
||||||
|
|
||||||
|
it 'returns http not found' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with private status of followed account' do
|
||||||
|
let(:status) { Fabricate(:status, visibility: :private) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
user.account.follow!(status.account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'bookmarks the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.bookmarked?(status)).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the status does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
post '/api/v1/statuses/-1/bookmark', headers: headers
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'without an authorization header' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
|
it 'returns http unauthorized' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(401)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST /api/v1/statuses/:status_id/unbookmark' do
|
||||||
|
subject do
|
||||||
|
post "/api/v1/statuses/#{status.id}/unbookmark", headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read'
|
||||||
|
|
||||||
|
context 'with public status' do
|
||||||
|
context 'when the status was previously bookmarked' do
|
||||||
|
before do
|
||||||
|
Bookmark.find_or_create_by!(account: user.account, status: status)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unbookmarks the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.bookmarked?(status)).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, bookmarked: false)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the requesting user was blocked by the status author' do
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Bookmark.find_or_create_by!(account: user.account, status: status)
|
||||||
|
status.account.block!(user.account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unbookmarks the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.bookmarked?(status)).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, bookmarked: false)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the status is not bookmarked' do
|
||||||
|
it 'returns http success' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with private status that was not bookmarked' do
|
||||||
|
let(:status) { Fabricate(:status, visibility: :private) }
|
||||||
|
|
||||||
|
it 'returns http not found' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
143
spec/requests/api/v1/statuses/favourites_spec.rb
Normal file
143
spec/requests/api/v1/statuses/favourites_spec.rb
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'Favourites' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
let(:scopes) { 'write:favourites' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
|
describe 'POST /api/v1/statuses/:status_id/favourite' do
|
||||||
|
subject do
|
||||||
|
post "/api/v1/statuses/#{status.id}/favourite", headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read read:favourites'
|
||||||
|
|
||||||
|
context 'with public status' do
|
||||||
|
it 'favourites the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.favourited?(status)).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, favourites_count: 1, favourited: true)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with private status of not-followed account' do
|
||||||
|
let(:status) { Fabricate(:status, visibility: :private) }
|
||||||
|
|
||||||
|
it 'returns http not found' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with private status of followed account' do
|
||||||
|
let(:status) { Fabricate(:status, visibility: :private) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
user.account.follow!(status.account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'favourites the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.favourited?(status)).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'without an authorization header' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
|
it 'returns http unauthorized' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(401)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST /api/v1/statuses/:status_id/unfavourite' do
|
||||||
|
subject do
|
||||||
|
post "/api/v1/statuses/#{status.id}/unfavourite", headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read read:favourites'
|
||||||
|
|
||||||
|
context 'with public status' do
|
||||||
|
before do
|
||||||
|
FavouriteService.new.call(user.account, status)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unfavourites the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.favourited?(status)).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, favourites_count: 0, favourited: false)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the requesting user was blocked by the status author' do
|
||||||
|
before do
|
||||||
|
FavouriteService.new.call(user.account, status)
|
||||||
|
status.account.block!(user.account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unfavourites the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.favourited?(status)).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, favourites_count: 0, favourited: false)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when status is not favourited' do
|
||||||
|
it 'returns http success' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with private status that was not favourited' do
|
||||||
|
let(:status) { Fabricate(:status, visibility: :private) }
|
||||||
|
|
||||||
|
it 'returns http not found' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
131
spec/requests/api/v1/statuses/pins_spec.rb
Normal file
131
spec/requests/api/v1/statuses/pins_spec.rb
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe 'Pins' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
let(:scopes) { 'write:accounts' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
|
describe 'POST /api/v1/statuses/:status_id/pin' do
|
||||||
|
subject do
|
||||||
|
post "/api/v1/statuses/#{status.id}/pin", headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:status) { Fabricate(:status, account: user.account) }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'read read:accounts'
|
||||||
|
|
||||||
|
context 'when the status is public' do
|
||||||
|
it 'pins the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.pinned?(status)).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'return json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, pinned: true)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the status is private' do
|
||||||
|
let(:status) { Fabricate(:status, account: user.account, visibility: :private) }
|
||||||
|
|
||||||
|
it 'pins the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.pinned?(status)).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the status belongs to somebody else' do
|
||||||
|
let(:status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the status does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
post '/api/v1/statuses/-1/pin', headers: headers
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'without an authorization header' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
|
it 'returns http unauthorized' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(401)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST /api/v1/statuses/:status_id/unpin' do
|
||||||
|
subject do
|
||||||
|
post "/api/v1/statuses/#{status.id}/unpin", headers: headers
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:status) { Fabricate(:status, account: user.account) }
|
||||||
|
|
||||||
|
context 'when the status is pinned' do
|
||||||
|
before do
|
||||||
|
Fabricate(:status_pin, status: status, account: user.account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'unpins the status successfully', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
expect(user.account.pinned?(status)).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'return json with updated attributes' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json).to match(
|
||||||
|
a_hash_including(id: status.id.to_s, pinned: false)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the status is not pinned' do
|
||||||
|
it 'returns http success' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the status does not exist' do
|
||||||
|
it 'returns http not found' do
|
||||||
|
post '/api/v1/statuses/-1/unpin', headers: headers
|
||||||
|
|
||||||
|
expect(response).to have_http_status(404)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'without an authorization header' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
|
it 'returns http unauthorized' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(401)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
101
spec/requests/api/v1/timelines/home_spec.rb
Normal file
101
spec/requests/api/v1/timelines/home_spec.rb
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe 'Home' do
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
let(:scopes) { 'read:statuses' }
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
|
||||||
|
let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
|
||||||
|
|
||||||
|
describe 'GET /api/v1/timelines/home' do
|
||||||
|
subject do
|
||||||
|
get '/api/v1/timelines/home', headers: headers, params: params
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:params) { {} }
|
||||||
|
|
||||||
|
it_behaves_like 'forbidden for wrong scope', 'write write:statuses'
|
||||||
|
|
||||||
|
context 'when the timeline is available' do
|
||||||
|
let(:home_statuses) { bob.statuses + ana.statuses }
|
||||||
|
let!(:bob) { Fabricate(:account) }
|
||||||
|
let!(:tim) { Fabricate(:account) }
|
||||||
|
let!(:ana) { Fabricate(:account) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
user.account.follow!(bob)
|
||||||
|
user.account.follow!(ana)
|
||||||
|
PostStatusService.new.call(bob, text: 'New toot from bob.')
|
||||||
|
PostStatusService.new.call(tim, text: 'New toot from tim.')
|
||||||
|
PostStatusService.new.call(ana, text: 'New toot from ana.')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the statuses of followed users' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json.pluck(:id)).to match_array(home_statuses.map { |status| status.id.to_s })
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with limit param' do
|
||||||
|
let(:params) { { limit: 1 } }
|
||||||
|
|
||||||
|
it 'returns only the requested number of statuses' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(body_as_json.size).to eq(params[:limit])
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the correct pagination headers', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
headers = response.headers['Link']
|
||||||
|
|
||||||
|
expect(headers.find_link(%w(rel prev)).href).to eq(api_v1_timelines_home_url(limit: 1, min_id: ana.statuses.first.id.to_s))
|
||||||
|
expect(headers.find_link(%w(rel next)).href).to eq(api_v1_timelines_home_url(limit: 1, max_id: ana.statuses.first.id.to_s))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the timeline is regenerating' do
|
||||||
|
let(:timeline) { instance_double(HomeFeed, regenerating?: true, get: []) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(HomeFeed).to receive(:new).and_return(timeline)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http partial content' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(206)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'without an authorization header' do
|
||||||
|
let(:headers) { {} }
|
||||||
|
|
||||||
|
it 'returns http unauthorized' do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(401)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'without a user context' do
|
||||||
|
let(:token) { Fabricate(:accessible_access_token, resource_owner_id: nil, scopes: scopes) }
|
||||||
|
|
||||||
|
it 'returns http unprocessable entity', :aggregate_failures do
|
||||||
|
subject
|
||||||
|
|
||||||
|
expect(response).to have_http_status(422)
|
||||||
|
expect(response.headers['Link']).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -34,11 +34,11 @@ RSpec.describe BatchedRemoveStatusService, type: :service do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes statuses from author\'s home feed' do
|
it 'removes statuses from author\'s home feed' do
|
||||||
expect(HomeFeed.new(alice).get(10)).to_not include([status_alice_hello.id, status_alice_other.id])
|
expect(HomeFeed.new(alice).get(10).pluck(:id)).to_not include(status_alice_hello.id, status_alice_other.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes statuses from local follower\'s home feed' do
|
it 'removes statuses from local follower\'s home feed' do
|
||||||
expect(HomeFeed.new(jeff).get(10)).to_not include([status_alice_hello.id, status_alice_other.id])
|
expect(HomeFeed.new(jeff).get(10).pluck(:id)).to_not include(status_alice_hello.id, status_alice_other.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'notifies streaming API of followers' do
|
it 'notifies streaming API of followers' do
|
||||||
|
|
|
@ -28,12 +28,12 @@ RSpec.describe RemoveStatusService, type: :service do
|
||||||
|
|
||||||
it 'removes status from author\'s home feed' do
|
it 'removes status from author\'s home feed' do
|
||||||
subject.call(@status)
|
subject.call(@status)
|
||||||
expect(HomeFeed.new(alice).get(10)).to_not include(@status.id)
|
expect(HomeFeed.new(alice).get(10).pluck(:id)).to_not include(@status.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'removes status from local follower\'s home feed' do
|
it 'removes status from local follower\'s home feed' do
|
||||||
subject.call(@status)
|
subject.call(@status)
|
||||||
expect(HomeFeed.new(jeff).get(10)).to_not include(@status.id)
|
expect(HomeFeed.new(jeff).get(10).pluck(:id)).to_not include(@status.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'sends Delete activity to followers' do
|
it 'sends Delete activity to followers' do
|
||||||
|
|
39
spec/workers/tag_unmerge_worker_spec.rb
Normal file
39
spec/workers/tag_unmerge_worker_spec.rb
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
describe TagUnmergeWorker do
|
||||||
|
subject { described_class.new }
|
||||||
|
|
||||||
|
describe 'perform' do
|
||||||
|
let(:follower) { Fabricate(:account) }
|
||||||
|
let(:followed) { Fabricate(:account) }
|
||||||
|
let(:followed_tag) { Fabricate(:tag) }
|
||||||
|
let(:unchanged_followed_tag) { Fabricate(:tag) }
|
||||||
|
let(:status_from_followed) { Fabricate(:status, created_at: 2.hours.ago, account: followed) }
|
||||||
|
let(:tagged_status) { Fabricate(:status, created_at: 1.hour.ago) }
|
||||||
|
let(:unchanged_tagged_status) { Fabricate(:status) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
tagged_status.tags << followed_tag
|
||||||
|
unchanged_tagged_status.tags << followed_tag
|
||||||
|
unchanged_tagged_status.tags << unchanged_followed_tag
|
||||||
|
|
||||||
|
tag_follow = TagFollow.create_with(rate_limit: false).find_or_create_by!(tag: followed_tag, account: follower)
|
||||||
|
TagFollow.create_with(rate_limit: false).find_or_create_by!(tag: unchanged_followed_tag, account: follower)
|
||||||
|
|
||||||
|
FeedManager.instance.push_to_home(follower, status_from_followed, update: false)
|
||||||
|
FeedManager.instance.push_to_home(follower, tagged_status, update: false)
|
||||||
|
FeedManager.instance.push_to_home(follower, unchanged_tagged_status, update: false)
|
||||||
|
|
||||||
|
tag_follow.destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'removes the expected status from the feed' do
|
||||||
|
expect { subject.perform(followed_tag.id, follower.id) }
|
||||||
|
.to change { HomeFeed.new(follower).get(10).pluck(:id) }
|
||||||
|
.from([unchanged_tagged_status.id, tagged_status.id, status_from_followed.id])
|
||||||
|
.to([unchanged_tagged_status.id, status_from_followed.id])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
178
yarn.lock
178
yarn.lock
|
@ -31,33 +31,33 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/highlight" "^7.22.5"
|
"@babel/highlight" "^7.22.5"
|
||||||
|
|
||||||
"@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6":
|
"@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9":
|
||||||
version "7.22.6"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.6.tgz#15606a20341de59ba02cd2fcc5086fcbe73bf544"
|
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730"
|
||||||
integrity sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==
|
integrity sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==
|
||||||
|
|
||||||
"@babel/core@^7.10.4", "@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.22.1":
|
"@babel/core@^7.10.4", "@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.22.1":
|
||||||
version "7.22.8"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.8.tgz#386470abe884302db9c82e8e5e87be9e46c86785"
|
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.9.tgz#bd96492c68822198f33e8a256061da3cf391f58f"
|
||||||
integrity sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==
|
integrity sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ampproject/remapping" "^2.2.0"
|
"@ampproject/remapping" "^2.2.0"
|
||||||
"@babel/code-frame" "^7.22.5"
|
"@babel/code-frame" "^7.22.5"
|
||||||
"@babel/generator" "^7.22.7"
|
"@babel/generator" "^7.22.9"
|
||||||
"@babel/helper-compilation-targets" "^7.22.6"
|
"@babel/helper-compilation-targets" "^7.22.9"
|
||||||
"@babel/helper-module-transforms" "^7.22.5"
|
"@babel/helper-module-transforms" "^7.22.9"
|
||||||
"@babel/helpers" "^7.22.6"
|
"@babel/helpers" "^7.22.6"
|
||||||
"@babel/parser" "^7.22.7"
|
"@babel/parser" "^7.22.7"
|
||||||
"@babel/template" "^7.22.5"
|
"@babel/template" "^7.22.5"
|
||||||
"@babel/traverse" "^7.22.8"
|
"@babel/traverse" "^7.22.8"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
"@nicolo-ribaudo/semver-v6" "^6.3.3"
|
|
||||||
convert-source-map "^1.7.0"
|
convert-source-map "^1.7.0"
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
gensync "^1.0.0-beta.2"
|
gensync "^1.0.0-beta.2"
|
||||||
json5 "^2.2.2"
|
json5 "^2.2.2"
|
||||||
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/generator@^7.22.5", "@babel/generator@^7.22.7":
|
"@babel/generator@^7.22.5":
|
||||||
version "7.22.7"
|
version "7.22.7"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.7.tgz#a6b8152d5a621893f2c9dacf9a4e286d520633d5"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.7.tgz#a6b8152d5a621893f2c9dacf9a4e286d520633d5"
|
||||||
integrity sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==
|
integrity sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==
|
||||||
|
@ -67,6 +67,16 @@
|
||||||
"@jridgewell/trace-mapping" "^0.3.17"
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
jsesc "^2.5.1"
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
|
"@babel/generator@^7.22.7", "@babel/generator@^7.22.9":
|
||||||
|
version "7.22.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d"
|
||||||
|
integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/types" "^7.22.5"
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.2"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.17"
|
||||||
|
jsesc "^2.5.1"
|
||||||
|
|
||||||
"@babel/generator@^7.7.2":
|
"@babel/generator@^7.7.2":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7"
|
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7"
|
||||||
|
@ -99,40 +109,40 @@
|
||||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
"@babel/helper-annotate-as-pure" "^7.22.5"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6":
|
"@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.22.9":
|
||||||
version "7.22.6"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz#e30d61abe9480aa5a83232eb31c111be922d2e52"
|
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz#f9d0a7aaaa7cd32a3f31c9316a69f5a9bcacb892"
|
||||||
integrity sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==
|
integrity sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/compat-data" "^7.22.6"
|
"@babel/compat-data" "^7.22.9"
|
||||||
"@babel/helper-validator-option" "^7.22.5"
|
"@babel/helper-validator-option" "^7.22.5"
|
||||||
"@nicolo-ribaudo/semver-v6" "^6.3.3"
|
|
||||||
browserslist "^4.21.9"
|
browserslist "^4.21.9"
|
||||||
lru-cache "^5.1.1"
|
lru-cache "^5.1.1"
|
||||||
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/helper-create-class-features-plugin@^7.22.5":
|
"@babel/helper-create-class-features-plugin@^7.22.5":
|
||||||
version "7.22.6"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.6.tgz#58564873c889a6fea05a538e23f9f6d201f10950"
|
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.9.tgz#c36ea240bb3348f942f08b0fbe28d6d979fab236"
|
||||||
integrity sha512-iwdzgtSiBxF6ni6mzVnZCF3xt5qE6cEA0J7nFt8QOAWZ0zjCFceEgpn3vtb2V7WFR6QzP2jmIFOHMTRo7eNJjQ==
|
integrity sha512-Pwyi89uO4YrGKxL/eNJ8lfEH55DnRloGPOseaA8NFNL6jAUnn+KccaISiFazCj5IolPPDjGSdzQzXVzODVRqUQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
"@babel/helper-annotate-as-pure" "^7.22.5"
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
"@babel/helper-environment-visitor" "^7.22.5"
|
||||||
"@babel/helper-function-name" "^7.22.5"
|
"@babel/helper-function-name" "^7.22.5"
|
||||||
"@babel/helper-member-expression-to-functions" "^7.22.5"
|
"@babel/helper-member-expression-to-functions" "^7.22.5"
|
||||||
"@babel/helper-optimise-call-expression" "^7.22.5"
|
"@babel/helper-optimise-call-expression" "^7.22.5"
|
||||||
"@babel/helper-replace-supers" "^7.22.5"
|
"@babel/helper-replace-supers" "^7.22.9"
|
||||||
"@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
|
"@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
|
||||||
"@babel/helper-split-export-declaration" "^7.22.6"
|
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||||
"@nicolo-ribaudo/semver-v6" "^6.3.3"
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5":
|
"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5":
|
||||||
version "7.22.6"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.6.tgz#87afd63012688ad792de430ceb3b6dc28e4e7a40"
|
resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz#9d8e61a8d9366fe66198f57c40565663de0825f6"
|
||||||
integrity sha512-nBookhLKxAWo/TUCmhnaEJyLz2dekjQvv5SRpE9epWQBcpedWLKt8aZdsuT9XV5ovzR3fENLjRXVT0GsSlGGhA==
|
integrity sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
"@babel/helper-annotate-as-pure" "^7.22.5"
|
||||||
"@nicolo-ribaudo/semver-v6" "^6.3.3"
|
|
||||||
regexpu-core "^5.3.1"
|
regexpu-core "^5.3.1"
|
||||||
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/helper-define-polyfill-provider@^0.4.1":
|
"@babel/helper-define-polyfill-provider@^0.4.1":
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
|
@ -179,19 +189,16 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/helper-module-transforms@^7.22.5":
|
"@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.22.9":
|
||||||
version "7.22.5"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef"
|
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz#92dfcb1fbbb2bc62529024f72d942a8c97142129"
|
||||||
integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==
|
integrity sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
"@babel/helper-environment-visitor" "^7.22.5"
|
||||||
"@babel/helper-module-imports" "^7.22.5"
|
"@babel/helper-module-imports" "^7.22.5"
|
||||||
"@babel/helper-simple-access" "^7.22.5"
|
"@babel/helper-simple-access" "^7.22.5"
|
||||||
"@babel/helper-split-export-declaration" "^7.22.5"
|
"@babel/helper-split-export-declaration" "^7.22.6"
|
||||||
"@babel/helper-validator-identifier" "^7.22.5"
|
"@babel/helper-validator-identifier" "^7.22.5"
|
||||||
"@babel/template" "^7.22.5"
|
|
||||||
"@babel/traverse" "^7.22.5"
|
|
||||||
"@babel/types" "^7.22.5"
|
|
||||||
|
|
||||||
"@babel/helper-optimise-call-expression@^7.22.5":
|
"@babel/helper-optimise-call-expression@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
|
@ -206,26 +213,22 @@
|
||||||
integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
|
integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
|
||||||
|
|
||||||
"@babel/helper-remap-async-to-generator@^7.22.5":
|
"@babel/helper-remap-async-to-generator@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz#14a38141a7bf2165ad38da61d61cf27b43015da2"
|
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz#53a25b7484e722d7efb9c350c75c032d4628de82"
|
||||||
integrity sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g==
|
integrity sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-annotate-as-pure" "^7.22.5"
|
"@babel/helper-annotate-as-pure" "^7.22.5"
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
"@babel/helper-environment-visitor" "^7.22.5"
|
||||||
"@babel/helper-wrap-function" "^7.22.5"
|
"@babel/helper-wrap-function" "^7.22.9"
|
||||||
"@babel/types" "^7.22.5"
|
|
||||||
|
|
||||||
"@babel/helper-replace-supers@^7.22.5":
|
"@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9":
|
||||||
version "7.22.5"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz#71bc5fb348856dea9fdc4eafd7e2e49f585145dc"
|
resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz#cbdc27d6d8d18cd22c81ae4293765a5d9afd0779"
|
||||||
integrity sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==
|
integrity sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-environment-visitor" "^7.22.5"
|
"@babel/helper-environment-visitor" "^7.22.5"
|
||||||
"@babel/helper-member-expression-to-functions" "^7.22.5"
|
"@babel/helper-member-expression-to-functions" "^7.22.5"
|
||||||
"@babel/helper-optimise-call-expression" "^7.22.5"
|
"@babel/helper-optimise-call-expression" "^7.22.5"
|
||||||
"@babel/template" "^7.22.5"
|
|
||||||
"@babel/traverse" "^7.22.5"
|
|
||||||
"@babel/types" "^7.22.5"
|
|
||||||
|
|
||||||
"@babel/helper-simple-access@^7.22.5":
|
"@babel/helper-simple-access@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
|
@ -263,14 +266,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac"
|
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac"
|
||||||
integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==
|
integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==
|
||||||
|
|
||||||
"@babel/helper-wrap-function@^7.22.5":
|
"@babel/helper-wrap-function@^7.22.9":
|
||||||
version "7.22.5"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz#44d205af19ed8d872b4eefb0d2fa65f45eb34f06"
|
resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.9.tgz#189937248c45b0182c1dcf32f3444ca153944cb9"
|
||||||
integrity sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw==
|
integrity sha512-sZ+QzfauuUEfxSEjKFmi3qDSHgLsTPK/pEpoD/qonZKOtTPTLbf59oabPQ4rKekt9lFcj/hTZaOhWwFYrgjk+Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-function-name" "^7.22.5"
|
"@babel/helper-function-name" "^7.22.5"
|
||||||
"@babel/template" "^7.22.5"
|
"@babel/template" "^7.22.5"
|
||||||
"@babel/traverse" "^7.22.5"
|
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
|
|
||||||
"@babel/helpers@^7.22.6":
|
"@babel/helpers@^7.22.6":
|
||||||
|
@ -841,16 +843,16 @@
|
||||||
"@babel/helper-plugin-utils" "^7.22.5"
|
"@babel/helper-plugin-utils" "^7.22.5"
|
||||||
|
|
||||||
"@babel/plugin-transform-runtime@^7.22.4":
|
"@babel/plugin-transform-runtime@^7.22.4":
|
||||||
version "7.22.7"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.7.tgz#eb9094b5fb756cc2d98d398b2c88aeefa9205de9"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz#a87b11e170cbbfb018e6a2bf91f5c6e533b9e027"
|
||||||
integrity sha512-o02xM7iY7mSPI+TvaYDH0aYl+lg3+KT7qrD705JlsB/GrZSNaYO/4i+aDFKPiJ7ubq3hgv8NNLCdyB5MFxT8mg==
|
integrity sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-module-imports" "^7.22.5"
|
"@babel/helper-module-imports" "^7.22.5"
|
||||||
"@babel/helper-plugin-utils" "^7.22.5"
|
"@babel/helper-plugin-utils" "^7.22.5"
|
||||||
"@nicolo-ribaudo/semver-v6" "^6.3.3"
|
|
||||||
babel-plugin-polyfill-corejs2 "^0.4.4"
|
babel-plugin-polyfill-corejs2 "^0.4.4"
|
||||||
babel-plugin-polyfill-corejs3 "^0.8.2"
|
babel-plugin-polyfill-corejs3 "^0.8.2"
|
||||||
babel-plugin-polyfill-regenerator "^0.5.1"
|
babel-plugin-polyfill-regenerator "^0.5.1"
|
||||||
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/plugin-transform-shorthand-properties@^7.22.5":
|
"@babel/plugin-transform-shorthand-properties@^7.22.5":
|
||||||
version "7.22.5"
|
version "7.22.5"
|
||||||
|
@ -930,12 +932,12 @@
|
||||||
"@babel/helper-plugin-utils" "^7.22.5"
|
"@babel/helper-plugin-utils" "^7.22.5"
|
||||||
|
|
||||||
"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.22.4":
|
"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.22.4":
|
||||||
version "7.22.7"
|
version "7.22.9"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.7.tgz#a1ef34b64a80653c22ce4d9c25603cfa76fc168a"
|
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.9.tgz#57f17108eb5dfd4c5c25a44c1977eba1df310ac7"
|
||||||
integrity sha512-1whfDtW+CzhETuzYXfcgZAh8/GFMeEbz0V5dVgya8YeJyCU6Y/P2Gnx4Qb3MylK68Zu9UiwUvbPMPTpFAOJ+sQ==
|
integrity sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/compat-data" "^7.22.6"
|
"@babel/compat-data" "^7.22.9"
|
||||||
"@babel/helper-compilation-targets" "^7.22.6"
|
"@babel/helper-compilation-targets" "^7.22.9"
|
||||||
"@babel/helper-plugin-utils" "^7.22.5"
|
"@babel/helper-plugin-utils" "^7.22.5"
|
||||||
"@babel/helper-validator-option" "^7.22.5"
|
"@babel/helper-validator-option" "^7.22.5"
|
||||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.5"
|
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.5"
|
||||||
|
@ -1009,11 +1011,11 @@
|
||||||
"@babel/plugin-transform-unicode-sets-regex" "^7.22.5"
|
"@babel/plugin-transform-unicode-sets-regex" "^7.22.5"
|
||||||
"@babel/preset-modules" "^0.1.5"
|
"@babel/preset-modules" "^0.1.5"
|
||||||
"@babel/types" "^7.22.5"
|
"@babel/types" "^7.22.5"
|
||||||
"@nicolo-ribaudo/semver-v6" "^6.3.3"
|
|
||||||
babel-plugin-polyfill-corejs2 "^0.4.4"
|
babel-plugin-polyfill-corejs2 "^0.4.4"
|
||||||
babel-plugin-polyfill-corejs3 "^0.8.2"
|
babel-plugin-polyfill-corejs3 "^0.8.2"
|
||||||
babel-plugin-polyfill-regenerator "^0.5.1"
|
babel-plugin-polyfill-regenerator "^0.5.1"
|
||||||
core-js-compat "^3.31.0"
|
core-js-compat "^3.31.0"
|
||||||
|
semver "^6.3.1"
|
||||||
|
|
||||||
"@babel/preset-modules@^0.1.5":
|
"@babel/preset-modules@^0.1.5":
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
|
@ -1093,7 +1095,7 @@
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
globals "^11.1.0"
|
globals "^11.1.0"
|
||||||
|
|
||||||
"@babel/traverse@^7.22.5", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8":
|
"@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8":
|
||||||
version "7.22.8"
|
version "7.22.8"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e"
|
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e"
|
||||||
integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==
|
integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==
|
||||||
|
@ -1277,17 +1279,17 @@
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6"
|
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.42.0.tgz#484a1d638de2911e6f5a30c12f49c7e4a3270fb6"
|
||||||
integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==
|
integrity sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==
|
||||||
|
|
||||||
"@floating-ui/core@^1.3.0":
|
"@floating-ui/core@^1.3.1":
|
||||||
version "1.3.0"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.3.0.tgz#113bc85fa102cf890ae801668f43ee265c547a09"
|
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.3.1.tgz#4d795b649cc3b1cbb760d191c80dcb4353c9a366"
|
||||||
integrity sha512-vX1WVAdPjZg9DkDkC+zEx/tKtnST6/qcNpwcjeBgco3XRNHz5PUA+ivi/yr6G3o0kMR60uKBJcfOdfzOFI7PMQ==
|
integrity sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==
|
||||||
|
|
||||||
"@floating-ui/dom@^1.0.1":
|
"@floating-ui/dom@^1.0.1":
|
||||||
version "1.3.0"
|
version "1.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.3.0.tgz#69456f2164fc3d33eb40837686eaf71537235ac9"
|
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.4.5.tgz#336dfb9870c98b471ff5802002982e489b8bd1c5"
|
||||||
integrity sha512-qIAwejE3r6NeA107u4ELDKkH8+VtgRKdXqtSPaKflL2S2V+doyN+Wt9s5oHKXPDo4E8TaVXaHT3+6BbagH31xw==
|
integrity sha512-96KnRWkRnuBSSFbj0sFGwwOUd8EkiecINVl0O9wiZlZ64EkpyAOG3Xc2vKKNJmru0Z7RqWNymA+6b8OZqjgyyw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@floating-ui/core" "^1.3.0"
|
"@floating-ui/core" "^1.3.1"
|
||||||
|
|
||||||
"@formatjs/cli@^6.1.1":
|
"@formatjs/cli@^6.1.1":
|
||||||
version "6.1.3"
|
version "6.1.3"
|
||||||
|
@ -3750,11 +3752,16 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001464:
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz#88b6ff1b2cf735f1f3361dc1a15b59f0561aa398"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz#88b6ff1b2cf735f1f3361dc1a15b59f0561aa398"
|
||||||
integrity sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==
|
integrity sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001502, caniuse-lite@^1.0.30001503:
|
caniuse-lite@^1.0.30001502:
|
||||||
version "1.0.30001515"
|
version "1.0.30001515"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz#418aefeed9d024cd3129bfae0ccc782d4cb8f12b"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz#418aefeed9d024cd3129bfae0ccc782d4cb8f12b"
|
||||||
integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==
|
integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==
|
||||||
|
|
||||||
|
caniuse-lite@^1.0.30001503:
|
||||||
|
version "1.0.30001516"
|
||||||
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz#621b1be7d85a8843ee7d210fd9d87b52e3daab3a"
|
||||||
|
integrity sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==
|
||||||
|
|
||||||
chalk@5.2.0:
|
chalk@5.2.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.2.0.tgz#249623b7d66869c673699fb66d65723e54dfcfb3"
|
||||||
|
@ -4822,11 +4829,16 @@ ejs@^3.1.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
jake "^10.8.5"
|
jake "^10.8.5"
|
||||||
|
|
||||||
electron-to-chromium@^1.4.428, electron-to-chromium@^1.4.431:
|
electron-to-chromium@^1.4.428:
|
||||||
version "1.4.457"
|
version "1.4.457"
|
||||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.457.tgz#3fdc7b4f97d628ac6b51e8b4b385befb362fe343"
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.457.tgz#3fdc7b4f97d628ac6b51e8b4b385befb362fe343"
|
||||||
integrity sha512-/g3UyNDmDd6ebeWapmAoiyy+Sy2HyJ+/X8KyvNeHfKRFfHaA2W8oF5fxD5F3tjBDcjpwo0iek6YNgxNXDBoEtA==
|
integrity sha512-/g3UyNDmDd6ebeWapmAoiyy+Sy2HyJ+/X8KyvNeHfKRFfHaA2W8oF5fxD5F3tjBDcjpwo0iek6YNgxNXDBoEtA==
|
||||||
|
|
||||||
|
electron-to-chromium@^1.4.431:
|
||||||
|
version "1.4.461"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz#6b14af66042732bf883ab63a4d82cac8f35eb252"
|
||||||
|
integrity sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==
|
||||||
|
|
||||||
elliptic@^6.5.3:
|
elliptic@^6.5.3:
|
||||||
version "6.5.4"
|
version "6.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
|
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
|
||||||
|
@ -6390,9 +6402,9 @@ immutable@^3.8.2:
|
||||||
integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==
|
integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==
|
||||||
|
|
||||||
immutable@^4.0.0, immutable@^4.0.0-rc.1, immutable@^4.3.0:
|
immutable@^4.0.0, immutable@^4.0.0-rc.1, immutable@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.0.tgz#eb1738f14ffb39fd068b1dbe1296117484dd34be"
|
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.1.tgz#17988b356097ab0719e2f741d56f3ec6c317f9dc"
|
||||||
integrity sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==
|
integrity sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==
|
||||||
|
|
||||||
import-fresh@^3.0.0, import-fresh@^3.2.1:
|
import-fresh@^3.0.0, import-fresh@^3.2.1:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
|
@ -9258,9 +9270,9 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
|
||||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||||
|
|
||||||
postcss@^8.2.15, postcss@^8.4.24:
|
postcss@^8.2.15, postcss@^8.4.24:
|
||||||
version "8.4.25"
|
version "8.4.26"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.25.tgz#4a133f5e379eda7f61e906c3b1aaa9b81292726f"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.26.tgz#1bc62ab19f8e1e5463d98cf74af39702a00a9e94"
|
||||||
integrity sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==
|
integrity sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==
|
||||||
dependencies:
|
dependencies:
|
||||||
nanoid "^3.3.6"
|
nanoid "^3.3.6"
|
||||||
picocolors "^1.0.0"
|
picocolors "^1.0.0"
|
||||||
|
@ -9726,9 +9738,9 @@ react-router@^4.3.1:
|
||||||
warning "^4.0.1"
|
warning "^4.0.1"
|
||||||
|
|
||||||
react-select@*, react-select@^5.7.3:
|
react-select@*, react-select@^5.7.3:
|
||||||
version "5.7.3"
|
version "5.7.4"
|
||||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.7.3.tgz#fa0dc9a23cad6ff3871ad3829f6083a4b54961a2"
|
resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.7.4.tgz#d8cad96e7bc9d6c8e2709bdda8f4363c5dd7ea7d"
|
||||||
integrity sha512-z8i3NCuFFWL3w27xq92rBkVI2onT0jzIIPe480HlBjXJ3b5o6Q+Clp4ydyeKrj9DZZ3lrjawwLC5NGl0FSvUDg==
|
integrity sha512-NhuE56X+p9QDFh4BgeygHFIvJJszO1i1KSkg/JPcIJrbovyRtI+GuOEa4XzFCEpZRAEoEI8u/cAHK+jG/PgUzQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.12.0"
|
"@babel/runtime" "^7.12.0"
|
||||||
"@emotion/cache" "^11.4.0"
|
"@emotion/cache" "^11.4.0"
|
||||||
|
@ -10357,7 +10369,7 @@ semver@^6.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||||
|
|
||||||
semver@^6.3.0:
|
semver@^6.3.0, semver@^6.3.1:
|
||||||
version "6.3.1"
|
version "6.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue