CakePHP 3 allow only REST index.json and and.json (no normal views) with Auth - rest

I've created the blog from blog tutorial, and I would to protect articles list, but I want that this be accesible across REST, I've activated json extensions.
All works well. I can add and retrieve list, but now I want to deny index and add from web and only be accesible from .json to public.
I tried with
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow('index.json');
}
But this obviously doesn't work. All webpage is login protected as is in tutorial. Web services should be accesible to Android App (code is ready and working).
Thank you!

Of course that doesn't work, the allow() methods expects valid method names, and that's all the authentication component cares about, method/action names, it doesn't matter how the action was requested.
What you are trying to do requires you to check the type of the request, and based on the results, allow the actions. Checking the request type can be done using Request::is().
See Cookbook > Request & Response Objects > Checking Request Conditions
So it might be as simple as
if ($this->request->is('json')) {
$this->Auth->allow(['index', 'add']);
}

Related

Send variable to 3rd party online form

In golang, is there a way to pipe a variable to part of a web form?
For example, sending "123 Random St." to the Street address part of https://www.dominos.com/en/pages/order/#/locations/search/ and so on? I found pizza_party*, but the GUI used is no longer available, I have also found pizzadash**, but this uses a credit card where I want to use cash. I even found a list of golang ones, but the links that they use doesn't work anymore.***
Therefore, my goal is so: order a pizza in golang through the dominos website API!
NOTE: Please suggest a package or function with example!
NOTE: I do not want to make a web scraper/data getter.
NOTE: Your answer must work on at least one box of my linked website.
NOTE: I want to fill out links similar to the provided link from the linux command line.
*https://github.com/coryarcangel/Pizza-Party-0.1.b
**https://github.com/bhberson/pizzadash
***https://golanglibs.com/top?q=pizza
This is how you post any form values onto an online form. Provided you know the POST endpoint of the service.
func main():
resp, err := http.PostForm(targetPostUrlHere,
url.Values{"Service_Type": {"Delivery"},
"Address_Type_Select": {"House"},
"Street": {"123 E 24th St"},
"Address_Line_2": {"4D"},
"City": {"New York"},
"Region": {"NY"},
"Postal_Code": {"10027"}})
}
**Note: The field keys and values are guesstimates. You must inspect the actual key names expected in the form.
In your case, https://www.dominos.com/en/pages/order/ is an endpoint for the form page. Once the form is filled and submitted, the information is submitted using POST method akin to the code afore-mentioned to a dedicated CREATE endpoint (C in the CRUD), which normally can be found in the <form> html tag.
<form action="posttargetendpoint" method="POST">...</form>
Once the POST operation is successful, usually a web service would redirect you to another page. In your case, it is https://www.dominos.com/en/pages/order/#/section/Food/category/AllEntrees/
However, any good web service wouldn't expose the POST endpoint in the clear since it is the vulnerable point of attack. You're welcome to find out by inspect he Domino's page source and adjust the field values in the Go code accordingly.
Now to make a command line prompt to wrap around the PostForm code, I suggest you look into https://github.com/codegangsta/cli which is a very nice package for creating quick command line app.
I assume you mean pipe information originating from your backend to another site on behalf of a user?
The standard way of passing information between domains is via HTTP params, usually via a GET request, but this capability would need to be supported by established protocols the remote site. You can also use an iframe to embed the page of another site onto your page, however, you wouldn't be able to remotely interact, call JS code, or even query the page at all. Cross-domain security safeguards justifiably prohibit such capability, and generally speaking, interacting on behalf of the user via their browser is also restricted for security reasons.
However, if you're looking to emulate user behavior such as with a bot or web scraper from your own host or browser then that's a different story. There are tons of frameworks provide rich capability for interacting with a page. I'd recommend checking out Selenium, which acts as a virtual browser. There are also tons of libraries in Python for processing data from HTML and structured data. You might want to check out Beatiful Soup and Scrapy.
Hope this helps.

Play Framework: Don't change URL after form validation failed

In a plain Play application I have the following scenario.
A route file which looks like this:
GET /accounts/add controllers.Accounts.add()
POST /accounts controllers.Accounts.create()
The first route results in a view where I can add a new account. The form to submit the new account looks something like this:
#helper.form(action = routes.Accounts.create()) {...}
Now the controller binds the input to the form and checks for any validation errors:
public static Result create() {
Form<Account> form = Form.form(Account.class).bindFromRequest();
if (form.hasErrors()) {
return badRequest(views.html.account.add.render(form));
}
...
}
Now the thing is, the client will see the same view with some additional error messages. However, meanwhile the URL has changed from http://example.com/accounts/add to http://example.com/accounts.
If the client now reloads the browser this calls GET http://example.com/accounts (which isn't even mapped in this scenario - thus getting a 404 - Not Found).
Maybe it's just me but I find this kind of annoying and browsing some GitHub projects I couldn't find a good solution for this case.
Of cause things would be much simpler if the second route is rewritten to:
POST /accounts/add controllers.Accounts.create()
... in which case everything works fine. But from a REST point of view this doesn't feel good either. The same applies to update scenarios (having GET /accounts/:id/update vs. PUT /accounts/:id).
Is there a guide on how to handle this? Am I getting something wrong or is this no problem at all (from a pragmatic point of view)?
It's not possible to leave the previous URL because a request for a new address has already been made. A controller only provides response for a requested resource. To go to the previous URL you could only make a redirect in case of validation failure but you would lost errors that way so this is not a solution.
I suggest mapping both actions with the same URL. This way you would solve problem with the browser reload.
If you create a REST service for http clients that aren't browsers you will probably want to serve different response than a simple http page. The separation of actions for particular clients could be a good solution for keeping REST API clean and a browser user happy.

