برنامه نویسی

احراز هویت در برنامه های React با استفاده از Firebase و خدمات آن. قسمت 3

ورود کاربر به

اکنون که ثبت نام کاربر تمام شده است، و کاربر را از سیستم خارج کرده ایم، کار بعدی این است که کاربر را دوباره وارد کنید.
اما ابتدا باید حالت ها را به ورودی های خود اضافه کنیم، سپس شروع به کار بر روی اجرای عملکرد کنیم.

    import React, {useState} from 'react'
    import { Box, FormControl, FormLabel, Button, Heading, Text, VStack, Input, useToast } from '@chakra-ui/react'
    import { LoginCurve } from 'iconsax-react'
    import { app } from '../../firebaseConfig'
    import {getAuth, signInWithEmailAndPassword} from 'firebase/auth'
    import { useNavigate } from 'react-router-dom'

    const Login = () => {

      //initialise firebase auth
      const auth = getAuth();

      //initialise toast component from chakra Ui
      const toast = useToast();

      //initialise navigate from react-router-dom
      const navigate = useNavigate();

      //states for each of the imputs
      const [email, setEmail] = useState('')
      const [password, setPassword] = useState('');

      const handleClick = async  () => {
        if(email && password){
          try {
            await signInWithEmailAndPassword(auth, email, password).then((cred) => {
              toast({
                title: "Login Successful.",
                description: "You have been logged in successfully!.",
                status: "success",
                duration: 3000,
                isClosable: true,
                variant: 'left-accent',
                position: 'top-right',

              });
              setEmail('');
              setPassword('');
              navigate('/profile')
            })
          } catch (error) {
            toast({
              title: "Error!",
              description: error.message,
              status: "error",
              duration: 3000,
              isClosable: true,
              variant: 'left-accent',
              position: 'top',
            });
          }
        }else{
          toast({
            title: "Error!",
            description: "Please fill in your details.",
            status: "error",
            duration: 3000,
            isClosable: true,
            variant: 'left-accent',
            position: 'top',
          });
        }
      }

      return (
        <Box mt='10'>
          <VStack spacing={6}>

            <Heading>Login</Heading>

            <Box maxW='400px'>
              <FormControl>
                <VStack spacing={4}>
                  <Box>
                    <FormLabel>Email</FormLabel>
                    <Input type='email' placeholder='Input your email' fontSize='14px' w='400px' value={email} onChange={(e) => setEmail(e.target.value)} />
                  </Box>

                  <Box>
                    <FormLabel>Password</FormLabel>
                    <Input type='password' placeholder='Input your password' fontSize='14px' w='400px' value={password} onChange={(e) => setPassword(e.target.value)} />
                  </Box>

                  <Box>
                    <Button type='submit' w='400px' colorScheme='teal' onClick={handleClick}>Login <LoginCurve style={{ marginLeft: '5px' }} /></Button>
                  </Box>
                </VStack>
              </FormControl>
            </Box>
          </VStack>
        </Box>
      )
    }

    export default Login
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد بالا، کد نهایی مولفه Login پس از افزودن حالت ها به ورودی های ما و نوشتن عملکرد است. در حالی که ما گام به گام به کدهای پایگاه داده می پردازیم، کد را در ویرایشگر کد کپی و پیست کنید.

بیایید با واردات شروع کنیم، من معتقدم در حال حاضر تقریباً با همه واردات به جز واردات آشنا هستیم signInWithEmailAndPassword() تابع. کاری که این عملکرد انجام می دهد این است که به ما اجازه می دهد تا با ایمیل و رمز عبوری که قبلاً توسط کاربر در حین ثبت نام ارائه شده است، وارد سیستم شویم. سپس تابع را در قسمت فراخوانی کردیم handleSubmit() تابع. اگر همه چیز خوب پیش برود، کاربر وارد شده و سپس به صفحه پروفایل هدایت می شود. و اگر مشکلی پیش بیاید خطای تست با پیغام خطا نمایش داده می شود.

