Firebase Database setValue: or removeValue failed: permission_denied iOS - ios

I'm trying to write data to Firebase Database but I keep receiving the following error when my saved button is pressed.
2016-12-02 11:09:42.548 StartupNow[1482:60415] [FirebaseDatabase] setValue: or removeValue: at /test/-KY-VpLZWbp4vjF3BpMk failed: permission_denied
Things I've tried:
I've made sure my .read and .write rules were set to true in my console, reconnected my savedButtonPressed button, and wrote the Firebase reference in a function and called it in my savedButtonPressed() method.
Extra Resource Here is the tutorial I'm following along. https://youtu.be/F42CzqIBxHQ?t=4m14s
var ref: FIRDatabaseReference?
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
}
#IBAction func saveButtonPressed() {
// TODO: Post data to Firebase
firebaseChild()
print("********************************")
print("********************************")
}
func firebaseChild () {
ref?.child("Test").childByAutoId().setValue("Hello Firebase")
}

I had a similar issue. It was resolved by resetting the read / write rules for the database. If you changed your rules try reseting them to the default.
Warning: These rules allow anyone to read and write to your database!
Default Rules for Real-time Database
{
"rules": {
".read": true,
".write": true
}
}
Default Rules for Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write;
}
}
}

FreddieOh and I chatted over Slack, and the problem was that the database that was listed in the GoogleService-info.plist file didn't match up with the one he was editing. (It looks like maybe in this case, he had deleted and recreated the project in the Firebase console, but hadn't updated the plist file.)
If you find yourself in the same situation where you've set your read and write access to true and are still getting permission denied errors, open up your GoogleService-info.plist file and look at the entry for DATABASE_URL. Then go to the Firebase Database in your project, look at the top of the data tab, and confirm that the URL listed there is the same as the one in your plist file.
I suppose the other thing to check for would be that you updated your database rules to allow global access but forgot to click the Publish button. That... may have happened to me at one point. :)

Go to your Firebase console, and perform following steps which is identify in image.
Please lookup image and follow these steps. If you are beginner and facing problem in image. I make little video about error.
Video Solution :
https://youtu.be/FcQCPqckvqo
Image Solution

