簡體   English   中英

在 Firebase 中組織組 Swift 上的身份驗證

[英]Organizing groups in Firebase Authentication on Swift

我在 Xcode 中的 Swift 上使用 Firebase 身份驗證。 我想為用戶登錄創建“組”,以便某些用戶可以訪問某些數據。 例如,在我的應用程序中,我希望籃球隊中的籃球運動員只能訪問籃球統計數據。 有誰知道這在 Firebase 中叫什么以及怎么做?

如前所述,身份驗證用戶(Auth user)只是身份驗證用戶,它不包含更多信息。 請參閱 Firebase(身份驗證)的隨附屏幕截圖:

驗證用戶

這就是為什么我們必須添加一個新的User結構(在users集合中),它提供所有這些類型的信息(可能是姓名、年齡、某些東西的組......等等)。 用戶文檔需要對 Auth 用戶的引用。 在示例中,我使用的是用戶 uid(@frank-van-puffelen 是使用 uid 的常用方法還是會導致安全相關問題?)

在此處輸入圖像描述

附帶說明一下,由於我們只獲取整個文檔,並且有時用戶可能擁有一些對其他人不可用的私有數據,因此將結構拆分為 PublicUser 和 PrivateUser 可能是有意義的。

無論如何,對於這個例子,讓我們在 swift 中創建一個用戶結構

用戶

//
//  User.swift
//  Firebase User
//
//  Created by Sebastian Fox on 18.08.22.
//

import Foundation
import SwiftUI
import Firebase

struct User: Codable, Identifiable, Hashable {
    
    var id: String?
    var name: String
    var group: SportType
    
    
    init(name: String, group: SportType, id: String?) {
        self.id = id
        self.name = name
        self.group = group
    }
    
    init?(document: QueryDocumentSnapshot) {
        let data = document.data()
        
        guard let name = data["name"] as? String else {
            return nil
        }
        
        guard let group = data["group"] as? SportType else {
            return nil
        }
        
        id = document.documentID
        self.name = name
        self.group = group
    }
    
    enum CodingKeys: String, CodingKey {
        case id
        case name
        case group
    }
}

extension User: Comparable {
    
    static func == (lhs: User, rhs: User) -> Bool {
        return lhs.id == rhs.id
    }
    
    static func < (lhs: User, rhs: User) -> Bool {
        return lhs.name < rhs.name
    }
}


// I also create an enum with sort types, this is not necessarily part of the User struct. To load it to the Firestone database it must be codable.

enum SportType: String, Codable, CaseIterable {
    case basektball = "Basketball"
    case baseball = "Baseball"
    case soccer = "Soccer"
    case chess = "Chess"
    case noSport = "No Sport"
}

現在,讓我們用 UserViewModel 來做魔術,它包含我們調用的函數來使用 Firebase (Firestore),例如 signUp(這里我們談論的是 Auth 用戶)、signIn(再次驗證用戶)或 createNewUser(這里是我們的新用戶)用戶結構):

UserViewModel.swift

//
//  UserViewModel.swift
//  Firebase User
//
//  Created by Sebastian Fox on 18.08.22.
//

import Foundation
import FirebaseFirestore
import Firebase
import FirebaseFirestoreSwift

class UsersViewModel: ObservableObject {
    
    let db = Firestore.firestore()
    
    // Published and saved to local device
    @Published var users = [User]()
    
    // Sign Up
    func signUp(email: String, password: String, completion: @escaping (Bool, String)->Void) {
        
        Auth.auth().createUser(withEmail: email, password: password) { authResult, error in
            
            // ERROR AND SUCCESS HANDLING
            if error != nil {
                // ERROR HANDLING
                print(error?.localizedDescription as Any)
                completion(false, "ERROR")
            }
            // SUCCESS HANDLING
            completion(true, authResult?.user.uid ?? "")
        }
    }
    
    // Sign In
    func signIn(email: String, password: String, completion: @escaping (Bool)->Void) {
        
        Auth.auth().signIn(withEmail: email, password: password) { (authResult, error) in
            
            // ERROR AND SUCCESS HANDLING
            if error != nil {
                // ERROR HANDLING
                print(error?.localizedDescription as Any)
                completion(true)
            }
            // SUCCESS HANDLING
            completion(true)
        }
    }
    
    // Sign Out
    func signOut() {
        try! Auth.auth().signOut()
    }
    
    // Create new user
    func createNewUser(name: String, group: SportType, id: String) {
        do {
            let newUser = User(name: name, group: group, id: id)
            try db.collection("users").document(newUser.id!).setData(from: newUser) { _ in
                print("User \(name) created")
            }
        } catch let error {
            print("Error writing user to Firestore: \(error)")
        }
    }
    
    // FOR TESTING: Get a list of all users
    func fetchAllUsers(_ completion: @escaping (Bool) ->Void) {
        self.users = []
        db.collection("users").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No documents")
                return
            }
            
            self.users = documents.map { queryDocumentSnapshot -> User in
                let data = queryDocumentSnapshot.data()
                let id = data["id"] as? String ?? ""
                let name = data["name"] as? String ?? ""
                let group = data["group"] as? String ?? ""
                return User(name: name, group: SportType(rawValue: group) ?? .noSport, id: id)
            }
            completion(true)
        }
    }
    
}

現在您有 2 個選項來注冊(身份驗證用戶)並創建一個新用戶(基於新用戶結構):

  1. 您有 2 個單獨的視圖,在第一個視圖上,用戶注冊,創建 Auth 用戶。 在第二個視圖中,僅在注冊后可用,用戶可以添加名稱、組或任何您想要的數據。 (我更喜歡這個選項)

  2. 您可以在一個視圖中處理所有事情。 您持有所有必要的數據,調用注冊 function 並在收到完成響應時調用 function 來創建用戶。

最后一件事,由於您無法從 Auth.auth() 中獲取該信息,因此如果您希望能夠更改這些數據,則必須從 Firestore 數據庫中獲取該特定用戶的用戶數據。 當然,您可以在創建新用戶時將這些信息作為值保存到 UserDefaults(存儲),稍后您可以在用戶登錄時保存該信息。

最好的,塞巴斯蒂安

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM