Published on

Firebase authentication: email orqali ro'yxatdan o'tish (1-qism)

Authors

Avtorizatsiya nega kerak?

Deyarli har qanday dasturda foydalanuvchilar o'z akkauntlariga ega bo'lishi talab etiladi. Bunga sabab — serverdagi ma'lumotlarni himoyalash. Agar sizning ilovangiz biron bir tashqi serverga ulansa, faqatgina ishonchli va tizimdan o'tgan foydalanuvchilar ma'lumotlarni ko'rishi yoki o'zgartirishi kerak. Aks holda, serveringiz URL manzilini topgan har qanday kishi ma'lumotlaringizga xohlagancha o'zgartirish kiritishi mumkin bo'ladi.

Shu sababli, ilovalarning asosiy qismi foydalanuvchilarni "Email/Password", "Apple bilan kirish", yoki "Google bilan kirish" orqali identifikatsiya qiladi. Biz darslarimizni eng klassik va xavfsiz usul — Email va Parol bilan ro'yxatdan o'tishdan boshlaymiz.

Bu dars ikkita qismdan iborat bo'ladi. Birinchi qismda (hozir) ro'yxatdan o'tish, akkauntdan chiqishni sozlasak, keyingi darsda parolni tiklash (reset password) kabi qolgan barcha qo'shimcha imkoniyatlarni ko'rib chiqamiz.

Firebase Konsolida sozlash

  1. Firebase Consolega kiring va loyihangizni oching.
  2. Chap panelda Authentication bo'limiga kiring.
  3. "Get Started" tugmasini bosing.
  4. Kirish usullaridan (Sign-in providers) "Email/Password" ni tanlang.
  5. Faqatgina birinchi tugmani (Email/Password) yoqing. "Email link (passwordless sign-in)"ni yoqishingiz shart emas.
  6. Save (Saqlash) tugmasini bosing. Endi tizimingiz email va parolni qabul qilishga tayyor!

Xcode'da kutubxonani qo'shish

Oldingi darsda biz loyihamizga faqat FirebaseAnalytics modulini qo'shgan edik. Endi bizga avtorizatsiya uchun kutubxona ham kerak bo'ladi:

  1. Xcode'da loyiha fayliga bosing.
  2. General yoki Frameworks, Libraries, and Embedded Content bo'limidan + tugmasini bosing.
  3. Ro'yxatdan FirebaseAuth modulini tanlang va qo'shing.

UI oynalarni tayyorlash