I have solved the same issue after trying to use every resource. The only solution is that
Go to fireBase Console -->select your project -->Go to database -->select the Rules("Show in the mid next to the Data")-->make the make both option true
{
"rules": {
".read": true,
".write": true
}
this will be work perfectly

Make sure to select real time database and edit the rule then publish .

Related

Changing Firebase configuration at runtime on iOS

For my project, I have 2 environments:
test
prod
and 2 localizations:
en
tr
and an app for each combination: (these names do not mirror Firebase project ids)
test_en
test_tr
prod_en
prod_tr
And I have a separate plist file for each of these apps in the project, with the names Firebase-(app_type).plist ie Firebase-test_en.plist or Firebase-prod_en.plist
I am initializing FIRApp using this way:
private func ensureLoaded() {
let options = FIROptions(contentsOfFile: Bundle.main
.path(forResource: "Firebase-\(firebaseApplicationName)", ofType: "plist"))!
if nil == FIRApp(named: firebaseApplicationName) {
FIRApp.configure(withName: firebaseApplicationName, options: options)
}
}
And it seems to work ok, until I try to actually connect to firebase database, where it says:
Firebase is not configured correctly, please call [FIRApp configure]
So my question is, how do I make firebase work where I want to dynamically change configurations? There are some other questions that describe how to change configuration based on some environment variables / compiler flags but they are all referring to changing the plist file, which changes the configuration during build time, but I want to change it dynamically during runtime. Is it supported at all, is there a way to make it work?
Thanks in advance.
I found what the problem was, we were using FIRApp.auth().currentUser somewhere in the app, which returns the auth for "default" app and since we had multiple configs, we had no notion of a "default" app, so the configuration was incomplete. I changed that to FIRAuth(app: myApp)?.currentUser and it works as expected now.

React native - How to implement iOS Settings

Wondering if someone could help me with this, or at least point me in the right direction.
I've been searching for documentation on how to get/set settings in a React Native iOS app so that those settings appear in the iOS Settings app listed under my app. I see that there is a Settings API, but it appears that the documentation is not complete. The function definitions are listed there, but that's it. No examples or anything.
Can anyone provide me with a simple example, or point me to a tutorial or something that will help me get going? I'm assuming I import Settings from react-native, just like I would do for other APIs, but beyond that I'm not sure where to go.
Thanks.
As stated in React Native documentation :
Settings serves as a wrapper for NSUserDefaults, a persistent
key-value store available only on iOS.
If you want to add iOS Settings bundle to your app you can use this.
As per Chris Sheffield's comment, here is what I have succeeded with so far:
Add a Settings.bundle to your Xcode project
Highlight the project > File > New > File
Choose "Settings Bundle" > Next
I just left the default name: Settings.bundle
Open the Root.plist file inside of the bundle
Make changes based on Apple's documentation (version I'm referencing is archived here: https://web.archive.org/...)
The important value to keep track of is the item's Identifier
Save, compile, and install the app
You can now use Settings.get('<identifier>') like either of these:
const varName = Settings.get('var_name')
const [ varName ] = useState(Settings.get('var_name'));
Notes
I suggest using some method of watching for changes so that your app updates when the user changes settings while it's running, but these are the only parts required.
I do not suggest letting the user also change those specific settings in-app since that goes against the principle of Single Source of Truth, but it's your app, you do what's best for you and your users.
Hope this plugin will help. react-native-permissions
export const _checkPermission = (permissionName) => {
return Permissions.check(permissionName).then(response => {
if (response === 'denied') {
return false
} else if (response === 'authorized') {
return true
} else if (response === 'restricted') {
return false
} else if (response === 'undetermined') {
return false
}
})
}
also, you can use this for asking permission
_requestPermission = (permissionName) => {
return Permissions.request(permissionName).then(response => {
return response
})
}
export const _alertForPermission = (permissionName) => {
return _requestPermission(permissionName)
}

Trying to use Realm Object Server Tutorial

I have created an Amazon Web Services EC2 instance and deploy one of the AMIs with a Realm Object Server as its documentation explains:
https://realm.io/docs/realm-object-server/#install-realm-object-server
Once installed and created my admin user, I have completed the iOS tutorial: https://realm.io/docs/tutorials/realmtasks/, just until point 7, enough for creating task, but when I add new task in app, nothing happens. Debugging, I notice that next sentence try, is not executing:
let items = self.items
try! items.realm?.write {
items.insert(Task(value: ["text": text]), at: items.filter("completed = false").count)
}
The items collection seems to be initialized properly:
In the ROS dashboard, can see the database referenced in Xcode:
In image can be see "Default permissions" property is no access, is this the reason of not creating new task? If so, how can I change that permissions? If that is not the reason, anyone could help me?
thanks in advance
The problem was that I did not follow al the complete tutorial because I do not want to use the desktop application, just mobile example, but realm init objects in desktop app, so I never got a valid realm where perform actions.
For a quick and simple start with this realm tutorial pointing to an online server, not local, you must initialize the TaskList object and add it to self.realm on setup
// Show initial tasks
func updateList() {
if self.realm.objects(TaskList.self).count == 0 {
let list = TaskList()
list.id = "000001"
list.text = "lista de prueba"
// Add to the Realm inside a transaction
try! self.realm.write {
self.realm.add(list)
}
}
if self.items.realm == nil, let list = self.realm.objects(TaskList.self).first {
self.items = list.items
}
self.tableView.reloadData()
}
checking if there is not a TaskList with if self.realm.objects(TaskList.self).count == 0 {, you can create one and init realm.
You probably forgot to launch Mac demo app first or login with a different user. The tutorial assumes that existing data will be synced at login. If you have never launched the Mac app or logged in a different user, it may happen that items are not managed by Realm.
The tutorial says the following:
First, please follow the Get Started instructions to get set up with the Realm Mobile Platform and to launch the macOS version of RealmTasks.
Also, you attempt to try this tutorial with ROS on AWS. The tutorial assumes running ROS on a same local machine.
So you should modify the Mac app code to connect to the AWS, then run it to synchronize the initial data. Then run the tutorial iOS app.
The default permissions here show whether all other users can access the Realm or not, which isn't the case here. We already have an internal issue around clarifying this.
The registered user who owns the Realm has individual permissions to it by default. If you wouldn't have permissions opening the synchronized Realm from the client would also fail because of insufficient permissions, so this isn't the problem here.
So going back to your code:
try! items.realm?.write { … }
My guess would be that the problem here is that the collection isn't already attached to a Realm, so that items.realm? evaluates to null. In that case the write transaction wouldn't be executed.
You can resolve this by making sure to add the items first to a Realm or executing the write directly on a synchronized Realm.

Disable confirmation on delete request in PHPhotoLibrary

What I am trying to do is to save videos to PHPhotoLibrary, and then remove them when upload to clients remote server in the application completes (basically, photo library serves as temporary storage to add additional layer of security in case anything at all fails (I already save my vides it in the applications directory).
Problem:
The problem is for that to work, everything has to work without input from the user. You can write video to photos library like this:
func storeVideoToLibraryForUpload(upload : SMUpload) {
if PHPhotoLibrary.authorizationStatus() != PHAuthorizationStatus.Authorized {
// Don't write to library since this is disallowed by user
return
}
PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in
// Write asset
let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromVideoAtFileURL(NSURL(fileURLWithPath: upload.nonsecureFilePath!)!)
let assetPlaceholder = assetRequest.placeholderForCreatedAsset
let localIdentifier = assetPlaceholder.localIdentifier
// Store local identifier for later use
upload.localAssetIdentifier = localIdentifier
}, completionHandler: { (success, error) -> Void in
....
})
}
And that works flawlessly, I get local identifier, I store it for later use.. Unicorns and rainbows.
Now when I want to remove that video immediately after upload finishes, I call following:
func removeVideoFromLibraryForUpload(upload : SMUpload) {
// Only proceed if there is asset identifier (video previously stored)
if let assetIdentifier = upload.localAssetIdentifier {
// Find asset that we previously stored
let assets = PHAsset.fetchAssetsWithLocalIdentifiers([assetIdentifier], options: PHFetchOptions())
// Fetch asset, if found, delete it
if let fetchedAssets = assets.firstObject as? PHAsset {
PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in
// Delete asset
PHAssetChangeRequest.deleteAssets([fetchedAssets])
}, completionHandler: { (success, error) -> Void in
...
})
}
}
}
Which successfully deletes the video, BUT user have to confirm deletion first. That is a problem as that backing up won't work.
I obviously know why there is confirmation (so you don't clear entire user library for example, but the thing is, My app made the video - and so I thought there will be way around it, since as an "owner" I should not be doing that, or at least have option to disable confirmation.
Thanks in advance!
TLDR: How can I disable confirmation on delete request, if my application created that content? (I don't want to delete anything else).
Note: Somebody can probably say this is rather strange thing to do but the application is distributed internally and there is good reason to do it like this (the video content is too valuable to be lost, even if user deletes the application for some reason, or there is anything at all that goes wrong, we need to be able to preserve the videos), so please don't question that and just focus your attention on the question :)
I cannot see a way to avoid the delete confirmation. It is an implementation detail of the Photos framework, similar to the way you cannot prevent the device from asking the user's permission to use the microphone when your app tries to use it, and is a matter of security & trust. Once you have saved an asset to the device photo library your app is no longer the owner of that asset, so as you noted in your question the device must of course ensure the app has the user's permission before it goes about deleting such data.
You can never entirely safeguard your users' data against their own unpredictable behaviour - if they decide to remove your app, or delete a particular asset from within Photos, it is up to them. I think your best option is to either put up with the built-in delete confirmation, or to provide a guide to your users that makes it clear that they should be careful to protect this important data by backing up their device, and not deleting the app!
If you did decide to stick to this approach, perhaps the best thing you could do is to prepare the user for the fact that their device may ask them for confirmation to delete a file that is being uploaded to your own servers. For example, put up your own modal alert just before trying to delete the asset. I wouldn't normally suggest that kind of approach for a public shipping app, but since you're only distributing internally it may be acceptable for your team.

For plug in running on iOS

What I want to implement is as follow:
A-app (calling app) : request the return value of a-string sent as parameter : request(a-string) -> b-string.
B-app (plug-in installed separately by me or others, it plays the role of dictionary or database ) : search a-string from database and return the result (b-string).
With successful experiences of plug-in on android and with Apple's confident rhetoric of plug-in, I thought plug-in, of course, run on iOS. After a lot of hard work, however, I finally found out:
* Note : The creation and use of loadable bundles is not supported in iOS.*
Nonetheless, not giving up, I finally made it with custom URl and pasteboard:
A-app : write a-string and false state to pasteboard & call B-app via custom URL.
B-app : viewDidLoad runs following func and thereafter exit program ; func { read pasteboard and search from database & write the result(b-string) and true state to pasteboard }
A-app : while-loop detects whether state is false or true. if true, catch b-string from pasteboard.
Anyway it works but it's too long thus almost useless. Do you have any idea for better solutions? Why doesn't Apple allow plug-in for iOS? Any responses are welcome. Thank you.
I can't answer why Apple doesn't allow plug-ins, but I can offer some advice on what you're trying to achieve.
The common pattern for sending data back to your application is to implement a callback url, so the A-app would also implement a custom URI and add that to the uri sent to B-app.
B-app would then process the uri as you have already implemented, but then instead of exiting, it simply sends the data you requested in the uri passed to it.
See http://x-callback-url.com for more details and example implementations.

Resources