Metabase 悬案

公共链接、公共嵌入和签名嵌入有什么区别?

假设您正在 Metabase 中进行一项有趣的分析,您需要分享您的工作——首先是为了获取反馈,随后作为最终产品。

公共链接和嵌入,以及静态嵌入都是免费的开源方式,可让您与没有 Metabase 帐户或无权访问原始数据的人员分享 Metabase 工件(例如图表和仪表板,但不要局限自己)。

在选择这些数据共享选项时,您需要考虑

  • 您需要多快分享结果
  • 您希望添加多少上下文信息
  • 数据安全级别

您能帮我们找到隐藏信息吗?

在本教程中,我们将从 Metabase 数据分析师的角度探讨一系列数据共享用例。我们的工作是调查一位队友留下的悬案,这位队友在即将解决 Metabase 最老的 Bug 时神秘消失了。

我们收到匿名举报,称我们队友的 Git 提交消息中可能隐藏着一条信息,所以我们想分析这些数据,查找任何异常或可疑之处。当然,我们也希望与社区分享这项调查(毕竟我们是开源的)。

如果您想跳到有趣的部分

仅供内部使用

在我们公开分享正在进行的调查结果之前,我们希望获得团队的一些反馈,并确保我们没有泄露任何个人身份信息 (PII)。初始分析(图 1)位于我们的内部 Metabase 实例中——此版本将仅与我们的团队共享。

A screenshot of the dashboard that we want to share publicly after review.

共享 Metabase 仪表板的 URL

为我们的仪表板创建一个公共链接

您可以收藏到实时调查仪表板的公共链接。我们决定以聚合形式显示提交数据,以使分析更易于阅读。我们还设置了自定义目标,以便人们可以查看仪表板上显示的每个统计数据关联的完整提交消息。随着调查的继续,我们可以发布更改以在公共链接上显示最新分析。

线索 1

在我们的探索性数据分析中,我们查看了 Git 提交消息长度的分布。其中一个异常值(长度最大的消息)包含以下消息

update the database sync event publication so that we can actually
track start & END as separate events but part of the same activity.
to do so we add a :tracking-hash to the events when they are published
which is meant to remain consistent throughout the sync, then we
implement our activity tracking code so that we can lookup an existing
activity item and update it based on the custom hash.

我们不确定为什么这里的 END 是大写。这可能没有任何意义,但我们会继续寻找……

下一步:线索 2

将 Metabase 仪表板添加到网站

接下来,我们希望在我们的实时调查仪表板旁边显示一个用于评论的网页表单,以便我们的社区可以前往一个地方为调查做出贡献。为此,我们将建立一个新网站,并将我们的仪表板和网页表单作为嵌入式 iframe 添加。

设置网站最简单的方法是使用免费的网站构建器。在这里,我们使用的是 Google 协作平台。如果您不使用 Google Workspace,可以尝试 Squarespace 或 Webflow 等工具。

Getting a website ready for our embeds.

然后,我们将回到 Metabase 仪表板上的共享选项,并复制公共嵌入下的代码。我们将向 Google 协作平台添加一个嵌入元素,并将代码片段粘贴到那里

Adding the Metabase iframe snippet to an embed element on our Google Site.

然后,我们将创建一个公共 Google 表单并将其保存到 Google 云端硬盘中。要将表单添加到我们的 Google 协作平台,我们可以向下滚动插入菜单(如上图 2 所示)并选择表单

现在,我们有了一个实时调查网站,其中显示了我们的 Metabase 仪表板以及一个评论表单。我们的社区将能够

  • 通过我们 Metabase 仪表板的公共嵌入访问最新数据和线索。
  • 使用嵌入式 Google 表单为搜索做出贡献。

线索 2

既然我们查看了最大异常值,那么查看消息长度最小的提交也很有意义。最短的消息只有三个字符长,而且它又被大写了

LAG

下一步:线索 3

限制对嵌入式 Metabase 仪表板的访问

今天早上,有人用数千个针对不存在的查询参数 filter=some_spooky_nonsense 的请求攻击了我们的 Metabase 公共嵌入。为了保护线索不落入坏人之手,我们希望确保只有经过验证的用户才能访问包含线索的行。

我们可以通过将公共嵌入更改为静态嵌入来添加这额外的安全层。我们希望仪表板的静态嵌入显示

  • 未登录用户的无数据。
  • 已登录用户的受限数据(除了线索以外的所有数据)。
  • 使用秘密密码登录用户的秘密数据(线索)。

静态嵌入不适用于 Google 协作平台等网站生成器,因为我们需要运行自己的 Web 服务器才能生成保护我们数据的签名令牌。如果您想继续学习静态嵌入教程的其余部分,您需要

设置登录页面

首先,我们需要一种方法来验证尝试访问我们实时调查网站的人员身份。通常,这是通过由身份验证服务(如 Google 登录)提供支持的登录页面完成的,以便

  • 成功登录后,我们的 Web 服务器将向 Metabase 仪表板上的筛选器发送一个查询参数,例如 user=verified,从而揭示线索。
  • 登录失败时,Metabase 仪表板筛选器将不会从 Web 服务器接收到正确的参数,从而隐藏线索,并显示其余数据。

为了演示基于登录的数据显示和隐藏,我们将从 login.pug 中定义的简单身份验证流程开始(这绝对证明您既真实又无可疑)。

form(method="POST" action="/login")
    input(type="text" name="username" value="metabot")
    input(type="password" name="password" value="unverified")
    input(type="hidden" name="redirect" value=redirectUrl)
    p Can you be trusted?
    button(type="submit" class="primary") Yes

根据用户登录信息重定向到不同的 URL

为了跟踪用户的登录信息,我们将修改 index.js 中的服务器代码,添加一个名为 messageType 的变量

function checkAuth(req, res, next) {
  const messageType = req.session.messageType;
  if (messageType) {
    return next();
  }
  req.session.redirectTo = req.path;
  return res.redirect("/login");
}

然后,我们将设置一些逻辑来处理不同类型的登录。messageType 中存储的值将用于筛选数据,该数据将显示在静态嵌入 URL

if (username === "metabot" && password === "regularPassword") {
  // require a login to view the commit messages
  req.session.messageType = "not secret";
  res.redirect(req.session.redirectTo);
} else if (username === "metabot" && password === "secretPassword") {
  // require a login with the secret password to view the clues
  req.session.messageType = "secret";
  res.redirect(req.session.redirectTo);
} else {
  // allow people without logins to submit comments
  res.redirect("/");
}

生成静态嵌入 URL

现在,我们可以更新 index.js 中的服务器代码,为每个登录用户动态生成静态嵌入的 URL。这些 URL 是安全的,因为它们使用我们的嵌入密钥签名。服务器还会将 messageType 的值(“secret”或“not secret”)传递给 Metabase 仪表板上的筛选器,以便隐藏或显示数据中的线索。我们将在下一步设置此筛选器。

app.get("/signed_dashboard/:id", checkAuth, (req, res) => {
  const messageType = req.session.messageType;
  const unsignedToken = {
    resource: { dashboard: DASHBOARD_ID },
    params: { keep_secret: messageType },
    exp: Math.round(Date.now() / 1000) + 10 * 60, // 10 minute expiration
  };
  // sign the JWT token with our secret key
  const signedToken = jwt.sign(unsignedToken, MB_EMBEDDING_SECRET_KEY);
  // construct the URL of the iframe to be displayed
  const iframeUrl = `${MB_SITE_URL}/embed/dashboard/${signedToken}`;
  res.render("dashboard", { messageType: req.params.id, iframeUrl: iframeUrl });
});

使用锁定参数限制数据

为了指定根据用户登录状态应显示的数据行,我们将回到 Git 提交数据,添加一个名为消息类型自定义列,该列使用CASE 表达式将包含线索的行设置为“secret”,其余数据设置为“not secret”。

Setting up the raw data so that we can show or hide the clues based on a filter value.

然后,为了确保我们能够限制实时调查仪表板上的所有数据,我们需要为仪表板上的每个问题创建一个消息类型列。

数据设置完成后,我们将为实时调查仪表板添加一个筛选器,并将该筛选器链接到我们每个问题中的所有消息类型列。我们还会将“not secret”置于默认值下,以便默认只显示非线索行。

Adding a filter to hide the rows with the clues.

现在,我们可以在仪表板上启用静态嵌入并设置锁定参数。锁定参数将在登录流程中从 Web 服务器接收“secret”或“not secret”的 messageType 值(取决于所使用的密码)。此锁定参数将把“secret”或“not secret”的值应用于我们原始仪表板上的筛选器,然后结果才显示在静态嵌入 URL

Adding a locked parameter to the static embed.

查看具有不同访问级别的静态嵌入

一旦我们将 layout.pug 更新为静态嵌入的前端代码,我们就可以运行服务器代码,构建一个本地站点,其中包含指向我们的实时调查仪表板的链接以及一个用于评论的嵌入式 Google 表单

Locally built website with a link to our static embed.

点击链接将提示人们登录以查看数据。我们目前找到的线索默认是隐藏的

People must log in to view the live investigation dashboard.

要访问包含线索的行,人们必须提供秘密密码

People must provide a secret password to view the clues in the data.

如果您没有有效的登录凭据,可以通过表单请求访问(或者只是作为一名热心评论者参与这个悬案)

People are redirected to the homepage if they can

线索 3

分布中隐藏的另一个线索——这次是在消息长度的中位数处

fixes mobile password reSET and confirmation #869

游戏开始

我们需要更多数据朋友的帮助。到目前为止,我们已经找到了线索 END、LAG 和 SET。我们的队友想告诉我们什么?获取数据,试着玩玩看您能否解开这个谜团。

点击此处获取提示。尝试使用提交消息长度计算其他摘要统计信息。

该解决方案并非由 Metabase 功能付费墙限制(那会让这个谜团有点太诡异),但如果您想使用 Metabase 探索数据集,您可以

进一步阅读

下一步:多租户自助分析

嵌入整个 Metabase 应用程序(包括查询构建器),为用户提供安全、个性化的数据访问权限。

下一篇文章
© . All rights reserved.