Dastlab, foydalanuvchi interfeyslarini (UI) yaratib olamiz. Bizga bir nechta asosiy ekranlar kerak bo'ladi:

  1. AuthenticationView – Dastlabki ekran ("Email bilan kirish" kabi tugmalari bor oyna).
  2. SignInEmailView – Email va parolni kiritish ekrani.
  3. SettingsView – Foydalanuvchi muvaffaqiyatli tizimga kirgandan so'ng paydo bo'ladigan oyna (bu yerda "Log out" - chiqish tugmasi bo'ladi).

Eslatma: Kodlarni boshqarish osonroq bo'lishi uchun MVVM arxitekturasidan (View va ViewModel) qisman foydalanamiz.

SignInEmailView

import SwiftUI

@MainActor
final class SignInEmailViewModel: ObservableObject {
    @Published var email = ""
    @Published var password = ""

    func signIn() {
        guard !email.isEmpty, !password.isEmpty else {
            print("Email yoki parol topilmadi.")
            return
        }

        Task {
            do {
                let returnedUserData = try await AuthenticationManager.shared.createUser(email: email, password: password)
                print("Muvaffaqiyatli ro'yxatdan o'tildi!")
                print(returnedUserData)
            } catch {
                print("Xatolik: \(error)")
            }
        }
    }
}

struct SignInEmailView: View {
    @StateObject private var viewModel = SignInEmailViewModel()

    var body: some View {
        VStack {
            TextField("Email...", text: $viewModel.email)
                .padding()
                .background(Color.gray.opacity(0.4))
                .cornerRadius(10)

            SecureField("Password...", text: $viewModel.password)
                .padding()
                .background(Color.gray.opacity(0.4))
                .cornerRadius(10)

            Button {
                viewModel.signIn()
            } label: {
                Text("Sign In")
                    .font(.headline)
                    .foregroundColor(.white)
                    .frame(height: 55)
                    .frame(maxWidth: .infinity)
                    .background(Color.blue)
                    .cornerRadius(10)
            }
            Spacer()
        }
        .padding()
        .navigationTitle("Sign In With Email")
    }
}

AuthenticationManager (Asosiy mantiq)

Barcha Firebase Authentication bilan bog'liq ishlarni bitta faylda tutish uchun maxsus AuthenticationManager klassini yaratamiz. Biz buni Singleton pattern orqali ishlatamiz. Katta ilovalarda Dependency Injection ishlatish yaxshiroq, biroq bu bootcamp uchun Singleton ayni muddao.

Foydalanuvchi ma'lumotlari modeli

Firebase qaytaradigan User obyektining hamma xususiyatlari ham bizga doim kerak emas. Shuning uchun o'zimizga keraklilarini ajratib, alohida struct tuzib olamiz:

import Foundation
import FirebaseAuth

struct AuthDataResultModel {
    let uid: String
    let email: String?
    let photoUrl: String?

    init(user: User) {
        self.uid = user.uid
        self.email = user.email
        self.photoUrl = user.photoURL?.absoluteString
    }
}

Menejer klassi

Endi, shu modeldan foydalangan holda asosiy vazifalarni bajaruvchi klassni yozamiz:

final class AuthenticationManager {

    static let shared = AuthenticationManager()
    private init() { }

    // Yangi foydalanuvchini yaratish
    func createUser(email: String, password: String) async throws -> AuthDataResultModel {
        let authDataResult = try await Auth.auth().createUser(withEmail: email, password: password)
        return AuthDataResultModel(user: authDataResult.user)
    }

    // Joriy foydalanuvchini tekshirish
    func getAuthenticatedUser() throws -> AuthDataResultModel {
        guard let user = Auth.auth().currentUser else {
            throw URLError(.badServerResponse)
        }
        return AuthDataResultModel(user: user)
    }

    // Tizimdan chiqish
    func signOut() throws {
        try Auth.auth().signOut()
    }
}

E'tibor bering, getAuthenticatedUser() va signOut() funksiyalarida async so'zi qatnashmagan. Chunki ular Firebase serveriga murojaat qilmaydi, balki to'g'ridan-to'g'ri ilovangiz xotirasidan o'qib / o'chirib beradi.

Dastur qatnovini (Flow) sozlash

Ilova yuklanganda eng birinchi bo'lib nimani ko'rsatishni hal qilishimiz kerak:

  1. Agar foydalanuvchi avval tizimga kirgan bo'lsa -> To'g'ridan to'g'ri SettingsView (Asosiy ekran).
  2. Agar u hali tizimga kirmagan bo'lsa -> AuthenticationView (Kirish ekrani).

Buning uchun RootView yaratamiz:

import SwiftUI

struct RootView: View {
    @State private var showSignInView: Bool = false

    var body: some View {
        ZStack {
            NavigationStack {
                SettingsView(showSignInView: $showSignInView)
            }
        }
        .onAppear {
            let authUser = try? AuthenticationManager.shared.getAuthenticatedUser()
            self.showSignInView = authUser == nil
        }
        .fullScreenCover(isPresented: $showSignInView) {
            NavigationStack {
                AuthenticationView()
            }
        }
    }
}

Tizimdan chiqish (Log Out) jarayoni uchun SettingsView:

import SwiftUI

@MainActor
final class SettingsViewModel: ObservableObject {
    func logOut() throws {
        try AuthenticationManager.shared.signOut()
    }
}

struct SettingsView: View {
    @StateObject private var viewModel = SettingsViewModel()
    @Binding var showSignInView: Bool

    var body: some View {
        List {
            Button("Log Out") {
                Task {
                    do {
                        try viewModel.logOut()
                        showSignInView = true
                    } catch {
                        print(error)
                    }
                }
            }
        }
        .navigationTitle("Settings")
    }
}

Xulosa

Agar siz kodingizni tekshirib ko'rsangiz va tasodifiy "test@test.com" bilan ro'yxatdan o'tsangiz, konsolingizda o'sha foydalanuvchining ID si chop etiladi. Yana ham qiziqrog'i, o'zingizning Firebase konsolingizdagi Authentication -> Users bo'limiga o'tsangiz, xuddi shu yerda yangi ro'yxatdan o'tgan pochta va unga biriktirilgan maxsus UID'ni (User ID) ko'rasiz. Bu juda zo'r!

Biroq, agar shu email bilan yana qaytadan ro'yxatdan o'tmoqchi bo'lsangiz xatolik yuz beradi, sababi bu profil yaratib bo'lingan. Xo'sh, oldin yaratilgan profilga qanday qilib oddiygina "kiramiz" (log in)? Parolimizni unutib qo'ysak nima bo'ladi? Bularning barchasi haqida keyingi darsda gaplashamiz.

Buy mea coffee