Combining classes in Anypic example project - parse-platform

I was going through the Anypic tutorial and the data model part specifically because I want to build a similar app. My question is why can't I remove the permission restrictions and let the image class hold the likes (int) and the comments (array of strings) and don't allow the users of the app to edit other users images. What can be the drawbacks of this approach?
Thank you

The permission restrictions are in place for security.
By separating the likes from the Photo class, it prevents other users from modifying someone else's photos. The way Parse ACLs (Access Control Lists) work is by restricting read/write access.
Let's consider the scenario that likes are contained within the Photo class. If one user wants to like someone else's photo, they will have to modify the user's photo directly, which requires write permissions in the ACL.
No big deal, right? Wrong. Someone with malicious intent could structure their own REST API calls to your app and perform whatever actions they want on other people's photos. I could remotely modify or delete your photos, spoof additional likes, and tons of other exploits depending on the rest of your app.
If you still wanted to keep likes within the Photo class, but not have public write access, then whenever someone tries to like a photo, you would have to perform the write in cloud code using the master key. You would also need to do extra validation beforehand so someone else couldn't spoof this request.
Parse ACLs are great because they are incredibly simple and quickly allow you to compartmentalize read/write access as needed within your app.

Related

Restful API: Best practice for admin and user scope

I am building an API where users and admins can interact with the same data, but with different needs.
A user can also have access to the admin panel, if he has the "admin" role.
Let's see for example we have a resource like Badges. A Badge is simply a reward when you achieve some actions into the app.
GET http://localhost/api/v1/badges
An authenticated user can call this endpoint and it returns the list of all badges, if they have it or not, with progress details.
GET http://localhost/api/v1/badges?user_id=2
with user_id parameter, we can see these details of another user (if he allows it).
But from the admin scope, I just need to see the list of all badges, without achievement details (CRUD operations).
So I have 2 options in mind:
Create "admin" endpoints: GET http://localhost/api/v1/admin/badges.
Adding custom header "X-App-Scope" to identify if I am in admin or user.
I don't like the second one because I think I will have so many if statements and behavior in the same endpoint, depending of the scope.
Because I have lots of use cases like this, I want to make sure my API architecture is good to handle user/admin needs.
Do you guys have any idea/example to manage stuff like this?
Thanks!
My personal preference is to separate admin API routes from user ones. i.e. having two routes
/api/v1/badges
/api/admin/v1/badges
You will have two unique documentation, one for each route, which makes it easier to maintain and understand
It will be easier to tell the difference between the user and the admin versions
There is no need extra code to check for request headers or url params.
It makes your middleware less complicated, especially if authentication and permissions are handled there.
It is more scalable for teams as there is only one kind of request and response format per API.
TL;DR: REST is designed in the expectation that you would use two different resources here.
The core problem is this: how would a general purpose component, like a browser, know that your special resource needs to have this custom header added?
In particular, consider the case where I send to you a copy of the URL for this resource, and nothing else. How are you to know to add the customer header to the request?
On the other hand, if you use different resources to share this information with each audience, everything just works.
The only way I found to stay as simple/clear as possible is to make multiple endpoints, for each use case:
GET http://localhost/api/v1/badges to get all badges in raw data
GET http://localhost/api/v1/users/badges to get all badges with user stats (progression, achievement...) in a transformed format
GET http://localhost/api/v1/users/{uuid}/badges to get all badges with user stats (progression, achievement...) in a transformed format for the specified user, if his profile is public
Now I have a lot of /users/XYZ endpoints, but my code seems easier to read & maintain, and I don't really need to see the code to guess what data will be returned, the conditions, etc...
I keep wondering how the other APIs are written when you have an admin section, because having /users everywhere isn't really "pretty", and I don't see that anywhere else.

How to make a custom Laravel policy that overwrites another in certain circumstances?

I am trying to create a Laravel policy (I think this might be best way to do it) that overwrites another policy under certain circumstances. I have two models that have a many to many relationship, accounts and programs.
I have a policy that prohibits viewing of accounts for users that do not have the account associated with a program that belongs to them. This works fine, but this also presents a problem. This makes it so a user cannot attach an account to a program, because they cannot see it.
What would be the best way to go about solving this? I was thinking about creating a custom policy, as Laravel docs say you can name a policy whatever you want and have it control any action, but I don't quite understand how that would work. I wrote an attach method on the program and account policy, but that doesn't seem to be working.
In summary, I want to restrict the user from seeing the account view page (if it is not associated with a program that belongs to them), but I want to allow them to attach the account to their program.

