צעדים ראשונים עם Firebase

07/07/2018

פיירבייס הוא שירות רשת המציע להחליף את כתיבת קוד צד השרת במערכת שלכם. הם כתבו בסיס נתונים שיתופי לאחסון מסמכים הכולל מנגנון אבטחה מקיף ומציעים אותו יחד עם שירות Hosting כך שאתם מקבלים סביבה מלאה לבנות ולהפיץ יישומי Web וכל זה בלי לכתוב שורה אחת של קוד צד שרת.

השירות שלהם מדהים, עובד טוב, מתועד היטב ואמין. גוגל קנו אותם ב 2015 ומאז הם נהנים מחיבור מעולה לשירותי הענן של גוגל.

בשבוע שעבר העברתי וובינר על פיירבייס והפוסט הזה הוא תקציר של מה שקרה שם. בגלל ששכחתי להקליט אעביר את אותו וובינר בשידור חוזר מחר (יום ראשון) אז אם נשמע לכם מעניין מוזמנים להצטרף בקישור:

https://zoom.us/meeting/register/3dea94be140a83cbcde7dc3c8da9331e

ועכשיו לקוד.

1. רישום ופתיחת פרויקט חדש

אנחנו נתחיל לעבוד עם פיירבייס בפרויקט חדש. כמו הרבה כלים היום גם הם מציעים כלי שורת פקודה לקיצור תהליכים המבוסס על node, אז צעד ראשון בעבודה איתם הוא להתקין node.js.

אחרי שיש לכם את זה ואתם יודעים להיכנס לשורת הפקודה ולהפעיל שם npm תוכלו להתקין את כלי שורת הפקודה של פיירבייס עם:

$ npm install -g firebase-tools

את זמן ההתקנה אפשר לנצל כדי להיכנס לאתר פיירבייס עצמו ולפתוח חשבון (כן זה בחינם). הקישור:

https://firebase.google.com

לוחצים על Sign In בפינה הימנית עליונה של המסך ואז בוחרים את חשבון הגוגל שלכם. לאחר מכן לוחצים Go To Console ואז כל הכפתור עם הפלוס הגדול שכתוב בו Add Project. אחרי שתבחרו שם לפרויקט לחצו שמירה והמשיכו למסך ההגדרות.

במסך ההגדרות הכנסו לפריט Database ושם לחצו על Create Database. זה יספיק בשביל להעלות עמוד פשוט לאוויר.

בזמן שעשינו את זה נדמה לי ש npm כבר הספיק לסיים עם ההתקנה. נחזור לשורת הפקודה ונעבור לתיקיה חדשה בה ניצור את הפרויקט ואז נפעיל:

$ firebase login
$ firebase init

הכלי יבקש מכם לבחור איזה פיצ'רים בפרויקט אתם רוצים ואנחנו נסמן את בסיס הנתונים Firestore ואת הסעיף Hosting. לאחר אישור תתבקשו לבחור מול איזה פרויקט פיירבייס אתם רוצים לעבוד, אז תבחרו את הפרויקט שהרגע יצרתם.

עכשיו פיירבייס יצר די הרבה קבצים בתיקיה ונחזור אליהם בהמשך לראות מה אומר כל אחד. כרגע הכי ישמח אותי להעלות עמוד פשוט לרשת סוג של Hello World כזה רק לראות שהכל עובד.

נחזור למסך הפרויקט ב Firebase ושם ליד המילה Project Overview יש ציור של גלגל שיניים. לחצו עליו ובחרו Project Settings. גוללים קצת למטה כדי לראות את הכפתור Add Firebase to your web app. לחיצה עליו פותחת Popup עם קטע קוד שצריך להדביק בתוך ה index.html. כך זה נראה אצלי:

<script src="https://www.gstatic.com/firebasejs/5.2.0/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "AIzaSyBBPOWYWbYnyotS1unEabl4ilzIslwJr4c",
    authDomain: "fir-webinar-96805.firebaseapp.com",
    databaseURL: "https://fir-webinar-96805.firebaseio.com",
    projectId: "fir-webinar-96805",
    storageBucket: "fir-webinar-96805.appspot.com",
    messagingSenderId: "667505904373"
  };
  firebase.initializeApp(config);
</script>

חוזרים ליישום שלנו ובתיקיה public תמצאו קובץ index.html שיצר כלי ההתקנה של פיירבייס. הוא כולל הרבה יותר קוד ממה שאנחנו צריכים לכן עדיף לרוקן אותו. במקום מה שהיה שם רישמו בתוך ה head את שני הסקריפטים שלקחנו ממסך ההגדרות של פיירבייס ובתוך ה body פיסקת טקסט קצרה.

