Xác thực một biến đầu vào

Hướng dẫn này giải thích cách xác thực một biến đầu vào.

Khi xác định một biến đầu vào, tốt nhất là bạn nên xác thực để đảm bảo người dùng nhập một giá trị phù hợp. Ví dụ: nếu bạn yêu cầu người dùng nhập một chữ số, việc xác minh rằng họ nhập 1 thay vì a sẽ xác minh rằng bước của bạn chạy mà không gặp lỗi.

Có 2 cách để xác thực một biến đầu vào:

  • Xác thực phía máy khách: Với tính năng xác thực phía máy khách, bạn xác minh thông tin đầu vào của người dùng ngay trên thiết bị của họ. Người dùng nhận được phản hồi ngay lập tức và có thể sửa mọi lỗi trong dữ liệu đầu vào khi định cấu hình bước này.
  • Xác thực phía máy chủ: Xác thực phía máy chủ cho phép bạn chạy logic trên máy chủ trong quá trình xác thực. Điều này rất hữu ích khi bạn cần tra cứu thông tin mà máy khách không có, chẳng hạn như dữ liệu trong các hệ thống hoặc cơ sở dữ liệu khác.

Xác thực phía máy khách

Có hai cách để triển khai quy trình xác thực phía máy khách:

  • Để xác thực cơ bản, chẳng hạn như xác minh một tiện ích chứa ít hơn một số ký tự nhất định hoặc chứa biểu tượng @, hãy gọi lớp Validation của Dịch vụ thẻ trong tiện ích bổ sung Google Workspace.
  • Để xác thực mạnh mẽ, chẳng hạn như so sánh các giá trị tiện ích với các giá trị tiện ích khác, bạn có thể thêm quy trình xác thực Ngôn ngữ biểu thức chung (CEL) vào các tiện ích thẻ được hỗ trợ sau đây bằng cách sử dụng CardService.

Gọi lớp Validation

Ví dụ sau đây xác thực rằng một tiện ích TextInput chứa không quá 10 ký tự:

Apps Script

const validation = CardService.newValidation().setCharacterLimit('10').setInputType(
    CardService.InputType.TEXT);

Để có thêm các lựa chọn xác thực, hãy sử dụng xác thực CEL.

Xác thực CEL

Quy trình xác thực Ngôn ngữ biểu thức chung (CEL) cung cấp các chế độ kiểm tra đầu vào tức thì mà không có độ trễ của quy trình xác thực phía máy chủ bằng cách giảm tải các chế độ kiểm tra giá trị đầu vào không phụ thuộc vào việc tra cứu dữ liệu từ các dịch vụ khác sang phía máy khách.

Bạn cũng có thể sử dụng CEL để tạo các hành vi của thẻ, chẳng hạn như hiển thị hoặc ẩn một tiện ích tuỳ thuộc vào kết quả xác thực. Loại hành vi này rất hữu ích khi bạn muốn hiện hoặc ẩn một thông báo lỗi giúp người dùng sửa thông tin đầu vào.

Việc tạo một quy trình xác thực CEL hoàn chỉnh bao gồm các thành phần sau:

  • ExpressionData trong Thẻ: Chứa logic xác thực và logic kích hoạt tiện ích được chỉ định khi một trong các Điều kiện được xác định được đáp ứng.

    • Id: Giá trị nhận dạng duy nhất cho ExpressionData trong Thẻ hiện tại.
    • Expression: Chuỗi CEL xác định logic xác thực (ví dụ: "value1 == value2").
    • Conditions: Danh sách các điều kiện chứa một lựa chọn về kết quả xác thực được xác định trước (THÀNH CÔNG hoặc THẤT BẠI). Các điều kiện được liên kết với EventAction ở phía tiện ích thông qua Triggers bằng actionRuleId dùng chung.
    • EventAction ở cấp thẻ: Kích hoạt quy trình xác thực CEL trong Thẻ và liên kết trường ExpressionData với các tiện ích kết quả thông qua các trình kích hoạt sau sự kiện.
      • actionRuleId: Mã nhận dạng duy nhất cho EventAction này.
      • ExpressionDataAction: Đặt thành START_EXPRESSION_EVALUATION để cho biết hành động này bắt đầu đánh giá CEL.
      • Trigger: Kết nối Conditions với EventActions phía Tiện ích dựa trên actionRuleId.
  • EventAction ở cấp tiện ích: Kiểm soát hành vi của tiện ích kết quả khi điều kiện thành công hoặc thất bại được đáp ứng. Ví dụ: một tiện ích kết quả có thể là TextParagraph chứa thông báo lỗi chỉ xuất hiện khi quá trình xác thực không thành công.

    • actionRuleId: So khớp actionRuleId trong Trigger phía thẻ.
    • CommonWidgetAction: Xác định những hành động không liên quan đến việc đánh giá, chẳng hạn như cập nhật khả năng hiển thị của tiện ích.
      • UpdateVisibilityAction: Một thao tác cập nhật trạng thái hiển thị của một tiện ích (VISIBLE hoặc HIDDEN).

