Deadbolt 2 Restrict function has only one possible failure code - scala

This question may have a bit of philosophical aspect to it.
I have been using Deadbolt 2 (Scala) in my Play application and it works quite well.
In looking at the Restrict function definition (line 47) I noticed that it will invoke the onAuthFailure for one of the following reasons:
No user in session (no subject)
Action specified no roles.
User attempted an action for which they did not possess one or more required roles.
In my application UI, I would like to receive a different status code for each of these so that a user that is not logged in (condition 1) will be redirected to login page but condition 3 would be more gracefully handled by just a warning (since they can do no harm anyway and might have accidentally tried to edit when they have 'read-only' access - perhaps a UI bug, but logging in again is a bit draconian).
If I had to settle for just 2 status codes, however, I would want to differentiate between 1 and the other 2. I can see how this could be accomplished but would like to get other opinions on the merits of even doing this.
If I were to implement this change, it looks like I could just override the Restrict function in my own extension of the DeadboltActions trait.
I'm a little new to scala, so I'm open to additional ideas on how to best accomplish these goals.

I decided to just add the code to differentiate between condition 1 and either 2 or 3 as follows:
In MyDeadboltHandler:
class MyDeadboltHandler(dynamicResourceHandler: Option[DynamicResourceHandler] = None) extends DeadboltHandler {
...
def onAuthFailure[A](request: Request[A]): Result = {
Logger.error("authentication failure")
val json = new JsonStatus("Failed to authenticate", -1).toJson.toString
if(noUserInSession(request)){
Results.Forbidden(json).withHeaders("Access-Control-Allow-Origin" -> "*")
}
else{
Results.Unauthorized (json).withHeaders("Access-Control-Allow-Origin" -> "*")
}
}
def noUserInSession(request:RequestHeader) = {
username(request) match {
case Some(u:String) => false
case _ => true
}
}
This works well for me and does not impose upon the basic Deadbolt-2 functionality.

Related

Repopulating form fields in Play Framework

Using the Play Framework (2.6) documentation; I am attempting to handle form submission. But I'm running into an issue in repopulating the form fields - which is what I want to do if it has errors (so users can edit their entry rather than having to re-enter).
newForm.bindFromRequest.fold(
errorForm => {
BadRequest(views.html.form(errorForm))
},
formData => {
val oWriteJso = Json.toJsObject(formData) match {
case x if(x.fields.nonEmpty) => getCreatedFieldValues(x)
case _ => None
}
val oRes = Redirect(routes.Application.index).flashing("success" -> "Entry saved!")
apiC.writeAndRedirect("c", collName, None, oWriteJso)(oRes)(request)
}
)
My issue is that the example in the documentation only shows how to pass errorForm directly to a form template (e.g. views.html.form) rather than being able to render the whole page again (i.e. using views.html.index or a Redirect) with the input form fields being populated from the previous request. I found this answer as the closest to this issue but it is a little old and I am using Scala so wasn't able to implement it. Just have no idea how anyone else is doing this or what the sensible, standard approach is. Thanks for any light on this_
If you use the Play helper functions for generating input tags in your view file. They should populate with your values from the last request.
For example you can create an HTML form in your view file using helper methods like this:
#helper.form(action = routes.Application.userPost()) {
#helper.inputText(userForm("name"))
#helper.inputText(userForm("age"))
}
You can take a look at Play documentation about helpers in view files at the following link:
https://www.playframework.com/documentation/2.7.x/ScalaForms#Showing-forms-in-a-view-template

Taking webpage screenshot on completion of a Cucumber Step Definition

