REST API 스팸 방지 및 CAPTCHA 지원

모델이 REST API를 통해 수정될 수 있다면, 스팸 가능성이 있는 속성을 수정할 수 있는 모든 관련 API 엔드포인트에도 지원을 추가해야 합니다. 이것은 결코 POSTPUT 변이만을 포함하는 것이 아니며, 모델의 비밀 또는 공개 플래그를 변경하는 것과 관련된 것과 같은 다른 것들을 포함할 수도 있습니다.

REST 엔드포인트에 지원 추가

주요 단계는 다음과 같습니다:

  1. resourcehelpers SpammableActions::CaptchaCheck::RestApiActionsSupport를 추가합니다.
  2. Update 서비스 클래스 생성자에 perform_spam_check: true를 전달합니다. Create 서비스에서는 기본적으로 true로 설정됩니다.
  3. Spammable 모델 인스턴스를 생성하거나 업데이트한 후 #check_spam_action_response!를 호출하여 생성하거나 업데이트한 인스턴스를 변수에 저장합니다.
  4. 요청의 failure 케이스에 대한 오류 처리 로직을 식별합니다. 생성하거나 업데이트에 실패했을 때 이러한 사례는 가능한 스팸 탐지를 나타내며, 이는 Spammable 인스턴스에 오류를 추가합니다. 오류는 보통 render_api_error! 또는 render_validation_error!와 유사합니다.
  5. 기존의 오류 처리 로직을 with_captcha_check_rest_api(spammable: my_spammable_instance) 호출로 래핑하여 오류가 발생한 경우, 변수에 저장한 Spammable 모델 인스턴스를 spammable: 명명된 인수로 전달합니다. 이 호출은 다음을 수행합니다:
    1. 모델에 필요한 스팸 확인을 수행합니다.
    2. 스팸이 감지되면:
      • 설명적인 스팸 특정 오류 메시지와 함께 Grape #error! 예외를 발생시킵니다.
      • 응답에 오류 필드를 추가합니다. 이 필드에 대한 자세한 내용은 REST API 문서의 스팸으로 감지된 요청 해결 섹션을 참조하십시오.
note
이미 설명된 표준 ApolloLink 또는 Axios interceptor CAPTCHA 지원을 사용하는 경우, 상기 필드 세부 사항을 무시할 수 있습니다. 왜냐하면 이러한 것들은 자동으로 처리되기 때문입니다. 이러한 것들은 직접 GraphQL API를 사용하여 잠재적인 스팸 확인을 처리하고 해결된 CAPTCHA 응답으로 요청을 다시 제출하려고 시도하는 경우에 관련이 됩니다.

snippets 리소스에서 postput 액션에 대한 예제는 다음과 같습니다:

module API
  class Snippets < ::API::Base
    #...
    resource :snippets do
      # 이 헬퍼는 `#with_captcha_check_rest_api`를 제공합니다
      helpers SpammableActions::CaptchaCheck::RestApiActionsSupport

      post do
        #...
        service_response = ::Snippets::CreateService.new(project: nil, current_user: current_user, params: attrs).execute
        snippet = service_response.payload[:snippet]

        if service_response.success?
          present snippet, with: Entities::PersonalSnippet, current_user: current_user
        else
          # 일반적인 오류 응답을 `with_captcha_check_rest_api(spammable: snippet)` 블록으로 래핑합니다
          with_captcha_check_rest_api(spammable: snippet) do
            # 가능한 스팸이 감지되었을 경우 `#with_captcha_check_rest_api`에서 Grape가 `error!`를 통해 처리할 예외가 발생합니다
            render_api_error!({ error: service_response.message }, service_response.http_status)
          end
        end
      end

      put ':id' do
        #...
        service_response = ::Snippets::UpdateService.new(project: nil, current_user: current_user, params: attrs, perform_spam_check: true).execute(snippet)

        snippet = service_response.payload[:snippet]

        if service_response.success?
          present snippet, with: Entities::PersonalSnippet, current_user: current_user
        else
          # 일반적인 오류 응답을 `with_captcha_check_rest_api(spammable: snippet)` 블록으로 래핑합니다
          with_captcha_check_rest_api(spammable: snippet) do
            # 가능한 스팸이 감지되었을 경우 `#with_captcha_check_rest_api`에서 Grape가 `error!`를 통해 처리할 예외가 발생합니다
            render_api_error!({ error: service_response.message }, service_response.http_status)
          end
        end
      end
    end
  end
end