כך נראה הקובץ public/index.html אצלי:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Welcome to Firebase Hosting</title>
    <script src="https://www.gstatic.com/firebasejs/5.2.0/firebase.js"></script>
    <script>
        // Initialize Firebase
        var config = {
            apiKey: "AIzaSyBBPOWYWbYnyotS1unEabl4ilzIslwJr4c",
            authDomain: "fir-webinar-96805.firebaseapp.com",
            databaseURL: "https://fir-webinar-96805.firebaseio.com",
            projectId: "fir-webinar-96805",
            storageBucket: "fir-webinar-96805.appspot.com",
            messagingSenderId: "667505904373"
        };
        firebase.initializeApp(config);
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  </head>
  <body>
    <p>Hello World</p>
  </body>
</html>

חזרה לשורת הפקודה ונפעיל:

$ firebase deploy

בתגובה הסקריפט ידפיס פלט שנראה בערך כך:

localhost:firebase-webinar ynonperek$ firebase deploy

=== Deploying to 'fir-webinar-96805'...

i  deploying firestore, hosting
i  firestore: checking firestore.rules for compilation errors...
✔  firestore: rules file firestore.rules compiled successfully
i  firestore: uploading rules firestore.rules...
i  hosting: preparing public directory for upload...
✔  hosting: 3 files uploaded successfully
✔  firestore: released rules firestore.rules to cloud.firestore

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/fir-webinar-96805/overview
Hosting URL: https://fir-webinar-96805.firebaseapp.com

השורה האחרונה היא הכתובת אליה העמוד שלכם עלה. כנסו לכתובת הזו מהדפדפן כדי לראות את הודעת הטקסט הקצרה שלכם באינטרנט.

2. זיהוי משתמשים

הצד החזק של שרת פיירבייס הוא פיתוח יישומים הכוללים תוכן גולשים כך שכל גולש יכול ליצור תוכן ספציפי עבורו או תוכן המשותף לו ולגולשים נוספים. יש להם מנגנוני אבטחה חזקים שמוודאים שכל גולש יכול לגשת רק לתכנים שמתאימים לו.

בשביל שנוכל להתחיל לשמור מידע ספציפי לגולשים נרצה שהמסך הראשון יהיה מסך הזדהות. פיירבייס תומכים בהמון מנגנוני הזדהות ובדוגמא שלנו ארצה להציג הזדהות דרך Google Account.

רצף העבודה יהיה:

  1. גולש מגיע אלינו לאתר
  2. הגולש לוחץ על כפתור "התחבר"
  3. מופיע Pop Up של גוגל עם תיבת התחברות
  4. לאחר התחברות לחשבון הגוגל אנחנו מקבלים מפיירבייס מידע לגבי מי הגולש ומזהה ייחודי של אותו משתמש. מכאן והלאה נוכל לסמן את כל הפעולות של המשתמש עם מזהה זה ואותו מזהה גם ישמש ביצירת כללי אבטחת המידע בבסיס הנתונים.

לפני שנוכל לכתוב את הקוד יש לעדכן בממשק הניהול של Firebase שיהיה אפשר להתחבר למערכת דרך גוגל. חזרו ל Console, לחצו על Authentication ואז בתפריט Sign In Method בחרו את Google. יש צ'ק בוקס קטן שצריך להזיז מצד לצד כדי להפעיל את שיטת החיבור ואחרי שמופיע הטקסט Enabled ליד גוגל אפשר להמשיך לקוד.

  1. תחילה נוסיף לקובץ index.html כפתור התחברות וקישור לקובץ js.
<button id="btn-signin">Sign In</button>
<script src="scripts/main.js"></script>

בקובץ ה main.js נרצה לטפל במצב שמשתמש מחובר או לא מחובר ולכן נתחיל בקטע הקוד הבא המשתמש ב API של פיירבייס:

firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
        const name = user.displayName;
        const id   = user.uid;
        alert(`Welcome! ${name}. Your id is ${id}`);
    } else {
        // user not signed in, do nothing
    }
});

הפונקציה שכתבנו תקרא בכל פעם שמשתמש מתחבר או מתנתק מהמערכת ובנוסף תיקרא אוטומטית בטעינת העמוד. המאפיינים displayName ו uid הם שעוזרים לנו לזהות את המשתמש הנוכחי.

כדי לטפל בהתחברות עצמה נוסיף את הקוד הבא:

$('#btn-signin').on('click', function() {
    var provider = new firebase.auth.GoogleAuthProvider();
    provider.setCustomParameters({ prompt: 'consent' });
    firebase.auth().signInWithPopup(provider);
});

הקוד תופס לחיצה על כפתור ה sign in שיצרנו ובכל פעם שהכפתור נלחץ מפעיל את הפונקציה signInWithPopup של פיירבייס. פונקציה זו תציג את ה Popup של ההתחברות לגוגל.

