export data from firebase firestore - firebase

I am doing an secret santa app for my university project and I store users into firebase firestore, then I want to pair them randomly. I think one way to do this is to download this database as json file. Can anyone tell me how to download firestore database as json file, or another way to pair them randomly?
Thats how i authenticate and add user into database:
registerButton.setOnClickListener {
auth.createUserWithEmailAndPassword(emailEditText.text.toString(), passwordEditText.text.toString())
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Log.d("Jemala", "createUserWithEmail:success")
val data = HashMap<String, Any>()
data["email"] = emailEditText.text.toString()
data["password"] = passwordEditText.text.toString()
data["fullname"] = fullnameEditText.text.toString()
val newCityRef = db.collection("people").document()
newCityRef.set(data)
Toast.makeText(this, "Registered Successfully", Toast.LENGTH_LONG).show()
val user = auth.currentUser
} else {
// If sign in fails, display a message to the user.
Log.w("Jemala", "createUserWithEmail:failure", task.exception)
Toast.makeText(
baseContext, "Authentication failed.",
Toast.LENGTH_SHORT
).show()
}
// ...
}
}

Related

Document references must have an even number of segments, but 8VMCfTZIAmOwRRb2JZsVT8K04o22 has 1

I am trying to add data to Firestore Database, when a user is created, this is where i am getting this error: firestoreDb.document(uidd).collection("users").add(users)
This is my code:
auth.createUserWithEmailAndPassword(email, password).addOnCompleteListener { task ->
btnRegister.isEnabled = false
if (task.isSuccessful) {
val success = true
Log.d(TAG, "createUserWithEmail:success")
val user = auth.currentUser
uidd = auth.currentUser!!.uid
val users = User(
auth.currentUser?.uid.toString(),
age)
Toast.makeText(this, uidd, Toast.LENGTH_SHORT).show()
firestoreDb = FirebaseFirestore.getInstance()
firestoreDb.document(uidd).collection("users").add(users)
} else {
val success = false
Log.w(TAG, "createUserWithEmail:failure", task.exception)
Toast.makeText(baseContext, "Authentication failed.", Toast.LENGTH_SHORT).show()
}
}
Please help me solve this issue :)
Directly under the root of Firestore you find collections, not documents.
I think what you're trying to do is create a document for the user uidd in the users collection under the root. That'd be:
firestoreDb = FirebaseFirestore.getInstance()
firestoreDb.collection("users").document(uidd).set(users)
Also see the documentation on setting a value to a document.

flutter refresh the user token of firebase in order to access firebase real-time database. (In a period of time)

I was using swift and Kotlin before.
We need to refresh the user token when we are using auth user of firebase to access firebase real-time database. (In a period of time)
How to do it in flutter?
Here with the code of Kotlin:
var mAuth: FirebaseAuth? = null
mAuth = FirebaseAuth.getInstance()
val cUser = mAuth?.currentUser
if (cUser!=null) {
cUser.getIdToken(true).addOnCompleteListener(object : OnCompleteListener<GetTokenResult> {
override fun onComplete(task: Task<GetTokenResult>) {
if (task.isSuccessful()) {
val idToken = task.getResult().getToken()
println("token has been refresh")
} else {
// Handle error -> task.getException();
println("token refresh Error Error Error Error Error Error")
val textError = context.getString(R.string.errorForInsertDataToFirebase)
alertPopUp(context, "", textError)
}
}
})
}

How to force logout firebase auth user from app remotely