بازیابی اطلاعات کاربر از احراز هویت firebase، پایگاه داده firestore و ذخیره سازی firebase

اکنون ما توانسته ایم کاربران را با ایمیل و رمز عبور آنها وارد سیستم کنیم و آنها را به صفحه نمایه هدایت کنیم تا هر کاربر بتواند نمایه خود را مشاهده کند اما در واقع چیزی در صفحه نمایه نمایش داده نمی شود، چگونه می توانیم این را برطرف کنم؟

ما می توانیم این کار را در 3 مرحله انجام دهیم.

  1. اولین کار این است که کاربر وارد شده فعلی را دریافت کنیم و از آنجا می توانیم ایمیل کاربر و تاریخ ایجاد حساب کاربری را دریافت کنیم.
  2. مرحله دوم دریافت آواتار کاربر از فضای ذخیره سازی Firebase است.
  3. سومین و آخرین مرحله، دریافت نام کاربری و بیوگرافی کاربر از پایگاه داده firestore است.
    import React, {useState, useEffect} from 'react'
    import {Box, Avatar, AvatarBadge, Text, Heading, Stack, Button, useToast} from '@chakra-ui/react'
    import {getAuth, signOut } from 'firebase/auth'
    import { getFirestore, query, where, getDocs, collection } from 'firebase/firestore'
    import { getStorage, ref, getDownloadURL } from 'firebase/storage'
    import { Link, useNavigate } from 'react-router-dom'
    import { app } from '../../firebaseConfig'


    const Profile = () => {
      const [currentUser, setCurrentUser] = useState(null);
      const [userDetails, setUserDetails] = useState('')
      const [avatar, setAvatar] = useState('');
      const auth = getAuth();
      const db = getFirestore();
      const storage = getStorage();
      const userRef = collection(db, 'user_data');
      const navigate = useNavigate();
      const toast = useToast();

      const signout = () => {
        signOut(auth).then(() => {
          navigate('/login');

          toast({
            title: "Logout Successful.",
            description: "You have been logged out successfully!.",
            status: "success",
            duration: 3000,
            isClosable: true,
            variant: 'left-accent',
            position: 'top-right',
          });

        })
      }

      const getCurrentUser = async () => {
        try {
          auth.onAuthStateChanged((user) => {
            setCurrentUser(user);
            const q = query(userRef, where('user_id', '==', user.uid));
            const avatarRef = ref(storage, user.uid);

            if(user){
              getDownloadURL(avatarRef).then((url) => {
                setAvatar(url);
              });

              getDocs(q).then(async (snapshot) => {
                let user_data = [];
                snapshot.docs.map((item) => {
                  user_data.push({ ...item.data(), id: item.id });
                  return setUserDetails(user_data);
                })
              });
            }
          })
        } catch (error) {
           toast({
            title: "Error!.",
            description: error.message,
            status: "error",
            duration: 3000,
            isClosable: true,
            variant: 'left-accent',
            position: 'top-right',
          });
        }
      };

      useEffect(() => {
        getCurrentUser()
      }, []);

      const newDate = currentUser?.metadata.creationTime
      const date = new Date(newDate).toDateString();

      return (
        <>
        {currentUser ? 
        <Box maxW='400px' mt='16' bg='gray.100' p='5' borderRadius={5} boxShadow='md' display='flex' alignItems='center' justifyContent='center' mx='auto'>
          <Box>
            <Heading mb='5'>My Profile</Heading>
            <Avatar bg='teal' size='xl' mb='5' display='block' mx='auto' src={avatar}>
              <AvatarBadge boxSize='0.7em' bg='green.500' />
            </Avatar>
            <Stack spacing={4} fontWeight='semibold'>
              <Text>Username: {userDetails[0]?.user_name}</Text>
              <Text>Bio: {userDetails[0]?.user_bio}</Text>
              <Text>Email: {currentUser?.email}</Text>
              <Text>Date Joined: {date}</Text>
            </Stack>
            <Box textAlign='center' mt='7'>
              <Button colorScheme='teal' onClick={signout}>Logout</Button>
            </Box>
          </Box>
        </Box> 
        : 
        <Box mx='auto' mt='16'>
          <Heading fontWeight='semibold' fontSize={25} mb='3'>OOPS!</Heading>
          <Text mb='3'>You are not authorised to view this page, please login to get acces</Text>
          <Link to='/login'>
                <Button>Login</Button>
          </Link>
        </Box>}
        </>
      )
    }

    export default Profile
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

پس از چسباندن کد باید یک رابط کاربری داشته باشیم که شبیه تصویر زیر باشد.

صفحه پروفایل

و تمام، کد بالا برای صفحه پروفایل است، یک بار دیگر ممکن است عجیب به نظر برسد اما بیایید با هم آن را مرور کنیم.

مثل همیشه، از واردات در بالا شروع می کنم، می دانم که ما با بیشتر چیزهایی که وارد کرده ام آشنا هستیم، بنابراین فقط به مواردی که قبلاً اشاره نکرده ام می پردازم.

بنابراین بیایید با ذخیره سازی Firebase شروع کنیم.

  1. ما وارد کردیم getDownloadUrl() از ذخیره سازی فایربیس چیزی که برای آن استفاده می شود دریافت یک URL قابل دسترسی از تصویری است که ما در فضای ذخیره سازی firebase آپلود کرده ایم، زیرا به طور پیش فرض، بلافاصله پس از آپلود تصویر، نامی به آن داده ایم اما فقط می توانیم به تصویر در کنسول firebase خود دسترسی داشته باشیم. نه جای دیگر

    1. مورد بعدی firebase firestore است، ما آن را وارد کردیم query() عملکرد و where() تابعی که برای پرس و جو از پایگاه داده firestore بر اساس برخی شرایط استفاده می شود. مفهومی در پایگاه داده firestore که من عمیقاً به آن نمی پردازم “پرس و جوهای firestore” است. پرس و جوهای firestore چیست؟

پرس و جوهای Firestore راهی برای بازیابی داده ها از پایگاه داده Firestore به روشی خاص است.

  1. Firestore یک پایگاه داده اسناد NoSQL است که داده ها را در اسناد و مجموعه ها ذخیره می کند و از کوئری ها می توان برای بازیابی اسناد از مجموعه ها بر اساس شرایط مشخص شده استفاده کرد.

  2. جستجوهای Firestore می توانند اسناد را بر اساس شرایط خاص فیلتر کنند، اسناد را بر اساس یک یا چند فیلد مرتب کنند، تعداد اسناد بازگردانده شده را محدود کنند و فقط فیلدهای خاصی را از هر سند بازیابی کنند.

  3. پرس و جوها همچنین می توانند برای ایجاد پرس و جوهای پیچیده تر ترکیب شوند.

  4. Firestore از دو نوع پرس و جو پشتیبانی می کند: پرس و جوهای ساده و پرس و جوهای پیچیده. پرس و جوهای ساده پرس و جوهایی هستند که از یک شرط فیلتر استفاده می کنند، در حالی که پرس و جوهای پیچیده از شرایط فیلتر چندگانه یا چند مرتبه یا شرایط محدود استفاده می کنند.

  5. پرس و جوهای Firestore را می توان در سمت مشتری، مانند برنامه های موبایل یا وب، یا در سمت سرور با استفاده از توابع ابری یا سایر فناوری های سمت سرور اجرا کرد.

بنابراین من فکر می کنم که ما اطلاعات کمی در مورد جستجوهای firestore و نحوه کار آنها در حال حاضر داریم، بنابراین اجازه دهید به کد خود بازگردیم.

چیز دیگری که ما وارد کردیم این بود getDocs() تابعی که برای دریافت تمام اسناد موجود در مجموعه firestore استفاده می شود.