I'm currently researching a way in which I can implement a screen capture method in my acceptance test suite in Scala Cucumber after each step definition is completed in the scenario.
I have already implemented a method that will take a screenshot of a webpage if one of the automation test fails by invoking the method in the after hooks class. This does work fine but this will only capture the web page once the entire scenario has been completed.
I wasn't sure if there was something like before and after hooks that could be applied to the steps instead of the scenario.
Hooks.scala
#After
def tearDown(result: Scenario){
if (result.isFailed) {
ifCurrentDriverTakesSnapshot {
takesSnapshot =>
Snapshotter.takeErrorSnapshot(takesSnapshot, result)
}
}
Snapshotter.Scala
def takeErrorSnapshot(takesScreenshot: TakesScreenshot, result: Scenario)
= {
try {
val screenshot = takesScreenshot.getScreenshotAs(OutputType.BYTES)
result.embed(screenshot, "image/png")
}
catch {
case e: WebDriverException =>
e.printStackTrace(System.err)
}
}
I would like to be able to do this in a class or method that can be called after each new page is opened or after each step definition. I could right a step definition that would handle the screen capture but I would like to do in a better way as I have 100's of test scenarios so it would be better to avoid adding a step for this in between every step definition as they have done in the below link.
Cucumber Java screenshots
If anyone could share some light on the matter i'd greatly appreciate it as I'm struggling to find much on the subject.
Thanks!!!

Switching a DbContext to using Ninject Dependency injection per user session

I have an application that is used in 2 different sites. Each site has it's own Database.
There are 2 DbContexts, 1 for each site. When the user opens my application there is a splash page where they choose their site. After choosing the site the kernel is rebound to use the DbContext for the selected site.
private void RebindDbContext(string site)
{
switch (site)
{
case "Site1":
_kernel.Rebind<DbContext>().To<DbContext1>().InRequestScope();
break;
case "Site2":
_kernel.Rebind<DbContext>().To<DbContext2>().InRequestScope();
break;
}
}
Now for the Bob & Mary explanation:
This works fine when Bob selects site 1. But when Mary selects a site 2. The dbContext for Bob is re-bound to site 2. What I want is for Bob and Mary to be able to use the application at the same time without affecting each other.
I have tried using TransientScope, ThreadScope and InRequest Scope but none of these have worked.
The application is being run on an IIS server
Thanks for any help
Bindings are intended to be done once per application, not dependent upon state. In this instance, you have a couple options:
1) A Ninject.Activation.IProvider
public class DbContextProvider : Ninject.Activation.IProvider
{
public Type Type
{
get { return typeof(DbContext); }
}
public object Create(IContext context)
{
var siteProvider = context.Kernel.Get<ISiteProvider>(); // use a provider to find which site is being used
switch (siteProvider.Current)
{
case "Site1":
return new DbContext1(); // or use a factory to create
case "Site2":
return new DbContext2();
}
}
}
then:
Bind<DbContext>().ToProvider<DbContextProvider>().InRequestScope();
2) Conditional Binding
The When() modifier has a bunch of overloads for different states, or you could create an extension method if you have one type you use a lot.
Bind<DbContext>().To<DbContext1>()
.When(request => request.ParentContext.Kernel.Get<ISiteProvider>().Current == "Site1")
.InRequestScope();
Bind<DbContext>().To<DbContext2>()
.When(request => request.ParentContext.Kernel.Get<ISiteProvider>().Current == "Site2")
.InRequestScope();
This is a good option if you only have a few conditions that this binding may be applied. If your logic gets ANY more complex than this, go for the provider. Also note that Conditional Bindings incur a performance penalty.
3) A ToMethod() Binding
For the simplest binding logic, you can have Ninject run some code each time the binding is resolved:
Bind<DbContext>().ToMethod(context =>
context.Kernel.Get<ISiteProvider>().GetSite());
Basically, which option you select depends on how much logic is involved in deciding which instance to activate. In each instance, you can either new() up an instance, or you have access to the IKernel in which you can resolve an instance:
context.Kernel.Get<DbContext2>();
here's some official documentation of the activation process:
https://github.com/ninject/Ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context

Celery - error handling and data storage

I'm trying to better understand common strategies regarding results and errors in Celery.
I see that results have statuses/states and stores results if requested -- when would I use this data? Should error handling and data storage be contained within the task?
Here is a sample scenario, in case it helps better understand my objective:
I have a geocoding task that goeocodes user addresses. If the task fails or succeeds, I'd like to update a field in the database letting the user know. (Error handling) On success I'd like the geocoded data to be inserted into the database (Data storage)
What approach should take?
Let me preface this by saying that I'm still getting a feel for Celery myself. That being said, I have some general inclinations about how I'd go about tackling this, and since no one else has responded, I'll give it a shot.
Based on what you've written, a relatively simple (though I suspect non-optimized) solution is to follow the broad contours of the blog comment spam task example from the documentation.
app.models.py
class Address(models.Model):
GEOCODE_STATUS_CHOICES = (
('pr', 'pre-check'),
('su', 'success'),
('fl', 'failed'),
)
address = models.TextField()
...
geocode = models.TextField()
geocode_status = models.CharField(max_length=2,
choices=GEOCODE_STATUS_CHOICES,
default='pr')
class AppUser(models.Model):
name = models.CharField(max_length=100)
...
address = models.ForeignKey(Address)
app.tasks.py
from celery import task
from app.models import Address, AppUser
from some_module import geocode_function #assuming this returns a string
#task()
def get_geocode(appuser_pk):
user = AppUser.objects.get(pk=appuser_pk)
address = user.address
try:
result = geocode_function(address.address)
address.geocode = result
address.geocode_status = 'su' #set address object as successful
address.save()
return address.geocode #this is optional -- your task doesn't have to return anything
on the other hand, you could also choose to decouple the geo-
code function from the database update for the object instance.
Also, if you're thinking about chaining tasks together, you
might think about if it's advantageous to pass a parameter as
an input or partial input into the child task.
except Exception as e:
address.geocode_status = 'fl' #address object fails
address.save()
#do something_else()
raise #re-raise the error, in case you want to trigger retries, etc
app.views.py
from app.tasks import *
from app.models import *
from django.shortcuts import get_object_or_404
def geocode_for_address(request, app_user_pk):
app_user = get_object_or_404(AppUser, pk=app_user_pk)
...etc.etc. --- **somewhere calling your tasks with appropriate args/kwargs
I believe this meets the minimal requirements you've outlined above. I've intentionally left the view undeveloped since I don't have a sense of how exactly you want to trigger it. It sounds like you also may want some sort of user notification when their address can't be geocoded ("I'd like to update a field in a database letting a user know"). Without knowing more about the specifics of this requirement, I would it sounds like something that might be best accomplished in your html templates (if instance.attribute value is X, display q in template) or by using a django.signals (set up a signal for when a user.address.geocode_status switches to failure -- say, by emailing the user to let them know, etc.).
In the comments to the code above, I mentioned the possibility of decoupling and chaining the component parts of the get_geocode task above. You could also think about decoupling the exception handling from the get_geocode task, by writing a custom error handler task, and using the link_error parameter (for instance., add.apply_async((2, 2), link_error=error_handler.s(), where error_handler has been defined as a task in app.tasks.py ). Also, whether you choose to handle errors via the main task (get_geocode) or via a linked error handler, I would think that you would want to get much more specific about how to handle different sorts of errors (e.g., do something with connection errors different than with address data being incorrectly formatted).
I suspect there are better approaches, and I'm just beginning to understand how inventive you can get by chaining tasks, using groups and chords, etc. Hope this helps at least get you thinking about some of the possibilities. I'll leave it to others to recommend best practices.

MVC on Lift/Scala

Has anyone tried to do a scala/lift application using MVC instead of view-first?
I know that you can create Controllers/views as:
package test.test.test.view
...
Lots of imports
...
class MvcRocks extends LiftView {
def dispatch = {
case "rule" => ruleDispatch _
case "bar" => barDispatch _
}
def barDispatch(): Box[NodeSeq] = {
Full(<lift:embed what="/mvc_rucks/bar" />)
}
}
And this code will be accessible if you add it to the menu(in the boot), even if its hidden as:
val entries = Menu(Loc("Home", List("index"), "Home")) ::
List(Menu(Loc("MvcRock", List("mvc_rocks", "bar"), "Mvc really Rocks", Hidden)))
LiftRules.setSiteMap(SiteMap(entries:_*))
Now, of course this will make it so, you declare every action in the menu, then have a case for each action(per controller) and that would open the "view" (that would be a file in /mvc_rucks/bar.html).
My question is, if you would implement a full mvc, you would need to put all your logic in the action barDispatch, but how would you send those variables to the HTML template? and how would you receive post/get information?
(Notice that if you html code has lift bindings, it will of course act as view-first, even after you did MVC before).
Since your question is not specific to Lift, I'd recommend you the Playframework. The version 1.1 supports Scala 2.8.
Playframework is totally MVC with a fantastic template engine and allows you to choose freely between java/scala.
And I say: To use Play, you don't need 'nuclear scientist knowledge'. Try it!