Расширение SecureActionBuilder для проверки запроса перед анализом тела

Я работаю над написанием веб-приложения, которое принимает составные файлы в качестве входных данных и загружает их в экземпляр S3. Поскольку некоторые файлы могут быть очень большими, я использую собственный анализатор тела для отправки фрагментов в S3 по мере их поступления.

Я хочу выполнить проверку запроса перед загрузкой файла (чтобы убедиться, что у пользователя есть разрешение/достаточно места и т. д.). Из документации Play кажется, что расширение ActionBuilder — правильный способ сделать это. Я заметил, что в SecureSocial есть SecureActionBuilder, и я считаю, что должен расширить его, чтобы создать безопасное действие (именно то, что я хочу).

Я попробовал этот простой тест, чтобы увидеть, могу ли я распечатать идентификатор пользователя, поэтому я могу выполнять действия на основе пользователя.

object FileValidationAction extends SecuredActionBuilder {
  def invokeBlock[A](request: SecuredRequest[A], block: SecuredRequest[A] => Future[SimpleResult]) = {
    Logger.info("User id is " + request.user.userProfile.userId)
    block(request)
  }
}

Однако метод так и не был вызван.

Затем я попытался переопределить метод из объекта SecuredActionBuilder:

object FileValidationAction extends SecuredActionBuilder {
  override def invokeBlock[A](request: Request[A], block: SecuredRequest[A] => Future[SimpleResult]) = {
    val securedResult: Option[SecuredRequest[A]] = request match {
      case r: SecuredRequest[A] => Option(r)
      case _ => None
    }
    Logger.info("Calling action ------- WOO!")
    securedResult match {
      case Some(r) =>
        block(r)
      case _ =>
        Future.successful(Forbidden)
    }
  }
}

Этот метод вызывается, но входящий запрос не является SecuredRequest, как я надеялся.

Как мне создать SecuredAction, используя собственный анализатор тела, который я могу проверить до того, как он завершит (или даже начнет) загрузку?

РЕДАКТИРОВАТЬ:

Чтобы уточнить, я буду вызывать действие со следующей сигнатурой метода:

def upload = FileValidationAction(streamingBodyParser(streamConstructor)) { request =>

person eliot    schedule 28.09.2014    source источник


Ответы (1)


Проблема в том, что вы не вызываете исходный код в SecuredActionBuilder, который фактически проверяет, присутствует ли пользователь, и создает экземпляр SecuredRequest.

Что-то вроде этого должно работать:

// A sample usage of the action
def checkFile = FileValidationAction { request =>
    Ok("")
  }

// The builder implementation
  object FileValidationAction extends FileValidationActionBuilder {
    def apply[A]() = new FileValidationActionBuilder()
  }

  class FileValidationActionBuilder(authorize: Option[Authorization[DemoUser]] = None) extends SecuredActionBuilder(authorize) {
    def validateFile[A](block: SecuredRequest[A] => Future[SimpleResult]): SecuredRequest[A] => Future[SimpleResult] = { securedRequest =>
      Logger.info(s"User id is ${securedRequest.user.main.userId}")
      block(securedRequest)
    }

    override def invokeBlock[A](request: Request[A], block: (SecuredRequest[A]) => Future[SimpleResult]): Future[SimpleResult] = {
      invokeSecuredBlock(authorize, request, validateFile(block))
    }
  }

Вам нужно будет добавить это в контроллер, где вы планируете использовать эти действия. Если вам нужно использовать его в нескольких контроллерах, создайте трейт, который вы можете расширить с помощью этого.

Также обратите внимание, что в этом примере кода я использую тип DemoUser, который у меня есть в примерах. Вам нужно будет изменить его на тип, который вы используете в своем приложении для представления пользователей.

person Jorge    schedule 29.09.2014
comment
Боюсь, ошибка все же есть. BodyParser выполняется до проверки файла. Мне нужно сделать некоторые проверки файла перед его загрузкой. Есть какой-либо способ сделать это? - person eliot; 30.09.2014
comment
Я добавил в редактирование, чтобы показать, как я буду использовать настраиваемое действие. На самом деле то же самое верно и для простого использования защищенного действия. Есть ли способ проверить пользователя перед разбором тела? - person eliot; 30.09.2014
comment
Действия анализируют запрос с помощью BodyParser, поэтому для достижения того, что вам нужно, следует использовать EssentialAction. EssentialActions предоставляет вам доступ к заголовкам запроса без разбора содержимого. У меня сейчас нет такого в модуле. Я постараюсь увидеть, как добавить поддержку для этого. - person Jorge; 30.09.2014
comment
Хорошо, я приму ответ здесь и опубликую вопрос в репозитории github. Спасибо еще раз. - person eliot; 01.10.2014
comment
что это за библиотека? я имею в виду, что вы используете для SecuredActionBuilder? - person HuntsMan; 13.03.2017