securesocialをscala2.11/Play2.3.4で使う

securesocialの(安定)最新版は2.1.4だが、scala2.11では使えない(かどうかわからないけど、sbtではダウンロードできない) ので、scala2.11で使いたい場合は3系(3.0-M1)に上げる必要がある。

"ws.securesocial"   %% "securesocial" % "2.1.2",

"ws.securesocial"   %% "securesocial" % "3.0-M1",

それに伴って色々変更すべき点があるみたい。

play.plugins

いままでは、

9994:securesocial.core.DefaultAuthenticatorStore
9995:securesocial.core.DefaultIdGenerator
9996:securesocial.core.providers.utils.DefaultPasswordValidator
9997:securesocial.controllers.DefaultTemplatesPlugin
...
10000:securesocial.core.providers.TwitterProvider
10001:securesocial.core.providers.FacebookProvider
10002:securesocial.core.providers.GoogleProvider
10003:securesocial.core.providers.LinkedInProvider
...

のように書く必要があったけど、一切不要になった。

Global.scala

ここに、アプリケーション独自のRuntimeEnvironmentの派生クラスを記述する必要がある。

/**
 * The runtime environment for this sample app.
 */
object ApplicationRuntimeEnvironment extends RuntimeEnvironment.Default[User] {
  protected override def include(p: IdentityProvider) = p.id ->   p
  protected override def oauth1ClientFor(provider: String) = new OAuth1Client.Default(ServiceInfoHelper.forProvider(provider), httpService)
  protected override def oauth2ClientFor(provider: String) = new OAuth2Client.Default(httpService, OAuth2Settings.forProvider(provider))

  override lazy val userService: UserService[User] = new UserServiceImpl
  override lazy val providers = ListMap(
    // oauth 2 client providers
    include(new FacebookProvider(routes, cacheService, oauth2ClientFor(FacebookProvider.Facebook))),
    include(new GoogleProvider(routes, cacheService,oauth2ClientFor(GoogleProvider.Google))),
    // username password
    include(new UsernamePasswordProvider[User](userService, avatarService, viewTemplates, passwordHashers))
  )
}

/**
 * An implementation that checks if the controller expects a RuntimeEnvironment and
 * passes the instance to it if required.
 *
 * This can be replaced by any DI framework to inject it differently.
 *
 * @param controllerClass
 * @tparam A
 * @return
 */
override def getControllerInstance[A](controllerClass: Class[A]): A = {
  val instance  = controllerClass.getConstructors.find { c =>
    val params = c.getParameterTypes
    params.length == 1 && params(0) == classOf[RuntimeEnvironment[User]]
  }.map {
        _.asInstanceOf[Constructor[A]].newInstance(ApplicationRuntimeEnvironment)
  }
  instance.getOrElse(super.getControllerInstance(controllerClass))
}

いままで、play.pluginsに使用するサービスを書いていたが、 今後は、RuntimeEnvironment.providersに記述する。 今回新たにgetControllerInstanceをoverrideしているのは、単にRuntimeEnvironmentをコントローラーに渡すためだと思う。

上記のRuntimeEnvironmentはUserServiceとprovidersの定義を上書きしているだけだが、他にもカスタマイズが入る場合(例えば、独自のテンプレートを使うとか)はここで独自に作成したサービスを指定することになると思う。

コントローラー

いままでは、objectとして定義していたけど、classで定義するようになる。

object UserController extends SecureSocial {
...
}

class UserController(override implicit val env:RuntimeEnvironment[User]) extends SecureSocial[User] {
...
}

routes

いままでは、使用するアクションをすべて記述していた(と思う)

GET     /login securesocial.controllers.LoginPage.login
GET     /logout securesocial.controllers.LoginPage.logout
GET     /signup                     securesocial.controllers.Registration.startSignUp
...(この後たくさん)

今後は

->      /auth   securesocial.Routes

だけでOK。

モデル、UserService

IdentityIdとかIdentityがなくなってる。その代わり(?)にBasicProfileというのができてる。 BasicProfileはIdentityとほぼ同じなので、書き換えは必要だけど、難しい話じゃない。

views

2系では標準のテンプレートがあって、bootstrapなログイン画面とか提供されていたけど、 3系にしたところcssやjsがNotFoundになってしまった。 ただ、public/securesocial/javascsriptsとかpublic/securesocial/bootstrap/cssなどにファイルを置けば読み込んでくれるので、特に問題にはならないと思う。(普通は独自のテンプレート定義するはずだし)