Using Flashing and Implicit Message at the same time - scala

I already have implicit message to be returned to the template but want to add flashing only if it fails to the login test.
Below is the code from my controller:
Action.async { request =>
....
if(not a valid id or password)
Redirect(routes.Admn.login).flashing("error" -> "Invalid Username or Password")
}
And this is from my template scala.html:
#(data: Form[MyForm])(implicit message: MessagesRequestHeader)
<body>
//user name input text
//user password input password
#flash.get("Invalid Username or Password")
</body>
this brings value not found flash error. it still doesnt work after adding #()(implicit flash:Flash). Any one have a good idea to make this code work?

#(data: Form[MyForm])(implicit message: MessagesRequestHeader, flash: Flash)
in my template worked.
Initially, thought that I am not allowed to add 2 params(?) in (implicit ~~ )

Related

Flask Error: “Method Not Allowed The method is not allowed for the requested URL” (Login and Home Page)

#app.route("/")
#app.route("/home",methods=['GET', 'POST'])
def home():
if current_user.is_authenticated:
posts=mongo.db.articles
#allpost=posts.find().limit(5)
it=current_user.user_json['interest']
allpost=posts.find( {'NewsType': it } ).limit(10)
#flash(session['email'])
return render_template('home.html', posts=allpost)
return render_template('login.html', title='Login',form=LoginForm())
This is my code for the Home Page
#app.route("/login", methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = LoginForm()
if form.validate_on_submit():
users = mongo.db.users
loginuser_json = users.find_one({'email': form.email.data})
if loginuser_json and bcrypt.check_password_hash(loginuser_json['password'], form.password.data):
# Create a custom user and pass it to login_user:
loginuser = User(loginuser_json)
login_user(loginuser,duration=d)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('home'))
return redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check username and password', 'danger')
return render_template('login.html', title='Login', form=form)
and this for the login route
When i write localhost:5000 in the browser it opens Login Page (because if user is not authenticated it should go to login page first)
But when i try to login from this page , it is giving an error "Method Not Allowed.The method is not allowed for the requested URL."
What should i do
In your code, it is not clear which code is called when the method is GET (usually when rendering your login page) and which is to be called when method is POST (called when you are submitting your form). To remove the mix up, do like this in your login
#app.route("/login", methods=['GET', 'POST'])
def login():
# code that runs for both GET and POST goes here
if request.method == 'POST':
if form.validate_on_submit():
#authenticate user and redirect to next page/home page
return render_template('login.html', title='Login', form=form) #this runs when method is get
Note the indentation and the respective code running under it
NOTE on your login template ensure the form method is post something like this
<form method=post>
<dl>
{{ render_field(form.email) }}
{{ render_field(form.password) }}
{{form.hidden_tag()}}
</dl>
<input type=submit value=Submit>
</form>
Lastly, on you home page, you have two routes that form the url_for(home) - though I do not think this is where your error is coming from - ensure both of them accept the method POST if you intend to use it there
#app.route("/",methods=['GET', 'POST'])#add post on this route
#app.route("/home",methods=['GET', 'POST'])
def home():
Hope this helps you sort out the error

Cucumber is not able to separate two different string from data table

