모델 및 서비스 스팸 방지 및 CAPTCHA 지원

REST API, GraphQL API 또는 Web UI에 스팸 또는 CAPTCHA 지원을 추가하기 전에 먼저 다음과 같은 지원을 추가해야 합니다.

  1. 백엔드 ActiveRecord 모델.
  2. 서비스 레이어.

지원하는 스팸 또는 CAPTCHA 요청의 유형과 관계없이 다음 중 모든 또는 대부분의 변경이 필요합니다. GraphQL API를 완전히 기반으로 하는 일부 최신 기능은 컨트롤러가 없을 수 있으며 컨트롤러에 mark_as_spam 작업을 추가할 필요가 없습니다.

이를 위해 다음을 수행하세요:

  1. ActiveRecord 모델에 Spammable 지원 추가.
  2. 컨트롤러에 mark_as_spam 작업을 지원 추가](#add-support-for-the-mark_as_spam-action-to-the-controller).
  3. 서비스의 실행 메서드에 check_for_spam 호출 추가](#add-a-call-to-check_for_spam-to-the-execute-method-of-services).

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)
    

참고: 기능의 구현 방식에 따라 컨트롤러에 필요한 기타 변경 사항이 있을 수 있습니다. 자세한 내용은 Web UI를 참조하십시오.

서비스의 실행 메서드에 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은 저장되지 않은(또는 변경된) Spammable 모델 인스턴스에 필요한 모든 변경이 완료된 후에 실행되어야 합니다. 이 순서는 스패머블 속성이 스팸 확인될 수 있도록 보장합니다.
    2. 잠재적인 스팸이 모델의 변경된 속성에서 감지되면 오류가 모델에 추가되고 save를 시도하기 전에 모델을 확인해야 합니다.
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