FaunaDB 自定义角色以限制对自己数据的访问

FaunaDB custom-role to limit access to own data only

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

我的计划是让网络应用程序单独进行身份验证,然后在 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")
>                                 

P.S。在使用这种方法之前,我只使用 Select(['data', 'ownerId'], Ref) 来匹配 ID 号,但它没有用,即使我尝试同时转换 ToString 或 ToNumber

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

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

但是,我的问题是会员资格,它没有按预期工作

如果您发现自己拥有 non-working 权限

,请执行以下解决步骤

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

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

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

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

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

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

希望这对 运行 解决此问题

的未来开发人员有所帮助