Преглед изворни кода

Add ability to block sign-ups from IP (#19037)

Eugen Rochko пре 1 година
родитељ
комит
d83faa1a89

+ 5 - 1
app/controllers/auth/registrations_controller.rb

@@ -82,7 +82,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
   end
 
   def check_enabled_registrations
-    redirect_to root_path if single_user_mode? || omniauth_only? || !allowed_registrations?
+    redirect_to root_path if single_user_mode? || omniauth_only? || !allowed_registrations? || ip_blocked?
   end
 
   def allowed_registrations?
@@ -93,6 +93,10 @@ class Auth::RegistrationsController < Devise::RegistrationsController
     ENV['OMNIAUTH_ONLY'] == 'true'
   end
 
+  def ip_blocked?
+    IpBlock.where(severity: :sign_up_block).where('ip >>= ?', request.remote_ip.to_s).exists?
+  end
+
   def invite_code
     if params[:user]
       params[:user][:invite_code]

+ 1 - 0
app/models/ip_block.rb

@@ -19,6 +19,7 @@ class IpBlock < ApplicationRecord
 
   enum severity: {
     sign_up_requires_approval: 5000,
+    sign_up_block: 5500,
     no_access: 9999,
   }
 

+ 55 - 11
app/services/app_sign_up_service.rb

@@ -2,23 +2,67 @@
 
 class AppSignUpService < BaseService
   def call(app, remote_ip, params)
-    return unless allowed_registrations?
+    @app       = app
+    @remote_ip = remote_ip
+    @params    = params
 
-    user_params           = params.slice(:email, :password, :agreement, :locale)
-    account_params        = params.slice(:username)
-    invite_request_params = { text: params[:reason] }
-    user                  = User.create!(user_params.merge(created_by_application: app, sign_up_ip: remote_ip, password_confirmation: user_params[:password], account_attributes: account_params, invite_request_attributes: invite_request_params))
+    raise Mastodon::NotPermittedError unless allowed_registrations?
 
-    Doorkeeper::AccessToken.create!(application: app,
-                                    resource_owner_id: user.id,
-                                    scopes: app.scopes,
-                                    expires_in: Doorkeeper.configuration.access_token_expires_in,
-                                    use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?)
+    ApplicationRecord.transaction do
+      create_user!
+      create_access_token!
+    end
+
+    @access_token
   end
 
   private
 
+  def create_user!
+    @user = User.create!(
+      user_params.merge(created_by_application: @app, sign_up_ip: @remote_ip, password_confirmation: user_params[:password], account_attributes: account_params, invite_request_attributes: invite_request_params)
+    )
+  end
+
+  def create_access_token!
+    @access_token = Doorkeeper::AccessToken.create!(
+      application: @app,
+      resource_owner_id: @user.id,
+      scopes: @app.scopes,
+      expires_in: Doorkeeper.configuration.access_token_expires_in,
+      use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?
+    )
+  end
+
+  def user_params
+    @params.slice(:email, :password, :agreement, :locale)
+  end
+
+  def account_params
+    @params.slice(:username)
+  end
+
+  def invite_request_params
+    { text: @params[:reason] }
+  end
+
   def allowed_registrations?
-    Setting.registrations_mode != 'none' && !Rails.configuration.x.single_user_mode
+    registrations_open? && !single_user_mode? && !omniauth_only? && !ip_blocked?
+  end
+
+  def registrations_open?
+    Setting.registrations_mode != 'none'
+  end
+
+  def single_user_mode?
+    Rails.configuration.x.single_user_mode
+  end
+
+  def omniauth_only?
+    ENV['OMNIAUTH_ONLY'] == 'true'
+  end
+
+  def ip_blocked?
+    IpBlock.where(severity: :sign_up_block).where('ip >>= ?', @remote_ip.to_s).exists?
   end
 end

+ 2 - 0
config/locales/simple_form.en.yml

@@ -85,6 +85,7 @@ en:
         ip: Enter an IPv4 or IPv6 address. You can block entire ranges using the CIDR syntax. Be careful not to lock yourself out!
         severities:
           no_access: Block access to all resources
+          sign_up_block: New sign-ups will not be possible
           sign_up_requires_approval: New sign-ups will require your approval
         severity: Choose what will happen with requests from this IP
       rule:
@@ -219,6 +220,7 @@ en:
         ip: IP
         severities:
           no_access: Block access
+          sign_up_block: Block sign-ups
           sign_up_requires_approval: Limit sign-ups
         severity: Rule
       notification_emails:

+ 1 - 1
spec/services/app_sign_up_service_spec.rb

@@ -11,7 +11,7 @@ RSpec.describe AppSignUpService, type: :service do
     it 'returns nil when registrations are closed' do
       tmp = Setting.registrations_mode
       Setting.registrations_mode = 'none'
-      expect(subject.call(app, remote_ip, good_params)).to be_nil
+      expect { subject.call(app, remote_ip, good_params) }.to raise_error Mastodon::NotPermittedError
       Setting.registrations_mode = tmp
     end