【问题标题】:FaunaDB custom-role to limit access to own data onlyFaunaDB 自定义角色,仅限制对自己数据的访问
【发布时间】:2023-03-07 05:53:01
【问题描述】:

我正在构建一个示例应用程序来评估 FaunaDB 和 Nextjs

我的计划是让 Web 应用程序单独进行身份验证,然后在 FaunaDB 上创建用户 然后在 FaunaDB 上创建一个令牌,并允许用户通过他自己的秘密令牌进行连接

我相信我在正确的轨道上让这个模型工作,但我在 FaunaDB 中的自定义角色遇到了问题

数据模型是User -> Board -> Tasks,本题我会使用boards的访问权限

这是自定义角色的代码

{
  ref: Role("Free_Tier_Role"),
  ts: 1601934616790000,
  name: "Free_Tier_Role",
  membership: [
    {
      resource: Collection("user"),
      predicate: Query(
        Lambda("ref", Select(["data", "isEnabled"], Get(Var("ref"))))
      )
    }
  ],
  privileges: [
    {
      resource: Collection("user"),
      actions: {
        read: true,
        write: false,
        create: false,
        delete: false,
        history_read: false,
        history_write: false,
        unrestricted_read: false
      }
    },
    {
      resource: Collection("board"),
      actions: {
        read: Query(
          Lambda(
            "ref",
            Equals(Identity(), Select(["data", "owner"], Get(Var("ref"))))
          )
        ),
        write: Query(
          Lambda(
            ["oldData", "newData"],
            And(
              Equals(
                Select("id", Identity()),
                Select(["data", "owner"], Var("oldData"))
              ),
              Equals(
                Select(["data", "owner"], Var("oldData")),
                Select(["data", "owner"], Var("newData"))
              )
            )
          )
        ),
        create: Query(
          Lambda(
            "newData",
            And(
              Equals(Identity(), Select(["data", "owner"], Var("newData"))),
              LT(Count(Match(Index("board_by_owner"), Identity())), 3)
            )
          )
        ),
        delete: Query(
          Lambda(
            "ref",
            Equals(Identity(), Select(["data", "owner"], Get(Var("ref"))))
          )
        ),
        history_read: false,
        history_write: false,
        unrestricted_read: false
      }
    },
    {
      resource: Collection("task"),
      actions: {
        read: Query(
          Lambda(
            "ref",
            Equals(Identity(), Select(["data", "owner"], Get(Var("ref"))))
          )
        ),
        write: Query(
          Lambda(
            ["oldData", "newData"],
            And(
              Equals(
                Select("id", Identity()),
                Select(["data", "owner"], Var("oldData"))
              ),
              Equals(
                Select(["data", "owner"], Var("oldData")),
                Select(["data", "owner"], Var("newData"))
              )
            )
          )
        ),
        create: Query(
          Lambda(
            "newData",
            And(
              Equals(Identity(), Select(["data", "owner"], Var("newData"))),
              LT(Count(Match(Index("task_by_owner"), Identity())), 10)
            )
          )
        ),
        delete: Query(
          Lambda(
            "ref",
            Equals(Identity(), Select(["data", "owner"], Get(Var("ref"))))
          )
        ),
        history_read: false,
        history_write: false,
        unrestricted_read: false
      }
    },
    {
      resource: Index("task_by_owner"),
      actions: {
        unrestricted_read: false,
        read: false
      }
    },
    {
      resource: Index("board_by_owner"),
      actions: {
        unrestricted_read: false,
        read: false
      }
    }
  ]
}

我面临的问题是 当我通过用户令牌登录并且该用户是董事会的所有者时,我得到一个空列表

> Map(Paginate(Documents(Collection('board'))),Lambda('x', Get(Var('x'))))
{ data: [] }

为了测试它们是否具有相同的值,我正在仪表板上的 shell 上运行此命令

Select(["data", "owner"], Get(Ref(Collection("board"), "278575744915866117")))

Ref(Collection("user"), "278571699875611143")

>> Time elapsed: 28ms

然后在我的令牌认证实例上运行 Identity()

> Identity()
Ref(Collection("user"), "278571699875611143")
>                                 

附:在这种方法之前,我只使用 Select(['data', 'ownerId'], Ref) 匹配 ID 号,但它不起作用,即使我尝试同时转换 ToString 或 ToNumber

【问题讨论】:

  • 您是否尝试过创建一个基于所有者过滤的索引,而不是使用Documents()
  • @Pier 这可行,但会很危险。基本上,如果您忘记按所有者过滤,那么该查询将显示每个人的文档。在权限中过滤将允许您请求所有文档,而 FaunaDB 仅返回当前用户的文档
  • 是的,显然你需要一个 Lambda() 在你的角色权限中检查所有者引用的存在。

标签: faunadb


【解决方案1】:

哇,我花了大约 2 天的时间来诊断发生了什么

基本上,我上面编写的代码只允许板或任务的所有者查看他/她自己的项目并更新它们

但是,对我来说,问题在于会员资格,它没有按预期工作

如果您发现自己拥有非工作权限,则需要遵循以下解决方案步骤

确保该角色适用于您的用户 这是我的做法

  1. 使用默认代码Query(Lambda("x", Add(Var("x"), Var("x")))) 创建示例函数“test_newFunc”
  2. 创建一个新角色,并包含所有“用户”,并允许调用“test_newFunc”
  3. 创建令牌,并使用令牌的秘密启动 shell
  4. 运行Call("test_newFunc", 2)
  5. 对我来说,我添加了成员​​谓词是

Lambda("docRef", Equals(true, Select(["data", "isEnabled"], Get(Var("docRef")))))

也就是说,用户必须有一个数据字段“isEnabled”,并且它的值必须为真

然后通过为模拟用户切换此字段的值进行测试,直到您确认正在应用此角色

这一步搞清楚后,你就可以测试每个权限的谓词了

希望这对未来遇到此问题的开发人员有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-01
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-15
    • 2013-02-13
    相关资源
    最近更新 更多