Conditional object ACL - parse-platform

New to Parse, coming from Google Firebase, I am not able to completely wrap my head around the security aspect of the platform, let alone write some code. From Firebase, I'm used to writing security rules, by defining conditions that need to be met for certain actions to be allowed (such as: allow write if owner field of post is equal to the current users uid).
So how would I solve following problem? I have an object Post containing properties title, content, owner, public.
Allow reading under following conditions:
if public == true
or currentUser matches field owner
Allow writing if currentUser matches field owner.
Is there a way to implement this? I have found a solution to restrict writing using Cloud Functions, although I am certain there must be a better way.
Thanks in advance!

Related

XAPI: how to query for a Team (aka tin can api, experience api) [duplicate]

I'm recording statements to the LRS and in each of those statements I always set the "Team" property.
I know I'm able to filter those statements by verb, activity and many other parameters as described here.
However, I can't find a way to filter statements by Team (which is a property of Context).
Is it possible?
I think the best you can do is to use identified groups (a group with an IFI) as the value of the "team" property and then request statements using the "related_agents" query parameter. Note that this will include statements where that identified group is also the "actor" or in any of the other positions accepting a Group/Agent object, so you'll still have to post process them. As far as I know there is no way to request based on an unidentified group since they aren't considered the same group across requests.
There is no way to specifically request only statements based solely on the "context.team" property.
I am assuming that you have added team property to context.extension property. You should not add properties that are not allowed, otherwise, you might have issues in future.
Regarding querying by team or any other extension property, it cannot be done as per standard xAPI Spec. However, your LRS could allow you to do that. e.g. You can get an LRS like GrassBlade LRS or Learning Locker and get it customised to add more filtering options.

JSON API REST endpoint with permissions-restricted fields

JSON API REST endpoint with permissions-restricted fields
I am working on a JSON API-compliant REST api. Some endpoints contain fields that should be restricted (read-only or not available) for certain users.
What is the best way to architect the api to allow that certain users have access to certain fields, while others do not? By "best", I mean:
Most compliant with REST standards, ideally JSON API standards
Most clarity in terms of preventing bugs and confusion on behalf of clients consuming the API
I am considering the following options, each with their set of concerns/ questions. I would be more than grateful for any other solutions!
Option 1: Return null on restricted fields for users without permissions
Different data values would be returned per-user. Is this strictly anti-REST?
Lack of distinction between null meaning "null value" and null meaning "You don't have access to this"
In REST/ JSON API architecture, is it okay for an endpoint to return different data per user, based on permissions? I have the impression that this would be contrary to the spirit of resource-based REST architecture, but I could not find anything specific to point to in any doc or standard (e.g. JSON API). Also applies to Option 2.
Is there any paradigm for adding some sort of "You don't have access" flag in the resource's metadata?
Option 2: Exclude restricted fields entirely for users without permissions
Different data values would be returned per-user. Is this strictly anti-REST?
Possibility of "undefined" errors in client, when trying to retrieve field value
Option 3: Move restricted field(s) onto another endpoint, available as an ?include='field_name' relation for those with permission
Example: /api/entity includes attribute field "cost" which is only available to Admin users. Admin users can request cost data via GET /api/entity?include=cost. For all users, "cost" is exposed as a relation in the resource object, with a "type" and "id".
This is the option I am leaning toward. The main con here is endpoint clutter. I have a lot of relations that would need to be made into separate endpoints, simply to support a permissions-quarantined data on an already-existing endpoint.
In the JSON API specs, I am having trouble determining if it's ok for an endpoint to exist as a relation only, e.g. can we have /api/entity/1/cost, but NOT have a top-level api endpoint, /api/cost. My assumption is that if a resource has a "type" (in this case, the relation type being 'cost'), it also has to live on a top-level endpoint.
In this scenario, the client could get a 401: Unauthorized error response if a non-admin user tries to GET /api/entity?include=cost or GET /api/cost/:id
Note: I have already built a separate permissions schema so that the client can determine which CRUD privileges the user has, per top-level endpoint, before making any requests. Permission sets are indexed by resource type.
Any help on the matter would be very much appreciated! And if anything needs to be clarified, feel free to ask.
I would definitely not use undefined or null to indicate fields that the user is not allowed to see. To me, that feels like a lie and represents that the data is really not there. They would have to really know your API in order to get a grasp of what is really going on.
I would recommend something more like your 3rd option, except I would make it a different endpoint altogether. So in your example, the endpoints would be:
/api/entity/1/cost
and for admins
/api/admin/entity/1/cost
or something like that.
This way your server code for the admin endpoint could just be focused on authenticating this admin user and getting them back all the fields that they have visibility on. If a non admin user tries to hit that route, reject them with an unauthorized status code.
I'm not saying that you should not implement the GET param to be able to specify fields as well. You can if you want to, but I don't think it just won't be necessary in this case.