restrict create/update/delete to requests with a user only

In Parse.com client APIs, it is possible to perform create/update/delete on object of any class. It would be good to set a minimal level of security that restrict these operations only to requests that are made by a Parse.User. This way, someone with access to say your REST or JS key can't just spam create or delete a ton of objects in your database.
I have 2 working solutions but they seem a tad too complicated for something so simple. If you know of a simpler way to accomplish this on Parse.com, please let me know.
Solution 1: Create a RegularUser role and assign all your users that role. Set up class level permission to this role. Undefined users (from requests made without a user) naturally do not have this role, thus access is revoked.
Solution 2: Create beforeSave and beforeDelete cloud code for every class and reject all requests without a user.
I'm pretty new to Parse and I have a feeling that I've missed a simple setting somewhere that lets you lock down your data for logged in users only. Please point that out if that is the case. If you are experienced in Parse.com and in your experience, there is no simpler way, I'd appreciate the confirmation as well. Thanks
I'm answering this a bit late, but I thought I would answer to help out other readers. Like Akshay pointed out, you should definitely set the appropriate Class Level Permissions. But I think what you were getting at can be addressed through ACLs, as suggested by the Parse docs: https://www.parse.com/docs/ios/guide#security-access-control-lists
You can set different types of ACLs for each class, or if you only want to allow users to access their own objects, it's really easy to implement that across all classes:
To make it super easy to create user-private ACLs for every object, we
have a way to set a default ACL that will be used for every new object
you create:
In Swift for iOS:
PFACL.setDefaultACL(PFACL(), withAccessForCurrentUser: true)
I have this set up in my app's AppDelegate, which has the effect that any object the user creates can only be read/updated/deleted by that user.

Where do I prevent users from accessing other users' data?

On a website I am building I need to allow users to edit their orders. Easy enough. But how do I ensure that a user cannot edit other users' orders? Do I perform checks in the model or in the controller to verify that the order belongs to the authenticated user?
Put checks in the view (yes, the view) for rapid response to user errors.
Put checks in the controller to ensure data integrity.
For example, in a web based app, you might have browser javascript to check all fields, including username, so the user gets rapid response to fix erroneous transactions. However, back at your server, you can not rely on the browser to really validate the data, since the browser is outside your control -- it might be corrupted, either intentionally or accidentally, and not doing validation as you intend. Thus you need to revalidate everything on your server to ensure integrity.
Well hopefully your site doesn't have any way for a user to even attempt to edit someone else's orders. But if it's still possible to try, you could put that logic in either the model or controller. It's a matter of opinion. Some people will say that the controller should do things like access checks, and the model only knows how to modify itself. Others will say "fat model, skinny controller" and say that the security checks need to be reusable across controllers and so they should go in the model. It's your call.

Updating App with Web Information

Hey everyone, I am sorry if this question has already been asked/answered
But I have a Cocoa program that has different arrays of models. Each model hold just Strings and one Image. Archiving and Loading works great.
Each model represents a web account, that is, it holds the username and password, and some other information related to the website. Moving forward I would like to be able to update information in each model by accessing the information from the website. For example updating a balance ($). I am wondering if there is a way to do that programatically that is:
Automatically log into web account using the entered username, pass, and website url
Update the balance based on the information following log in.
Thanks for the help in advance!
Tamara
There is no single approach to log into any arbitrary website. You will need to know what the API for the given website is. If the website provides a web service to query things like balance, then you would connect using that web service (REST-based if at all possible; SOAP is more of a pain in Cocoa), and update your model based on the results. If the website provides no web service, then you would have to scrape through the HTML responses looking for what you want, and this is generally very complex and fragile. There is no general answer to this question; you'd have to know what form the website is in.
On another note, make sure that you are not storing user passwords in unencrypted files. User passwords on Mac should always be stored in Keychain. There are many posts on SO about how to best use Keychain.
Rob, isn't it possible to just look through the login page's html source and see what are the names of the fields for user and pass, and then just send a POST request to that page from code ?

Resources