Ember Model RESTAdapter nested endpoint

I'm building a web app using Ember 1.5 and I use Ember Model 0.0.11 to link the app to an API. I'm currently having trouble getting Ember Model to use nested API endpoints.
For instance, my app has a User model, which has a hasMany relationship with a Post model. Now, when I want to load the posts for a certain user, I'd like the Post.findQuery('user_id', {user_id}); method to access the GET /users/{user_id}/posts endpoint. Instead, it seems that the Ember Model solution prefers to send the query as a parameter to the GET /posts endpoint.
Ember Model's RESTAdapter does allow for easy customization, but before I start coding a completely custom RESTAdapter I'd love to know if someone has already done this and how they solved the problem.
The solution for us to handle nested API routes was to have a links hash returned with the requested payload. If you can change the API output, this is the way to go for now. For example, when requesting a workspace, the returned JSON looks like this (excuse the escaped characters):
{
"data":
{
"object":"workspace",
"id":"wrk_krVZWGaJ",
"organization_name":"Legros, Klein and Boehm",
"workspace_name":"Legros, Klein and Boehm",
"workspace_path":"legros, klein and boehm",
"status":true,
"credit_production":7,
"credit_revision":16,
"links":{
"projects":"\/v1\/workspaces\/wrk_krVZWGaJ\/projects",
"productions":"\/v1\/workspaces\/wrk_krVZWGaJ\/productions",
"subscription":"\/v1\/workspaces\/wrk_krVZWGaJ\/subscription",
"assets":"\/v1\/workspaces\/wrk_krVZWGaJ\/assets",
"descriptions":"\/v1\/workspaces\/wrk_krVZWGaJ\/descriptions",
"roles":"\/v1\/workspaces\/wrk_krVZWGaJ\/roles",
"registrations":"\/v1\/workspaces\/wrk_krVZWGaJ\/registrations",
"users":"\/v1\/workspaces\/wrk_krVZWGaJ\/users"
}
}
}
The model defines the links as async hasMany relationships, i.e. DS.attr('projects', {async: true}). When the workspace is loaded from the store, the linked projects aren't included. When you use {{#each workspace.projects}} or workspace.get('projects') anywhere else, ember-data will make a GET request to /v1/workspaces/wrk_krVZWGaJ/projects/, rather than the default route of /projects/. Neato, eh?
More details on the RESTAdapter findHasMany method.

App with no DB: You must call the "WebSecurity.InitializeDatabaseConnection" method before you call any other method of the "WebSecurity" class

First things first. I'm a complete OAuth newbie. This will be my first stab at it, and things are getting hairy...
I'm writing a single page application using Durandal & Web API.
The user needs to be able to login using any social network.
I don't have access to a database whatsoever, I have to call an unprotected 3rd party web service which I consume server-side, and need to protect using OAuth.
So I've managed to add the files to my solution which generates the login using facebook contol/button (created a new MVC4 web application, and did a manual copy and paste of all the auth related files, updated bootstrappers etc..), and the code seems to work for the most part.
When facebook redirects back to
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(this.Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
if (!result.IsSuccessful)
{
return this.RedirectToAction("ExternalLoginFailure");
}
if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))
{
return this.RedirectToLocal(returnUrl);
}
//code removed for brevity ....
}
I get the error specified once the following line tries to execute.
OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false)
I've removed the [InitializeSimpleMembership] attribute from the controller, as I don't have a database.
Please forgive me if this is the dumbest question ever, but...
Why does the login fail? I mean at that point, isn't the app trying to log into facebook, why does it need a databse? Or am I correct in saying I can remove/replace that code section, with a login/authorise call on the web-service I'm using?
Not the dumbest question ever. Not by a long shot. But you are getting the error because your membership provider is still set to use the SimpleMembershipProvider and OAuthWebSecurity will use the default membership provider. If you don't want to use a database you will have to create or find a different membership provider to use.
EDIT:
I know you said you don't have access to a DB but if you can use SQL Compact you can just stick with the default SimpleMembershipProvider(check out Hanselman's blog) or DevArt has a SQLLite provider. Also the MemFlex Project has a RavenDb provider. If none of those work I think you might just have to write your own.

How to prevent from user to delete all the data when using backbone.js

Lets suppose that I have some web app that using backbone.js in the client side, and on the server side some RESTful API that support the DELETE method.
The database of the app contains some categories and posts, and on the client side I have collection that called "categories" that using fetch() to retrieve all the categories from the server using GET method.
How can I prevent from any user to just open his console in chrome or firebug in Firefox, explore my JavaScript files, figuring the structure of my backbone models and just run collections.destroy() from his console and delete all my database....
Am I missing something here?
I've googled it but didn't find an answer...
You have to put up some validation on your server side since you cannot trust what came from the client.
For example you could write some security checks that run before execute the database's calls, like these (PHP pseudo-code):
$model = Posts;
if($model->checkUserRights('read')) {
$model = Posts->findById($_GET['id']);
echo json_encode($model);
} else {
echo "You have not the require rights to access ".$model->tableName;
}
And in Posts's model:
public function checkUserRights($op){
// Run some code for each possible operations's type
}
You could also add some rules to filter the values you will return to the clients or the values they will post to your server, before process an update request.
It's really up to you and what technology you will use on your server.
You can easily prevent this on the server side by not doing anything when the DELETE method is received from the client.
If you're using rails, your delete method would look like this
def destroy
#not allowing deletions through the REST api
end