Merge pull request #1995 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes
This commit is contained in:
commit
0194bd33fe
25 changed files with 479 additions and 63 deletions
2
.github/workflows/check-i18n.yml
vendored
2
.github/workflows/check-i18n.yml
vendored
|
@ -25,7 +25,7 @@ jobs:
|
||||||
- name: Set up Ruby
|
- name: Set up Ruby
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
ruby-version: '3.0'
|
ruby-version: .ruby-version
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
- name: Check locale file normalization
|
- name: Check locale file normalization
|
||||||
run: bundle exec i18n-tasks check-normalized
|
run: bundle exec i18n-tasks check-normalized
|
||||||
|
|
2
.github/workflows/linter.yml
vendored
2
.github/workflows/linter.yml
vendored
|
@ -53,7 +53,7 @@ jobs:
|
||||||
- name: Set-up Node.js
|
- name: Set-up Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16.x
|
node-version-file: .nvmrc
|
||||||
cache: yarn
|
cache: yarn
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: yarn install --frozen-lockfile
|
run: yarn install --frozen-lockfile
|
||||||
|
|
71
Vagrantfile
vendored
71
Vagrantfile
vendored
|
@ -3,16 +3,14 @@
|
||||||
|
|
||||||
ENV["PORT"] ||= "3000"
|
ENV["PORT"] ||= "3000"
|
||||||
|
|
||||||
$provision = <<SCRIPT
|
$provisionA = <<SCRIPT
|
||||||
|
|
||||||
cd /vagrant # This is where the host folder/repo is mounted
|
|
||||||
|
|
||||||
# Add the yarn repo + yarn repo keys
|
# Add the yarn repo + yarn repo keys
|
||||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
|
||||||
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
|
sudo apt-add-repository 'deb https://dl.yarnpkg.com/debian/ stable main'
|
||||||
|
|
||||||
# Add repo for NodeJS
|
# Add repo for NodeJS
|
||||||
curl -sL https://deb.nodesource.com/setup_14.x | sudo bash -
|
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
|
||||||
|
|
||||||
# Add firewall rule to redirect 80 to PORT and save
|
# Add firewall rule to redirect 80 to PORT and save
|
||||||
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
|
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port #{ENV["PORT"]}
|
||||||
|
@ -33,32 +31,56 @@ sudo apt-get install \
|
||||||
redis-tools \
|
redis-tools \
|
||||||
postgresql \
|
postgresql \
|
||||||
postgresql-contrib \
|
postgresql-contrib \
|
||||||
yarn \
|
|
||||||
libicu-dev \
|
libicu-dev \
|
||||||
libidn11-dev \
|
libidn11-dev \
|
||||||
libreadline-dev \
|
libreadline6-dev \
|
||||||
libpam0g-dev \
|
autoconf \
|
||||||
|
bison \
|
||||||
|
build-essential \
|
||||||
|
ffmpeg \
|
||||||
|
file \
|
||||||
|
gcc \
|
||||||
|
libffi-dev \
|
||||||
|
libgdbm-dev \
|
||||||
|
libjemalloc-dev \
|
||||||
|
libncurses5-dev \
|
||||||
|
libprotobuf-dev \
|
||||||
|
libssl-dev \
|
||||||
|
libyaml-dev \
|
||||||
|
pkg-config \
|
||||||
|
protobuf-compiler \
|
||||||
|
zlib1g-dev \
|
||||||
-y
|
-y
|
||||||
|
|
||||||
# Install rvm
|
# Install rvm
|
||||||
read RUBY_VERSION < .ruby-version
|
sudo apt-add-repository -y ppa:rael-gc/rvm
|
||||||
|
sudo apt-get install rvm -y
|
||||||
|
|
||||||
curl -sSL https://rvm.io/mpapis.asc | gpg --import
|
sudo usermod -a -G rvm $USER
|
||||||
curl -sSL https://rvm.io/pkuczynski.asc | gpg --import
|
|
||||||
|
|
||||||
curl -sSL https://raw.githubusercontent.com/rvm/rvm/stable/binscripts/rvm-installer | bash -s stable --ruby=$RUBY_VERSION
|
SCRIPT
|
||||||
source /home/vagrant/.rvm/scripts/rvm
|
|
||||||
|
$provisionB = <<SCRIPT
|
||||||
|
|
||||||
|
source "/etc/profile.d/rvm.sh"
|
||||||
|
|
||||||
# Install Ruby
|
# Install Ruby
|
||||||
rvm reinstall ruby-$RUBY_VERSION --disable-binary
|
read RUBY_VERSION < /vagrant/.ruby-version
|
||||||
|
rvm install ruby-$RUBY_VERSION --disable-binary
|
||||||
|
|
||||||
# Configure database
|
# Configure database
|
||||||
sudo -u postgres createuser -U postgres vagrant -s
|
sudo -u postgres createuser -U postgres vagrant -s
|
||||||
sudo -u postgres createdb -U postgres mastodon_development
|
sudo -u postgres createdb -U postgres mastodon_development
|
||||||
|
|
||||||
# Install gems and node modules
|
cd /vagrant # This is where the host folder/repo is mounted
|
||||||
|
|
||||||
|
# Install gems
|
||||||
gem install bundler foreman
|
gem install bundler foreman
|
||||||
bundle install
|
bundle install
|
||||||
|
|
||||||
|
# Install node modules
|
||||||
|
sudo corepack enable
|
||||||
|
yarn set version classic
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
# Build Mastodon
|
# Build Mastodon
|
||||||
|
@ -72,18 +94,11 @@ echo 'export $(cat "/vagrant/.env.vagrant" | xargs)' >> ~/.bash_profile
|
||||||
|
|
||||||
SCRIPT
|
SCRIPT
|
||||||
|
|
||||||
$start = <<SCRIPT
|
|
||||||
|
|
||||||
echo 'To start server'
|
|
||||||
echo ' $ vagrant ssh -c "cd /vagrant && foreman start"'
|
|
||||||
|
|
||||||
SCRIPT
|
|
||||||
|
|
||||||
VAGRANTFILE_API_VERSION = "2"
|
VAGRANTFILE_API_VERSION = "2"
|
||||||
|
|
||||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
|
|
||||||
config.vm.box = "ubuntu/bionic64"
|
config.vm.box = "ubuntu/focal64"
|
||||||
|
|
||||||
config.vm.provider :virtualbox do |vb|
|
config.vm.provider :virtualbox do |vb|
|
||||||
vb.name = "mastodon"
|
vb.name = "mastodon"
|
||||||
|
@ -100,7 +115,6 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
# Use "virtio" network interfaces for better performance.
|
# Use "virtio" network interfaces for better performance.
|
||||||
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
|
vb.customize ["modifyvm", :id, "--nictype1", "virtio"]
|
||||||
vb.customize ["modifyvm", :id, "--nictype2", "virtio"]
|
vb.customize ["modifyvm", :id, "--nictype2", "virtio"]
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# This uses the vagrant-hostsupdater plugin, and lets you
|
# This uses the vagrant-hostsupdater plugin, and lets you
|
||||||
|
@ -118,7 +132,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
end
|
end
|
||||||
|
|
||||||
if config.vm.networks.any? { |type, options| type == :private_network }
|
if config.vm.networks.any? { |type, options| type == :private_network }
|
||||||
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'vers=3', 'tcp', 'actimeo=1']
|
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ['rw', 'actimeo=1']
|
||||||
else
|
else
|
||||||
config.vm.synced_folder ".", "/vagrant"
|
config.vm.synced_folder ".", "/vagrant"
|
||||||
end
|
end
|
||||||
|
@ -129,9 +143,12 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
config.vm.network :forwarded_port, guest: 8080, host: 8080
|
config.vm.network :forwarded_port, guest: 8080, host: 8080
|
||||||
|
|
||||||
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
|
# Full provisioning script, only runs on first 'vagrant up' or with 'vagrant provision'
|
||||||
config.vm.provision :shell, inline: $provision, privileged: false
|
config.vm.provision :shell, inline: $provisionA, privileged: false, reset: true
|
||||||
|
config.vm.provision :shell, inline: $provisionB, privileged: false
|
||||||
|
|
||||||
# Start up script, runs on every 'vagrant up'
|
config.vm.post_up_message = <<MESSAGE
|
||||||
config.vm.provision :shell, inline: $start, run: 'always', privileged: false
|
To start server
|
||||||
|
$ vagrant ssh -c "cd /vagrant && foreman start"
|
||||||
|
MESSAGE
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -55,12 +55,14 @@ module Admin
|
||||||
def approve
|
def approve
|
||||||
authorize @account.user, :approve?
|
authorize @account.user, :approve?
|
||||||
@account.user.approve!
|
@account.user.approve!
|
||||||
|
log_action :approve, @account.user
|
||||||
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
|
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.approved_msg', username: @account.acct)
|
||||||
end
|
end
|
||||||
|
|
||||||
def reject
|
def reject
|
||||||
authorize @account.user, :reject?
|
authorize @account.user, :reject?
|
||||||
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
|
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
|
||||||
|
log_action :reject, @account.user
|
||||||
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
|
redirect_to admin_accounts_path(status: 'pending'), notice: I18n.t('admin.accounts.rejected_msg', username: @account.acct)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -54,12 +54,14 @@ class Api::V1::Admin::AccountsController < Api::BaseController
|
||||||
def approve
|
def approve
|
||||||
authorize @account.user, :approve?
|
authorize @account.user, :approve?
|
||||||
@account.user.approve!
|
@account.user.approve!
|
||||||
|
log_action :approve, @account.user
|
||||||
render json: @account, serializer: REST::Admin::AccountSerializer
|
render json: @account, serializer: REST::Admin::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def reject
|
def reject
|
||||||
authorize @account.user, :reject?
|
authorize @account.user, :reject?
|
||||||
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
|
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
|
||||||
|
log_action :reject, @account.user
|
||||||
render_empty
|
render_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Api::V1::FiltersController < Api::BaseController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
ApplicationRecord.transaction do
|
ApplicationRecord.transaction do
|
||||||
filter_category = current_account.custom_filters.create!(resource_params)
|
filter_category = current_account.custom_filters.create!(filter_params)
|
||||||
@filter = filter_category.keywords.create!(keyword_params)
|
@filter = filter_category.keywords.create!(keyword_params)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -52,11 +52,11 @@ class Api::V1::FiltersController < Api::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
def resource_params
|
def resource_params
|
||||||
params.permit(:phrase, :expires_in, :irreversible, context: [])
|
params.permit(:phrase, :expires_in, :irreversible, :whole_word, context: [])
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_params
|
def filter_params
|
||||||
resource_params.slice(:expires_in, :irreversible, :context)
|
resource_params.slice(:phrase, :expires_in, :irreversible, :context)
|
||||||
end
|
end
|
||||||
|
|
||||||
def keyword_params
|
def keyword_params
|
||||||
|
|
|
@ -7,6 +7,7 @@ import Avatar from 'flavours/glitch/components/avatar';
|
||||||
import Permalink from 'flavours/glitch/components/permalink';
|
import Permalink from 'flavours/glitch/components/permalink';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { openModal } from 'flavours/glitch/actions/modal';
|
||||||
|
|
||||||
const Account = connect(state => ({
|
const Account = connect(state => ({
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
|
@ -16,7 +17,14 @@ const Account = connect(state => ({
|
||||||
</Permalink>
|
</Permalink>
|
||||||
));
|
));
|
||||||
|
|
||||||
export default @withRouter
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
openClosedRegistrationsModal() {
|
||||||
|
dispatch(openModal('CLOSED_REGISTRATIONS'));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @connect(null, mapDispatchToProps)
|
||||||
|
@withRouter
|
||||||
class Header extends React.PureComponent {
|
class Header extends React.PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
@ -24,12 +32,13 @@ class Header extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
openClosedRegistrationsModal: PropTypes.func,
|
||||||
location: PropTypes.object,
|
location: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { signedIn } = this.context.identity;
|
const { signedIn } = this.context.identity;
|
||||||
const { location } = this.props;
|
const { location, openClosedRegistrationsModal } = this.props;
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
|
|
||||||
|
@ -41,10 +50,26 @@ class Header extends React.PureComponent {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
let signupButton;
|
||||||
|
|
||||||
|
if (registrationsOpen) {
|
||||||
|
signupButton = (
|
||||||
|
<a href='/auth/sign_up' className='button button-tertiary'>
|
||||||
|
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
signupButton = (
|
||||||
|
<button className='button button-tertiary' onClick={openClosedRegistrationsModal}>
|
||||||
|
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
content = (
|
content = (
|
||||||
<>
|
<>
|
||||||
<a href='/auth/sign_in' className='button'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
<a href='/auth/sign_in' className='button'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
||||||
<a href={registrationsOpen ? '/auth/sign_up' : 'https://joinmastodon.org/servers'} className='button button-tertiary'><FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' /></a>
|
{signupButton}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ $ui-header-height: 55px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&__logo {
|
&__logo {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -81,10 +82,15 @@ $ui-header-height: 55px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-tertiary {
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1306,7 +1306,8 @@ img.modal-warning {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
background: $ui-base-color;
|
background: $ui-base-color;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { registrationsOpen, me } from 'mastodon/initial_state';
|
||||||
import Avatar from 'mastodon/components/avatar';
|
import Avatar from 'mastodon/components/avatar';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { openModal } from 'mastodon/actions/modal';
|
||||||
|
|
||||||
const Account = connect(state => ({
|
const Account = connect(state => ({
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
|
@ -15,7 +16,14 @@ const Account = connect(state => ({
|
||||||
</Link>
|
</Link>
|
||||||
));
|
));
|
||||||
|
|
||||||
export default @withRouter
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
openClosedRegistrationsModal() {
|
||||||
|
dispatch(openModal('CLOSED_REGISTRATIONS'));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default @connect(null, mapDispatchToProps)
|
||||||
|
@withRouter
|
||||||
class Header extends React.PureComponent {
|
class Header extends React.PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
@ -23,12 +31,13 @@ class Header extends React.PureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
openClosedRegistrationsModal: PropTypes.func,
|
||||||
location: PropTypes.object,
|
location: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { signedIn } = this.context.identity;
|
const { signedIn } = this.context.identity;
|
||||||
const { location } = this.props;
|
const { location, openClosedRegistrationsModal } = this.props;
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
|
|
||||||
|
@ -40,10 +49,26 @@ class Header extends React.PureComponent {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
let signupButton;
|
||||||
|
|
||||||
|
if (registrationsOpen) {
|
||||||
|
signupButton = (
|
||||||
|
<a href='/auth/sign_up' className='button button-tertiary'>
|
||||||
|
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
signupButton = (
|
||||||
|
<button className='button button-tertiary' onClick={openClosedRegistrationsModal}>
|
||||||
|
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
content = (
|
content = (
|
||||||
<>
|
<>
|
||||||
<a href='/auth/sign_in' className='button'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
<a href='/auth/sign_in' className='button'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
||||||
<a href={registrationsOpen ? '/auth/sign_up' : 'https://joinmastodon.org/servers'} className='button button-tertiary'><FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' /></a>
|
{signupButton}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2217,6 +2217,7 @@ $ui-header-height: 55px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
&__logo {
|
&__logo {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -2233,10 +2234,15 @@ $ui-header-height: 55px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-tertiary {
|
||||||
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7138,10 +7144,12 @@ noscript {
|
||||||
|
|
||||||
.verified {
|
.verified {
|
||||||
border: 1px solid rgba($valid-value-color, 0.5);
|
border: 1px solid rgba($valid-value-color, 0.5);
|
||||||
|
margin-top: -1px;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
border-top-left-radius: 4px;
|
border-top-left-radius: 4px;
|
||||||
border-top-right-radius: 4px;
|
border-top-right-radius: 4px;
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
|
@ -7973,7 +7981,8 @@ noscript {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
background: $ui-base-color;
|
background: $ui-base-color;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
|
@ -59,7 +59,7 @@ class AccountMigration < ApplicationRecord
|
||||||
|
|
||||||
def set_target_account
|
def set_target_account
|
||||||
self.target_account = ResolveAccountService.new.call(acct, skip_cache: true)
|
self.target_account = ResolveAccountService.new.call(acct, skip_cache: true)
|
||||||
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error
|
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error, Addressable::URI::InvalidURIError
|
||||||
# Validation will take care of it
|
# Validation will take care of it
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ module DomainMaterializable
|
||||||
|
|
||||||
Instance.refresh
|
Instance.refresh
|
||||||
count_unique_subdomains!
|
count_unique_subdomains!
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def count_unique_subdomains!
|
def count_unique_subdomains!
|
||||||
|
|
|
@ -54,7 +54,7 @@ class CustomFilter < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def irreversible=(value)
|
def irreversible=(value)
|
||||||
self.action = value ? :hide : :warn
|
self.action = ActiveModel::Type::Boolean.new.cast(value) ? :hide : :warn
|
||||||
end
|
end
|
||||||
|
|
||||||
def irreversible?
|
def irreversible?
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Form::Redirect
|
||||||
|
|
||||||
def set_target_account
|
def set_target_account
|
||||||
@target_account = ResolveAccountService.new.call(acct, skip_cache: true)
|
@target_account = ResolveAccountService.new.call(acct, skip_cache: true)
|
||||||
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error
|
rescue Webfinger::Error, HTTP::Error, OpenSSL::SSL::SSLError, Mastodon::Error, Addressable::URI::InvalidURIError
|
||||||
# Validation will take care of it
|
# Validation will take care of it
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ module Mastodon
|
||||||
:af,
|
:af,
|
||||||
:ar,
|
:ar,
|
||||||
:ast,
|
:ast,
|
||||||
|
:be,
|
||||||
:bg,
|
:bg,
|
||||||
:bn,
|
:bn,
|
||||||
:br,
|
:br,
|
||||||
|
|
|
@ -2,6 +2,7 @@ default: &default
|
||||||
adapter: postgresql
|
adapter: postgresql
|
||||||
pool: <%= ENV["DB_POOL"] || ENV['MAX_THREADS'] || 5 %>
|
pool: <%= ENV["DB_POOL"] || ENV['MAX_THREADS'] || 5 %>
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
|
connect_timeout: 15
|
||||||
encoding: unicode
|
encoding: unicode
|
||||||
sslmode: <%= ENV['DB_SSLMODE'] || "prefer" %>
|
sslmode: <%= ENV['DB_SSLMODE'] || "prefer" %>
|
||||||
|
|
||||||
|
|
|
@ -79,69 +79,72 @@ class BackfillAdminActionLogs < ActiveRecord::Migration[6.1]
|
||||||
safety_assured do
|
safety_assured do
|
||||||
AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log|
|
||||||
next if log.account.nil?
|
next if log.account.nil?
|
||||||
log.update(human_identifier: log.account.acct)
|
log.update_attribute('human_identifier', log.account.acct)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log|
|
||||||
next if log.user.nil?
|
next if log.user.nil?
|
||||||
log.update(human_identifier: log.user.account.acct, route_param: log.user.account_id)
|
log.update_attribute('human_identifier', log.user.account.acct)
|
||||||
|
log.update_attribute('route_param', log.user.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
Admin::ActionLog.where(target_type: 'Report', human_identifier: nil).in_batches.update_all('human_identifier = target_id::text')
|
Admin::ActionLog.where(target_type: 'Report', human_identifier: nil).in_batches.update_all('human_identifier = target_id::text')
|
||||||
|
|
||||||
AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log|
|
AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log|
|
||||||
next if log.domain_block.nil?
|
next if log.domain_block.nil?
|
||||||
log.update(human_identifier: log.domain_block.domain)
|
log.update_attribute('human_identifier', log.domain_block.domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log|
|
AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log|
|
||||||
next if log.domain_allow.nil?
|
next if log.domain_allow.nil?
|
||||||
log.update(human_identifier: log.domain_allow.domain)
|
log.update_attribute('human_identifier', log.domain_allow.domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log|
|
AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log|
|
||||||
next if log.email_domain_block.nil?
|
next if log.email_domain_block.nil?
|
||||||
log.update(human_identifier: log.email_domain_block.domain)
|
log.update_attribute('human_identifier', log.email_domain_block.domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log|
|
AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log|
|
||||||
next if log.unavailable_domain.nil?
|
next if log.unavailable_domain.nil?
|
||||||
log.update(human_identifier: log.unavailable_domain.domain)
|
log.update_attribute('human_identifier', log.unavailable_domain.domain)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log|
|
||||||
next if log.status.nil?
|
next if log.status.nil?
|
||||||
log.update(human_identifier: log.status.account.acct, permalink: log.status.uri)
|
log.update_attribute('human_identifier', log.status.account.acct)
|
||||||
|
log.update_attribute('permalink', log.status.uri)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log|
|
||||||
next if log.account_warning.nil?
|
next if log.account_warning.nil?
|
||||||
log.update(human_identifier: log.account_warning.account.acct)
|
log.update_attribute('human_identifier', log.account_warning.account.acct)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log|
|
||||||
next if log.announcement.nil?
|
next if log.announcement.nil?
|
||||||
log.update(human_identifier: log.announcement.text)
|
log.update_attribute('human_identifier', log.announcement.text)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log|
|
||||||
next if log.ip_block.nil?
|
next if log.ip_block.nil?
|
||||||
log.update(human_identifier: "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}")
|
log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}")
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log|
|
||||||
next if log.custom_emoji.nil?
|
next if log.custom_emoji.nil?
|
||||||
log.update(human_identifier: log.custom_emoji.shortcode)
|
log.update_attribute('human_identifier', log.custom_emoji.shortcode)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log|
|
||||||
next if log.canonical_email_block.nil?
|
next if log.canonical_email_block.nil?
|
||||||
log.update(human_identifier: log.canonical_email_block.canonical_email_hash)
|
log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log|
|
AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log|
|
||||||
next if log.appeal.nil?
|
next if log.appeal.nil?
|
||||||
log.update(human_identifier: log.appeal.account.acct, route_param: log.appeal.account_warning_id)
|
log.update_attribute('human_identifier', log.appeal.account.acct)
|
||||||
|
log.update_attribute('route_param', log.appeal.account_warning_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class BackfillAdminActionLogsAgain < ActiveRecord::Migration[6.1]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
class Account < ApplicationRecord
|
||||||
|
# Dummy class, to make migration possible across version changes
|
||||||
|
has_one :user, inverse_of: :account
|
||||||
|
|
||||||
|
def local?
|
||||||
|
domain.nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def acct
|
||||||
|
local? ? username : "#{username}@#{domain}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class User < ApplicationRecord
|
||||||
|
# Dummy class, to make migration possible across version changes
|
||||||
|
belongs_to :account
|
||||||
|
end
|
||||||
|
|
||||||
|
class Status < ApplicationRecord
|
||||||
|
include RoutingHelper
|
||||||
|
|
||||||
|
# Dummy class, to make migration possible across version changes
|
||||||
|
belongs_to :account
|
||||||
|
|
||||||
|
def local?
|
||||||
|
attributes['local'] || attributes['uri'].nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def uri
|
||||||
|
local? ? activity_account_status_url(account, self) : attributes['uri']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class DomainBlock < ApplicationRecord; end
|
||||||
|
class DomainAllow < ApplicationRecord; end
|
||||||
|
class EmailDomainBlock < ApplicationRecord; end
|
||||||
|
class UnavailableDomain < ApplicationRecord; end
|
||||||
|
|
||||||
|
class AccountWarning < ApplicationRecord
|
||||||
|
# Dummy class, to make migration possible across version changes
|
||||||
|
belongs_to :account
|
||||||
|
end
|
||||||
|
|
||||||
|
class Announcement < ApplicationRecord; end
|
||||||
|
class IpBlock < ApplicationRecord; end
|
||||||
|
class CustomEmoji < ApplicationRecord; end
|
||||||
|
class CanonicalEmailBlock < ApplicationRecord; end
|
||||||
|
|
||||||
|
class Appeal < ApplicationRecord
|
||||||
|
# Dummy class, to make migration possible across version changes
|
||||||
|
belongs_to :account
|
||||||
|
end
|
||||||
|
|
||||||
|
class AdminActionLog < ApplicationRecord
|
||||||
|
# Dummy class, to make migration possible across version changes
|
||||||
|
|
||||||
|
# Cannot use usual polymorphic support because of namespacing issues
|
||||||
|
belongs_to :status, foreign_key: :target_id
|
||||||
|
belongs_to :account, foreign_key: :target_id
|
||||||
|
belongs_to :user, foreign_key: :user_id
|
||||||
|
belongs_to :domain_block, foreign_key: :target_id
|
||||||
|
belongs_to :domain_allow, foreign_key: :target_id
|
||||||
|
belongs_to :email_domain_block, foreign_key: :target_id
|
||||||
|
belongs_to :unavailable_domain, foreign_key: :target_id
|
||||||
|
belongs_to :account_warning, foreign_key: :target_id
|
||||||
|
belongs_to :announcement, foreign_key: :target_id
|
||||||
|
belongs_to :ip_block, foreign_key: :target_id
|
||||||
|
belongs_to :custom_emoji, foreign_key: :target_id
|
||||||
|
belongs_to :canonical_email_block, foreign_key: :target_id
|
||||||
|
belongs_to :appeal, foreign_key: :target_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def up
|
||||||
|
safety_assured do
|
||||||
|
AdminActionLog.includes(:account).where(target_type: 'Account', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.account.nil?
|
||||||
|
log.update_attribute('human_identifier', log.account.acct)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(user: :account).where(target_type: 'User', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.user.nil?
|
||||||
|
log.update_attribute('human_identifier', log.user.account.acct)
|
||||||
|
log.update_attribute('route_param', log.user.account_id)
|
||||||
|
end
|
||||||
|
|
||||||
|
Admin::ActionLog.where(target_type: 'Report', human_identifier: nil).in_batches.update_all('human_identifier = target_id::text')
|
||||||
|
|
||||||
|
AdminActionLog.includes(:domain_block).where(target_type: 'DomainBlock').find_each do |log|
|
||||||
|
next if log.domain_block.nil?
|
||||||
|
log.update_attribute('human_identifier', log.domain_block.domain)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(:domain_allow).where(target_type: 'DomainAllow').find_each do |log|
|
||||||
|
next if log.domain_allow.nil?
|
||||||
|
log.update_attribute('human_identifier', log.domain_allow.domain)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(:email_domain_block).where(target_type: 'EmailDomainBlock').find_each do |log|
|
||||||
|
next if log.email_domain_block.nil?
|
||||||
|
log.update_attribute('human_identifier', log.email_domain_block.domain)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(:unavailable_domain).where(target_type: 'UnavailableDomain').find_each do |log|
|
||||||
|
next if log.unavailable_domain.nil?
|
||||||
|
log.update_attribute('human_identifier', log.unavailable_domain.domain)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(status: :account).where(target_type: 'Status', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.status.nil?
|
||||||
|
log.update_attribute('human_identifier', log.status.account.acct)
|
||||||
|
log.update_attribute('permalink', log.status.uri)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(account_warning: :account).where(target_type: 'AccountWarning', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.account_warning.nil?
|
||||||
|
log.update_attribute('human_identifier', log.account_warning.account.acct)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(:announcement).where(target_type: 'Announcement', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.announcement.nil?
|
||||||
|
log.update_attribute('human_identifier', log.announcement.text)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(:ip_block).where(target_type: 'IpBlock', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.ip_block.nil?
|
||||||
|
log.update_attribute('human_identifier', "#{log.ip_block.ip}/#{log.ip_block.ip.prefix}")
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(:custom_emoji).where(target_type: 'CustomEmoji', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.custom_emoji.nil?
|
||||||
|
log.update_attribute('human_identifier', log.custom_emoji.shortcode)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(:canonical_email_block).where(target_type: 'CanonicalEmailBlock', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.canonical_email_block.nil?
|
||||||
|
log.update_attribute('human_identifier', log.canonical_email_block.canonical_email_hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
AdminActionLog.includes(appeal: :account).where(target_type: 'Appeal', human_identifier: nil).find_each do |log|
|
||||||
|
next if log.appeal.nil?
|
||||||
|
log.update_attribute('human_identifier', log.appeal.account.acct)
|
||||||
|
log.update_attribute('route_param', log.appeal.account_warning_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2022_11_04_133904) do
|
ActiveRecord::Schema.define(version: 2022_12_06_114142) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
|
@ -43,6 +43,16 @@ namespace :tests do
|
||||||
puts 'CustomFilterKeyword records not created as expected'
|
puts 'CustomFilterKeyword records not created as expected'
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
unless Admin::ActionLog.find_by(target_type: 'DomainBlock', target_id: 1).human_identifier == 'example.org'
|
||||||
|
puts 'Admin::ActionLog domain block records not updated as expected'
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
unless Admin::ActionLog.find_by(target_type: 'EmailDomainBlock', target_id: 1).human_identifier == 'example.org'
|
||||||
|
puts 'Admin::ActionLog email domain block records not updated as expected'
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Populate the database with test data for 2.4.3'
|
desc 'Populate the database with test data for 2.4.3'
|
||||||
|
@ -84,8 +94,8 @@ namespace :tests do
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'destroy', 'Account', 1, now(), now()),
|
(1, 'destroy', 'Account', 1, now(), now()),
|
||||||
(1, 'destroy', 'User', 1, now(), now()),
|
(1, 'destroy', 'User', 1, now(), now()),
|
||||||
(1, 'destroy', 'DomainBlock', 1312, now(), now()),
|
(1, 'destroy', 'DomainBlock', 1, now(), now()),
|
||||||
(1, 'destroy', 'EmailDomainBlock', 1312, now(), now()),
|
(1, 'destroy', 'EmailDomainBlock', 1, now(), now()),
|
||||||
(1, 'destroy', 'Status', 1, now(), now()),
|
(1, 'destroy', 'Status', 1, now(), now()),
|
||||||
(1, 'destroy', 'CustomEmoji', 3, now(), now());
|
(1, 'destroy', 'CustomEmoji', 3, now(), now());
|
||||||
SQL
|
SQL
|
||||||
|
|
|
@ -147,6 +147,87 @@ RSpec.describe Admin::AccountsController, type: :controller do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'POST #approve' do
|
||||||
|
subject { post :approve, params: { id: account.id } }
|
||||||
|
|
||||||
|
let(:current_user) { Fabricate(:user, role: role) }
|
||||||
|
let(:account) { user.account }
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
account.user.update(approved: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is admin' do
|
||||||
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
|
|
||||||
|
it 'succeeds in approving account' do
|
||||||
|
is_expected.to redirect_to admin_accounts_path(status: 'pending')
|
||||||
|
expect(user.reload).to be_approved
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'logs action' do
|
||||||
|
is_expected.to have_http_status :found
|
||||||
|
|
||||||
|
log_item = Admin::ActionLog.last
|
||||||
|
|
||||||
|
expect(log_item).to_not be_nil
|
||||||
|
expect(log_item.action).to eq :approve
|
||||||
|
expect(log_item.account_id).to eq current_user.account_id
|
||||||
|
expect(log_item.target_id).to eq account.user.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is not admin' do
|
||||||
|
let(:role) { UserRole.everyone }
|
||||||
|
|
||||||
|
it 'fails to approve account' do
|
||||||
|
is_expected.to have_http_status :forbidden
|
||||||
|
expect(user.reload).not_to be_approved
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'POST #reject' do
|
||||||
|
subject { post :reject, params: { id: account.id } }
|
||||||
|
|
||||||
|
let(:current_user) { Fabricate(:user, role: role) }
|
||||||
|
let(:account) { user.account }
|
||||||
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
account.user.update(approved: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is admin' do
|
||||||
|
let(:role) { UserRole.find_by(name: 'Admin') }
|
||||||
|
|
||||||
|
it 'succeeds in rejecting account' do
|
||||||
|
is_expected.to redirect_to admin_accounts_path(status: 'pending')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'logs action' do
|
||||||
|
is_expected.to have_http_status :found
|
||||||
|
|
||||||
|
log_item = Admin::ActionLog.last
|
||||||
|
|
||||||
|
expect(log_item).to_not be_nil
|
||||||
|
expect(log_item.action).to eq :reject
|
||||||
|
expect(log_item.account_id).to eq current_user.account_id
|
||||||
|
expect(log_item.target_id).to eq account.user.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when user is not admin' do
|
||||||
|
let(:role) { UserRole.everyone }
|
||||||
|
|
||||||
|
it 'fails to reject account' do
|
||||||
|
is_expected.to have_http_status :forbidden
|
||||||
|
expect(user.reload).not_to be_approved
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'POST #redownload' do
|
describe 'POST #redownload' do
|
||||||
subject { post :redownload, params: { id: account.id } }
|
subject { post :redownload, params: { id: account.id } }
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,15 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
|
||||||
it 'approves user' do
|
it 'approves user' do
|
||||||
expect(account.reload.user_approved?).to be true
|
expect(account.reload.user_approved?).to be true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'logs action' do
|
||||||
|
log_item = Admin::ActionLog.last
|
||||||
|
|
||||||
|
expect(log_item).to_not be_nil
|
||||||
|
expect(log_item.action).to eq :approve
|
||||||
|
expect(log_item.account_id).to eq user.account_id
|
||||||
|
expect(log_item.target_id).to eq account.user.id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #reject' do
|
describe 'POST #reject' do
|
||||||
|
@ -118,6 +127,15 @@ RSpec.describe Api::V1::Admin::AccountsController, type: :controller do
|
||||||
it 'removes user' do
|
it 'removes user' do
|
||||||
expect(User.where(id: account.user.id).count).to eq 0
|
expect(User.where(id: account.user.id).count).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'logs action' do
|
||||||
|
log_item = Admin::ActionLog.last
|
||||||
|
|
||||||
|
expect(log_item).to_not be_nil
|
||||||
|
expect(log_item.action).to eq :reject
|
||||||
|
expect(log_item.account_id).to eq user.account_id
|
||||||
|
expect(log_item.target_id).to eq account.user.id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST #enable' do
|
describe 'POST #enable' do
|
||||||
|
|
|
@ -22,9 +22,11 @@ RSpec.describe Api::V1::FiltersController, type: :controller do
|
||||||
|
|
||||||
describe 'POST #create' do
|
describe 'POST #create' do
|
||||||
let(:scopes) { 'write:filters' }
|
let(:scopes) { 'write:filters' }
|
||||||
|
let(:irreversible) { true }
|
||||||
|
let(:whole_word) { false }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
post :create, params: { phrase: 'magic', context: %w(home), irreversible: true }
|
post :create, params: { phrase: 'magic', context: %w(home), irreversible: irreversible, whole_word: whole_word }
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns http success' do
|
it 'returns http success' do
|
||||||
|
@ -34,11 +36,29 @@ RSpec.describe Api::V1::FiltersController, type: :controller do
|
||||||
it 'creates a filter' do
|
it 'creates a filter' do
|
||||||
filter = user.account.custom_filters.first
|
filter = user.account.custom_filters.first
|
||||||
expect(filter).to_not be_nil
|
expect(filter).to_not be_nil
|
||||||
expect(filter.keywords.pluck(:keyword)).to eq ['magic']
|
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
|
||||||
expect(filter.context).to eq %w(home)
|
expect(filter.context).to eq %w(home)
|
||||||
expect(filter.irreversible?).to be true
|
expect(filter.irreversible?).to be irreversible
|
||||||
expect(filter.expires_at).to be_nil
|
expect(filter.expires_at).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with different parameters' do
|
||||||
|
let(:irreversible) { false }
|
||||||
|
let(:whole_word) { true }
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a filter' do
|
||||||
|
filter = user.account.custom_filters.first
|
||||||
|
expect(filter).to_not be_nil
|
||||||
|
expect(filter.keywords.pluck(:keyword, :whole_word)).to eq [['magic', whole_word]]
|
||||||
|
expect(filter.context).to eq %w(home)
|
||||||
|
expect(filter.irreversible?).to be irreversible
|
||||||
|
expect(filter.expires_at).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'GET #show' do
|
describe 'GET #show' do
|
||||||
|
|
|
@ -1,5 +1,48 @@
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe AccountMigration, type: :model do
|
RSpec.describe AccountMigration, type: :model do
|
||||||
|
describe 'validations' do
|
||||||
|
let(:source_account) { Fabricate(:account) }
|
||||||
|
let(:target_acct) { target_account.acct }
|
||||||
|
|
||||||
|
let(:subject) { AccountMigration.new(account: source_account, acct: target_acct) }
|
||||||
|
|
||||||
|
context 'with valid properties' do
|
||||||
|
let(:target_account) { Fabricate(:account, username: 'target', domain: 'remote.org') }
|
||||||
|
|
||||||
|
before do
|
||||||
|
target_account.aliases.create!(acct: source_account.acct)
|
||||||
|
|
||||||
|
service_double = double
|
||||||
|
allow(ResolveAccountService).to receive(:new).and_return(service_double)
|
||||||
|
allow(service_double).to receive(:call).with(target_acct, anything).and_return(target_account)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'passes validations' do
|
||||||
|
expect(subject).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with unresolveable account' do
|
||||||
|
let(:target_acct) { 'target@remote' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
service_double = double
|
||||||
|
allow(ResolveAccountService).to receive(:new).and_return(service_double)
|
||||||
|
allow(service_double).to receive(:call).with(target_acct, anything).and_return(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'has errors on acct field' do
|
||||||
|
expect(subject).to model_have_error_on_field(:acct)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a space in the domain part' do
|
||||||
|
let(:target_acct) { 'target@remote. org' }
|
||||||
|
|
||||||
|
it 'has errors on acct field' do
|
||||||
|
expect(subject).to model_have_error_on_field(:acct)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue