【问题标题】:Google Cloud Datastore / Mobile Backend Starter - Permissions failure on update/updateAll callsGoogle Cloud Datastore / Mobile Backend Starter - update/updateAll 调用权限失败
【发布时间】:2014-06-07 13:09:48
【问题描述】:

使用 Mobile Backend Starter (MBS) Android 类(在 Google Dev Console 中创建新项目并在 Google I/O 2013 上演示时作为示例项目分发的那些)我能够将新实体插入云数据存储通过调用 CloudBackendMessaging.insertAll 或 .updateAll。如果不存在实体,后者将创建实体,因此在功能上似乎与插入新记录相同。

插入/创建工作正常。但是,当我尝试更新数据存储中的现有条目时,我收到了权限错误,例如(来自后端日志)

方法:mobilebackend.endpointV1.updateAll

错误代码:401

原因:必填

消息:更新 CloudEntity:XXXXXX 的权限不足:用户:YYYYYY

这会导致 logcat 客户端出现匹配的访问错误。

在所有情况下,我都使用有效的 Google 帐户(我自己的)进行安全访问身份验证。

因此,插入的实体显示为我的用户 ID“拥有”,“更新者”和“创建者”显示我的 Google 帐户的电子邮件地址。

但是,当更新现有记录时,使用完全相同的 CloudBackendMessenger 对象,因此使用相同的凭据等。后端告诉我由于权限问题我无法更新。但如果我只是用相同的凭据创建实体,这肯定不正确吗?查看文档,似乎我应该能够在所有情况下编辑由同一用户 ID 拥有的实体(无论 KindName 以及它是否预先添加 [public]、[private] 或什么都没有)。

任何通过 Mobile Backend Starter for Datascore 收到关于 UPDATES 权限错误的人都可以解释一下吗?今天大部分时间我都在为此苦苦思索。

【问题讨论】:

  • 似乎解决方法是查询,即获取您要更新的 CloudEntity,例如通过 list() 调用,然后通过 update() 调用对其进行更新。但是,如果您可以直接在实体上执行更新(通过它的 UID 即 setId() 指定)而不必先获取它,那将会更好/更有效。
  • 您是否也尝试过使用“事务”来更新单个实体?developers.google.com/appengine/docs/java/datastore/…
  • @Franz Noel。这很有趣 - 您能否详细说明如何通过 CloudEntity 在移动/客户端上将事务与 MBS 一起使用,或者使用代码 sn-p?

标签: android google-app-engine google-cloud-datastore


【解决方案1】:

如果您不介意所有用户都能够访问您尝试更新的实体,那么到目前为止发布的答案可以解决该问题。但是,谷歌在此处详细介绍了保留访问权限的更好解决方案 - https://cloud.google.com/cloud/samples/mbs/authentication

如果您想将用户的 Google 帐户信息传递到后端 每次调用,使用 CloudBackend#setCredential() 方法(也可用 在子类 CloudBackendAsync 和 CloudBackendMessaging 上)设置 调用任何移动后端之前的 GoogleAccountCredential 对象 方法。

GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this, "<Web Client ID>");
credential.setSelectedAccountName("<Google Account Name>");
cloudBackend.setCredential(credential);

设置凭据使客户端能够在后端运行时进行操作 在“由客户端 ID 保护”模式下,还设置 createdBy/updatedBy/owner CloudEntity 的属性自动。

【讨论】:

【解决方案2】:

与上面的其中一个 cmets 类似,我通过在执行插入/更新/删除功能之前获取原始 CloudEntity 成功地解决了这个问题。

    CloudQuery cq = new CloudQuery("datastoretype");
    cq.setLimit(1);
    cq.setFilter(Filter.eq("_id",id));

    cloudEntity.setId(id);
    mProcessingFragment.getCloudBackend().get(cloudEntity, handler);

此后,做以下事情就变得微不足道了:

    mProcessingFragment.getCloudBackend().update(cloudEntity, handler);

文档肯定应该更清楚地说明这一点,无论是严格要求还是错误。

【讨论】:

  • 我正在尝试遵循您的代码,但我看不到您在更新中如何使用 cloudquery。尝试您的过滤器时,我也收到错误消息。那么你能在这里发布你的完整代码吗?
【解决方案3】:

我在使用 cloudBackendAsync.update(cloudEntity) 时遇到了类似的错误“更新 CloudEntity 的权限不足”。我通过确保 cloudEntity 具有它的 createdAt 字段集来解决它。 createdAt 是自动生成的,我想我不应该碰它。但它对我有用。就我而言,我首先获取云实体列表。这是我创建云实体字段的时候。然后,当我更新时,我从以前获得的实体中设置 createdAt 字段。 编辑:也必须为所有者字段做类似的事情。

【讨论】:

  • 这很有趣 - 并且可能解释了为什么如果我“获取”即列出记录然后用它更新,那么我实际上可以在没有权限问题的情况下执行更新。我想知道是否有一种方法可以将 createdAt 字段设置为正确的值,而无需先实际获取记录(出于性能原因 - 我有很多更新要做)。您知道该字段是如何格式化/如何合成的吗?
  • 您可以从谷歌开发控制台检查 createdAt 格式。转到您的应用控制台 -> 云数据存储 -> 查询 -> 选择种类,您可以看到列出的实体。
  • 好的,我会试一试。非常感谢您的提示,谁知道创建日期会出现权限错误?
  • 我也必须为所有者字段做同样的事情。实体已成功更新,但缺少所有者字段,该字段最初也是自动生成的。
猜你喜欢
  • 2013-06-02
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多