How to I use Cloud Firestore to store private user data that only they can read, write and delete?

Viewed 1241

Some more context...

I'm building an app with Swiftui. A user can login or sign up (seems to be working!) and then when logged in, fill out a form with a date picker, and textfields. This data is uploaded to firebase successfully in a document and then displayed in a list on the app. No matter which user is signed in the same data is displayed in the list. What I would like to achieve:

Only the signed in user can see the data they have added to their list. Only the signed in user can read, write and delete this data.

Very new to programming, thanks in advance for any help available.

import SwiftUI
import Firebase
import Combine

class SessionStore: ObservableObject {
    var didChange = PassthroughSubject<SessionStore, Never>()
    @Published var session: User? {didSet{self.didChange.send(self) }}
    var handle: AuthStateDidChangeListenerHandle?
    
    func listen() {
        handle = Auth.auth().addStateDidChangeListener({ (auth, user) in
            if let user = user {
                self.session = User(uid: user.uid, email: user.email)
            }
            else {
                self.session = nil
            }
        })
        
    }
    
    
    func signUp(email: String, password: String, handler: @escaping AuthDataResultCallback) {
        Auth.auth().createUser(withEmail: email, password: password, completion: handler)
    }
    
    func signIn(email: String, password: String, handler: @escaping AuthDataResultCallback) {
        Auth.auth().signIn(withEmail: email, password: password, completion: handler)
        
    }
    
    func signOut() {
        do {
            try Auth.auth().signOut()
            self.session = nil
        }catch {
            print("error signing out")
        }
        
    }
    
    func unbind() {
        if let handle = handle {
            Auth.auth().removeStateDidChangeListener(handle)
        }
    }
    
    deinit {
        unbind()
        
    }
}

struct User {
    var uid: String
    var email: String?
    
    init(uid: String, email: String?) {
        self.uid = uid
        self.email = email
    }
}

2 Answers

Since you have login working already, you should have access to a users id (UID) and use that from the user (user.uid) as an identifier alongside the data you're storing. Check out this article on firestore and saving user data for more info on what this looks like!

You can use a security rule in your Firebase. There are several ways of doing this, for example, you can store the UID of the authenticated user when it signs up in the data of your document, and then you can check if it matches the uid of the request:

Firestore example

rules_version = '2';
 service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth.uid == resource.data.uid;
    }
  }
}

You can also use the Document ID as the UID of the user and check if it matches.

Related