【问题标题】:Organizing groups in Firebase Authentication on Swift在 Swift 上的 Firebase 身份验证中组织组
【发布时间】:2022-08-18 18:14:15
【问题描述】:

我在 Xcode 中的 Swift 上使用 Firebase 身份验证。我想为用户登录创建“组”,以便某些用户可以访问某些数据。例如,在我的应用程序中,我希望篮球队中的篮球运动员只能访问篮球统计数据。有谁知道这在 Firebase 中被称为什么以及如何做到这一点?

  • Firebase 身份验证仅处理身份验证用户。您所描述的是授权,它故意不处理 - 但留给其他后端服务。例如,在 Firebase 的数据库和存储解决方案中,它会是 firebase.google.com/docs/rules/…
  • 嗨@coder44,我不确定您是在谈论身份验证中的用户,还是您已经创建了“用户”文档。如果您正在谈论身份验证,我认为除了身份验证中的用户之外,您还必须在(Firestore)数据库中使用文档“user”创建一个集合“users”。此用户包含此类进一步的信息,在这种情况下,例如“sportstype”或“group”,这可能是您的 swift 代码中的运动类型的枚举。
  • @SebastianFox 嗨塞巴斯蒂安,我有点困惑。所以我已经有了一个在设置 Firebase 身份验证时创建的“用户”集合。那么现在,您是说我应该在“用户”集合中为我想要的每个用户组创建一个新文档吗? –
  • 嘿@Coder44,正如弗兰克所说,Firebase Authenticator 不处理那种东西,你需要例如Firestore,如果您已经使用 Firestore 并且有一个用户实体/集合,它必须包含属性“组”,但为了避免误解,您能否添加一些关于您在 swift 项目中已有的用户处理的代码。明天,我将准备一个包含代码和屏幕截图的答案(德国凌晨 2 点 25 分,对我来说绝对太晚了 ;-))

标签: ios swift firebase firebase-authentication


【解决方案1】:

如前所述,身份验证用户(Auth user)只是身份验证用户,它不包含更多信息。请参阅 Firebase(身份验证)随附的屏幕截图:



这就是为什么我们必须添加一个新的用户结构(在用户集合),它提供了所有这些类型的信息(可以是姓名、年龄、某事物的组......无论如何)。用户文档需要对 Auth 用户的引用。在示例中,我使用的是用户 uid(@frank-van-puffelen 是使用 uid 的常用方法还是会导致安全相关问题?)



附带说明一下,由于我们只获取整个文档,并且有时用户可能拥有一些对其他人不可用的私有数据,因此将结构拆分为 PublicUser 和 PrivateUser 可能是有意义的。

无论如何,对于这个例子,让我们在 swift 中创建一个 User 结构

用户

//
//  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)")
        }
    }
    
    // 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. 您可以在一个视图中处理所有事情。您持有所有必要的数据,调用 signUp 函数,当您收到完成响应时,调用该函数来创建用户。

    最后一件事,由于您无法从 Auth.auth() 中获取该信息,因此如果您希望能够更改这些数据,则必须从 Firestore 数据库中获取该特定用户的用户数据。当然,您可以在创建新用户时将这些信息作为值保存到 UserDefaults(存储),稍后您可以在用户登录时保存该信息。

    最好的,塞巴斯蒂安

【讨论】:

    猜你喜欢
    • 2019-01-30
    • 2020-01-28
    • 2015-10-14
    • 2019-04-19
    • 2020-04-18
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多