יצירת תוסף ל-Classroom

זוהי ההדרכה הראשונה בסדרת ההדרכה המפורטת על תוספים ל-Classroom.

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

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

  • יוצרים פרויקט חדש ב-Google Cloud לאפליקציית האינטרנט.
  • יצירה של אפליקציית אינטרנט בסיסית עם לחצני כניסה לחשבון.
  • פרסום דף אפליקציה פרטי בחנות Google Workspace Marketplace (GWM) לאפליקציית האינטרנט.

בסיום, תוכלו להתקין את התוסף ולטעון אותו ב-iframe של התוספים ל-Classroom.

דרישות מוקדמות

ניתן לבחור שפה בהמשך כדי לראות את הדרישות המוקדמות המתאימות:

Python

בדוגמה של Python אנחנו משתמשים ב-Flask framework. בדף הסקירה הכללית אפשר להוריד את קוד המקור המלא שכולל את כל ההדרכות המפורטות. הקוד של ההדרכה המפורטת הזו נמצא בספרייה /flask/01-basic-app/.

אם צריך, מתקינים את Python 3.7 ואילך ומוודאים ש-pip זמין.

python -m ensurepip --upgrade

מומלץ גם להגדיר ולהפעיל סביבה וירטואלית חדשה ב-Python.

python3 -m venv .classroom-addon-env
source .classroom-addon-env/bin/activate

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

cd flask/01-basic-app
pip install -r requirements.txt

Node.js

בדוגמה של Node.js נעשה שימוש ב-framework Express. בדף הסקירה הכללית אפשר להוריד את קוד המקור המלא שכולל את כל ההדרכות המפורטות.

במידת הצורך, מתקינים את NodeJS v16.13+.

צריך להתקין את המודולים של הצמתים הנדרשים באמצעות npm.

npm install

Java

הדוגמה ב-Java משתמשת ב-Spring Boot framework. בדף הסקירה הכללית אפשר להוריד את קוד המקור המלא שכולל את כל הדרכות מפורטות.

מתקינים את Java 11 ואילך אם היא עדיין לא מותקנת במחשב.

אפליקציות Spring Boot יכולות להשתמש ב-Gradle או ב-Maven כדי לטפל בגרסאות build ולנהל יחסי תלות. בדוגמה הזו נכלל wrapper של Maven שמבטיח גרסת build מוצלחת בלי שתצטרכו להתקין את Maven.

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

java --version
./mvnw --version

או ב-Windows:

java -version
mvnw.cmd --version

איך מגדירים פרויקט ב-Google Cloud

הפרויקטים ב-Google Cloud שולטים בגישה ל-Classroom API ולשיטות האימות הנדרשות. ההוראות הבאות מסבירות איך לבצע את השלבים המינימליים ליצירה ולהגדרה של פרויקט חדש לשימוש עם התוסף.

יוצרים את הפרויקט

נכנסים לדף ליצירת פרויקט כדי ליצור פרויקט חדש ב-Google Cloud. תוכלו לציין כל שם לפרויקט החדש. לוחצים על Create.

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

בחרו את הפרויקט במסוף Google Cloud

צירוף של GWM SDK לפרויקט ב-Google Cloud

עוברים לדפדפן ספריית API. מחפשים את Google Workspace Marketplace SDK. ה-SDK אמור להופיע ברשימת התוצאות.

כרטיס Google Workspace Marketplace SDK

בוחרים את כרטיס ה-SDK של Google Workspace Marketplace ולוחצים על הפעלה.

הגדרת GWM SDK

GWM מספק את הרישום שדרכו משתמשים ואדמינים מתקינים את התוסף. כדי להמשיך, צריך להגדיר את OAuth Consent Screen ואת הגדרת האפליקציה ודף האפליקציה בחנות של GWM SDK.

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

נכנסים לדף ליצירת מסך ההסכמה של OAuth. יש לספק את הפרטים הבאים:

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

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

    • https://www.googleapis.com/auth/userinfo.email (כבר כלול)
    • https://www.googleapis.com/auth/userinfo.profile (כבר כלול)

    היקפי ההרשאות הבאים ספציפיים לתוספים ל-Classroom:

    • https://www.googleapis.com/auth/classroom.addons.teacher
    • https://www.googleapis.com/auth/classroom.addons.student

    צריך לכלול גם היקפי הרשאות של Google API שהאפליקציה דורשת ממשתמשי קצה.

    לוחצים על שמור והמשך.

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

מוודאים שההגדרות נכונות ואז חוזרים אל מרכז השליטה.

הגדרת האפליקציה

