#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, как это, но таким образом мне нужно создавать экземпляры самостоятельно, и мне было интересно, как это сделать.
Как я могу добавить обработку доступа к базе данных в логику обратного вызова?