Как реализовать доступ к базе данных во время логики обратного вызова play-pac4j

#scala #dependency-injection #playframework #slick #pac4j

Вопрос:

Я реализую аутентификацию OAuth2 в своем приложении play framework с помощью библиотеки play-pac4j(не java, а версия языка scala).

Я хотел бы добавить свою собственную логику, которая обращается к базе данных через slick во время процесса обратного вызова от поставщика OAuth. Однако я не знаю, как это правильно реализовать.

Я попробовал следующие методы, но сдался.

  • Создайте и установите CustomCallbackLogic класс при создании CallbackController в configure() SecurityModule.scala
  • Сделайте CustomCallbackLogic расширение DefaultCallbackLogic и переопределите какой-либо необходимый метод
  • Доступ к базе данных в методе переопределения

Причина, по которой я сдался, заключалась в том, что я не знал, как выполнить DI при создании экземпляра CallbackLogic.

Исходный код выглядит следующим образом.

Окружающая среда

  • игровой фреймворк 2.8.8
  • scala 2.13.6
  • играть-pac4j 11.0.0-PLAY2.8
  • играй-ловко 5.0.0

CustomCallbackLogic.scala

Необходимо ввести класс реализации запроса и конфигурацию доступа к БД, а также контекст выполнения в качестве пула потоков.

 class CustomCallbackLogic @Inject() (
  protected val dbConfigProvider: DatabaseConfigProvider,
  userFindQuery: UserFindQuery
)(implicit ec: ExecutionContext)
extends DefaultCallbackLogic {

  override def saveUserProfile(...): Unit = {
    // database access logic via slick
    val email = profile.getAttributes...
    userFindQuery.run(email)...
  }
}
 

Запрос на поиск пользователя

 trait UserFindQuery {
  def run(email: String): Future[Option[User]]
}
 

UserFindQueryImpl

 class UserFindQueryImpl @Inject() (
  protected val dbConfigProvider: DatabaseConfigProvider)
  (implicit val ec: ExecutionContext)
extends HasDatabaseConfigProvider[PostgresProfile] {

  override def run(email: String): Future[Option[UserView]] = {
    val action = Users
      .filter(_.email === email)
      ...
    db.run(action)
  }
}
 

SecuritiModule.scala

This is a module for pac4j setting.
Setting about callback related class in confiture() according to the documents.
This module is added to play.modules.enabled in application.conf .

 class SecurityModule(environment: Environment, configuration: Configuration)
extends AbstractModule {
  override def configure(): Unit = {

    bind(classOf[SessionStore]).to(classOf[PlayCacheSessionStore])
    bind(classOf[SecurityComponents]).to(classOf[DefaultSecurityComponents])

    // callback
    val callbackController = new CallbackController()
    val customCallbackLogic = new customCallbackLogic() // how can I DI here
    callbackController.setDefaultUrl("/")
    callbackController.setCallbackLogic(customCallbackLogic)
    bind(classOf[CallbackController]).toInstance(callbackController)

    // logout
    ...
  }
  ...
}
 

Если это класс scala под классом контроллера, Guice будет автоматически создавать экземпляры и DI, как это, но таким образом мне нужно создавать экземпляры самостоятельно, и мне было интересно, как это сделать.

Как я могу добавить обработку доступа к базе данных в логику обратного вызова?