נכנסים לדף App Configuration של GWM SDK. יש לספק את הפרטים הבאים:

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

  • אם רוצים להגביל את ההתקנה למנהלי הדומיין, יש להגדיר את Installation Settings (הגדרות ההתקנה) לערך Admin Only install.

  • בקטע שילוב אפליקציה, בוחרים באפשרות תוסף ל-Classroom. תתבקשו להזין URI מאובטח להגדרת קובץ מצורף. זוהי כתובת ה-URL שאתם מצפים שתיטען כשמשתמש פותח את התוסף שלכם. למטרות ההדרכה המפורטת הזו, זה צריך להיות https://<your domain>/addon-discovery.

  • קידומות URI מותרות משמשות לאימות מזהי ה-URI שהוגדרו ב-AddOnAttachment באמצעות courses.*.addOnAttachments.create והשיטה courses.*.addOnAttachments.patch. האימות הוא התאמה לקידומת של מחרוזת מילולית, ולכן בשלב הזה אי אפשר להשתמש בתווים כלליים לחיפוש. בינתיים, אפשר להשאיר את השדות האלה ריקים.

  • מוסיפים את אותם היקפי הרשאות OAuth שצוינו במסך ההסכמה של OAuth בשלב הקודם.

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

רישום חנות

עוברים לדף רישום החנות של GWM SDK. יש לספק את הפרטים הבאים:

  • בקטע App Details (פרטי האפליקציה), מוסיפים שפה או מרחיבים את התפריט הנפתח ליד השפה שכבר רשומה. ציינו שם של אפליקציה ותיאורים, יופיעו בדף האפליקציה בחנות GWM של התוסף. לוחצים על סיום כדי לשמור.
  • בוחרים קטגוריה לתוסף.
  • בקטע נכסים גרפיים, מספקים תמונות בשדות החובה. אפשר לשנות אותם מאוחר יותר, והם יכולים לשמש כ-placeholders אם הגדרתם את החשיפה של האפליקציה לפרטי בשלב הקודם.
  • בקטע קישורים לתמיכה, מציינים את כתובות ה-URL המבוקשות. הן יכולות להיות placeholders, אם הגדרתם את חשיפת האפליקציה לפרטי בשלב הקודם.

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

התקנת התוסף

עכשיו אפשר להתקין את התוסף באמצעות הקישור שמופיע בראש הדף רישום בחנות של GWM SDK. לוחצים על App URL בחלק העליון של הדף כדי להציג את דף האפליקציה, ובוחרים באפשרות Install (התקנה).

יצירה של אפליקציית אינטרנט בסיסית

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

אפליקציית אינטרנט לדוגמה ב-iframe

מטמיעים את שתי נקודות הקצה הבאות:

  • /: תוצג הודעת פתיחה ולחצן לסגירה של הכרטיסייה הנוכחית וגם של תוסף ה-iframe.
  • /addon-discovery: להצגת הודעת פתיחה ושני לחצנים: אחד לסגירת התוסף iframe ואחד לפתיחת אתר בכרטיסייה חדשה.

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

יצירת סקריפט של כלי עזר

יצירה של ספריית static/scripts. יצירת קובץ חדש addon-utils.js. מוסיפים את שתי הפונקציות הבאות.

/**
 *   Opens a given destination route in a new window. This function uses
 *   window.open() so as to force window.opener to retain a reference to the
 *   iframe from which it was called.
 *   @param {string} destinationURL The endpoint to open, or "/" if none is
 *   provided.
 */
function openWebsiteInNewTab(destinationURL = '/') {
  window.open(destinationURL, '_blank');
}

/**
 *   Close the iframe by calling postMessage() in the host Classroom page. This
 *   function can be called directly when in a Classroom add-on iframe.
 *
 *   Alternatively, it can be used to close an add-on iframe in another window.
 *   For example, if an add-on iframe in Window 1 opens a link in a new Window 2
 *   using the openWebsiteInNewTab function above, you can call
 *   window.opener.closeAddonIframe() from Window 2 to close the iframe in Window
 *   1.
 */
function closeAddonIframe() {
  window.parent.postMessage({
    type: 'Classroom',
    action: 'closeIframe',
  }, '*');
};

יצירת מסלולים

הטמעת נקודות הקצה /addon-discovery ו-/.

Python

הגדרה של ספריית האפליקציות

לצורך הדוגמה הזו, צריך לבנות את הלוגיקה של האפליקציה כמודול Python. זוהי הספרייה webapp בדוגמה שסופקה שלנו.

אתם יכולים ליצור ספרייה למודול השרת, למשל webapp. מעבירים את הספרייה static לספריית המודול. יוצרים גם את ספריית template בספריית המודול; קובצי ה-HTML נכנסים לכאן.

יצירת מודול השרת*

יוצרים את הקובץ __init__.py בספריית המודול ומוסיפים את קובצי הייבוא וההצהרות הבאים.

from flask import Flask
import config

app = Flask(__name__)
app.config.from_object(config.Config)

# Load other module script files. This import statement refers to the
# 'routes.py' file described below.
from webapp import routes

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

from webapp import app
import flask

@app.route("/")
def index():
    return flask.render_template("index.html",
                                message="You've reached the index page.")

