0

我正在尝试在反应应用程序中实现 CASL 授权,我认为我对如何实现它不太了解。

标准的 Can 组件似乎可以与基本的 CRUD 操作一起使用,但我无法获得产生任何效果的条件。我想我错过了一些东西。

我目前的理论是我需要使用 TypeScript 而不是普通的 Javascript 才能使整个工作正常进行。我目前不知道任何 TypeScript,我真的很想推进我的应用程序,而不必学习另一种语言。如果必须的话,我会学习 TypeScript,但我需要知道它是否值得去做。以下是我迄今为止构建的内容的简化版本。

代码沙箱示例

预期行为 我希望应用程序显示此人可以阅读和创建事物记录。他们还应该能够更新或删除特定的 Apple 记录。

预期输出:
我可以查看事物
我可以创建事物
我可以更新这个苹果
我可以删除这个苹果

实际行为 它忽略与条件有关的任何内容,并允许对所有内容进行创建、读取、更新和删除。

实际输出:
我可以查看事物
我可以创建事物
我可以更新任何事物
我可以删除任何事物

主应用

import "./styles.css";
import ThingManager from "../components/ThingManager";
import AbilityContextComponent from "../components/AbilityContextComponent";

export default function App() {
  return (
    <div className="App">
      <AbilityContextComponent>
        <ThingManager />
      </AbilityContextComponent>
    </div>
  );
}

能力上下文组件 用于构建能力上下文并封装能力的生成

import React from "react";
import { AbilityContext } from "../src/Can";
import { defineAbility } from "@casl/ability";

class AbilityContextComponent extends React.Component {
  render() {
    const ability = defineAbility((can) => {
      can("read", "thing");
      can("create", "thing");
      can("update", "thing", { userId: 3 });
      can("delete", "thing", { userId: 3 });
    });

    return (
      <AbilityContext.Provider value={ability}>
        {this.props.children}
      </AbilityContext.Provider>
    );
  }
}

export default AbilityContextComponent;

Can组件在这里生成

import { createContextualCan } from "@casl/react";
import React from "react";

export const AbilityContext = React.createContext();
export const Can = createContextualCan(AbilityContext.Consumer);

最后一个组件可能会使用对“事物”的授权

import React from "react";
import { Can } from "../src/Can";

class ThingManager extends React.Component {
  render() {
    const thing = {
      Name: "Apple",
      Description: "this is an Apple",
      Colour: "Green",
      UserId: 3
    };

    return (
      <div>
        <h3>Manage your things here</h3>
        <Can I="read" a="thing">
          <p>I can look at things</p>
        </Can>
        <Can I="create" a="thing">
          <p>I can create a thing</p>
        </Can>
        <Can I="update" a="thing">
          <p>I can update any thing</p>
        </Can>
        <Can I="delete" a="thing">
          <p>I can delete any thing</p>
        </Can>
        <Can I="update" this={thing}>
          <p>I can delete this {thing.Name}</p>
        </Can>
        <Can I="delete" this={thing}>
          <p>I can delete any {thing.Name}</p>
        </Can>
      </div>
    );
  }
}

export default ThingManager;

4

1 回答 1

0

我一直在寻找有关如何更改“主题”的信息,这是 CASL 对您尝试设置权限的事物的术语。在这种情况下,我称之为“事物”。

事实证明,有很多方法可以检测主题类型。

主题类型检测

通常,它们都涉及告诉 Can 组件传入对象的主题是什么。

基本方法是调用您传递给“this”的对象上的函数主题。

从 "@casl/ability" 导入主题并像subject("thing", apple)一样调用它

CodeSandBox 上的工作版本

import React from "react";
import { Can } from "../src/Can";
import { subject } from "@casl/ability";

class ThingManager extends React.Component {
  render() {
    const apple = {
      Name: "Apple",
      Description: "this is an Apple",
      Colour: "Green",
      UserId: 3
    };
    
    return (
      <div>
        <h3>Manage your things here</h3>
        <Can I="read" a="thing">
          <p>I can look at things</p>
        </Can>
        <Can I="create" a="thing">
          <p>I can create a thing</p>
        </Can>
        <Can I="update" a="thing">
          <p>I can update a thing</p>
        </Can>
        <Can I="delete" a="thing">
          <p>I can delete a thing</p>
        </Can>
        <Can I="update" this={subject("thing", apple)}>
          <p>I can delete this {apple.Name}</p>
        </Can>
        <Can I="delete" this={subject("thing", apple)}>
          <p>I can delete any {apple.Name}</p>
        </Can>
      </div>
    );
  }
}

export default ThingManager;

我也得到了关于 Can 如何工作的理论有点错误。您会在工作示例中注意到“我可以更新事物”和“我可以删除事物”文本仍在显示。这是因为只要用户可以更新/删除至少一件事,一般的“我可以更新一个”和“我可以删除一个”类型的组件都会显示他们的孩子。它并不是说“此用户可以访问所有内容”。

于 2021-10-11T15:20:03.903 回答