נסו את זה לוקאלית על המכונה שלכם. הפעילו משורת הפקודה:

$ firebase serve

ואז כנסו מהדפדפן ל localhost:5000. אם הכל הלך חלק תראו כפתור להתחברות, לחיצה על הכפתור תקפיץ תיבת התחברות של גוגל ולאחר חיבור מוצלח תקבלו alert שיגיד ברוכים הבאים עם שם המשתמש והמזהה הייחודי של Firebase.

3. שמירה וטעינת מידע

עכשיו שיש לנו שרת עם אפשרות להזדהות נרצה לשמור מידע עבור כל לקוח מזוהה בבסיס הנתונים. בפיירבייס זה ממש קל לעשות.

בסיס הנתונים של פיירבייס שומר אוספים של מסמכים, כאשר כל מסמך הוא אוביקט JSON. אתם יכולים להוסיף אוביקט JSON לאוסף תחת מפתח מסוים או לתת לפיירבייס לבחור מפתח לבד. בדרך כלל ניתן לפיירבייס לבחור מפתח כשיש לנו רשימה של דברים לשמור ונבחר לבד את המפתח כשיש לנו אוביקט יחיד שרוצים כל הזמן לעבוד רק איתו.

הדוגמא הראשונה שלי לשמירת מידע תעבוד עם אוביקט יחיד: נרצה לתת לכל משתמש לבחור שורת טקסט קצרה ולשמור אותה בבסיס הנתונים ואז לטעון אותה במועד מאוחר יותר.

נתחיל עם הקובץ index.html ונוסיף אליו את הקוד הבא כדי להציג תיבת טקסט ושני כפתורים:

      <input type="text" name="tagline" />
      <button id="btn-savetagline">Save Tagline</button>
      <button id="btn-loadtagline">Load Tagline</button>

עכשיו אפשר לחזור לקובץ main.js ולהוסיף אליו את שתי הפונקציות לשמירה וטעינת הטקסט מבסיס הנתונים:

$('#btn-savetagline').on('click', function() {
   text = $('input[name="tagline"]').val();
   userid = firebase.auth().currentUser.uid;
   firebase.firestore().collection('taglines').doc(userid).update({
      text,
   });
});

$('#btn-loadtagline').on('click', function() {
  userid = firebase.auth().currentUser.uid;
  firebase.firestore().collection('taglines').doc(userid).get().then(function(doc) {
    $('input[name="tagline"]').val(doc.data().text);
  });
});

שימו לב במיוחד לשורה שמתחילה ב firebase בשתי הפונקציות. בפונקציה הראשונה שורה זו לוקחת מסמך לפי המפתח userid מתוך האוסף taglines. מאחר ו userid הוא ייחודי במערכת ומייצג משתמש מסוים אז כתיבה כזו אומרת שכל משתמש יוכל להגדיר לעצמו שורת טקסט יחידה. אם אותו משתמש יגדיר וישמור שורה נוספת האוביקט ידרס ויוחלף בשורה החדשה.

הפונקציה השניה מאתרת את האוביקט לפי אותו userid ושולפת ממנו את השדה text.

יכולים להפעיל:

$ firebase serve

כדי לראות את הקוד רץ מקומית על המכונה שלכם או:

$ firebase deploy

כדי להעלות לאינטרנט ולשתף עם חברים.

4. מה בנינו ומה עוד נשאר

בפחות משעה יצרנו מערכת המאפשרת למשתמשים להזדהות באמצעות חשבון הגוגל שלהם ולשמור (קצת) מידע ייחודי עבורם.

עדיין נשארו לנו הרבה נושאים פתוחים:

  1. נצטרך להגדיר חוקי אבטחה בשרת כדי לוודא שמשתמשים לא יוכלו לרמות ולגשת למידע של משתמשים אחרים.

  2. נרצה להבין איך לשמור רשימות של מספר אוביקטים (למשל פיד של סטטוסים כמו בפייסבוק או טוויטר).

  3. נרצה להבין איך לסנכרן מידע בין מספר גולשים ולהבדיל בין מידע פרטי למידע ציבורי.

ביום ראשון (כלומר מחר) אציג בוידאו את כל מה שכתבתי כאן בפוסט בפורמט של וובינר כך שיהיה אפשר לשאול שאלות ולנסות איתי יחד את הדברים. המטרה לסיים את השעה כשלכל אחד מכם יש מערכת עובדת שעושה את מה שתיארתי כאן בפוסט.

ביום חמישי יהיה החלק השני של הוובינר בו נדבר על שלושת הנקודות שעוד נותרו. מוזמנים להצטרף או לחכות לפוסט הסיכום שבטח יגיע כמה ימים אחרי.