Ví dụ sau đây minh hoạ cách triển khai quy trình xác thực CEL để kiểm tra xem 2 dữ liệu đầu vào văn bản có bằng nhau hay không. Thông báo lỗi sẽ xuất hiện nếu hai giá trị này không bằng nhau.

  • Khi failCondition được đáp ứng (đầu vào không bằng nhau), tiện ích thông báo lỗi sẽ được đặt thành VISIBLE và xuất hiện.
    Hình 1: Khi điều kiện failCondition được đáp ứng (đầu vào không bằng nhau), tiện ích thông báo lỗi sẽ được đặt thành VISIBLE và xuất hiện.
  • Khi successCondition được đáp ứng (các giá trị đầu vào bằng nhau), tiện ích thông báo lỗi sẽ được đặt thành HIDDEN và không xuất hiện.
    Hình 2: Khi điều kiện successCondition được đáp ứng (các giá trị đầu vào bằng nhau), tiện ích thông báo lỗi sẽ được đặt thành HIDDEN và không xuất hiện.

Sau đây là mã ứng dụng mẫu và tệp kê khai JSON:

Apps Script

function onConfig() {

  // Create a Card
  let card = CardService.newCardBuilder();

  const textInput_1 = CardService.newTextInput()
    .setTitle("Input number 1")
    .setFieldName("value1"); // FieldName's value must match a corresponding ID defined in the inputs[] array in the manifest file.
  const textInput_2 = CardService.newTextInput()
    .setTitle("Input number 2")
    .setFieldName("value2"); // FieldName's value must match a corresponding ID defined in the inputs[] array in the manifest file.
  let sections = CardService.newCardSection()
    .setHeader("Two number equals")
    .addWidget(textInput_1)
    .addWidget(textInput_2);

  // CEL Validation

  // Define Conditions
  const condition_success = CardService.newCondition()
    .setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID")
    .setExpressionDataCondition(
      CardService.newExpressionDataCondition()
      .setConditionType(
        CardService.ExpressionDataConditionType.EXPRESSION_EVALUATION_SUCCESS));
  const condition_fail = CardService.newCondition()
    .setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID")
    .setExpressionDataCondition(
      CardService.newExpressionDataCondition()
      .setConditionType(
        CardService.ExpressionDataConditionType.EXPRESSION_EVALUATION_FAILURE));

  // Define Card-side EventAction
  const expressionDataAction = CardService.newExpressionDataAction()
    .setActionType(
      CardService.ExpressionDataActionType.START_EXPRESSION_EVALUATION);
  // Define Triggers for each Condition respectively
  const trigger_success = CardService.newTrigger()
    .setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID");
  const trigger_failure = CardService.newTrigger()
    .setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID");

  const eventAction = CardService.newEventAction()
    .setActionRuleId("CEL_TEXTINPUT_EVALUATION_RULE_ID")
    .setExpressionDataAction(expressionDataAction)
    .addPostEventTrigger(trigger_success)
    .addPostEventTrigger(trigger_failure);

  // Define ExpressionData for the current Card
  const expressionData = CardService.newExpressionData()
    .setId("expData_id")
    .setExpression("value1 == value2") // CEL expression
    .addCondition(condition_success)
    .addCondition(condition_fail)
    .addEventAction(eventAction);
  card = card.addExpressionData(expressionData);

  // Create Widget-side EventActions and a widget to display error message
  const widgetEventActionFail = CardService.newEventAction()
    .setActionRuleId("CEL_TEXTINPUT_FAILURE_RULE_ID")
    .setCommonWidgetAction(
      CardService.newCommonWidgetAction()
      .setUpdateVisibilityAction(
        CardService.newUpdateVisibilityAction()
        .setVisibility(
          CardService.Visibility.VISIBLE)));
  const widgetEventActionSuccess = CardService.newEventAction()
    .setActionRuleId("CEL_TEXTINPUT_SUCCESS_RULE_ID")
    .setCommonWidgetAction(
      CardService.newCommonWidgetAction()
      .setUpdateVisibilityAction(
        CardService.newUpdateVisibilityAction()
        .setVisibility(
          CardService.Visibility.HIDDEN)));
  const errorWidget = CardService.newTextParagraph()
    .setText("The first and second value must match.")
    .setVisibility(CardService.Visibility.HIDDEN) // Initially hidden
    .addEventAction(widgetEventActionFail)
    .addEventAction(widgetEventActionSuccess);
  sections = sections.addWidget(errorWidget);

  card = card.addSection(sections);
  // Build and return the Card
  return card.build();
}

