I'm trying to get a handle on how to use custom Swift classes to model my Syncano backend. I have classes MPUser and MPUserProfile exactly as described in this guide. However, instead of adding an avatar field, I'd like to add a friends list. Should this property be:
An array of MPUsers
An array of MPUserProfiles
An array of integers corresponding to the other users' IDs
Something else?
Edit: their page on classes makes it sounds like I would want an array of type Reference (referring to users' IDs) but their arrays can only have string/int/boolean/float. I'm now wondering if an array of (non-Reference) integers will work fine.
Thank you for your help.
Currently Syncano doesn't support holding arrays of references. It's something we are working on (adding many-to-many relationships), but in the meantime you should could safely just use array type and store ID of referenced objects in there.
When you store array of IDs, you can use either ID of a user, or ID of a user profile.
The connection between them is as follows:
User is a physical user that logs into your app.
His profile is an object that belongs to him.
User A cannot be accessed by user B, but profile of user A can be accessed by user B.
You can get a profile of user A either by using profile ID (object id from user_profile class), or by using user A id (owner field in object inside user_profile class).
Depending on which route you take, you can then ask Syncano for list of all friends doing either:
give me all user profiles, where ID is in [array of user profile IDs]
or, give me all user profile, where owner is in [array of user IDs]
An array of MPUser's definitely. I haven't used Syncano so I may be utterly wrong on this, but having using Couch, Firebase and played with Realm...
The whole idea of key/value/object/document stores like these is that details of the storage are abstracted away in the back end. So you put an MPUser in an array, and when you access that array sometime later you get it back. Totally magic. That the DB itself might physically store that as an Int64 or inline the entire string is of no interest to you - data in, data out.
I suspect you have worked in the SQL world, which is why you put that last option there? Generally that's not how you work in object stores - thank gawd.
Related
Scenario:
(with an ASP.NET web app - Core or MVC)
I have a database with Users and Items for each user.
That means the UserId is a foreign key in the Items table.
From the browser I login as a User. I get my Items as a list of ItemViewModels, which are mapped (AutoMapper) to ItemViewModels via a simple api GET request.
I want to update one of the items (which should belong to me - the logged in user) via a simple API call. So I send the modified item back to the server via a PUT request as an ItemViewModel.
First approach:
The simplest approach would be to include the Item's database ID, ItemId, in the ItemViewModel - so when I receive the item to be updated as an ItemViewModel, I can map it back to the existing item in the database.
This however sounds pretty unsafe to me, as anyone could modify the PUT request with any ItemId and affect items which don't belong to the user who executed the request. Is there anything I'm missing about this approach?
Second approach:
Don't pass the database PK ItemId in the ItemViewModel.
Instead use an additional form of identification: let's say that user X has 10 items. And they are numbered from 1 to 10 using a property named UserItemId(which also exists in the database).
I can then pass this UserItemId in the ItemViewModel and when I get it back I can map it to an existing Item in the database (if all was ok with the request) or discard it and reject the request if the UserItemId didn't match anything from the logged in user's items.
Is anyone using this approach?
Pros:
The user only has access to it's own items and can't affect anyone else's since it doesn't know the actual Item ID (primary key), and any modifications are restricted to it's items.
Cons:
A great deal of extra management must be implemented on the server side for this approach to work.
Any other approaches ?
Please consider that the case mentioned above applies to all entities in the database which a client side implementation can CRUD, so it's not just the simple case described above.
The proposed solution should work for the entire app data.
I know this question has been asked here and here but the first one doesn't have a satisfying answer and I don't think the second one really applies to my situation, since it just deals with the UserId.
Thanks.
EDIT
Please consider the Item above as an aggregate root which contains multiple complex subItems each with a table in the db. And the question applies for them as much as for the main Item. That means that each subItem is passed as a ViewModel to the client.
I should mention that regarding further securing the update request:
For the first approach I can easily check if the user is allowed to change the item. But I should do this for all subItems too.
For the second approach I can check if the user can update the Item as follows: I get the userItemId of the incoming ViewModel -> I get all the logged in user's items from the database and try to find a match with the same userItemId, if I get a hit then I proceed with the update.
I think your application is not secure, if you only hide the Id.
You must check, before changing the database entity, if the user is allowed to change the entity.
In your case you should check, if your Id from the authenticated user is the UserId in your item.
If your ViewModel ist similar or identical for your API you could use a FilterAttribute in your controller.
Example:
I have an Albums table filled with cd albums and I want to change album number 5 . An album model gets passed to the detail view of AlbumsController.
In the view I can then edit the album fields and submit the changes to album number 5.
If I change the hidden ID value of album number 5 into ID 27 album number 27 will get the values of album number 5
Is there a MVC ASP.Net build in way to prevent changing of keys ? Am I missing something ?
One way to solve this problem is to compute the hash of Album number and set it in the hidden field. The reason to use hash is that it is hard for the user to guess what value is it.
At the same time, hold the computed hash on the server Session. So next time when user posts data, you can check the posted hash with Session hash, and if there are one and same, then update the album object. If hashes doesn't match, then throw the error to user saying that data got tampered.
EDIT
To check user permissions on a given object, first get HttpContext.User.Identity which will give you the information about logged-in user into application. Using this information cross check if the same user got enough permissions on the object (say for example album 123) to perform update/delete operations.
You should be storing somewhere in your database the proper mappings between albums and users for allowed permissions. An index table where AlbumId and UserId should be stored.
Assuming you give the user a list of albums to change and permission to change them, then 'change album 5 to X' and 'change album 27 to X' are both valid commands they are going to be able to construct from the information you give them.
I Assume what you mean is,
how can I prevent a user modifying albums they have no permission to
modify by injecting a different id variable.
Once you phrase it like that the answer is obvious. When you receive the change request on the server, check the users permission to change the particular album before you do it!!
Also, using a GUID instead of an int Id, will make you life much easier
I recently have just been able to populate my core data DB. I have an attribute named username and I would like to get the total number of users on the system (in the DB) and print it out. I know I need to use NSFetchRequest along with NSEntityDescription. I am just not sure how to go about it. I haven't really seen a question like this on SO. The entity is named Account and my attribute is labeled username
For your particular case, I suppose you have each username as a separate record so you can use the -countForFetchRequest:error: method of NSManagedObjectContext to get the number of objects a given fetch request would have returned if it had been passed to executeFetchRequest:error:
I have an existing large app using plists to store its data. I store application state indicating current item selected, current user, and various other current selections in user defaults. This worked fine when the data was in plists. Now I'm refactoring to use Core Data instead of plists. I want to store a reference to an object instance as the currently viewed object. I know sqlite and Core Data have an ID for this object in the database, but I'm not sure what to store in user defaults. Three options come to mind:
Generate my own sequential ID, store that with the objects I want to remember as "current", store that ID in user defaults.
Try to use NSManagedObjectID and store in user defaults. I "think" I can convert it to a string as follows. Does this work?
NSString *stringID = [[[managedObject objectID] URIRepresentation] absoluteString];
I could create a current state entity in Core Data which is a singleton, only one row. This entity could have a to-one relationship to the current object I want to keep track of.
Suggestions appreciated for the approach with best design consideration.
Repeating from a comment, what are the drawbacks to approach #2? I've read conflicting accounts on the web. Some say the object ID is not consistent across migrations, yet Apple itself seems to suggest this as the solution.
In the Apple Class Reference for NSManagedObjectID, they discuss this very case and talk about saving the ID in user defaults. It says, "Object IDs can be transformed into a URI representation which can be archived and recreated later to refer back to a given object (using managedObjectIDForURIRepresentation: (NSPersistentStoreCoordinator) and objectWithID: (NSManagedObjectContext). For example, the last selected group in an application could be stored in the user defaults through the group object’s ID."
Does that mean the object ID URI representation always stays valid, even across migrations?
You should use your own unique identifier (ideally which will not server only for the purpose of this question) for your objects and use this identifier to retrieve the object from Core Data and store this identifier in the NSUserDefaults. So, yours 1. solution is correct, though it need not to be sequential.
The 3. solution would work also, but it is not very clean.
I want to be able to read the names of the exchange accounts.
ABSource objects only have 2 properties from what i could tell.One of them is an integer specifying the type of source(ex: 0 for local addressbook, 1 for exchange addressbook) and the other is a string specifying the name of the source.Unfortunetely the name of the source will not be the name of your exchange account,it will always be called "Contacts".The problem is that if you would save all the sources in an array and when writing a contact to a specific source you would acces it from there it will work...it will add it to the right source,my problem is i want to be able to select which account to add to from a table view and so far have found no way of differentiating the accounts.
Yes, for some Exchange accounts (and other types of accounts) it seems like there is no way to get any other name except "Contacts".
What you should do is:
Create a separate object that holds the ID and name of the source and has a boolean which tracks whether this account has been selected. Hold these objects within the array that is responsible for populating the UITableView. When the user selects a source, modify the boolean and at the end, when you want to know what the user selected, go through the array and select only the IDs from the objects that have been selected.