Closed GopherJ closed 4 years ago
OK. I read your issue and I see what you're trying to get at. There is a very simple solution.
Rhai supports object maps, in the syntax: #{a: 1, b: "hello", c: [1, 2, true]}
An object map, converted into Rust, is HashMap<String, Dynamic>
. See https://github.com/jonathandturner/rhai/blob/master/README.md#object-maps
All you need to do is to create this type and then set it as the value of a Scope
variable or return it from a registered function (the function simply returns HashMap<String, Dynamic>
).
For example:
let mut object: HashMap<String, Dynamic> = HashMap::new();
object.insert("foo".to_string(), true.into_dynamic());
object.insert("bar".to_string(), "hello".to_string().into_dynamic());
object.insert("baz".to_string(), 123.into_dynamic());
let mut scope = Scope::new();
scope.push_constant("my_object", object);
let result = engine.eval_expression_with_scope::<bool>(&mut scope, "my_object.baz < 42")?;
If you don't want to even provide the values in Rust, your users can define their own objects in Rhai script, then you read it back as a HashMap
with all values already set. You can make sure your user only provides a valid object map by parsing it as an expression eval_expression::<Map>
which will error out if the result is not a valid object map (i.e. the HashMap
you need).
Since Rhai object maps has a syntax that is exactly the same as JSON (except for the leading #
), your user can use serde
etc. to serialize a data structure into JSON, then turn it into a Rhai object map script by prepending it with #
.
This HashMap
can then be passed to Enforce
and checked by a separate Rhai script as an object map. This way it round-trips.
Thinking of this some more... First of all, it looks like your user can define their own access control objects through some form of meta description, which is then turned into some objects in your code.
You can easily build up a HashMap
with fields from the object metadata, especially when if it is only one level deep (i.e. consisting of only attributes of primitive types).
On the other hand, you may think of transparently round-tripping the user's AC object with all the attributes, if you don't really act on those attributes in your code. This way your code needs not even care about the structure of these user objects. The way to do it is to have the user submit a valid piece of JSON as their object representation, which the user can get easily by serializing their own data type, or from a web service backend on the user's side.
Either way, access the fields of this object as an object map in Rhai.
Let's close this one, great thanks @schungx on your quick help.
See also: https://github.com/casbin/casbin-rs/issues/78.
While implementing ABAC for casbin-rs, we don't know in advance how many types will we get and what are they and what are the getter used by them.
It's the users of casbin-rs who define their types. How can we solve this?