کار بعدی که انجام دادیم این بود که برای آواتار، جزئیات کاربر و کاربر فعلی حالت هایی ایجاد کردیم. پس از آن، تمام توابعی را که از firebase وارد کردیم، مقداردهی اولیه کردم.
در مرحله بعد، تابع Signout است که ما ایجاد کردیم و به دکمه ای متصل کردیم تا وقتی روی آن کلیک شد، کاربران از سیستم خارج شوند و سپس آنها را به صفحه ورود هدایت کنید.

نکته بعدی و مهم این است که داده های کاربر را از firebase دریافت کنید.
زمانی که ما آن را مقداردهی اولیه کردیم getAuth() تابع، ما دسترسی به onAuthStateChanged() تابعی که به ما کمک می کند تا وضعیت احراز هویت کاربری را که در حال حاضر وارد شده است یا نه، پیگیری کنیم و از آن به شی “user” دسترسی داریم که تمام جزئیات مربوط به کاربر فعلی وارد شده را به ما می دهد و سپس آن را ارسال می کنیم. کاربر به setCurrentUser() تابع.

مورد بعدی این است که از پرس و جوهای firestore برای دریافت جزئیات کاربر وارد شده فعلی استفاده کنید. تابع query دارای دو آرگومان است userRef و where() تابع، در تابع Where ما در شرایط پرس و جو خود ارسال می کنیم و به این ترتیب پیش می رود.

ما از firebase می خواهیم که تمام اسناد موجود در مجموعه را بررسی کند و سندی را که آن را دارد به ما تحویل دهد user_id کلید برابر با شناسه کاربر وارد شده فعلی است.

پس از آن، ما یک مرجع برای آواتار خود ایجاد کردیم. اگر هنوز به یاد داشته باشیم، کاری که قبلا انجام دادیم این بود که بلافاصله پس از ثبت نام کاربر و آپلود عکس خود، نام تصویر را به شناسه کاربر تغییر دادیم.

بلوک کد بعدی بررسی می کند که آیا کاربر حضور دارد یا خیر، و در صورت وجود، باید URL دانلود آواتار کاربر را برای ما دریافت کند.

پس از آن، ما از آن استفاده کردیم getDocs() تابع و سپس در پرس و جو ارسال کنید تا جزئیات کاربر را دریافت کنید. سپس از .then() روش برای گرفتن عکس فوری، یک آرایه خالی ایجاد کردیم و آن را روی متغیر user_data قرار دادیم.

پس از دریافت عکس فوری، به طور خودکار به آن دسترسی داریم docs() روش، سپس از طریق آن حلقه زدیم و پس از انجام این کار، داده ها را به آرایه خالی فشار دادیم، سپس user_data آرایه به setUserDetails() تابع.

اگر متوجه شدیم در snapshot.docs() روشی که ما فشار دادیم item.data() به آرایه و این به این دلیل است که داده‌ای که ما می‌خواهیم که از firebase می‌آید در آن قرار دارد data() تابع. ما می‌توانیم این مورد را با ورود به سیستم کنسول بررسی کنیم console.log(item).

سپس تابع را در a فراخوانی کردیم useEffect().
وای! بچه ها ما به تازگی یک برنامه فول استک ساده با firebase ساختیم، این بسیار شگفت انگیز است، از اینکه من را در طول پروژه دنبال کردید، و همچنین از خواندن این مقاله متشکرم، امیدوارم به زودی مقاله دیگری منتشر کنم.

نتیجه

Firebase را می توان برای ساخت برنامه های فول استک هم برای وب و هم برای موبایل استفاده کرد، در این مقاله نحوه استفاده از ویژگی ها و خدمات مختلف firebase را نشان دادیم، این فقط یک پروژه ساده است و firebase دارای ویژگی های زیادی است که می توان از آنها برای ساخت موارد بیشتر استفاده کرد. برنامه های کاربردی پیچیده برای کسب اطلاعات بیشتر، اسناد firebase را بررسی کنید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا