I would like to have access to the current user somewhere deep in my models of my Play app, for things like setting the author, checking that the user can actually save this type, etc.
Ideally, what I would like to use is Guice's #RequestScoped to inject the same UserIdentity across my request, wherever I need it. However, as far as I can tell, the Play! Framework only supports #Singleton and no-scope. So either we'd get the same UserIdentity injected across requests or a different one for every model/util we requested. Both are no-gos for obvious reasons.
Is there some way to utilise this behaviour in Play 2.5?
Other things I have tried
I've tried using a combination of Play's session and cache. But the problem I have is that session is immutable, so I can't add anything to it to reuse in that same request.
I've looked at a bunch of auth frameworks but they all seem to focus on securing actions, not providing me with a current User object.
Check out my answer to a question on redirecting requests, where I given an example of getting the current user in each request.
In this case the authorization key is handed out on login and the client passes it in on every request thereafter.
Related
Imagine I have a Razor Page or such like. Imagine the data used by that Razor Page is not used by any other page at all. So the data retrieval is very specific to this page only.
Is it bad practice to just grab the data directly using a database connection from within that Razor Page local to the only place that data is to be used?
If so, why should I abstract the data away into a separate API that isn't re-used anywhere? Why is it good practice?
It seems to me, that REST APIs are sometimes used unnecessarily and for no good reason. As if because every example video shows data retrieval from REST APIs. Correct me if I am wrong.
If your application is purely a server-side app, there is no justification for creating RESTful API that serves up JSON for it. Those kinds of APIs are usually created for "external" consumers, by which I mean third parties or the browser (via JavaScript). They are commonly implemented for client side apps - single page apps typically like React, Angular or Blazor where JSON is the data format of choice for the browser.
As to whether you should open database connections in your PageModel class, that's another question. For simple apps, why not? But for apps that need unit testing, it's not a good idea. You will be unable to execute unit test against the PageModel class without hitting the database.
As a habit, I tend to put the code that connects to a database in a series of separate classes, each one having an interface, and then inject them into the PageModel via dependency injection. That way I can mock the service represented by the interface for unit testing.
You might want to implement services that generate data as JSON within a Razor Pages app if you have some functionality that depends on Ajax requests for data. For those, you could use Web API controllers, minimal request handlers or even named handler methods that return JsonResult objects in the PageModel classes. With all of those, you might still want to put the code that actually calls the database in a separate class that is injected into the handler.
I need to programmatically interact with a WebObjects website and extract data from the responses. The particular WebObjects site I am scraping uses component actions and stores sessions in cookies (not urls). This means that all urls look something like this:
http://example.com/WOApp/WebObjects/WOApp.woa/wo/7.0.0.0.29.1.1.1
My first questions are:
Does urls like this not completely destroy local and shared caching opportunities (cachable constraint in REST)? I imaging the only effective caching with such urls is the WebObjects server itself.
Isn't addressability broken as well? Each resource does have a unique endpoint, but it changes constantly. Furthermore (I think) that WebObjects also makes too old URLs invalid since they "time-out" after a period of time. I'm not sure whether this applies only to urls with sessions though.
Regarding the scraping I am not sure whether it's possible to extract any meaningful endpoints from the website. For example, with a normal website I would look through the HTML and extract the POST urls, then use them in my scraper by posting directly to them instead of going through the normal request-response cycle.
In this case I obviously cannot use any URLs extracted from the HTML since they are dynamically generated on each request, but I read something about being able to access WebObjects components directly if the security settings have not been set to disallow this (see https://developer.apple.com/legacy/library/documentation/LegacyTechnologies/WebObjects/WebObjects_3.5/PDF/WebObjectsDevGuide.pdf, p. 53 "Limitations on Direct requests"). I don't understand exactly how to do this though or if it's even possible.
If it's not possible what would be a good approach then? The only options I can think of is:
Using a full-blown browser client to interact with the website (e.g. WatiR or Selenium) and extract & process the HTML from their responses
Manually extracting the dynamic end-points by first request the page where they are on and then find the place in the HTML where they're located. Then use them afterwards as if they were "static".
I am interested in opinions on how to approach this scenario since I don't believe any of the solutions above are particularly good.
You've asked a number of questions, and I'll see if I can cover each in turn.
Does urls like this not completely destroy local and shared caching
opportunities (cachable constraint in REST)? I imaging the only
effective caching with such urls is the WebObjects server itself.
There is, indeed, a page cache within the WebObjects application server, and you're right to observe that these component action URLs probably thwart any other kind of caching. Additionally, even though the session ID is not present in the URL, you'd need the session ID in the cookie to re-create the same page, so having just that URL would get you a session restoration error from the application server.
Isn't addressability broken as well? Each resource does have a unique
endpoint, but it changes constantly.
Well, yes, on the face of it this is true. You've given a component action URL as an example, and they're tied to the session.
Furthermore (I think) that
WebObjects also makes too old URLs invalid since they "time-out" after
a period of time. I'm not sure whether this applies only to urls with
sessions though.
Again, all true. Component action URLs generate sessions, and sessions time out.
At this point, let me take a quick diversion. I'm assuming you're not the owner of the WebObjects application—you're talking about having to scrape a WebObjects app, and you've identified some ways in which this particular app doesn't conform to REST principles. You're completely right—a fully component-action-based WebObjects application won't be RESTful. WebObjects pre-dates REST by a few years. Having said that, there are ways in which a WebObjects application can be completely RESTful:
Using session-less direct actions gives a degree of REST-like behaviour, and would certainly solve the problems you identify with caching, addressability and expiry.
Using the ERRest framework to create a 100% RESTful application.
Of course, none of this will help you if you're just trying to scrape a legacy application.
Regarding the scraping I am not sure whether it's possible to extract
any meaningful endpoints from the website. For example, with a normal
website I would look through the HTML and extract the POST urls, then
use them in my scraper by posting directly to them instead of going
through the normal request-response cycle.
Again, if it's a fully component action-based application, you're right—all those URLs will be dynamically generated and useless to you.
In this case I obviously cannot use any URLs extracted from the HTML
since they are dynamically generated on each request, but I read
something about being able to access WebObjects components directly if
the security settings have not been set to disallow this…
That's talking about getting a component to render directly from its template with some restrictions:
As you note, the application can easily prevent it from happening at all.
As mentioned on p.53, the user input and action-invocation phases of rendering the component are skipped, which probably means this approach would be limited to rendering a component that didn't have any dynamic content anyway. This might be of some very limited use to you, though you'd need to know the component names you were interested in, and they wouldn't normally be exposed anywhere.
I'm not sure you're going to find anything better than the types of high-level functional approaches you've already suggested above, such as automating at the browser level with Selenium. If what you need is REST-style direct addressability of resources within the application, you're not going to get that unless you can re-write the application to use direct actions or ERRest where you need them.
A little late, but could help.
I use the Apache's mod_ext_filter (little modified) to pre/post filter the requests/responses from our WebObjects application. The filter calls PHP scripts and can read the dynamical hyperrefs and other things from the HTML pages. The scripts can also modify the HTTP requests, so we can programatically add/remove parameters from the request to implement new workflows in front of the legacy app and cleanup the requests before they will reach WebObjects. It is also possible to handle an additional database within the scripts and store some things over multiple requests.
So you can get the dynamically created links (maybe a button's name or HTML form destination) and can recognize these names within the request.
It is also possible to "remote control" such applications with little scripts like "click on the third button on the page". The only thing you need is a DOM parser to get the structure of the HTML pages and then rebuild the actions which the browser would do (i.e. create the HTTP request manually and send it as POST to the extracted form destination href). The only problem is the Javascript code, which we analyze and reprogram within PHP (i.e. enable/disable input elements, so they will not be transmitted within the requests)
There were some problems within the WebObjects Adapter Module for Apache. It still uses Content-Length within the HTTP header, which you cannot change in mod_ext_filter. If you change the HTML or the parameters within the request, the length of the content will not longer match. But it is possible to change that.
Theoretically it could also be possible to control such an closed-source legacy application from a new UI on a tablet or smartphone, which delegates the user interaction to the backend WebObjects app.
The scripts depends on the page structure, so if your WebObjects app will be changed, you have to correct some things in the scripts (i.e. third button could be now the fourth button).
It should also be possible to add a Restful interface in front of the application and query the data from the legacy app by the filter scripts.
Alright, so a better title here may have been "Progressive Enhancement with REST in CakePHP", but at least now I'll know you didn't read the question if your answer just refers to the difference between the two ;)
I'm pretty familiar with REST and how to integrate it with CakePHP, but I'm not 100% on board with how to still maintain a conventionally functioning website. Using Router::mapResources sounds like a great idea, but this creates a problem with maintaining the "gracefully degradation" version of the site, because both POST requests to /resource/ AND GET requests for /resource/add will route to the same action (add). Clearly I'll want this action to return a JSON object if they're using the REST api, but if they're using the degraded version of the site (no JS perhaps), it should be a add form, right?
What's the best way to deal with this. Do you route your REST requests to other action names using Router::resourceMap()? Do you do that crazy hack I saw to have the /api/ prefix part of the resourceMap so you can use api_action functions? Do you have the actions handle both REST and conventional requests via checking isAjax()? If so, how do you ensure that you can rely on the browser to properly support the other two request types?
I've searched around quite a bit but haven't found anything about how to keep conventional requests available in Cake along side REST, so if anyone has any advice or experience, I'd love to hear it!
CakePHP uses extension routing as well, via Router::parseExtension() so;
/test/action will render views/test/action.ctp
/test/action.html also
/test/action.json will render views/test/json/action.ctp
/test/action.xml will render views/test/xml/action.ctp
If all views are designed to handle the same data as set by your controller, you'll be able to show a regular HTML form and handle the posted data the same way as you'd handle the AJAX request.
You'll probably might have to add checks if any data is posted/submitted inside the /add, /edit, /delete actions to prevent items being deleted without a form being posted (haven't tested that though, it might be that cake blocks these urls if mapresources is set for the controller)
REST in CakePHP:
http://book.cakephp.org/2.0/en/development/rest.html
(Extension) Routing
http://book.cakephp.org/2.0/en/development/routing.html#file-extensions
I am starting to develop a GWT application in MVP style (GWTP) and which uses Spring security for authentication and authorization on server side.
In many views of the application, I have to enable or disable controls with respect to a granted authority of the current user. I already have an RPC service which provides access to a userDetailsDto containing all the necessary information.
Now my question: What is the best place to store the user DTO on client side?
Since the user rights are relevant in many presenters, I would have to pass it around everywhere. Alternatively, I could set an RPC service instance in every presenter and requets the user details each time (probably cached on client-side). But i don't like the idea of having a user RPC service in each presenter just for this purpose.
To be honest, I'd rather would prefer a central registry where to put the UserDetails object and which is accessable from anywhere in my app. Is there already such a registry in GWT?
As in my example, you might often be confronted with horizontally used objects. How to deal with them in GWT?
Simply store your current user in public static variable.
It will be accessible from everywhere.
I inject an "AppState" object into all of the presenters that need to know things like the rights of the user logged in, their preferences, etc. I prefer injection to a public static variable because it feels more controlled, is easier to mock up in tests, and the extra typing forces me to consider whether each object really needs access to the global data.
I am currently re-writing an old web-application and I want it to be RESTful. Now, one important philosophy behind a RESTful app, is that each request to the end-point has to be stateless.
With the application I am aiming for a common codebase for the API as for normal browsing. In other words, I want to avoid special URLs like http://api.domain.tld or http://domain.tld/api. I intend to interpret the HTTP Accept header for this.
One challenge I came up with, are request parameters, that a user browsing the page usually only chooses once. A good example for this is the language. Again, I can use the Accept-Language header to pick an initial language. But what if the user wishes to change this? It would be unusable if the user needed to switch the language after each request.
In my opinion, this is really a request parameter, and should be passed on as such. For example: http://domain.tld/resource?lang=en. So once the user switched the language, I would need to append this parameter to each URL on the page.
In a way, this makes the browsing-session stateful. Are there any "best practices" for this? How would you approach this. One idea I have, is to store these "global" parameters in the session, but add them to each URL nevertheless. If only to make the API easily discoverable.
On a sidenote: I am currently building the web-page using Flask which provides a method url_for to build URLs. I am considering overriding this, so each generated URL will have the parameter. But this is not a Flask specific problem. This is something most RESTful services should consider, so I will tag it neither with python, nor flask!
State Transfer
REST doesn't require each request to be stateless. The requirement is that the server does not have to manage state on behalf of the client. In effect, each request has to carry sufficient state to allow the server to process it.
Your approach, providing the user language is perfectly sensible. Others might prefer to retrieve it from a shared database but this can have some scalability concerns.