@app.route("/classroom-addon")
def classroom_addon():
    return flask.render_template(
        "addon-discovery.html",
        message="You've reached the addon discovery page.")

שימו לב ששני המסלולים שלנו מעבירים משתנה message לתבניות ה-Jinja המתאימות שלהם. כך ניתן לזהות את הדף שאליו המשתמש הגיע.

יצירת קובצי תצורה והפעלת קבצים

בתיקיית השורש של האפליקציה, יוצרים את הקבצים main.py ו-config.py. הגדר את המפתח הסודי שלך ב-config.py.

import os

class Config(object):
    # Note: A secret key is included in the sample so that it works.
    # If you use this code in your application, replace this with a truly secret
    # key. See https://flask.palletsprojects.com/quickstart/#sessions.
    SECRET_KEY = os.environ.get(
        'SECRET_KEY') or "REPLACE ME - this value is here as a placeholder."

בקובץ main.py, מייבאים את המודול ומפעילים את שרת Flask.

from webapp import app

if __name__ == "__main__":
    # Run the application over HTTPs with a locally stored certificate and key.
    # Defaults to https://localhost:5000.
    app.run(
        host="localhost",
        ssl_context=("localhost.pem", "localhost-key.pem"),
        debug=True)

Node.js

נתיבים רשומים בקובץ app.js עם השורות הבאות.

const websiteRouter = require('./routes/index');
const addonRouter = require('./routes/classroom-addon');

app.use('/', websiteRouter);
app.use('/addon-discovery', addonRouter);

פותחים את /01-basic-app/routes/index.js ובודקים את הקוד. המסלול הזה מגיע כשמשתמש הקצה מבקר באתר החברה. המסלול מעבד תגובה באמצעות התבנית index של Handlebars, ומעביר לתבנית אובייקט נתונים שמכיל את המשתנים title ו-message.

router.get('/', function (req, res, next) {
  res.render('index', {
    title: 'Education Technology',
    message: 'Welcome to our website!'
  });
});

פותחים את המסלול השני /01-basic-app/routes/classroom-addon.js ובודקים את הקוד. אפשר להגיע למסלול הזה כשהביקור של משתמש הקצה הוא בתוסף. שימו לב שבמסלול הזה נעשה שימוש בתבנית discovery של כידון ובפריסה addon.hbs, כדי לעבד את הדף באופן שונה מהאתר של החברה.

router.get('/', function (req, res, next) {
  res.render('discovery', {
    layout: 'addon.hbs',
    title: 'Education Technology Classroom add-on',
    message: `Welcome.`
  });
});

Java

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

בפרויקט לדוגמה הזה, יוצרים מחלקה של בקר, Controller.java, כדי להגדיר את נקודות הקצה. בקובץ הזה, מייבאים את ההערה @GetMapping מהתלות spring-boot-starter-web.

import org.springframework.web.bind.annotation.GetMapping;

כדי לציין את מטרת המחלקה, צריך לכלול את ההערה של בקר המסגרת של Spring מעל הגדרת המחלקה.

@org.springframework.stereotype.Controller
public class Controller {

לאחר מכן יש ליישם את שני המסלולים ומסלול נוסף לטיפול בשגיאות.

/** Returns the index page that will be displayed when the add-on opens in a
*   new tab.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the index page template if successful, or the onError method to
*   handle and display the error message.
*/
@GetMapping(value = {"/"})
public String index(Model model) {
  try {
    return "index";
  } catch (Exception e) {
    return onError(e.getMessage(), model);
  }
}

/** Returns the add-on discovery page that will be displayed when the iframe
*   is first opened in Classroom.
*   @param model the Model interface to pass error information that's
*   displayed on the error page.
*   @return the addon-discovery page.
*/
@GetMapping(value = {"/addon-discovery"})
public String addon_discovery(Model model) {
  try {
    return "addon-discovery";
  } catch (Exception e) {
    return onError(e.getMessage(), model);
  }
}

/** Handles application errors.
*   @param errorMessage message to be displayed on the error page.
*   @param model the Model interface to pass error information to display on
*   the error page.
*   @return the error page.
*/
@GetMapping(value = {"/error"})
public String onError(String errorMessage, Model model) {
  model.addAttribute("error", errorMessage);
  return "error";
}

בדיקת התוסף

מפעילים את השרת. לאחר מכן נכנסים אל Google Classroom בתור אחד מהמשתמשים בבחינה של המורים. נכנסים לכרטיסייה עבודות ויוצרים מטלה חדשה. לוחצים על הלחצן תוספים מתחת לאזור הטקסט ובוחרים את התוסף. ה-iframe נפתח והתוסף טוען את ה-URI להגדרת קבצים מצורפים שציינתם בדף App Configuration של GWM SDK.

כל הכבוד! אתם מוכנים להמשיך לשלב הבא: הכנסת משתמשים באמצעות Google SSO.