I have a project which uses firebase auth with firebaseUI to authenticate users. I have enabled Google, Facebook and email providers. What I need is to remotely logout or disable some of the users.
I want the users to logout from the app on doing so. I tried disabling the user in the firebase console and also used the firebase admin SDK (https://firebase.google.com/docs/auth/admin/manage-sessions) to revoke the refresh tokens.
I waited for more than 2 days and still noticed that the user was logged in and could access the firestore data.
I have also gone through and tried
Firebase still retrieving authData after deletion
Can anyone point to what I am doing wrong ?
You also cannot remotely force a user to be signed out. Any sign out will have to happen from the device that the user is signed in on.
There is no way to revoke an access token once that is minted. This means that even if you disable the user's account, they may continue to have access for up to an hour.
If that is too long, the trick (as also mentioned in my answer to the question you linked) is to maintain a list of blocked users in your database (or elsewhere) and then check against that in your security rules (or other authorization layer).
For example in the realtime database, you could create a list of blocked user's UIDs:
banned_uids: {
"uid1": true
"uid2": true
}
And then check against that in your security rules with:
".read": "auth.uid !== null && !root.child('banned_uids').child(auth.uid).exists()"
You can send a message data with FCM to force to log out.
For example, if the users use android application.
Save the FCM token in a collection in firebase Realtime.
configure the Android client app, in the service. LINK You have to make when receive a message with especial string, force to log out.
make the trigger you need in cloud functions, to send the data LINK when you need the user log out.
SUCCESS!
As per your scenarios, i assume that you need to make user logout when user is disabled.
Use One global variable to store TokenNo (might be in shared preference or sqlite):
Add following code to your manifest:
<service android:name=".YourFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Add following code in your
public class LogoutOntokenchange extends FirebaseMessagingService{
#Override
public void onNewToken (String token){
if(TokenNo=>1){ //if tokenNo >=1 means he already logged in
TokenNo=0;
FirebaseAuth.getInstance().signOut(); //Then call signout method
}
else{
TokenNo=1; //store token no in db
}
}
}
What Happens here:
When user logged in first time onNewToken is called then It goes into else then TokenNo is updated to 1 from 0.
When You disable any user then automatically token is refreshed.Then OnNewToken is called then TokenNo>=1 so user will be logged out.
NOTE: When user log in for first time i.e if TokenNo variable is not stored then store it as 0.
For reference: https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService
The only way I can think about is adding a if-else block in your starting activity.
Store the that status of user (verified/banned/deleted) in Firebase Real-time database. Then retrieve the status of user at start of application and add the code:
if (currentUserStatus.equals("banned"))
{
currentUser.logout();
}
What I've done is I created for each user upon registration a Firestore document with the UID as document ID. In this document I store an array which stores all fcm tokens the individual user receives when logging into a new device. That way I always keep track where the user is logged in. When the user logs out manually the fcm token will be deleted from the document in Firestore as well as on the device.
In order to be able to log out the user everywhere they are signed in I did the following. When starting the app and once the user is logged in I start a snapshot listener that listens to all changes in the users document. As soon as there is a change I retrieve the new array of fcm tokens, search inside the array for the local current device fcm token. If found, I do nothing. If the fcm token is no longer in the array I will call the local logout method and go back to the login screen.
Here are the methods I used in swift on iOS. The closures (passOnMethod) will just trigger an unwind segue to the login view controller.
import Foundation
import Firebase
class FB_Auth_Methods {
let db = Firestore.firestore()
var listener: ListenerRegistration?
func trackLoginStatus(passOnMethod: #escaping () -> () ) {
listener?.remove()
if let loggedInUserA_UID = Auth.auth().currentUser?.uid {
listener = db.collection(K.FStore.collectionOf_RegisteredUsers_Name)
.document(loggedInUserA_UID)
.addSnapshotListener { (snapshotDocument, error) in
if let error = error {
print(error)
} else {
if let document = snapshotDocument {
if let data = document.data() {
if let fcmTokens = data[K.FStore.Users.fcmTokens] as? [String] {
print("Found the following tokens: \(fcmTokens)")
self.compareTokensAgainstCurrentDeviceToken(fcmTokens: fcmTokens, passOnMethod: { () in
passOnMethod()
})
}
}
}
}
}
}
}
func compareTokensAgainstCurrentDeviceToken(fcmTokens: [String], passOnMethod: #escaping () -> () ) {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print(error)
} else if let result = result {
if fcmTokens.contains(result.token) {
print("Token found, doing nothing")
} else {
print("Token no longer found, logout user")
do {
try Auth.auth().signOut()
InstanceID.instanceID().deleteID { error in
if let error = error {
print(error)
} else {
passOnMethod()
}
}
} catch let signOutError as NSError {
print (signOutError)
}
}
}
}
}
}
And here is the method I use when logging out the user everywhere but at the current device.
func deleteAllFcmTokensExceptCurrent(loggedInUserA: User, passOnMethod: #escaping () -> () ) {
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print(error)
} else if let result = result {
let batch = self.db.batch()
let deleteAllFcmRef = self.db.collection(K.FStore.collectionOf_RegisteredUsers_Name).document(loggedInUserA.uid)
batch.updateData([K.FStore.Users.fcmTokens: FieldValue.delete()], forDocument: deleteAllFcmRef)
let updateFcmTokenRef = self.db.collection(K.FStore.collectionOf_RegisteredUsers_Name).document(loggedInUserA.uid)
batch.updateData([K.FStore.Users.fcmTokens: FieldValue.arrayUnion([result.token])], forDocument: updateFcmTokenRef)
batch.commit { (error) in
if let error = error {
print(error)
} else {
passOnMethod()
}
}
}
}
}
Not tested yet, as our backend programmer, who is in charge of setting up Firestore rules was gone for the day, but in theory this should work: (and it's something I'll test tomorrow)
Having a FirebaseAuth.AuthStateListener in charge of serving UI based on the status of the user
This combined with rules in firestore
match /collection
allow read: if isAuth();
Where isAuth is:
function isAuth() {
return request.auth.uid != null;
}
If the user is then disabled, while being logged in, whenever the user tries to read data from the collection, he should be denied, and a signOut() call should be made.
The AuthStateListener will then detect it, and sign the user out.