Description: Login Window contains 3 main objects "username"(textbox) , "password"(textbox) and "login"(button)
Observation: when running test, in username text box it is entering testtest(i.e. entering value of password in the same editbox)
Could you please help me with this issue as it is breaking basic functionality and it is a blocker for me to automate?
Feature file:
#login
Feature: Login
Scenario Outline: Login
Given I launch url
Then I enter <username>
Then I enter password <password>
Then I click on login button
Then I verify login screen
Then I click on logOut
Examples:
| username | password |
| test | test |
StepDefinition
Given(/^I launch webapp url$/, function () {
return browser.get('https://example.com');
});
Then(/^I enter (.*)$/, function (username) {
const Login = new loginPage();
return Login.enterUserName(username);
});
Then(/^I enter password (password)$/, function (password) {
const Login = new loginPage();
return Login.enterPassword(password);
console.log('pass');
});
The issue obviously comes from your code. First, please check you not use same element variable in function enterUserName() and enterPassword.
Second, check the locator for finding username and password won't find same element on page.
Third, A issue in your code: Then(/^I enter password (password)$/, function (password) {
It should be Then(/^I enter password (.*)$/, function (password) {

Play Framework 2.6 CSRF and Session

I got strange issue. I'm implementing cart functionality on my website and I use session to store cart positions. I have a POST action to add new position to cart, and I have CSRF filter enabled to secure website. I call it with ajax on a product page, so first call is okay, but second says Unauthorized and in logs there are [CSRF] Check failed because no token found in headers for /cart. But it has. I call it with:
$("form").submit(function(e){
e.preventDefault();
$.ajax({
url: '/cart',
method: 'POST',
data: getCartPosition(),
beforeSend: function(xhr){xhr.setRequestHeader('Csrf-Token', $('input[name=csrfToken]').val());},
success: function (data, textStatus) {
alert('Added!');
},
error: function (error) {
alert('Error!');
}
});
});
and I put CSRF token in template somewhere:
#CSRF.formField
and it's in request:
I have enabled this in config
play.filters.csrf.bypassCorsTrustedOrigins=true
play.filters.hosts {
# Allow requests to example.com, its subdomains, and localhost:9000
allowed = ["localhost:9000", "localhost:4200"]
}
But what is strange that it seems it puts csrfToken in session, because after failed request I have session like this
Session(Map(cart -> {"positions":
[{"trackId":1},{"trackId":24},{"trackId":20}]},
username -> user,
token -> 0639d0b0-e7c8-4e82-9aad-2a43044e72db,
csrfToken -> e705413843ea96a6491a0e9e800ba36a712c4f70-1506542471068-0baeef7535eb9c889fb6fed2))
Idk why it's there, my add2cart action looks like:
private def cartAction(addToCartForm: Form[CartPosition], action: (Cart, CartPosition) => Cart)(implicit request: UserRequest[Any]) = {
addToCartForm.fold(
_ => BadRequest("Error!"),
position => {
getCart match {
case Some(cart) => Ok("Ok").withSession("cart" -> Json.toJson(action(cart, position)).toString(), "username" -> request.session.get("username").getOrElse(""), "token" -> request.session.get("token").getOrElse(""))
case _ => Ok("Ok, no").withSession("cart" -> Json.toJson(action(Cart(Seq.empty), position)).toString())
}
}
)
}
def addToCart() = guestAction { implicit request =>
cartAction(addToCartForm.bindFromRequest, addCartPos)
}
and addCartPos just adds position to json
I've got same issue with Play 2.7.3.
In my case, the form is generated by the Twirl with the csrf token and because I'm using ajax to submit the form, I've copied the csrf token from the rendered form and pass it to the ajax header as writen in the Play's documentation.
The form can be submitted multiple times so I need to updated the token. Therefore I'm passing through ajax response new csrf token taken in the controller from play.filters.csrf.CSRF.getToken.get.value.
But unfortunatelly, the second submission failed as cutoffurmind mentioned.
And the fix is as described by Knut Arne Vedaa to add new token to the session. I did it by the withSession method.
So the controller response is looking like this:
Ok(Json.obj(
"status" -> (user != None),
"notif" -> "Success login",
"data" -> Map(
"adminUrl" -> "www.something ...",
"csrf" -> play.filters.csrf.CSRF.getToken.get.value
)
)).withSession(
"uid" -> user.getOrElse(User()).id.toString,
"csrfToken" -> play.filters.csrf.CSRF.getToken.get.value
)
It doesn't look like an issue as Play Framework doesn't have session data kept on the server, so it is logical that the token has to be updated in the client site after the ajax request. The main issue is that it is not mentioned in the documentation (in the CSRF ajax section), what could be handy as people simply doesn't read the doc from A to Z in expected order.
In my case the solution was to set the play.filters.csrf.cookie.name config option to a value other than null:
play.filters.csrf.cookie.name = csrf_token

send an email using a template - grails

I want to send an email using a template. I want to have a GSP file where i could style it, and send the email. Currently the send mail function is as follows:
def sendEmail(){
mailService.sendMail {
to "email","**email**"
from "email"
subject "Hi"
body 'Hi'
}
}
in my config.groovy file
grails {
mail {
host = "smtp.gmail.com"
port = 465
username = "email"
password = "pwd"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}
}
I went through another Stack Overflow post on this: Where should i add the mail templates ? is it in the views folder ?
sendMail{
multipart true
to "[hidden email]"
subject "Subject goes here"
html g.render( template: '/emails/mailTemplate')
inline 'springsourceInlineImage', 'image/jpg', new File('./web-app/images/springsource.png')
}
UPDATE
I TREID ADDING A mailTemplate.gsp UNDER EMAILS/ BUT IT DIDNT WORK.
ERROR I GOT Template not found for name [/emails/mailTemplate] and path [/emails/_mailTemplate.gsp]
You can use groovyPageRenderer.render() to parse your email. Below, an example:
class MailingService {
def groovyPageRenderer
def mailService
def yourFunction(User user) {
def content = groovyPageRenderer.render(view: '/mails/myTemplate')
mailService.sendMail {
to user.email
from "email#test.com"
subject "MySubject"
html(content)
}
}
}
In this case, the template is here: /views/mails/MyTemplateFile.gsp
Hope this helps.
Edit:
And the render could be used with a model. Example:
groovyPageRenderer.render(view:'/mails/myTemplate',model:[user:user])
Edit2:
I forgot to add the mailService in my first reply
well, you can try this code...
mailService.sendMail {
to user.email
from "email#test.com"
subject "MySubject"
body(view:'/emails/mailTemplate', model: [a:A])
}
here mailTemplate.gsp is in view/emails. In body of mail service you can use render syntax.
then add '<%# page contentType="text/html" %>' in top of mailTemplate.gsp
Well looking at your code, everything looks good enough.
html g.render(template : '/path/to/template')
should render your template and it will become the body of your mail message.
Have you made sure that you made your template as _template. Since all the gsp's that start with (_) are only considered as a template.
You should also make all the styling(css) inline so that it gets rendered without errors in all mail providers.

"Verifying" method for a form doesn't make an error show up

I have a standard, straightforward code for authenticating an user:
# controller
val addForm = Form(
tuple("email" -> nonEmptyText, "password" -> nonEmptyText)
.verifying("Invalid email or password", result => User.authenticate(result._1, result._2).isRight)
)
def add = Action { Ok(views.html.session.add(addForm)) }
def create = Action {
addForm.bindFromRequest.fold(
failure => BadRequest(views.html.session.add(failure)),
success => Redirect(routes.Home.index)
.flashing("key1" -> "You have logged in.")
)
}
I expected it to show me an error if NOT User.authenticate(result._1, result._2).isRight but there is no error showing up. Yes, authentication works well but there are no errors when it fails.
#helper.form(action = routes.Session.create()) {
#helper.inputText(form("email"))
#helper.inputText(form("password"))
<!-- ........... -->
}
Why?
Do you have a check in your view along the lines of
#if(addForm.hasErrors) { ... }
For example, a basic layout might be:
#if(addForm.hasErrors) {
<div class="alert-message error">
<p>Please correct the following:</p>
<ul>
#addForm.errors.map { error =>
<li>#error.key #error.message</li>
}
</ul>
</div>
}
You dont have key in form to display this error, thats why error is not showing up
Try this in failure case for nonEmptytTxt validation, email and your custom validation
BadRequest(views.html.sesion.add(failure.withError("password","Invalid email or password")))