Tệp kê khai JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "CEL validation example",
      "logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "actionElement",
          "state": "ACTIVE",
          "name": "CEL Demo",
          "description": "Demonstrates CEL Validation",
          "workflowAction": {
            "inputs": [
              {
                "id": "value1",
                "description": "The first number",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "INTEGER"
                }
              },
              {
                "id": "value2",
                "description": "The second number",
                "cardinality": "SINGLE",
                "dataType": {
                  "basicType": "INTEGER"
                }
              }
            ],
            "onConfigFunction": "onConfig",
            "onExecuteFunction": "onExecute"
          }
        }
      ]
    }
  }
}

Các tiện ích và thao tác xác thực CEL được hỗ trợ

Tiện ích thẻ hỗ trợ xác thực CEL

Các tiện ích sau đây hỗ trợ xác thực CEL:

  • TextInput
  • SelectionInput
  • DateTimePicker

Các thao tác xác thực CEL được hỗ trợ

  • Các phép toán số học
    • +: Thêm hai số int64, uint64 hoặc double.
    • -: Trừ hai số int64, uint64 hoặc double.
    • *: Nhân hai số int64, uint64 hoặc double.
    • /: Chia hai số int64, uint64 hoặc double (phép chia số nguyên).
    • %: Tính toán số dư của hai số int64 hoặc uint64.
    • -: Phủ định một số int64 hoặc uint64.
  • Các thao tác logic:
    • &&: Thực hiện một phép toán logic AND trên hai giá trị boolean.
    • ||: Thực hiện một phép toán logic OR trên hai giá trị boolean.
    • !: Thực hiện một thao tác logic NOT trên một giá trị boolean.
  • Các phép so sánh:
    • ==: Kiểm tra xem hai giá trị có bằng nhau hay không. Hỗ trợ số và danh sách.
    • !=: Kiểm tra xem hai giá trị có khác nhau hay không. Hỗ trợ số và danh sách.
    • <: Kiểm tra xem số int64, uint64 hoặc double đầu tiên có nhỏ hơn số thứ hai hay không.
    • <=: Kiểm tra xem số int64, uint64 hoặc double đầu tiên có nhỏ hơn hoặc bằng số thứ hai hay không.
    • >: Kiểm tra xem số int64, uint64 hoặc double đầu tiên có lớn hơn số thứ hai hay không.
    • >=: Kiểm tra xem số int64, uint64 hoặc double đầu tiên có lớn hơn hoặc bằng số thứ hai hay không.
  • Liệt kê các thao tác:
    • in: Kiểm tra xem một giá trị có trong danh sách hay không. Hỗ trợ số, chuỗi và danh sách lồng nhau.
    • size: Trả về số lượng mục trong một danh sách. Hỗ trợ các số và danh sách lồng nhau.