Xcode - ask user to accept request from other user

I was having trouble wording the title, sorry.
Basically, I want to know the best practice when asking permissions from one user to another. An example would be those family tracker apps, where one user requests to follow another, and said user has to accept that request so the first user can follow their locations.
I am using Parse if that makes a difference. Thanks!
For achieving this with Parse, I would recommend creating a class in Parse called Following which will have two User class pointers - fromUser and toUser. The class could also have a bool called allowed.
When a user requests to follow someone else, a new Following object is created and allowed defaults to false. Only when the toUser accepts to be followed, then you can update allowed to be true.
In terms of how to prompt the toUser if they accept the follower, you could use a simple UIAlertController.
Also, I highly recommend checking out the Parse Anypic tutorial.

Is it possible to filter statements by Team in Tin Can?

I'm recording statements to the LRS and in each of those statements I always set the "Team" property.
I know I'm able to filter those statements by verb, activity and many other parameters as described here.
However, I can't find a way to filter statements by Team (which is a property of Context).
Is it possible?
I think the best you can do is to use identified groups (a group with an IFI) as the value of the "team" property and then request statements using the "related_agents" query parameter. Note that this will include statements where that identified group is also the "actor" or in any of the other positions accepting a Group/Agent object, so you'll still have to post process them. As far as I know there is no way to request based on an unidentified group since they aren't considered the same group across requests.
There is no way to specifically request only statements based solely on the "context.team" property.
I am assuming that you have added team property to context.extension property. You should not add properties that are not allowed, otherwise, you might have issues in future.
Regarding querying by team or any other extension property, it cannot be done as per standard xAPI Spec. However, your LRS could allow you to do that. e.g. You can get an LRS like GrassBlade LRS or Learning Locker and get it customised to add more filtering options.

Multiple authentication methods for Apiary

I'm just getting started with Apiary and I can't tell if this is a limitation of the product or just me not understanding what to do.
I'm documenting an API which authenticates the user as part of every request. Sometimes the authentication is part of the path (a request for the user's profile would have the user id in the path), other times just as parameters (?user_id=1&auth=secret), and for POST requests, part of the incoming body as JSON.
Also, there are 3 methods of authentication in the app. You can log in with a Facebook UID, email address, or using the unique id of the device you're using. The result is something that looks like this:
##User [/user/{facebook_uid}{?access_token}, /user/{email}{?device_id}, /users/{device_auth_id}{?device_id}]
This works fine, and displays in the API as I'd expect:
But this introduces 2 issues:
1) If I wanted to add a set of parameters shared by all authentication methods, I would need to add it to all 3 like this:
## User [/user/{facebook_uid}{?access_token, extra_thing, this_too},
/user/{email}{?device_id, extra_thing, this_too},
/users/{device_auth_id}{?device_id, extra_thing, this_too}]
This seems a bit messy, it'd be much nicer to apply shared parameters at the end of the path array so they apply to all, something like this:
## User [/user/{facebook_uid}{?access_token}, /user/{email}{?device_id}, /users/{device_auth_id}{?device_id}]{&extra_thing, this_too}
But this doesn't work. Is there a way to do this? The documentation wasn't very helpful with more complicated stuff like this.
Also, would there be a way to create some kind of template which I could apply to all my methods? In the case where the authentication is part of the path its a bit unavoidable, but for other requests it would be nice to just do something like include: authentication and have it pull the unique_id/auth combo from a defined template somewhere.
Thanks!
First, there isn't really support for having a single model with multiple resource representations. It is an unusual thing to do and is actually good food for thought.
Second, using multiple URIs in [path segment] is probably going to confuse Apiary's mock server and make it unusable.
In my opinion, I'd split this into three models: Facebook User, E-mail User and Device User, with slightly different documentation (how are they created? Can you really create all of them through api? etc. etc.)
It also depends on how you want to document this. As path segments are not validated (it would be strange to have different resources based on the type of the arguments), you can just have (and I'd personally do just that)
## User [/user/{id}{?access_token, extra_thing, this_too}]
+ Parameters
+ id (required, string, `test#example.com`)...id of the user. Can be either user's e-mail, facebook id or device id from where user was created.
As for reusable parts, this is currently being implemented with authentication being part of that.

Resources