I've got a question about the best way to allow user's information to be visible between users in certain situations.
For example, my app will have a "FriendRequest" class to model friend requests between users. The "FriendRequest" class has two User pointers, "toUser" and "fromUser".
I also set a default ACL for all user objects to restrict access to that user only for read/write.
My question is, when a user sends a friend request, I add the pointers for each user, and set the ACL of the "FriendRequest" object to allow both users to read and write to that object. However, when the user retrieves the friend request data, the "fromUser" data is not returned from the query because the ACL of the "fromUser" allows access to only that user - not to the other user who receives the friend request.
What is the best way to allow this data to be visible? Whenever a "FriendRequest" is created, should I add read permissions to the "fromUser" ACL for the "toUser" to be able to read it's information?
Any help is appreciated!
Thanks
Ok lets setup some sample data to make the example problem clearer.
In the Users table:
{objectId:"BBBB", name:"Bob", age:18, email:"bob#email.com", ACL: only Bob Read/Write}
{objectId:"JJJJ", name:"Jane", age:27, email:"jane#email.com", ACL: only Jane Read/Write}
So Bob sends a friend request to Jane. You create a new object in the FriendRequest class.
{objectId:"XXXX", fromUser: <ptr to BBBB>, toUser: <ptr to JJJJ>, ACL: Bob and Jane Read/Write}
In your current setup, since you have setup the ACL so that noone else can read them.
Option 1
As you have suggested, when Bob makes the request to Jane, since it is initiated from a device where Bob is logged in, he can add Jane to the ACL. You will then need to remove Jane from the ACL either when she accepts or rejects the friend request, or perhaps after a certain amount of time.
This is simple when Jane needs to request data from Bob, as she can pull it from his user class, however it requires more management later on (ensuring the ACLs are reset properly later on, using a scheduled task to ensure that all friend requests not resolved after 2 weeks are "rest", finally, if there is some reason you are securing all user classes so that they are read only, temporarily making all of Bob's attributes readable to Jane might be a bad thing.
Lazy Option
You could just make all users read-to-all. More insecure obviously and something I imagine you want to avoid since you are using ACLs and posted this in the first place.
Data Duplication Option
This requires temporarily data duplication, but then you are only the specific information you require, nothing more. Say you want name and email but not age from the user.
{objectId:"XXXX",
fromUser: <ptr to BBBB>,
fromUserName: 'Bob'
fromuserEmail: 'bob#email.com'
toUser: <ptr to JJJJ>,
ACL: Bob and Jane Read/Write}
So when Bob creates the request, he puts his own info into the request object. Jane can read this info. Once the request is complete, you could make it so that Jane could read Bob's data, or you may have some other table FriendRelations which described these relationships (again, duplicating relevant data if this made things more secure for you).
Related
I would like to know the usage scenario of POST vs PUT in a WebAPI . I know the basic concepts that POST is for creating resource and PUT is for updating resource but not able to fully understand why we need a PUT over a POST.
I have 2 WebAPI methods which creates/updates data to my SQL store
1. CreateUser(UserDto)
2. UpdateUser(UserDto)
UserDto contains userId, username and email.
I can use POST for both CreateUser and UpdateUser methods which creates and updates user to my store.
Then what is the real advantage of using POST for CreateUser and PUT for updateuser? Is it just a standard/convention?
Thank you
POST always creates something new. PUT updates a existing thing. It is a convention.
You should have:
POST /users : to create a new user. The payload should not include the ID
PUT /user/(id) : to replace a user DTO with the data in the payload. Again, the payload should not contain an user id
PATCH /user/(id): to update specific members of the user, but the id.
It is a design convention, like software design patterns, to make it easy to communicate and understand by whoever has to consume the API.
POST is usually used to add a new resource into collection of resources.
Like this: POST /users.
This operation is NOT idempotent and it will have a side effect at each call.
While PUT is usually used with a replace semantic and you know the exact resource which you want to replace.
Like this: PUT /users/1.
This operation is idempotent and it will not have any side effects on subsequent calls.
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.
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.
For example, I have a field that give user to type their domain, the user can type any domain on this, but I don't valid this domain is belong that user. Of course, I can generate a random number text file for user to upload, and when I get the random number text file, if it is match, I can just treat it as a valid domain holder. But, except from this method, is that anyway to do so? Thanks.
Options I have seen:
Have user Create a Text file in document root, check for it
Send Email to contacts listed in whois (Or other ROLE type accounts (postmaster, hostmaster, etc...), with token they need to
return
Have them create an 'A' record in their DNS that is unique and you can query for.
There really isn't any other way of telling if they have control over the domain. Using whois information isn't 100% accurate as people don't update it, or their info isn't registered to them, or is hidden behind something like domains by proxy. There is no standard information in DNS, that can tell you ownership. Since google uses the DNS method and the text file method (I think), you can probably safely assume that is a good way to verify it.
I came across another Stackoverflow post regarding Get vs Post and it made me think. With CI, my URL for deleting a record is http://domain.com/item/delete/100, which deletes record id 100 from my DB. The record_id is pulled via $this->uri->segment. In my model I do have a where clause that checks that the user is indeed the owner of that record. A user_id is stored in a session inside the DB. Is that good enough?
My understanding is, POST should be used for one time modification for data and GET is for retrieving regards (e.g. viewing an item or permalink).
You really ought to require a post request when deleting. In CodeIgniter this could be as simple as checking $this->input->post('confirm')
Part of the justification is you don't want data changed on a get request. Since you said you are requiring the person be the owner, there still is the problem that some one puts an image with the source being http://domain.com/item/delete/100 Using post isn't a cure-all as you can do post requests from javascript so it would still be possible for a malicious user to create the delete request if you aren't properly filtering input.
I should admit that I'm a bit of a purist and just feel requiring post is the right way. Its how the standards were written (okay you could argue it should be a DELETE request but browsers typically don't support them) and in other cases you really need to use them (there have been cases of web crawlers deleting pages).
If you want to have the delete link be http://domain.com/item/delete/100 then you could display a confirmation message with a form that does a post action as confirming the deletion.
I hope this helps,
Bill