Các trường hợp xác thực CEL không được hỗ trợ

  • Kích thước đối số không chính xác cho các thao tác nhị phân: Các thao tác nhị phân (ví dụ: add_int64, bằng) yêu cầu chính xác 2 đối số. Việc cung cấp một số lượng đối số khác sẽ gây ra lỗi.
  • Kích thước đối số không chính xác cho các phép toán một ngôi: Các phép toán một ngôi (ví dụ: negate_int64) yêu cầu chính xác một đối số. Việc cung cấp một số lượng đối số khác sẽ gây ra lỗi.
  • Các loại không được hỗ trợ trong các phép toán số học: Các phép toán số học nhị phân và đơn nguyên chỉ chấp nhận đối số số. Việc cung cấp các loại khác (ví dụ: boolean) sẽ gây ra lỗi.

Xác thực phía máy chủ

Với quy trình xác thực phía máy chủ, bạn có thể chạy logic phía máy chủ bằng cách chỉ định onSaveFunction() trong mã của bước. Khi người dùng rời khỏi thẻ cấu hình của bước, onSaveFunction() sẽ chạy và cho phép bạn xác minh thông tin đầu vào của người dùng.

Nếu dữ liệu đầu vào của người dùng hợp lệ, hãy trả về saveWorkflowAction.

Nếu thông tin đầu vào của người dùng không hợp lệ, hãy trả về một thẻ cấu hình hiển thị thông báo lỗi cho người dùng để giải thích cách giải quyết lỗi.

Vì quá trình xác thực phía máy chủ là không đồng bộ, nên người dùng có thể không biết về lỗi nhập cho đến khi họ xuất bản quy trình.

id của mỗi dữ liệu đầu vào đã xác thực trong tệp kê khai phải khớp với name của một tiện ích thẻ trong mã.

Ví dụ sau đây xác thực rằng dữ liệu đầu vào văn bản của người dùng có chứa dấu "@":

Tệp kê khai

Đoạn trích tệp kê khai chỉ định một onSaveFunction() có tên là "onSave":

JSON

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "addOns": {
    "common": {
      "name": "Server-side validation example",
      "logoUrl": "https://www.gstatic.com/images/branding/productlogos/calculator_search/v1/web-24dp/logo_calculator_search_color_1x_web_24dp.png",
      "useLocaleFromApp": true
    },
    "flows": {
      "workflowElements": [
        {
          "id": "actionElement",
          "state": "ACTIVE",
          "name": "Calculate",
          "description": "Asks the user for an email address",
          "workflowAction": {
            "inputs": [
              {
                "id": "email",
                "description": "email address",
                "cardinality": "SINGLE",
                "required": true,
                "dataType": {
                  "basicType": "STRING"
                }
              }
            ],
            "onConfigFunction": "onConfigCalculate",
            "onExecuteFunction": "onExecuteCalculate",
            "onSaveFunction": "onSave"
          }
        }
      ]
    }
  }
}

Mã ứng dụng

Mã của bước này bao gồm một hàm có tên là onSave(). Thao tác này xác thực rằng chuỗi do người dùng nhập có chứa @. Nếu có, thao tác này sẽ lưu bước trong quy trình. Nếu không, hệ thống sẽ trả về một thẻ cấu hình kèm theo thông báo lỗi giải thích cách khắc phục lỗi.

Apps Script

/**
 * Validates user input asynchronously when the user
 * navigates away from a step's configuration card.
*/
function onSave(event) {

  // "email" matches the input ID specified in the manifest file.
  var email = event.workflow.actionInvocation.inputs["email"];

  // Validate that the email address contains an "@" sign:
  if(email.includes("@")) {

  // If successfully validated, save and proceed.
    return {
      "hostAppAction" : {
        "workflowAction" : {
          "saveWorkflowAction" : {}
        }
      }
    };

  // If the input is invalid, return a card with an error message
  } else {

var card = {
    "sections": [
      {
        "header": "Collect Email",
        "widgets": [
          {
            "textInput": {
              "name": "email",
              "label": "email address",
              "hostAppDataSource" : {
                "workflowDataSource" : {
                  "includeVariables" : true
                }
              }
            }
          },
          {
            "textParagraph": {
              "text": "<b>Error:</b> Email addresses must include the '@' sign.",
              "maxLines": 1
            }
          }
        ]
      }
    ]
  };
  return pushCard(card);
  }
}