모델 및 서비스 스팸 방지 및 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을 추가하여 스팸으로 확인할 수 있는 필드를 나타냅니다. 모델 당 최대 두 개의 필드가 지원됩니다. “title” 및 “description“으로 “title” 또는 “description“을 지정할 수 있습니다. 예를 들어, 다음 줄은 content 필드를 description으로 지정합니다:

    attr_spammable :content, spam_description: true
    
  3. #check_for_spam? 메서드 구현을 추가합니다:

    def check_for_spam?(user:)
      # 변경된 속성, 사용자 유형, 데이터의 공개 여부 및 기타 기준을 포함하는 여러 적용 가능한 검사를 기반으로
      # 부울 결과를 반환합니다. 이는 모델의 유형에 따라 달라질 수 있으며,
      # 스팸 확인 요구 사항이 변환될 수 있습니다.
    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를 사용할 수도 있습니다.) 이 메서드는 명명된 인수를 사용하므로 기존 예제를 참조하면 사용 방법이 명확합니다. 그러나 두 가지 중요한 고려 사항이 있습니다:
    1. check_for_spam은 저장되지 않은 (dirty) Spammable 모델 인스턴스에 필요한 모든 변경이 완료된 이후에 실행되어야 합니다. 이 순서는 스팸 확인할 수 있는 속성이 존재함을 보장합니다.
    2. 모델이 오류를 확인하고 save를 시도하기 전에 check_for_spam이 실행되어야 합니다. 모델의 변경된 속성에서 잠재적인 스팸이 감지되면 저장을 방지해야 합니다.
module Widget
  class CreateService < ::Widget::BaseService
    # 스팸 확인이 필요할 가능성이 높기 때문에 `perform_spam_check`의 기본값을 `true`로 추가합니다.
    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
      
      # 스팸 확인 전에 모델을 조작할 수 있는 추가 코드
      
      # 이를 여기서 실행: 스팸 확인이 필요한 경우
      widget.check_for_spam(user: current_user, action: :create) if perform_spam_check
      
      # 모델을 저장하는 관련 코드(속성을 변경하지 않아야 함)
      widget.save
    end
    
    private
    
    attr_reader :perform_spam_check