יום שני, 21 באוקטובר 2013

Enterprise Architecture: Authorization

קשה להגדיר מהי Enterprise Architecture, לרוב זוהי ארכיטקטורה של / ועבור ארגונים גדולים.

אחד מנושאי-הליבה שחוזר על עצמו ב Enterprise Architecture הם נושאי ה Authentication ו Authorization (בקיצור: A&A):
  • Authentication - אימות הזהות של משתמש ("האם הוא מי שהוא טוען שהוא?")
  • Authorization - כיצד שולטים בהרשאות מה המשתמש, לאחר שאימתנו את זהותו, יכול לעשות.
ישנם מעט Enterprise שלא כוללים A&A, למשל כמעט כל הגישות בווב יהיו על גבי HTTPS (הדורשת הזדהות) ולא HTTP.

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

בפוסט זה אני רוצה להתמקד בתחום ה Authorization ולהציג עקרון מעניין, שאני מניח שלא מוכר בקרב רבים, הנקרא Role-Based Authorization (בקיצור: RBA, נקרא גם Role-Based Access Control קרי RBAC).






הקדמה: המודל הנאיבי

ניהול המשתמשים הפשוט (והנאיבי) ביותר כולל טבלה בבסיס הנתונים של המשתמשים וססמותיהם. כשהמשתמש מתחבר למערכת עליו להקליד שם משתמש (כלומר: user id) וסיסמה ואז משווים את הפרטים למידע בטבלה. אם המידע נכון - שומרים את זהות המשתמש על ה session (באם זה server-side session, cookie וכו').
כמובן שכדאי שהססמאות יהיו "מגובבות" (hashed) ואולי גם "מטושטשות" (מה שנקרא salted [א]). נושא זה הוא תחום ה Authentication, אימות זהות המשתמש, נושא שאנני מתכוון לעסוק בו בפוסט זה.

עבור ה authorization, ניהול ההרשאות של כל משתמש, יוצרים טבלה נוספת "הרשאות" הכוללת user id, resource id, permission type (להזכיר: מימוש נאיבי לחלוטין). כל פעם שמשתמש ייגש למשאב, נבדוק בטבלה אם יש לו הרשאה לפעולה (למשל: read, write וכו') ואז נאפשר לו / נמנע ממנו את הפעולה.

ניתן לתאר את המודל הנאיבי באופן הבא:



מודל נאבי זה אינו scalable לניהול כאשר יש הרבה מאוד אובייקטים ו/או משתמשים. כדי שמודל Authorization "יעבוד כראוי" חשוב מאוד שיהיה נהיל (maintainable) ופשוט. מבחן בסיסי הוא לענות על שתי שאלות:
  1. "האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?" במקרה שלנו - ממש לא. הוא יכול לקבל הרשאות לעשרות, מאות, אולי אלפי אובייקטים. גם אם יש לנו את רשימה של האובייקטים זמינה בקלות - יכול לקחת זמן מה לפענח ולהבין מה הוא בדיוק כל אובייקט. לדוגמה: אם אלו מסמכים - מה מכילים המסמכים השונים שיש למשתמש הרשאות.
  2. "כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?" במקרה הזה - כן, זהו אובייקט ספציפי.

היכן משתמשים במודל זה?
אני מקווה שרק ב textbooks של קורסי "מבוא לאבטחה", אם כי סביר שיש לא מעט מערכות שמנוהלות בערך כך. בפועל - אם מספר האובייקטים והמשתמשים מצומצם (נאמר, עשרה מכל אחד) - מודל זה יכול להיות פשוט ויעיל.

עוד בעיה של המודל הוא software scalability. הטבלה בבסיס הנתונים עלולה לצמוח במהירות. למשל: חשבו על שרת קבצים המאכסן כמיליון קבצים עבור כמה מאות משתמשים (תסריט סביר של חברה בינונית). אם עבור כל גישה לכל אובייקט נצטרך לסרוק טבלה של מיליוני שורות (אובייקטים x משתמשים) - אנחנו בבעיה.

יתרון של המודל שהוא בהחלט פשוט וקל להבנה - זוהי תכונת מפתח של המצופה ממודל Authorization.
למה אני חוזר ומדגיש נקודה זו? כי בסוף את ניהול ההרשאות עושים בני-אדם. מודל "מעולה מתמטית" שהמשתמשים לא מבינים  - שקול למודל גרוע. הנה 2 דוגמאות אופייניות:
  1. משתמש א' מנסה להגדיר הרשאות למשתמש ב' - אך לא מצליח לעשות זאת. אחרי כמה ניסיונות הוא נשבר, בוחר את הקבוצה "Everyone" ומסמן כל checkbox שהוא רואה ב UI בכדי לאפשר למשתמש ב' את הגישה המיוחלת.
    התוצאה: המידע חשוף לכולם ואיננו מאובטח.
  2. מנהל האבטחה / איש IT שאחראי על ההרשאות לא מצליח לעקוב למי יש גישה למה. עובדים עוברים תפקידים, עוזבים, מידע נוסף - אבל אין יכולת לעקוב אחרי מה שמתרחש. אין יכולת לאכוף חוקים אבטחה ארגוניים. מערכת האבטחה מסתמכת בעיקר על עובדים ללא הבנה בענייני אבטחה, שאבטחה היא בעיקר מעצור בשבילם "to get the job done".
    התוצאה: חוסר שליטה. לעתים מוסיפים מערכת אבטחה חיצונית שמגבילה את צעדי המשתמשים באופן דרקוני - בניסיונות להחזיר את השליטה.


מה הוא רואה: הכל, או כלום? 


מודל: Access Control List


בואו נתקדם מהמודל הנאיבי 2 צעדים קדימה:
  1. ננהל את המשתמשים בקבוצות (בעזרת מערכת x.509/LDAP/Active Directory וכו') וננהל הרשאות לקבוצות, לא בודדים. התוצאה: הרבה פחות הרשאות לנהל.
  2. נקבע היררכיה בין המשאבים, כך שאם נתנו הרשאה למודל אב - האובייקטים הבנים יורשים אותה (אלא אם הוגדר אחרת במפורש) - שוב: פחות משאבים לנהל עליהם הרשאות.

המודל יראה בערך כך:



מודל זה פישט משמעותית את כמות הרשומות ב"טבלת ההרשאות" ושיפר את ה scalability של הניהול: במקום עשרות משאבים / משתמשים, אנו יכולים כעת לנהל מאות. במידה ויש אחידות גבוהה של המשתמשים / משאבים - אולי אפילו אלפים.

מודל ה Access Control Lists (בקיצור: ACL) - מפשט את יכולת הניהול אפילו קצת יותר: הוא מאגד את ה Permissions לאובייקט אחד שנקרא ACL. נובעים מכך כמה יתרונות:
  1. ה ACL הוא חלק מהמשאב. אם מזיזים את המשאב - ה ACL זז איתו, ואין צורך לנהל (ברמת הקוד) מעקב ושינויים בטבלת ההרשאות.
  2. בגלל שה ACL הוא אובייקט יחיד, יש פחות רשומות לנהל (יותר software scalability) / ניתן לנהל cache יותר יעיל.
יתרונות אלו נראים קטנים - אך הם, בסופו של דבר, חשובים.

לאחר התוספות, המודל יראה כך:



היכן משתמשים במודל זה?
  • מערכות קבצים כמו Windows NT או Unix
  • IBM Tivoli, Cisco Network Infrastructure ומערכות Enterprise אחרות
כמובן שיש וריאציות מעט-שונות של המודל.

עקרון מוסכם כיום הוא שהרשאות חייבות להיות חיוביות (positive) בלבד - כלומר: "מה המשתמש יכול לעשות" ולא "מה המשתמש לא יכול לעשות". זאת, בכדי למנוע סיבוכיות / דו-משמעות של ההרשאות שניתנו. במערכת הקבצים של "חלונות" עברו על כלל זה - מה שמסבך מאוד את ניהול ההרשאות.



  1. "האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?" - לא. מודל ה ACL שיפר את ה scalability של המודל הנאיבי, אך הוא עדיין נחשב מודל מאותגר-scalability מבחינת ניהול.
    ארגונים גדולים נוהגים לרכוש כלי ניתוח שסורקים את ה ACLs במערכות הקבצים, ומייצרות דוחות המקלים על ההבנה מה כל משתמש יכול לעשות.
  2. "כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?" - פחות או יותר כן, כל עוד המשאבים מנוהלים היררכית בצורה הגיונית (מה שלעתים קרובות קורה).
חולשה של מודל ה ACL הוא טיפול בהסרה של הרשאות - מה שעלול לדרוש עדכון של ACLs רבים והלוגיקה מאחוריו עלולה להיות בלתי-מובנת לחלק מהמשתמשים.


מודל: Policy-Based Authorization

במשך השנים ניסו ליצור מודל קל יותר לניהול, שיתאר יותר את צורכי האבטחה של הארגון ופחות ייצמד למבנה המשאבים הטכני במערכת. זהו מודל ה Policy-Based Authorization (בקיצור: PBA או PBAC).

הרעיון הוא שהארגון יקבע סט של כללי-אבטחה / מדיניות אבטחה (Policies), יכיל אותם על משאבים, והמערכת תאכוף אותם.
למשל: "לחשבוניות שנוצרו בשבוע האחרון יש הרשאות קריאה למשתמשים מסוג x, המתחברים מתוך הרשת הארגונית".

בהפשטה, המודל יכול להראות משהו כזה:


במודל זה יש וריאציות רבות יותר ממודלים אחרים.

היכן משתמשים במודל זה?
מודל זה מקובל בעולם ה Enterprise במערכות רבות, נפוץ גם בעולם אבטחה (דוגמה מאוד פשוטה: Firewall)
  1. "האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?" - !Hell No: למרות שיש הרבה פחות חוקים (policies) מ Permission במודלים הקודמים - הם עכשיו מורכבים הרבה יותר ומסובכים למעקב. ליתר דיוק ניתן לומר שמודל זה עשוי להיות מוצלח במקרים מסוימים, במיוחד כאשר כללים בסיסיים יכולים לתאר אוסף גדול מאוד של מקרים, משאבים או משתמשים (למשל: "אסור לגשת ל port 1433 בלי רשות של רגע ודודלי").
    קל במודל להגדיר Policies באופנים שונים, ברמות הפשטה שונות, ובסגנון שונה שיקשה על ההבנה שלהן.
  2. "כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?" - שוב, מאוד תלוי.
סה"כ, מודל ה PBA הוא שנוי במחלוקת לגבי היכולת שלו לפשט את ניהול ההרשאות במערכת ה Enterprise Scale.
כיצד אם כן מערכות אבטחה רבות משתמשות במודל זה? התשובה שלי היא שאנשי אבטחה רבים סובלים ממודל מסובך שקשה לנהל ולעקוב אחריו. עבור כמה מקרים - המודל היה מוצלח, ועבור רבים אחרים - הוא נבחר מ"סיבות היסטוריות".

מודל ה PBA יכול גם לסבול מבעיות software scalability קשות, כאשר מספר ה policies עולה. בחלק מהמערכות, "מקמפלים" את ה policies לאוטומט שיוכל לבצע את אימות ה policies בצורה יעילה יותר.


מודל ה Role-Based Authorization


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

מודל ה Role-Based Authorization (בקיצור: RBA) הוא מודל נוסף שמנסה לתאר את הארגון וצרכיו, ולא רק להיצמד למבנה המשאבים הטכני.

במודל ה RBA ממדלים Role ("תפקיד") כסט של מטלות (Tasks) לביצוע. אנשים שאמורים לבצע מטלות דומות, לרוב יהיו בתפקידים זהים או דומים. לאותם בעלי תפקידים דומים נותנים סט של הרשאות על משאבים.

בצורה הפשוטה ביותר ניתן לבטא את מודל ה RBA באופן הבא:



על פניו נראה שאין פה תחכום גדול: Role נראה כ Group בשינוי אדרת. זוהי אכן הסיבה שרבים מתבלבלים / לא מבינים את מודל ה RBA כראוי. בעצם, יש למודל מספר תכונות שלא ניתן להסיק מהתרשים בלבד:

סמנטיקה: עצם כך שהקבוצה נקראת "Role" מעודדת את המשתמשים לייצר קבוצות ע"פ התפקידים הקיימים בארגון: { רופאים, אחיות, אחיות בכירות } או { קניין, קניין חוץ, מנהל חשבונות }. צורה זו עוזרת לארגן את המשתמשים בשפה/סמנטיקה מרכזית בארגון - שכולם מכירים ומבינים.

ריכוזיות: לעתים רבות משייכים את המשאבים ל Role ולא להיפך, כך שאובייקט ה Role הוא בעצם זה ש"מחזיק" את ההרשאות. גישה ריכוזית זו עוזרת לעקוב בקלות אחר ההרשאות - במיוחד במערכות מבוזרות בהן המשאבים נמצאים במערכות שונות.

אחידות: מכיוון שמספר התפקידים בארגון הוא לא מאוד גדול (לא יותר מכמה עשרות, ברוב הארגונים), יחידת ההרשאות (שהן ה Role) הן Coarse-Grained, כלומר: מעט קבוצות המכילות הרבה משאבים.

לגישה זו יש מספר תוצרים:
  1. למשתמשים תהיה גישה למשאבים שהם לא זקוקים להם (כי עמיתים מקבילים להם היו זקוקים להם לעבודתם). כלומר: ההרשאות הן לא "מינימליות".
  2. הרבה יותר קל ופשוט לנהל את ההרשאות:
    1. אם ל"רופא" אחר יש הרשאה למשאב, מספיק שאוסיף אותך ל Role "רופא", כדי שתקבל "אותן הרשאות. "שכפול הרשאות" הוא פעולה דיי מסובכת עד בלתי-אפשרית במערכת שמנהלת הרשאות כ ACLs. 
    2. כשעובדים מבצעים מעברי פרויקטים / תת-תפקיד, סיכוי גבוה שההרשאות שמוגדרות להם עכשיו - מספיקות. ==> תחזוקה קלה.
    3. מכיוון שיש מעט קבוצות, והן מתמפות ל"שפה הטבעית של הארגון", למי שמגדיר את ההרשאות ברור הרבה יותר טוב למי הן מיועדות.
    4. כאשר רוצים לבצע סקירה של המשאבים שזמינים לרופאים, קל מאוד לבדוק את ה Role של הרופאים ולראות מה זמין להם.

בואו נבחן את המודל:
  1. "האם ניתן להבין בקלות מה בדיוק משתמש x מורשה לעשות?" - כן. ה Role מוכר בארגון ויש הרבה נקודות התייחסות.
  2. "כאשר אני מספק למישהו הרשאה, האם קל להבין למה בדיוק אני מספק לו הרשאה?" - כן, ניתן לסקור את ה Role בקלות ולמצוא את כל המשאבים. סביר שהמשתמש מכיר את המשאבים כי הוא בעצמו חבר ב Role.

היכן ניתן למצוא את המודל?
שרתי ווב, JEE, Windows, .NET, מערכות שונות של SAP, Oracle, IBM ועוד.

סה"כ מודל ה RBA נחשב כ "Best Practice" בתעשיית ה Enterprise וכמודל מוצלח במיוחד. הוא מספק פשטות ניהול שהיא הדרך הכמעט-יחידה של ארגון לשלוט ולהבין אילו הרשאות יש לעובדים, מבלי לטרטר אותם יותר מדי. 

הנה גרסה מעט יותר מורכבת של המודל (בכדי לסבר את העין):



כמובן שלמודל ה RBA יש גם כמה חסרונות:
  1. המודל לא מספק שליטה במידע רגיש שאמור להיות זמין לקבוצה קטנה של אנשים. במקרים אלו מספקים מודל הרשאות נוסף (למשל: ACL למשאבים רבים - כמו קבצים, PBA למקרים רוחביים / מופשטים כמו Ethical Wall [ב]) על גבי קבוצה מסוימת של משאבים ב Role, כלומר: מגבילים חלק מהמשאבים המשויכים ל Role לתת קבוצה של ה Role.
  2. מה קורה בארגון שבו אין בעלי תפקידים ברורים? ארגונים בהם מידע מוגש על בסיס "need to know"? - מודל ה RBA פשוט לא מתאים.


סיכום


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


שיהיה בהצלחה!

ליאור



---

[א] הנה הסבר מוצלח בנושא: https://crackstation.net/hashing-security.htm

[ב] המקרה בו 2 בעלי תפקידים לא מורשים לגשת למידע אחד של השני מסיבות אתיות. לדוגמא: משרד עו"ד שמייצג שתי חברות מתחרות בתיקים שונים. עדיין, אסור לעו"ד שמייצג את חברה א' למצוא מידע על החברה המתחרה ב'.


יום שלישי, 15 באוקטובר 2013

שלום, אנגולר! (Angular.js)

לפני כשנה, כתבתי סדרת הפוסטים על MVC בצד הלקוח, והתמקדתי ב 3 ספריות:
  • Backbone
  • Knockout
  • Ember
הזכרתי, כדרך אגב, את Angular.js של גוגל, שנראתה לי אז עוד אחת מיני רבות.

במהלך השנה האחרונה, Angular הפכה לסופר-פופולרית: שנייה לאחר Backbone ע"פ Github, וכנראה ראשונה בקצב הצמיחה והחשיפה התקשורתית. ייתכן והיא הייתה מספיק משמעותית גם לפני שנה - ופספסתי זאת.

במשך זמן רב, הייתי שרוי תחת מסתורין: שמעתי חצאי-אמירות לגבי אנגולר, אך לא הצלחתי להרכיב מהן תמונה מציאותית / יציבה: מהי בעצם אנגולר ומה היא עושה. 

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


משמעות המילה Angular = בעל פינות או זוויות חדות. אולי השם בא לבטא של Angular יש תפיסות חד-משמעיות?!

אז מה היא אנגולר (AngularJS)?


בכדי לענות על השאלה לעומק, נדרשים כנראה 3-4 פוסטים, אבל הנה כמה נקודות מעניינות:
  • אנגולר היא ספריית MVC בצד הלקוח. היא כוללת מודל, View, Controller ו Services.
  • בניגוד ל Backbone וכמו אמבר - זוהי ספרייה בעלת דעה ברורה, שלקחה החלטות עבור המשתמש. המשמעות: פחות שורות קוד שיש להקליד - אך גם פחות גמישות.
  • בניגוד לספריות אחרות, ובצורה דיי ייחודית, אנגולר משתלבת בצורה "טבעית" למדי בתוך ה HTML, במקום לייצר (כמו ספריות אחרות) הפשטות מעל ה HTML.
  • אנגולר נכתבה בראייה מרכזית של בדיקתיות (Testability). ניתן לכתוב לה בקלות בדיקות יחידה[א], ניתן לכתוב לה בקלות בדיקות אינטגרציה/מערכת. זו לא טענה שקל לטעון בעד אמבר (EmberJS) - למשל.
    אנגולר היא ספריית-האם של Karma (כלי מצוין להרצת בדיקות בג'אווהסקריפט, שאנו משתמשים בו בלי-קשר).
    בכדי לתמוך בבדיקות יחידה, אנגולר כוללת מנגנון Dependency Injection [ב] מובנה.
    כל אלה = כבר סיבה טובה להעריך את אנגולר!
  • אנגולר אינה תלויה בשום ספריה אחרת, והקהילה שלה בעצם מעודדת אי-שימוש ב jQuery. היא כוללת תת-ספריה שנקראת jQuery Light המספקת כמה יכולות בסיסיות מקבליות ליכולותיה של jQuery ובתחביר דומה מאוד.
  • אנגולר תואמת AMD, אם כי לא ל require.js.
  • לאנגולר יש אינטגרציה עם ספרייה "לוהטת" אחרת: Twitter Bootstrap.
    אנגולר לא מייצרת UI עשיר ויפה (אלא רק Markup - ממש כמו ספריות MVC אחרות). Bootstrap משלימה גם את היופי וגם מתאימה לפילוסופיה של אנגולר. השלמה זו צריכה לעבוד יפה גם עם אלטרנטיבות ל Bootstrap כמו Foundation, Neat, Pure או Semantic.
  • לאנגולר מנגנון Two-Way Data-Binding יעיל (פרטים בהמשך).
  • לאנגולר יש מנגנון Templating ייחודי משלה (פרטים בהמשך).
  • ה "Sweet Spot" של אנגולר היא אפליקציות עסקיות, ואפליקציות CRUD בפרט (הזנת ושליפת נתונים). אנגולר לא מתאימה, למשל, למשחקים או ל UI לא-שגרתי.
  • אנגולר פופולרית: אנגולר היא ה "A" ב "MEAN" - סט טכנולוגיות פופולרי שמתתעד להיות התחליף המודרני ל LAMP.
  • אנגולר איננה פשוטה כמו Backbone, לוקח זמן ללמוד אותה ולהתמצא בפרטים.
  • אנגולר טוענת שהיא "Forward Looking" ומיישמת היום תקני ווב עתידיים / נראית כמו שהווב יראה עוד כמה שנים.
    יש דיבורים על כך שספרייה חדשנית אחרת של גוגל, Polymer, תשתלב לבסוף באנגולר.
    אני לא מתייחס לטיעונים האלו ברצינות, אנו יודעים למי ניתנה הנבואה...
  • אנגולר היא מבית גוגל, מה שאומר שיש מאחוריה מפתחי ווב מוכשרים אבל גם מנגנון יחסי-ציבור חסר-תקדים. פרויקטים של גוגל נוטים לעשות המון באזז עוד לפני שהם באמת הצליחו, מה שמותיר ספק אם לאנגולר צפוי מחזור חיים דומה לזה שהיה ל GWT.


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



שלום עולם!


בואו נראה דוגמת קוד קטנה באנגולר:


  1. שימו לב שדף ה HTML באנגולר הוא משמעותי. ראשית הוספנו סקריפטים - כמו כל דף HTML.
    נכון, היה יעיל יותר להוסיף את תגיות ה script לאחר ה <body>, דילגתי על שיפורי ביצועים לצורך פשטות הקוד.
  2. בתוך ה body הוספתי H1 והגדרתי את HelloWorldCtrl כקונטרולר האחראי על אזור זה (תג ה H1). הסיומת Ctrl מקובלת באנגולר לסימון קונטרולרים. צירוף האותיות ng משמש לכל ה properties / תגיות שאנגולר מוסיף ל HTML.
    אנגולר, במקום לבצע הפשטה של ה DOM/HTML - מרחיב אותו. קידומת ה data היא רשות אם אתם רוצים לשמור את קובץ ה HTML שלכם תקני. ניתן (ומקובל) להשתמש פשוט בקיצור, כגון ng-controller, וכך לחסוך קצת הקלדה [ג].
  3. בתוך תגית ה HTML הכנסנו ביטוי בשם message. אם עבדתם פעם עם mustache - אתם מכירים את השפה: סוגריים מסולסלים כפולים עוטפים ביטוי שיחושב.
  4.  באופן דומה למדי, גם הביטוי {{1 + 1}} יחושב. הבדל קטן: הוא לא דורש context (באנגולר נקרא: scope) בעוד הביטוי {{ message }} דורש context - והוא יקבל אותו מה controller האחראי על האזור.
  5. קוד הג'אווהסקריפט שלנו פשוט למדי: הגדרנו קונטרולר (התאמה ע"פ שם) שברגע ההפעלה שלו רושם על ה context/scope ערך בשם message. קידומת $ למשתנים (קרי scope$) מסמלת שאלו משתנים מיוחדים של אנגולר.
  6. כשספריית אנגולר נטענת, אנגולר מפענח את ה DOM ומחפש אחר תוית data-ng-app/ng-app. תוית זו מסמנת את אזור האפליקציה של אנגולר. אפליקציות אנגולר יכולות להתארח או לחיות זו לצד זו.
    לאחר מכן אנגולר ימשיך לפענח את ה DOM וימצא את data-ng-controller.
    בשלב הבא הוא יאתחל את ה controller ואז בעזרתו יחליף את {{ message }} בביטוי הרצוי.

הנה התוצאה המדהימה של האפליקציה שלנו:


כפי שאתם רואים, אנגולר "התעסקה" לנו ב HTML markup:


זו חלק מהשיטה.

סיכום ביניים:
  • ה HTML הוא מרכזי בפתרון. לא כמו Backbone שמעדיפה HTML עם DIV אחד ריק.
  • Controller הוא מעין "מנהל אזורי"
  • חלק משמעותי מהכתיבה באנגולר (ה View / HTML) - הוא דקלרטיבי.


שלום עולם 2: Data-Binding דו-כיווני

קשה להגדיר את הדוגמה הקודמת כדוגמה מייצגת אפליקציית אנגולר - רק בגלל שאנגולר היא מקיפה ולה כלים רבים. הדוגמה הבאה תשלים אזור חשוב מאוד באנגולר: ה 2WDB (קיצור של Two-Way Data Binding).

2WDB אומר בקיצור:
  • ברגע שמעדכנים את המודל - ה View מתעדכן אוטומטית.
  • ברגע שמעדכנים את ה View - המודל מתעדכן אוטומטית.
  • (אין מה לדאוג: אין לופ אינסופי)
מנגנון זה הוא אחד מ"חוסכי הקלדת ה boilerplate code" הגדולים של אנגולר באפליקציות CRUD: רישום לאירועים ועדכון מודלים או Views - קוד טכני שאין בו הרבה חוכמה.

בואו נתבונן בדוגמה הבאה:


  1. קישרנו את שדה ה input ל מודל בשם message. היכן "מחלקת המודל" בקוד ג'אווהסקריפט? - לא קיימת, במקרה זה היא implicit.
  2.  הביטוי {{message}} נמצא בתחום השיפוט של השליט האזורי - הרי הוא ה HelloWorldCtrl. המודל שהגדרנו בשלב 1, מתיישב על ה scope$ של הקונרטולר כפרמטר ובו הערך של שדה ה input. הגדרת HTML זו בלבד (ללא קוד הג'אווהסקריפט) מספיקה בכדי לייצר databinding עובד. הנה לינק לדוגמה עובדת, ללא כל קוד ג'אווהסקריפט.
    כאשר לא מוגדר controller, אזי ה binding ייעשה על ה scope$ הגלובאלי.
  3. ביצעו אתחול של הטקסט לערך התחלתי.
  4. הוספנו האזנה (watch$) על המודל של ה message. כל פעם שיש שינוי נמיר מופעים של האות e ל UpperCase. שימו לב שבעקבות ה 2WDB, הערך ההתחלתי שקבענו ("!Hello World") כבר עובר טרנספורמציה. הנה דוגמת קוד חיה. נסו להקליד e קטנה בתיבת הטקסט ותראו מה קורה.

כל שינוי שנעשה ב View (תיבת הטקסט) משפיע על המודל (אובייקט ג'אווהסקריפט בזיכרון, במקרה שלנו הוא בלתי-מפורש). בקונטרולר אנו מנטרים את השינוי במודל (watch$) ומבצעים בו שינוי נוסף - שחוזר ומעדכן את ה View (תיבת הטקסט). זהו ה 2WDB של אנגולר.



ה Directive

אחד המרכיבים המסתוריים של אנגולר הם ה Directives, בואו נציץ בהם ונראה במה מדובר.
בוודאי שמתם לב שהשתמשנו בתגיות HTML ו Properties שאינם קיימים ב HTML5, כל ה *-ng.
אנגולר מרחיבה את שפת ה HTML [ד] בשפה משלה, ובעצם מעניקה למפתח את היכולת להמשיך ולהרחיב את שפת ה HTML.

איך בדיוק זה עובד? - מעקב אחר ה LifeCycle המלא הוא מעבר להיקף של פוסט זה [ה], אך אספק הסבר קצר, ואני מניח שרוב הקוראים יצליחו להרכיב תמונה מהירה ולא רחוקה מהמציאות של מה שמתרחש.

לאנגולר יש Compiler (רכיב מרכזי) שסורק את ה HTML (הקיים והמתעדכן) ומבצע בו שינויים. אם הוא מזהה תגית לא סטנדרטית, למשל "lb-superlink", הוא יחפש רכיב (מעין "plugin" לקומפיילר) שמתאר את האלנמט הזה ויאמר לו מה לעשות. רכיב כזה נקרא Directive.

מספר directives מסופקים, מהקופסא, עם אנגולר: למשל ng-repeat - רכיב שיכפיל קטע markup לכל רכיב ברשימה שמופיעה במודל (למשל: lineItems).

מתכנתים יכולים להרחיב ולכתוב directives בעצמם. הנה קוד של directive פשוט למדי, ה (Superlink (tm - תגית המספקת טקסט אסתטי שניתן ללחוץ עליו :



  1. lb-superlink הוא הדירקטיב (directive) שמיד נגדיר. בעת לחיצה על הלינק - תופעל הפונקציה ()foo.
    כפי שניתן לראות, ה IDE מזהיר אותי שזה אלמנט לא סטנדרטי ב HTML.
  2. כפי שציינו בהקדמה, אנגולר תואמת למערכת המודולים של AMD. בחרתי בדוגמה זו להראות קוד קצת יותר "מציאותי", אשר מארגון את הקוד סביב המודול myModule.
  3. על דירקטיב (directive) להיות מוגדר עם שם camelCase, כאשר אנגולר מפרק את השם ליחידות ותאפשר מספר צורות של תחביר ב HTML לגשת לדירקטיב שהוגדר. למשל, שמו של ng-repeat הוא בעצם "ngRepeat" (בצורת camelCase) וניתן גם לקרוא לו בצורות כגון ng_repeat, ng:repeat או data-ng-repeat.
    באופן דומה יהיה ניתן להפעיל את הדירקטיב שלנו בצורת lb-superlink, lb_superlink וכו'.
  4. התחביר ליצירת אובייקטים שהם instantiated באנגולר הם ע"י פונקציה המחזירה אובייקט Prototype (כלומר: תבנית העיצוב בשם Prototype), המוגדר בתוך ה return. זהו תחביר קיים (אם כי לא מאוד נפוץ) להגדרת מחלקות בג'אווהסקריפט.
  5. restrict מגדיר כיצד יהיה ניתן להשתמש בתוך ה HTML בדירקטיב שלנו. "E" הוא קיצור של אלמנט, קרי <lb-superlink>. אם היינו כותבים "AE" היה ניתן להגדיר את הדירקטיב גם כ attribute על אלמנט קיים קרי <span lb-superlink>.
  6. ה template מתאר את ה markup שהדרקטיב שלנו ייצר. בחרנו ב div פשוט עם label עבור accessibility. עוד פרטים - בהמשך.
  7. כאשר replace הוא אמת - התג המקורי <lb-superlink> יוסר מתוך ה HTML ע"י הקומפיילר. ניתן להשאיר את התג הקיים או להחליף אותו.
  8. transclude אומר שאנו רוצים לקחת ערכים מתוך התג המקורי <lb-superlink> ולהציב אותם בתוך התג כ ng-transclude ב template. במקרה שלנו: תג ה label.
  9. link הוא ערך חשוב. הוא בעצם פונקציית ה processing שתופעל בנוסף לפעולות הסטנדרטיות שהוגדרו ע"י ה properties הנ"ל. כאן אנו יכולים לכתוב קוד ג'אווהסקריפט חופשי משלנו. במקרה שלנו אנו מבצעים bind לארוע לחיצה על האלמנט שנוצר. השתמשנו כאן ב jQuery Light שמגיע עם אנגולר ("bind"). כפי שניתן לראות - התחביר דומה מאוד.
  10. קוד זה (eval=evil) נראה קצת פחות אסתטי, אך הוא מקובל באנגולר. אנו קוראים את ערך ה attribute בשם click (במקרה שלנו: "()foo"), ומבצעים לו eval, במסגרת ה scope הרלוונטי לאלמנט. בת'כלס אנו מפעילים את פונקציית foo שהוגדרה על ה scope$ של הקונטרולר.

הנה ה markup שנוצר (כפי שאתם זוכרים, אנגולר "מעשיר" את ה markup בביטויים כגון ng-scope):


סיכום

עשינו סקירה + צלילה-מהירה לתוך אנגולר, ספרייה שתופסת לאחרונה תשומת לב וקהל מעריצים רב. ברור שנותר רב נסתר על הגלוי, אל אני מקווה שהצלחתי בקריאה של 5 עד 10 דקות להסיר חלק מהמסתורין מסביב לאנגולר לאלו שאינם מכירים. נראה לי חשוב ומעניין להכיר, אפילו במעט, ספרייה שמשפיעה במידה לא-מבוטלת על עולם ה FrontEnd.


שיהיה בהצלחה!

----

[א] אם אתם רוצים לקרוא מעט יותר על בדיקות יחידה: על בדיקות יחידה.

[ב] אם אתם רוצים לקרוא מעט יותר על Dependency Injection: להבין Dependency Injection.

[ג] בעצם, אנגולר הפרה את תקן ה HTML5 לאורך זמן, ורק לאחרונה הוסיפה את האופציה להוסיף קידומת -data ולציית לתקן.

[ד] אנגולר מתבססת תקן עתידי של Custom Elements, שאם יתוקנן כמתוכנן - יהפוך את התחביר של אנגולר ל HTML5 תקני.

[ה] תוכלו להתעמק בנושא לא-פשוט זה בעזרת מדריך ה Directives של אנגולר: http://docs.angularjs.org/guide/directive


לינקים אחרים

הרבה תוכן מעמיק על אנגולר, גם בעברית, בבלוג של אייל ורדי

סיכום של שנתיים עבודה עם אנגולר, ע"י Alexey Migutsky

Weekly על אנגולר, שכולל בערך אינסוף לינקים (לא סתמיים) בנושא: http://syntaxspectrum.com/