securesocial
securesocial copied to clipboard
[3.0-M1] Examples needed for views overriding
I'm trying to supply new templates for the multiple views, without success. The biggest issue seems to be related to not available contexts and requests. I tried to write new ViewTemplates both in Java and Scala, but it didn't work. I could get a little bit further with Scala, but had the same issues as Java.
@jaliss, I think we all would appreciate some examples on that. Would it be possible to add some view customization to the demo app? Having both Java and Scala implementations of the ViewTemplates trait would be a big plus.
Sorry for asking that, instead of contributing, but be sure that I would, if I had any success.
@tavlima the views are supposed to be written in Scala. I have custom views working in a project. I have not tried to implement them in Java. The controllers using the views are based in Scala so I don't think writing them directly in Java will make them work.
Can you share a stack trace or more information of what's going on? A sample project showing this fail would be great.
I will try to view customization in the sample app so others can use as a guide. I will be with limited internet access the following days so I won't be able to tackle this right away.
@jaliss, sorry for the delay but, after a while, I managed to extend the ViewTemplates using Scala and could point to my own templates. It was a bit painful, as I'm not Scala fluent. The examples I asked for would be really helpful.
Were any examples posted ?
@jaliss examples for extending ViewTemplates to customise views (scala is fine) against 3.0-M4 would be really useful, as this seems to be difficult for a number of people. I've been working at this for a day or so, reviewing the posts in the SecureSocial google group and so far am unable to get compilation between the def overrides in my customised environment with custom view.scala.html code. Typical fails with either "ambigous implicit variable" compile time error, or "could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment" compile time error.
Hi sdk451,
Here are the basic steps to customize your templates:
- Create the views that you want to customize. You can copy the views from this folder : https://github.com/jaliss/securesocial/tree/3.0-M3/module-code/app/securesocial/views and modify them
- Create a class MyViewTemplates where you reference the pages you just created instead of referencing securesocial.views This file is based on : https://github.com/jaliss/securesocial/blob/3.0-M3/module-code/app/securesocial/controllers/ViewsPlugin.scala
Example:
class MyViewTemplates(env:RuntimeEnvironment[_]) extends ViewTemplates{
implicit val implicitEnv = env
override def getLoginPage(form: Form[(String, String)], msg:
Option[String])(implicit request: RequestHeader, lang: Lang): Html = {
* views.html.login(form, msg)(request, lang, env) // This is a new
page for example*
}
override def getSignUpPage(form: Form[RegistrationInfo], token:
String)(implicit request: RequestHeader, lang: Lang): Html = {
//securesocial.views.html.Registration.signUp(form, token)(request,
lang, env)
views.html.Registration.signUp(form, token)(request, lang, env)
}
override def getStartSignUpPage(form: Form[String])(implicit request:
RequestHeader, lang: Lang): Html = {
Logger.debug("Calling startSignUp page")
views.html.startSignUp(form)(request, lang, env)
//securesocial.views.html.Registration.startSignUp(form)(request,
lang, env)
}
override def getStartResetPasswordPage(form: Form[String])(implicit
request: RequestHeader, lang: Lang): Html = {
Logger.debug("Calling Custom getStartRestePasswordPage...")
views.html.Registration.startResetPassword(form)(request, lang, env)
//securesocial.views.html.Registration.startResetPassword(form)(request, lang, env)
}
override def getResetPasswordPage(form: Form[(String, String)],
token: String)(implicit request: RequestHeader, lang: Lang): Html = {
//securesocial.views.html.Registration.resetPasswordPage(form,
token)(request, lang, env)
views.html.Registration.resetPasswordPage(form, token)(request,
lang, env)
}
override def getPasswordChangePage(form: Form[ChangeInfo])(implicit
request: RequestHeader, lang: Lang): Html = {
views.html.Registration.passwordChange(form)(request, lang, env)
}
override def getNotAuthorizedPage(implicit request: RequestHeader,
lang: Lang): Html = {
securesocial.views.html.notAuthorized()(request, lang, env)
}
}
- In your Global.scala, add a reference to the new Template
object MyRuntimeEnvironment extends RuntimeEnvironment.Default[SwUser] {
override implicit val executionContext =
play.api.libs.concurrent.Execution.defaultContext
override lazy val routes = new CustomRoutesService()
override lazy val userService: SwUserService = new SwUserService()
override lazy val eventListeners = List(new UserEventListener())
*override lazy val viewTemplates: ViewTemplates = new
MyViewTemplates(this)*
...
}
Repeat the steps for MailTemplate :)
Hope this helps
Olivier
Olivier Droz Ing. Inf. Dipl. EPF Rte de la Feuillère 29 1010 Lausanne www.olivierdroz.ch
On Mon, May 23, 2016 at 7:40 AM, sdk451 [email protected] wrote:
@jaliss https://github.com/jaliss examples for extending ViewTemplates to customise views (scala is fine) against 3.0-M4 would be really useful, as this seems to be difficult for a number of people. I've been working at this for a day or so, reviewing the posts in the SecureSocial google group and so far am unable to get compilation between the def overrides in my customised environment with custom view.scala.html code. Typical fails with either "ambigous implicit variable" compile time error, or "could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment" compile time error.
— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub https://github.com/jaliss/securesocial/issues/464#issuecomment-220891419
Thanks for answering Olivier.
I was using securesocial-3.0-M4 which doesn't have a templated RuntimeEnvironment. I switched back to 3.0-M3, and closely followed your code snippets. Unfortunately I still get ambigous implicit values for the RequestHeader var.
My code (I am running java, except for this section which is in scala):
MyViewTemplates.scala:
package service;
import securesocial.controllers.{ChangeInfo, RegistrationInfo, MailTemplates, ViewTemplates} import securesocial.core.{ BasicProfile, RuntimeEnvironment } import play.api.mvc.{RequestHeader, Request} import play.twirl.api.{ Html, Txt } import play.api.data.Form import play.api.i18n.Lang //import play.api.Play.current
import views.html.custom.login
class MyViewTemplates(env: RuntimeEnvironment[_]) extends ViewTemplates.Default(env) { implicit val implicitEnv = env
override def getLoginPage(form: play.api.data.Form[(String, String)],
msg: Option[String])(implicit request: RequestHeader, lang: Lang): Html = { views.html.custom.login(form, msg)(request, lang, env) } }
MyEnvironment.scala:
package service
//import javax.inject._ import com.google.inject.Inject import securesocial.core.RuntimeEnvironment import securesocial.core.services.UserService
import securesocial.controllers.{MailTemplates, ViewTemplates} import securesocial.core.authenticator._ import securesocial.core.providers._ import securesocial.core.providers.utils.{Mailer, PasswordHasher, PasswordValidator} import securesocial.core.services._
import scala.collection.immutable.ListMap
class MyEnvironment @Inject() extends RuntimeEnvironment.Default[UserCredential] { override implicit val executionContext = play.api.libs.concurrent.Execution.defaultContext
type U = UserCredential
override val userService: UserService[U] = new MyUserService()
// override lazy val routes = new CustomRoutesService()
override lazy val viewTemplates = new MyViewTemplates(this)
override lazy val providers = ListMap(include(new
UsernamePasswordProvider[U](userService, avatarService, viewTemplates, passwordHashers)))
}
// UserCredential is my implementation of DemoUser
Global.java:
import securesocial.core.RuntimeEnvironment; import service.MyEnvironment;
public class Global extends GlobalSettings {
@Singleton
public static RuntimeEnvironment env = new MyEnvironment();
/// bunch of other stuff not relevant to secure social setup
}
and here is the custom login.scala.html which is a direct copy of the login view from securesocial 3.0-M3. I have created a custom folder in my views.html package - it has minor tweaks to the @ inputs - request needs to be play.api.mvc.RequestHeader - probably because the Play java and scala apis are packaged differently (scala - play.api., java - play.)
\custom\login.scala.html:
@(loginForm: play.api.data.Form[(String,String)], errorMsg: Option[String] = None)(implicit request: play.api.mvc.RequestHeader, lang: play.api.i18n.Lang, env:securesocial.core.RuntimeEnvironment[_])
@import securesocial.core.providers.UsernamePasswordProvider.UsernamePassword
@securesocial.views.html.main(Messages("securesocial.login.title")) {
@Messages("securesocial.login.title")
@errorMsg.map { msg =>
<div class="alert alert-error">
@Messages(msg)
</div>
}
@request.flash.get("success").map { msg =>
<div class="alert alert-info">
@msg
</div>
}
@request.flash.get("error").map { msg =>
<div class="alert alert-error">
@msg
</div>
}
@defining( env.providers.values.filter( _.id != UsernamePassword) ) { externalProviders =>
@if( externalProviders.size > 0 ) {
<div class="clearfix">
<p>@Messages("securesocial.login.instructions")</p>
<p>
@for(p <- externalProviders) {
@securesocial.views.html.provider(p.id)
}
</p>
</div>
}
@env.providers.get(UsernamePassword).map { up =>
<div class="clearfix">
@if( externalProviders.size > 0 ) {
@Messages("securesocial.login.useEmailAndPassword")
} else {
@Messages("securesocial.login.useEmailAndPasswordOnly")
}
@securesocial.views.html.provider("userpass",
Some(loginForm)) } } }
Not sure if the imports are causing something odd in the implicit scope (could conceiveably be different between scala and java)
finally the compiler error is:
- read from stdout: ...\app\views\custom\login.scala.html:38: ambiguous implicit values:
- Read from stdout: both method requestHeader in object PlayMagicForJava of type => play.api.mvc.RequestHeader
- Read from stdout: and value request of type play.api.mvc.RequestHeader
- Read from stdout: match expected type play.api.mvc.RequestHeader
- ....app\views\custom\login.scala.html:38: ambiguous implicit values: both method requestHeader in object PlayMagicForJava of type => play.api.mvc.RequestHeader and value request of type play.api.mvc.RequestHeader match expected type play.api.mvc.RequestHeader
- Read from stdout:
- Read from stdout: ^
On Mon, May 23, 2016 at 4:54 PM, Olivier Dorz [email protected] wrote:
Hi sdk451,
Here are the basic steps to customize your templates:
- Create the views that you want to customize. You can copy the views from this folder :
https://github.com/jaliss/securesocial/tree/3.0-M3/module-code/app/securesocial/views and modify them
- Create a class MyViewTemplates where you reference the pages you just created instead of referencing securesocial.views This file is based on :
https://github.com/jaliss/securesocial/blob/3.0-M3/module-code/app/securesocial/controllers/ViewsPlugin.scala
Example:
class MyViewTemplates(env:RuntimeEnvironment[_]) extends ViewTemplates{
implicit val implicitEnv = env
override def getLoginPage(form: Form[(String, String)], msg: Option[String])(implicit request: RequestHeader, lang: Lang): Html = {
- views.html.login(form, msg)(request, lang, env) // This is a new page for example*
}
override def getSignUpPage(form: Form[RegistrationInfo], token: String)(implicit request: RequestHeader, lang: Lang): Html = {
//securesocial.views.html.Registration.signUp(form, token)(request, lang, env)
views.html.Registration.signUp(form, token)(request, lang, env)
}
override def getStartSignUpPage(form: Form[String])(implicit request: RequestHeader, lang: Lang): Html = {
Logger.debug("Calling startSignUp page")
views.html.startSignUp(form)(request, lang, env)
//securesocial.views.html.Registration.startSignUp(form)(request, lang, env)
}
override def getStartResetPasswordPage(form: Form[String])(implicit request: RequestHeader, lang: Lang): Html = {
Logger.debug("Calling Custom getStartRestePasswordPage...")
views.html.Registration.startResetPassword(form)(request, lang, env)
//securesocial.views.html.Registration.startResetPassword(form)(request, lang, env)
}
override def getResetPasswordPage(form: Form[(String, String)], token: String)(implicit request: RequestHeader, lang: Lang): Html = {
//securesocial.views.html.Registration.resetPasswordPage(form, token)(request, lang, env)
views.html.Registration.resetPasswordPage(form, token)(request, lang, env)
}
override def getPasswordChangePage(form: Form[ChangeInfo])(implicit request: RequestHeader, lang: Lang): Html = {
views.html.Registration.passwordChange(form)(request, lang, env)
}
override def getNotAuthorizedPage(implicit request: RequestHeader, lang: Lang): Html = {
securesocial.views.html.notAuthorized()(request, lang, env)
}
}
- In your Global.scala, add a reference to the new Template
object MyRuntimeEnvironment extends RuntimeEnvironment.Default[SwUser] {
override implicit val executionContext = play.api.libs.concurrent.Execution.defaultContext
override lazy val routes = new CustomRoutesService()
override lazy val userService: SwUserService = new SwUserService()
override lazy val eventListeners = List(new UserEventListener())
override lazy val viewTemplates: ViewTemplates = new MyViewTemplates(this)
...
}
Repeat the steps for MailTemplate :)
Hope this helps
Olivier
Olivier Droz Ing. Inf. Dipl. EPF Rte de la Feuillère 29 1010 Lausanne www.olivierdroz.ch
On Mon, May 23, 2016 at 7:40 AM, sdk451 [email protected] wrote:
@jaliss https://github.com/jaliss examples for extending ViewTemplates to customise views (scala is fine) against 3.0-M4 would be really useful, as this seems to be difficult for a number of people. I've been working at this for a day or so, reviewing the posts in the SecureSocial google group and so far am unable to get compilation between the def overrides in my customised environment with custom view.scala.html code. Typical fails with either "ambigous implicit variable" compile time error, or "could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment" compile time error.
— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub < https://github.com/jaliss/securesocial/issues/464#issuecomment-220891419>
— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/jaliss/securesocial/issues/464#issuecomment-220900708
Looks like more an ambiguous reference to a requestHeader that is also in PlayMagicForJava. I never used PlayMagicForJava. Do you really need that?
Olivier Droz Ing. Inf. Dipl. EPF Rte de la Feuillère 29 1010 Lausanne www.olivierdroz.ch
On Tue, May 24, 2016 at 5:16 AM, sdk451 [email protected] wrote:
Thanks for answering Olivier.
I was using securesocial-3.0-M4 which doesn't have a templated RuntimeEnvironment. I switched back to 3.0-M3, and closely followed your code snippets. Unfortunately I still get ambigous implicit values for the RequestHeader var.
My code (I am running java, except for this section which is in scala):
MyViewTemplates.scala:
package service;
import securesocial.controllers.{ChangeInfo, RegistrationInfo, MailTemplates, ViewTemplates} import securesocial.core.{ BasicProfile, RuntimeEnvironment } import play.api.mvc.{RequestHeader, Request} import play.twirl.api.{ Html, Txt } import play.api.data.Form import play.api.i18n.Lang //import play.api.Play.current
import views.html.custom.login
class MyViewTemplates(env: RuntimeEnvironment[_]) extends ViewTemplates.Default(env) { implicit val implicitEnv = env
override def getLoginPage(form: play.api.data.Form[(String, String)], msg: Option[String])(implicit request: RequestHeader, lang: Lang): Html = { views.html.custom.login(form, msg)(request, lang, env) } }
MyEnvironment.scala:
package service
//import javax.inject._ import com.google.inject.Inject import securesocial.core.RuntimeEnvironment import securesocial.core.services.UserService
import securesocial.controllers.{MailTemplates, ViewTemplates} import securesocial.core.authenticator._ import securesocial.core.providers._ import securesocial.core.providers.utils.{Mailer, PasswordHasher, PasswordValidator} import securesocial.core.services._
import scala.collection.immutable.ListMap
class MyEnvironment @Inject() extends RuntimeEnvironment.Default[UserCredential] { override implicit val executionContext = play.api.libs.concurrent.Execution.defaultContext
type U = UserCredential
override val userService: UserService[U] = new MyUserService()
// override lazy val routes = new CustomRoutesService()
override lazy val viewTemplates = new MyViewTemplates(this)
override lazy val providers = ListMap(include(new UsernamePasswordProvider[U](userService, avatarService, viewTemplates, passwordHashers)))
}
// UserCredential is my implementation of DemoUser
Global.java:
import securesocial.core.RuntimeEnvironment; import service.MyEnvironment;
public class Global extends GlobalSettings {
@Singleton public static RuntimeEnvironment env = new MyEnvironment();
/// bunch of other stuff not relevant to secure social setup
}
and here is the custom login.scala.html which is a direct copy of the login view from securesocial 3.0-M3. I have created a custom folder in my views.html package - it has minor tweaks to the @ inputs - request needs to be play.api.mvc.RequestHeader - probably because the Play java and scala apis are packaged differently (scala - play.api., java - play.)
\custom\login.scala.html:
@(loginForm: play.api.data.Form[(String,String)], errorMsg: Option[String] = None)(implicit request: play.api.mvc.RequestHeader, lang: play.api.i18n.Lang, env:securesocial.core.RuntimeEnvironment[_])
@import securesocial.core.providers.UsernamePasswordProvider.UsernamePassword
@securesocial.views.html.main(Messages("securesocial.login.title")) {
@Messages("securesocial.login.title")
@errorMsg.map { msg =>
@Messages(msg)}
@request.flash.get("success").map { msg =>
@msg}
@request.flash.get("error").map { msg =>
@msg}
@defining( env.providers.values.filter( _.id != UsernamePassword) ) { externalProviders =>
@if( externalProviders.size > 0 ) {
@Messages("securesocial.login.instructions")
@for(p
}
@env.providers.get(UsernamePassword).map { up =>
@if( externalProviders.size > 0 ) {@Messages("securesocial.login.useEmailAndPassword")
} else {@Messages("securesocial.login.useEmailAndPasswordOnly")
} @securesocial.views.html.provider("userpass", Some(loginForm))} } }
Not sure if the imports are causing something odd in the implicit scope (could conceiveably be different between scala and java)
finally the compiler error is:
- read from stdout: ...\app\views\custom\login.scala.html:38: ambiguous implicit values:
- Read from stdout: both method requestHeader in object PlayMagicForJava of type => play.api.mvc.RequestHeader
- Read from stdout: and value request of type play.api.mvc.RequestHeader
- Read from stdout: match expected type play.api.mvc.RequestHeader
- ....app\views\custom\login.scala.html:38: ambiguous implicit values: both method requestHeader in object PlayMagicForJava of type => play.api.mvc.RequestHeader and value request of type play.api.mvc.RequestHeader match expected type play.api.mvc.RequestHeader
- Read from stdout:
- Read from stdout: ^
On Mon, May 23, 2016 at 4:54 PM, Olivier Dorz [email protected] wrote:
Hi sdk451,
Here are the basic steps to customize your templates:
- Create the views that you want to customize. You can copy the views from this folder :
https://github.com/jaliss/securesocial/tree/3.0-M3/module-code/app/securesocial/views and modify them
- Create a class MyViewTemplates where you reference the pages you just created instead of referencing securesocial.views This file is based on :
https://github.com/jaliss/securesocial/blob/3.0-M3/module-code/app/securesocial/controllers/ViewsPlugin.scala
Example:
class MyViewTemplates(env:RuntimeEnvironment[_]) extends ViewTemplates{
implicit val implicitEnv = env
override def getLoginPage(form: Form[(String, String)], msg: Option[String])(implicit request: RequestHeader, lang: Lang): Html = {
- views.html.login(form, msg)(request, lang, env) // This is a new page for example*
}
override def getSignUpPage(form: Form[RegistrationInfo], token: String)(implicit request: RequestHeader, lang: Lang): Html = {
//securesocial.views.html.Registration.signUp(form, token)(request, lang, env)
views.html.Registration.signUp(form, token)(request, lang, env)
}
override def getStartSignUpPage(form: Form[String])(implicit request: RequestHeader, lang: Lang): Html = {
Logger.debug("Calling startSignUp page")
views.html.startSignUp(form)(request, lang, env)
//securesocial.views.html.Registration.startSignUp(form)(request, lang, env)
}
override def getStartResetPasswordPage(form: Form[String])(implicit request: RequestHeader, lang: Lang): Html = {
Logger.debug("Calling Custom getStartRestePasswordPage...")
views.html.Registration.startResetPassword(form)(request, lang, env)
//securesocial.views.html.Registration.startResetPassword(form)(request, lang, env)
}
override def getResetPasswordPage(form: Form[(String, String)], token: String)(implicit request: RequestHeader, lang: Lang): Html = {
//securesocial.views.html.Registration.resetPasswordPage(form, token)(request, lang, env)
views.html.Registration.resetPasswordPage(form, token)(request, lang, env)
}
override def getPasswordChangePage(form: Form[ChangeInfo])(implicit request: RequestHeader, lang: Lang): Html = {
views.html.Registration.passwordChange(form)(request, lang, env)
}
override def getNotAuthorizedPage(implicit request: RequestHeader, lang: Lang): Html = {
securesocial.views.html.notAuthorized()(request, lang, env)
}
}
- In your Global.scala, add a reference to the new Template
object MyRuntimeEnvironment extends RuntimeEnvironment.Default[SwUser] {
override implicit val executionContext = play.api.libs.concurrent.Execution.defaultContext
override lazy val routes = new CustomRoutesService()
override lazy val userService: SwUserService = new SwUserService()
override lazy val eventListeners = List(new UserEventListener())
override lazy val viewTemplates: ViewTemplates = new MyViewTemplates(this)
...
}
Repeat the steps for MailTemplate :)
Hope this helps
Olivier
Olivier Droz Ing. Inf. Dipl. EPF Rte de la Feuillère 29 1010 Lausanne www.olivierdroz.ch
On Mon, May 23, 2016 at 7:40 AM, sdk451 [email protected] wrote:
@jaliss https://github.com/jaliss examples for extending ViewTemplates to customise views (scala is fine) against 3.0-M4 would be really useful, as this seems to be difficult for a number of people. I've been working at this for a day or so, reviewing the posts in the SecureSocial google group and so far am unable to get compilation between the def overrides in my customised environment with custom view.scala.html code. Typical fails with either "ambigous implicit variable" compile time error, or "could not find implicit value for parameter env: securesocial.core.RuntimeEnvironment" compile time error.
— You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub < https://github.com/jaliss/securesocial/issues/464#issuecomment-220891419
— You are receiving this because you commented. Reply to this email directly or view it on GitHub < https://github.com/jaliss/securesocial/issues/464#issuecomment-220900708>
— You are receiving this because you commented. Reply to this email directly or view it on GitHub https://github.com/jaliss/securesocial/issues/464#issuecomment-221156065
PlayMagicForJava is brought in by default by the Play framework if you are using Java to help with the Twirl templating (in scala). One of the subtle play framework differences for java users.
I finally figured out that the compile issues weren't with my ViewTemplates subclass or the overriden methods in it (had to ensure the method signatures were aligned correctly with ViewTemplates.Default), but actually the implicit scope vars being passed through my custom login.scala.html template into the main.scala.html and provider,scala.html sub templates within my login.scala.html. (Still pretty weak on the scala side of Play!) Basically the request and lang implicit vars are also provided by the playframework to any view template, so the compiler couldn't decide which of the ones passed in from MyViewTemplates or the framework to pass to main or provider.
I will post up my final play 2.4.2 for java solution (on the secure social google group) when I've finished and tested it, so others can see a complete working example.
Thanks for looking this, I appreciate the help.
May have spoken too early. So far - I can get custom views working for java with v3.0-M3 (including re-using securesocial view templates like provider and main) but this version has a dependency injection runtime error that I haven't been able to fix. v3.0-M4 java templating doesn't appear to work if you want to reuse existing securesocial templates like provider or main, as these require an implicit play.api.i18n.Messages object as an input which conflicts with the Java play.i18n.Messages implictMessages variable passed into templates by PlayMagicForJava. It can't be made explicit (as then the method signature in the ViewTemplates subclass conflicts with the superclass, causing a compile error). Can't see an obvious way to get customised views working for v3.0-M4 for Java developers. Happy to be directed to someone using Java who has this going...