itsniper / FTASync

Allows you to sync CoreData entities with a Parse backend.
MIT License
311 stars 59 forks source link

ACL question #8

Open hugomelis opened 11 years ago

hugomelis commented 11 years ago

For my app I need to have a way to give other users access to an entity if they are invited. So a user can invite another user to have access on an entity. I found out Parse.com has an excellent way of dealing with this in the form of ACL's.

I would love to use these ACL's in the way they are meant to be used and expand the standard use of the default ACL for all records, but I cannot seem to find out where to put the code to fill them.

My first guess was to put them into this method:

In that method I can check which entity is being updated and then add the specific user defined ACL for that entity. I am not sure if that is the way this was intended? Could you please give me some pointers on this. Maybe there is a way better (nicer) way to handle this, maybe even not with the ACL's.

cleqo commented 11 years ago

First than all if you set a defualt ACL changing the ACL of an object wont work as the the new ACL you create uses the defualt as a template, second, the ACL should be set in a different section any of the methods in FTASync seems inadequate so I recommend to create a helper method [FTASyncParent insertLocalEntityForClass:@"ClassName"] there you create all the variables you need and there you set the default ACL behavior then some other object adds the new ACL when need it. For your app, what you need to do its to create a role per user in a helper method that creates a role like @"userIdClassNameRole" then whenever you need to grant acces to that object just add a user to that role, it's actually pretty easy and works like a charm. (This way every user has sharing options for any entity you create)

Also remember to use PFObject *remoteObject = FTASyncParentSbclassObject.remoteObject [remoteObject doStuff] some how if you use [FTASyncParentSbclassObject.remoteObject doStuff] the custom accessor doesn't gets called and changes doesn't reflect in parse I had suffer hours with that issue.

cleqo commented 11 years ago

} //You need to add the property so whenever you are locally creating a new object, you can set a defaultACL this to avoid critical changes in FTASync

cleqo commented 11 years ago

Its very important to set the ownerId property in FTASyncParent class, and add it in the [FTAParseSync getObjectsOfClass:(NSString )className updatedSince:(NSDate )lastUpdate] query if you alter the ACL for objects and you get not only user created objects the FTASync will make a mess in your data base, make sure to sync only the objects created and owned for the user.

Also remember that if you use localEntitly.remoteObject in that moment all the properties will be copied and it will require more code so best practice its to use it after all local properties are set, also, set the custom ACL at the end for the same reasons

hugomelis commented 11 years ago

Thanks Cleqo! I will try this stuff this weekend, and will report back with the results! Thanks for your time and effort...

hugomelis commented 11 years ago

Well yesterday and today I have been trying to get this to work in my app, but I cannot seem to fill in the last gaps in the code. I will try to explain what I did so far:

1) I added the method: "insertLocalEntityForClassName" into the FTAParentSync class. I changed the following line from: NSManagedObjectContext moc_ = [NSManagedObjectContext defaultContext]; to: NSManagedObjectContext moc_ = [NSManagedObjectContext MR_defaultContext]; because of an error, and added the following property to the .h file: @property (nonatomic) BOOL defaultACL; and did a @synthesize in the .m file (I guess it is not needed in the datamodel?) After that I replaced the existing method: "remoteObject" with the one you supplied. Then I added the method: "setDefaultACLForObject" to FTASyncPartent.m And after that the method: "createInitialUserRoles" also to the FTASyncParent.m class.

Then I kind of seem to miss where to call the "createInitialUserRoles", and the "insertLocalEntityForClassName" method from?

Also about the adding of the ownerId, do I need to put that in the datamodel? Or is it just a property in the class? I guess for the query to work in FTAParseSync I have to add something like this: [query whereKey:@"ownerId" equalTo:] but I cannot seem to find out where to get the ownerId from?

Many questions, hopefully you can help me out with! Thanks...

cleqo commented 11 years ago

yeah sorry for that, but as i told you i was still working on it, and it resulted to be a hell, working with roles its not as easy as it seems, as you have to retrieve it for everything, at the end the structure its quite difficult im thinking in posting a FTASync plus role per class per object, so any object created by an user can have Friend, public, private or selected users only ACL, after two days i made it work but its quite complex, the create initial users roles its used once, when you sign up the user for first time, after that you have to create a complex structure of roles to make it work correctly, the ownerId indeed goes directly in FTASynParent model so every object inherited also have it, the "insertLocalEntityForClassName" method goes in _FTASyncParent so you call it everywhere and it will be an auto sync object, its quite difficult but it works quite nice actually and the query constraint is right, just ensure to add it in both cases when there is a last update of the class and when doesn't.

The defaultACL needs to be out of model, thats the easier way to not affect any of the delicate structure in FTASync

You can also add an shouldSync property to FTASyncParent core data model, and decide in realtime when to sync local objects, its quite nice and requires minimum changes to make in the predicates of FTASyncHandler, but it will only work in objects without relationships or where all objects in relationships are set to shouldSync = NO

in my app the structure for roles ended been something like this:

after that i have to retrieve each role, and assign it every time to grant public acces controlled post creation, my app will scale to a point if i don't do that, changing ACL will be impossible in a future. In your case it will be probably much more easier as you only have to assign a new user to the role ACL and a new user to the "users" PFRelation

the sets default ACL behavior in my app goes like this, but you use it as you need it

}

This its much more complex than you need, but it will give you an idea of what you can do with ACL and FTASync,

IMPORTANT you can see i add a roles array to the user object, thats it because to add users to an object or set subroles you need to fetch the role to work, remember than relations can only be set with objects already saved in parse (thats why i set the sub roles after creation in the create default roles for user)

This structure what it does, its to create a parent role with read access or write access wich only the user can acces, then it creates sub roles that will inherit that permissions as the user wants it, and a public role that its granted to every person that wants to see an object that could be protected for the user, that way, if the user actually grant public permissions, i just have to add the public role to the parent role, and everyone can read or write the objects, the public role ACL needs to be public also, so every one can retrieve it and get the roles theme selfs.

cleqo commented 11 years ago

p.d. i'm mexican sorry for my english :)

hugomelis commented 11 years ago

I almost got it to work correctly (I think), but am still learning on the ways you have created this system. Hard thing is though I cannot test it very well because I have no PRO account on parse.com and you seem to can only have 1 customer role then. Are you on a PRO account?

I will continue tomorrow on this project and will report back any new findings! Thanks anyway for the support so far!! And by the way I am not a native English speaker as well, I am from Holland.. ;)

cleqo commented 11 years ago

Oh, yeah you need a pro account to create more than one role i forgot about that even when doing my early testing