Merge branch 'main' into glitch-soc/merge-upstream
Conflicts: - `app/models/concerns/domain_materializable.rb`: Fixed a code style issue upstream in a PR that got merged in glitch-soc earlier. Changed the code to match upstream's.
This commit is contained in:
		
						commit
						9a3d91f629
					
				
					 22 changed files with 443 additions and 59 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 | ||||||
|  |  | ||||||
|  | @ -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