-
-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement ABAC model #78
Comments
@xcaptain Could you give us an example of usage? The first and the second. Also are you interested in implementation of this? |
@GopherJ A simple example, Trump can access this box of masks only if it has a label says "for USA". or Trump can access this box of masks only if it has a label says "for USA" and it has been paid. 😄 We can simply say RBAC: a subject can act on an object if this subject has some attributes(role) I would like to try this issue but I still didn't find any good ideas to solve it. |
Thanks I mean some example code. I have no idea on how does it should look like. Tuple is not a good solution. |
Have no clue yet, need to investigate more. |
I have some ideas for this: rhaiscript/rhai#131 |
Thanks @schungx I have read your ideas and it seems good. I'll give a try recently. |
I think in the first argument of let a = #{ // object map literal with 3 properties
a: 1,
bar: "hello",
"baz!$@": 123.456, // like JS, you can use any string as property names...
"": false, // even the empty string!
a: 42 // <- syntax error: duplicated property name
}; |
In PR# rhaiscript/rhai#128 I've added a nice helper method called |
@schungx we need to bring use rhai::{Engine, EvalAltResult, Scope};
use serde_json::json;
#[cfg(not(feature = "no_object"))]
fn main() -> Result<(), EvalAltResult> {
let mut engine = Engine::new();
let mut scope = Scope::new();
let my_json: String = serde_json::to_string(&json!({
"age": 19
}))
.unwrap();
// Todo: we should check if it's object
engine.eval_with_scope::<()>(&mut scope, &format!("let my_json = #{}", my_json))?;
let result = engine.eval_with_scope::<bool>(&mut scope, "my_json.age > 18")?;
println!("result: {}", result);
Ok(())
} is there a better way to bring an user-defined |
Concat the JSON into a script is the easiest way, but the problem being you have to create a different script text during each call. I'd suggest making it constant: let script = format!("const my_json = #{}; my_json.age > 18", my_json);
let result = engine.eval::<bool>(&script)?; If you want to keep the object in let mut scope = Scope::new();
let map = engine.parse_json(&my_json, false); // true if you need null's
scope.push_constant("my_json", map);
let result = engine.eval_with_scope::<bool>(&mut scope, "my_json.age > 18")?; If you want to use the existing crate, you can simulate my_json.insert('#', 0);
let map = eval_expression::<Map>(&my_json)?; |
@xcaptain we can bring Or maybe
|
@schungx Is it possible to add a feature in rhai which is called: And in this feature, it allows users to bring Serializable value into scope. Sure we should also consider Because now it seems we need to serialize the given data (I don't want users to write json manually), and then convert it to |
@xcaptain on our side I think we should define a new trait Then we do the implementation for fn enforce<T: ToRhai>(rvals: &[T]) trait ToRhai {
fn to_rhai(self) -> String;
} impl ToRhai for String impl<T> ToRhai for T where T: Serialize maybe we'll get conflicts because
will help |
I tried the following code but it seems doesn't compile: #![feature(specialization)]
use serde::Serialize;
trait ToRhai {
fn to_rhai(&self) -> String;
}
impl ToRhai for String {
fn to_rhai(&self) -> String {
self.to_owned()
}
}
impl<T> ToRhai for T
where
T: serde::ser::Serialize,
{
default fn to_rhai(&self) -> String {
format!("#{}", serde_json::to_string(self).unwrap())
}
}
#[derive(Serialize)]
struct MyJson {
age: usize,
}
fn enforce<S: ToRhai>(rvals: &[S]) {
let rvals: Vec<String> = rvals.iter().map(|x| x.to_rhai()).collect();
println!("{:?}", rvals);
}
fn main() {
let j = MyJson { age: 18 };
enforce(&["alice".to_owned(), j, "read".to_owned()]);
} |
it works after switching to dynamic dispatcher: #![feature(specialization)]
use serde::Serialize;
trait ToRhai {
fn to_rhai(&self) -> String;
}
impl ToRhai for String {
fn to_rhai(&self) -> String {
self.to_owned()
}
}
impl<T> ToRhai for T
where
T: serde::ser::Serialize,
{
default fn to_rhai(&self) -> String {
format!("#{}", serde_json::to_string(self).unwrap())
}
}
#[derive(Serialize)]
struct MyJson {
age: usize,
}
fn enforce(rvals: &[Box<dyn ToRhai>]) {
let rvals: Vec<String> = rvals.iter().map(|x| x.to_rhai()).collect();
println!("{:?}", rvals);
}
fn main() {
let j = MyJson { age: 18 };
enforce(&[
Box::new("alice".to_owned()),
Box::new(j),
Box::new("read".to_owned()),
]);
} |
If you're not going to keep the object around (possibly to evaluate many expressions with that single object), it might be faster simply to splice the JSON into the beginning of the expression text using the |
@GopherJ my suggestion: keep Therefore, it would be much better to have Finally, I'm quite sure it is OK if |
@schungx Yes we decided to go this way to support just Strings, otherwise we need to bring many overhead like nightly, serde, Box.... |
closed as #102 |
Current we are matching directly over object, means subject can act on object, with ABAC we can do matching like: subject can act on object is this object has specific attributes.
ABAC doc
This problem may be a little hard because we are using
Vec<&str>
as the parameter forenforce
, which requires every element in the vector has the same type that is&str
. I have 2 ideas about this issue.Vec<&str>
to tuple, so we don't need to worry about the type.obj
as a string, parsing this string into a struct inrhai
then do the matching.The text was updated successfully, but these errors were encountered: