モデルとサービススパム保護とCAPTCHAサポート

REST API、GraphQL API、またはWeb UIにスパムやCAPTCHAのサポートを追加する前に、まず必要なサポートを追加する必要があります:

  1. バックエンドの ActiveRecord モデル。
  2. サービス層。

サポートしているスパムや CAPTCHA リクエストの実装の種類にかかわらず、以下の変更のすべて、あるいはほとんどが必要です。完全に GraphQL API をベースとした新しい機能の中には、コントローラを持たないものもあり、その場合はmark_as_spam アクションをコントローラに追加する必要はありません。

そのためには

  1. ActiveRecord モデルにSpammable サポートを追加.
  2. コントローラにmark_as_spam アクションのサポートを追加.
  3. サービスの execute メソッドにcheck_for_spam への呼び出しを追加.

ActiveRecordモデルにSpammable

  1. モデルクラスにSpammable モジュールをインクルードします:

    include Spammable
    
  2. attr_spammable を追加することで、どのフィールドがスパムチェックされるかを示すことができます。モデルあたり最大2つのフィールドがサポートされます: “title” と “description” です。どのフィールドを “title” または “description” とみなすかを指定することができます。例えば、この行はcontent フィールドをdescriptionとして指定します:

    attr_spammable :content, spam_description: true
    
  3. #check_for_spam? メソッド実装を追加します:

    def check_for_spam?(user:)
      # Return a boolean result based on various applicable checks, which may include
      # which attributes have changed, the type of user, whether the data is publicly
      # visible, and other criteria. This may vary based on the type of model, and
      # may change over time as spam checking requirements evolve.
    end
    

    必要なロジックチェックの例については、このメソッドの他の既存のSpammable モデルの実装を参照してください。

コントローラにmark_as_spam アクションのサポートを追加します。

SpammableActions::AkismetMarkAsSpamAction モジュールは、#mark_as_spam アクションのサポートをコントローラに追加します。このコントローラにより、管理者は関連するSpammable モデルのスパムを管理エリアページのスパムログセクションで管理できるようになります。

  1. SpammableActions::AkismetMarkAsSpamAction モジュールをコントローラに組み込みます。

    include SpammableActions::AkismetMarkAsSpamAction
    
  2. #spammable_path メソッドの実装を追加します。スパム管理ページは、編集後にこのページにリダイレクトします。必要なパスロジックの例として、既存のコントローラのこのメソッドの実装を参照してください。一般的には、Spammable モデルのコントローラの#show アクションとします。

    def spammable_path
      widget_path(widget)
    end
    
note
この機能の実装方法によっては、コントローラに他の変更が必要になるかもしれません。詳細はWeb UIを参照してください。

サービスの execute メソッドにcheck_for_spam への呼び出しを追加します。

この方法は、スパム可能な属性を永続化できるすべてのサービスに適用されます:

  1. app/services 、該当するCreateまたはUpdateサービスの中で、モデルのcheck_for_spam メソッドを呼び出します。
  2. スパム検査に失敗した場合
    • エラーはモデルに追加され、そのモデルは無効となり、保存されなくなります。
    • needs_recaptcha プロパティはtrue に設定されます。

    モデルに対するこれらの変更により、後続のバックエンドおよびフロントエンドの CAPTCHA ロジックによる処理が可能になります。

関連する各サービスにこれらの変更を加えてください:

  1. execute メソッドの中で、モデルのcheck_for_spam メソッドを呼び出します。before_create before_update(このメソッドは名前付き引数を使用するので、既存の例を参照すれば使い方は明らかです。しかし、2つの重要な考慮事項があります:
    1. check_for_spam は、保存されていない(そしてダーティな)Spammable モデルインスタンスに必要なすべての変更が行われた_後に_実行されなければなりません。この順序付けにより、スパムチェックされるスパム可能な属性が確実に存在するようになります。
    2. check_for_spam は、モデルにエラーがないかチェックされ、save を試みる_前に_実行されなければなりません。モデルの変更された属性に潜在的なスパムが検出された場合、保存を阻止しなければなりません。
module Widget
  class CreateService < ::Widget::BaseService
    # NOTE: We add a default value of `true` for `perform_spam_check`, because spam checking is likely to be necessary.
    def initialize(project:, current_user: nil, params: {}, perform_spam_check: true)
      super(project: project, current_user: current_user, params: params)

      @perform_spam_check = perform_spam_check
    end

    def execute
      widget = Widget::BuildService.new(project, current_user, params).execute

      # More code that may manipulate dirty model before it is spam checked.

      # NOTE: do this AFTER the spammable model is instantiated, but BEFORE
      # it is validated or saved.
      widget.check_for_spam(user: current_user, action: :create) if perform_spam_check

      # Possibly more code related to saving model, but should not change any attributes.

      widget.save
    end

    private

    attr_reader :perform_spam_check