Struggling to get this working, lack of understanding, but if anyone could help me to get there, that would be great. Currently I have a user logging in as an administrator by just setting a boolean, this works fine:
if (authority == "true"){
let acl = PFACL(user: PFUser.currentUser()) // Only user can write
acl.setPublicReadAccess(true) // Everybody can read
acl.setWriteAccess(true, forUser: PFUser.currentUser()) // Also
var role:PFRole = PFRole(name: "Administator", acl: acl)
role.users.addObject(PFUser.currentUser())
role.saveInBackground()
self.activityIndicator.stopAnimating()
let vc : AnyObject! = self.storyboard?.instantiateViewControllerWithIdentifier("Admin")
self.showViewController(vc as UIViewController, sender: vc)
}
This sets an admin role in my parse database. What I am trying to do is to give privileges to this user so that he could edit all other users e.g. giving points to the students for the correctly completed tasks.
if let object = userObject?{
println(tasksCorrect)
object["tasksCorrect"] = tasksCorrect + 1
println(object)
object.saveInBackground()}
You need to ensure that user objects have an ACL that includes read/write access for the "Administrator" role.
Related
I would like my user to add/edit details about their profile after they register with my app.
#IBAction func doneEditting(sender: AnyObject) {
self.completeEdit()
}
func completeEdit() {
var user = PFUser()
user["location"] = locationTextField.text
user.saveInBackgroundWithBlock {
(succeeded: Bool, error: NSError?) -> Void in
if let error = error {
let errorString = error.userInfo?["error"] as? NSString
println("failed")
} else {
self.performSegueWithIdentifier("Editted", sender: nil)
}
}
}
the breakpoint stops right at user.saveInBackgroundWithBlock. No of the docs show how to append new columns after the signup.
Thanks!
You are mentioning that the user should be able to edit their profile after they have registered. When registering a user with Parse using signUpInBackgroundWithBlock, then the Parse SDK will automatically create a PFUser for you.
In your provided code you are creating and saving a completely new PFUser instead of getting the one which is currently logged in. If you are not using the PFUser which is logged in, then you will get the following error at user.saveInBackgroundWithBlock (which you are also mentioning in your post):
User cannot be saved unless they are already signed up. Call signUp first
To fix this, you will need to change:
var user = PFUser()
To the following:
var user = PFUser.currentUser()!
The rest of your code (for example user["location"] = locationTextField.text) works fine and will dynamically/lazily add a new column to your User database (which is what you want).
Parse allows you to add columns to a class lazily, meaning that you can add a field to your PFObject and if it is not present in your Parse class, Parse will add that column for you.
Here's example how you would add a column via code:
// Add the new field to your object
yourObject["yourColumnName"] = yourValue
yourObject.saveInBackground()
You'll notice that Parse will create a new column named yourColumnName on their web portal.
reference from HERE.
I have an app that can save multiple accounts to access my server API and retrieve data. Each account has its own credentials so the data pulled from server changes depending on which account is selected.
When my app runs first time, my API class checks my CoreData model to see which account is active and uses that account's credentials throughout the app. I can select a different account and set it as active and unset/inactivate all other accounts in my Accounts tableView and reset the Credentials object with the new selected account, but when I do my app still uses the account that the app first started with.
How do I structure my class to use the account's credentials that I select in my Accounts tableView? Below is my API class I use. This class is called when my app starts.
class API {
init(){
self.credentials = getActiveStore()
// I then use self.credentials to make API calls.
// Rest of the code is omitted for brevity
}
func getActiveStore() -> Credentials?{
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let fetchRequest = NSFetchRequest(entityName: "User")
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(format: "active = %#", 1 as NSNumber) //NSPredicate(format: "active == YES", argumentArray: nil)
var error:NSError?
let fetchResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as! [WooStore]
if fetchResults.count == 1 {
let name = fetchResults[0].name
let url = fetchResults[0].url
let username = fetchResults[0].username
let password = fetchResults[0].password
return Credentials(name: name, url: url, username: username, password: password)
}
return nil
}
}
I would just use the NSManagedObject that is returned as your credentials object. There is no reason to create a new object that is just a copy of the NSManagedObject.
Subclass NSManagedObject, add any convenience methods that you want to the subclass and return it.
Update
My User is an NSManagedObject class which doesn't have an initializer
All objects have an initializer. Even NSManagedObject.
However, you don't need to initialize the object because it is already initialized and populated! It is sitting in your fetchResults array.
if let cred = fetchResults.lastObject {
return cred
} else {
return nil
}
Instead of referencing the first object in the array over and over again just to construct some other object.
Update
and I still don't see the effect I want to have. The data still belongs to previous user after I selected different account.
Based on your code, you determine the active user based on a boolean flag in the persistent store. While this is not a good idea, lets roll with it.
To change the user, you would need to set the current user's flag to 0. Then you need to fetch the soon to be active user and set their flag to 1. Then save the context so that the changes are persisted in the store. Then this code will do what you expect it to do.
You would do all of that wherever in your app you are switching users. NOT in the code you have provided here.
I have an app that saves multiple user accounts for retrieving data from my API. There is always one account set to be active or flagged TRUE. When I select a different account I deactivate previously active account and activate selected account or set it to be TRUE. I do these using CoreData in my Accounts table view.
When my app starts my API class checks my CoreData to see which account is active and assigns its credentials to my Credential object.
I then use these credentials to access and get data from my server. All works perfect until this point.
My problem is when I select a different account and reset my Credentials object in my didSelectRowAtIndexPath method, my API class still has the previously active account's credentials. I can see/print the Credentials object has the selected account's credentials.
How do I adjust my objects to have/use only selected account's credentials?
class API {
var credentials:Credentials!
init(){
self.credentials = getActiveStore()
// I use self.credentials.username to make API calls later in the code
}
func getActiveStore() -> Credentials?{
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let fetchRequest = NSFetchRequest(entityName: "User")
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(format: "active = %#", 1 as NSNumber)
var error:NSError?
let fetchResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as! [User]
if fetchResults.count == 1 {
let name = fetchResults[0].name
let url = fetchResults[0].url
let username = fetchResults[0].username
let password = fetchResults[0].password
return Credentials(name: name, url: url, username: username, password: password)
}
return nil
}
}
Now this is the class that never changes. When I refresh my data after selecting a different account, the data I see belongs to previously active account. API class doesn't want to change.
Are you creating a new credentials every time you select a new cell? Because you credentials gets update just in the criation of the object
init(){
self.credentials = getActiveStore()
// I use self.credentials.username to make API calls later in the code
}
If you want credentials to be update a new instance of your API has to be created.
Another way is to create an update method and call it when a new cell is selected
func updateCredentials(){
self.credentials = getActiveStore()
// I use self.credentials.username to make API calls later in the code
}
My app has a login and signup. Once the user is logged in he can then choose to upgrade the account. When the account is upgraded, a new class in parse is created called "Upgrade". Here it has a bunch of subclasses with stored information. Then once the user is upgraded it brings him to a special page that only upgraded users have access to. But how can I check on login if the user is upgraded, and if he is, automatically bring him to the special page.
In my parse, I have the User information stored with subclasses "Username" and "Password". Then in a separate class I have the upgrade information stores with subclasses "Address", "Phone Number", and I have a linker to link back to the user who created it.
my current code for login is:
#IBAction func loginButton(sender:AnyObject) {
var username = self.usernameTextField.text
var password = self.passwordTextField.text
if(password.utfCount <5) {
var alert = UIAlertView(title:"Invalid", message: "Password must be greater than 5", delegate: self, cancelButtonTitle:"OK")
}
else {
PFUser.logInWithUsernameInBackground(username, password: password, block:{(user, error) -> Void in
if ((user != nil) {
self.performSegueWithIdentifier("LoginSegue", sender: nil)
This is the basic code but it does not check to see if the user is upgraded.
I tried:
if(PFUser.currentUser() == PFQuery(className:"Upgrade")) {
self.performSegueWithIdentifier("UpgradedSegue")
But obivously this didnt work due to the current user not equaling that class.
What kind of code could I user to check if the user made a Upgrade class within parse?
I have tried messing around with fetchinbackground code and enter code hereobjectinbackground but I can't seem to make those work.
I don't know the Swift very well, so sorry if there are errors, but try something like:
var query = PFQuery(className:"Upgrade")
query.whereKey("user", equalTo:currentUser.objectId)
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject!, error: NSError!) -> Void in
if error != nil
println("The getFirstObject request failed.")
} else if object == nil{
//No Upgrade object with that user's ID
} else {
// The find succeeded, user has created an Upgrade object
println("Successfully retrieved the object.")
}
}
You could also set up your code to store the pointer to the Upgrade object on the user, rather than the other way around. You could set a bool value on the user to see if they have upgraded. If it is true, then take them to the upgrade screen, or fetch the Upgrade object, whatever you need first.
With this code, I try to add user to existing Parse.com role "banned":
var roleACL = PFACL()
var role = PFRole(name: "banned", acl:roleACL)
role.users.addObject(userObject) // This should add user
role.saveInBackground()
I get error 137
A duplicate value for a field with unique values was provided (Code: 137, Version: 1.6.1)
I guess it tries to recreate the role.
However, form the doc, at https://www.parse.com/docs/ios_guide#roles-security/iOS I don't see how i can add a user to an existing role.
Got the solution. The misleading code above, as is on Parse.com site tries to recreate a role.
The correct code is :
var queryRole = PFRole.query() // You need to get role object
queryRole.whereKey("name", equalTo:"banned")
queryRole.getFirstObjectInBackgroundWithBlock() {
(roleObject: PFObject!, error: NSError!) -> Void in
if error == nil {
// Assign user to banned role
var roleToAddUser = roleObject as PFRole
roleToAddUser.users.addObject(userObject)
roleToAddUser.saveInBackground()
}
}