Check if user is logged in: Firebase iOS Swift 4

I am still having difficulty in checking whether the user is logged in with Google or Facebook to read and write on Firebase Database. I want to present a log in screen to a first time user and when the user authenticates, the log in screen is dismissed and it sent to the tabViewControllers. Here's my Swift 4 code below, which is placed in the AppDelegate, application(application:didFInishLaunchingWithOptions launchOptions:).
if Auth.auth().currentUser == nil {
print("NO USER") // this does print out in the console before the app crashes
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginVC = storyboard.instantiateViewController(withIdentifier: "loginVC") as! LogInViewController
self.window?.rootViewController = loginVC
} else {
let tabController = window!.rootViewController as! UITabBarController
if let tabViewControllers = tabController.viewControllers {
// First tab (only one so far...)
let navController = tabViewControllers[0] as! UINavigationController
let controller1 = navController.viewControllers.first as! UserProfileViewController
controller1.coreDataStack = coreDataStack
}
}
}
Please note the LogInViewController Scene is created in the Main.storyboard file and it has a Storyboard ID of "loginVC". When I try to run this, the program crashes at the part where the tabViewController[0] tries to fetch from the coreDataStack.
Hi you need to store UID of the user here is my code for login screen as you said if user open app for first time he have to login / authenticate and second time is automatically.
override func viewDidLoad() {
super.viewDidLoad()
if let uid = KeychainWrapper.standard.string(forKey: KEY_UID) {
autoLoginWithUID(uid: uid)
}
}
after app launches try it to auto login him if have stored his UID otherwise screen stays
func autoLoginWithUID(uid: String) {
KeychainWrapper.standard.set(uid, forKey: KEY_UID)
print(uid)
//Keep db and userRef as class constants shouldn't be here
let db = Firestore.firestore()
let userRef = db.collection("Users").document(uid)
userRef.getDocument { (document, error) in
if let document = document {
print("User data: \(document.data())")
self.performSegue(withIdentifier: "LogIn", sender: nil)
} else {
print("User does not exist")
}
}
}
Here I look in db if I have user with this UID if I got it its stored in global variable and continue. You can also store users credentials and log user by them. But dont know which way is more secure.
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
// ...
return
}
// User is signed in
// ...
}
}
If you want more code from UserRequest let me know ;)

Facebook login in iOS (Swift 4) - Get permissions and store in Firebase

I've found some good resources on Stackoverflow and youtube helping getting around the fact that the Facebook iOS SDK descriptions are not up to date. I've now successfully managed to create the Facebook login feature and a new user is registered in Firebase. However my current issue is two fold.
1) I understand that Firebase do NOT store the email of the user under Authentication if the user log in with Facebook. My question is - how to get the email from Facebook so that I can store it under the users profile, and how do I ensure that a user that has signed in / logged in with Facebook one day and by email another day are the same user?
2a) The .userFriends info is a list of friends that also use the app - I'm struggling to understand what info that Facebook provide and how I can use this to suggest other friends the user can follow in the app.
I've read the Facebook SDK info! But can someone help translating this into what it means in terms of Swift 4...
2B) Not knowing the data structure - I'm thinking of storing .userFriends into a new node - but unsure if I should do it under the specific user profile, or denormalise it and put it under root with the user uid as the identifier... let me know your thoughts please..
Working code - issue is with the commented section
#objc func loginButtonClicked() {
let loginManager = LoginManager()
loginManager.logIn(readPermissions: [.publicProfile, .email, .userFriends], viewController: self) { loginResult in // request access to user's facebook details
switch loginResult {
case .failed(let error):
print(error)
case .cancelled:
print("User cancelled login.")
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
print(grantedPermissions)
print(declinedPermissions)
// Check permissions granted and declined add do action depending... eg. get name and surname for profile
// if FacebookAccessToken.grantedPermissions = {
// // TODO: publish content.
// }
// else {
// var loginManager = LoginManager()
// loginManager.logIn(readPermissions: [.publicProfile], viewController: self) { loginResult in
// //TODO: process error or result.
// }
// }
FacebookAccessToken = accessToken
let credential = FacebookAuthProvider.credential(withAccessToken: (FacebookAccessToken?.authenticationToken)!)
Auth.auth().signIn(with: credential) {( user, error) in
if let error = error {
print(error)
return
}
let currentUser = Auth.auth().currentUser
// Navigates back
self.dismiss(animated: true, completion: {});
self.navigationController?.popViewController(animated: true);
print("Successfully logged in user with Facebook")
}
}
}
}

Resources