Skip to content
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

[Question] Using Casbin for data filtering #276

Open
adeelfareed opened this issue Nov 3, 2021 · 5 comments
Open

[Question] Using Casbin for data filtering #276

adeelfareed opened this issue Nov 3, 2021 · 5 comments
Assignees
Labels
question Further information is requested

Comments

@adeelfareed
Copy link

adeelfareed commented Nov 3, 2021

Hi, I don't understand how should I use get_implicit_permissions_for_user to access only the resources that user has created or is assigned to?

Following are some example policy rules.
In this example, users with a reader role will be able to see posts, however, the admins will be able to edit/delete posts too. I need an additional filter that users can only edit their own posts not others'.

p, post_read, post_group, (GET)
p, post_manage, post_group, (UPDATE)|(DELETE)|(POST)

g2, /api/post/:id, post_group

g, role:admin, role:post_manage
g, role:admin, role:post_read

g, role:reader, role:post_read

g, alice, role:admin
g, bob, role:reader

Conf:

[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[role_definition]
g = _, _
g2 = _, _
g3 = _, _
g4 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = g(r.sub, p.sub) && g2(r.obj, p.obj) && regexMatch(r.act, p.act) || r.sub == "root"
@casbin-bot
Copy link
Member

@smrpn @hackerchai @PsiACE @GopherJ

@casbin-bot casbin-bot added the question Further information is requested label Nov 3, 2021
@hsluoyz
Copy link
Member

hsluoyz commented Nov 4, 2021

@adeelfareed can you give a detailed example?

@adeelfareed
Copy link
Author

@hsluoyz Please take a look, I have added an example.

@valkum
Copy link
Contributor

valkum commented Feb 2, 2022

We have a

pub trait RbacApiEx: RbacApi {
    /// Gets implicit users for a role
    fn get_implicit_users_for_role(&mut self, role: &str, domain: Option<&str>) -> Vec<String> {
        let mut res: HashSet<String> = HashSet::new();
        let mut q: Vec<String> = vec![role.to_owned()];
        while !q.is_empty() {
            let name = q.swap_remove(0);
            let users = self.get_role_manager().write().get_users(&name, domain);
            for r in users.into_iter() {
                if res.insert(r.to_owned()) {
                    q.push(r);
                }
            }
        }
        res.into_iter().collect()
    }

    /// Gets implicit resources for a user
    fn get_implicit_resources_for_user(
        &mut self,
        user: &str,
        domain: Option<&str>,
    ) -> Vec<Vec<String>> {
        let permissions = self.get_implicit_permissions_for_user(user, domain);
        let mut result = Vec::new();
        for permission in permissions {
            // This resource is directly accessible by the user.
            if permission[0] == user {
                result.push(permission.clone());
                continue;
            }

            // Now handle the implicit permissions
            // First collect all rules that are implicitly accessible (v0) by the role (v1)
            // The result is a Vec of Vecs which contain all v0 entries that are accessible by v1.
            // The target v1 can be in v1 to v5 of the direct permissions
            let t = permission
                .iter()
                .skip(1)
                .map(|token| {
                    let mut tokens = self.get_implicit_users_for_role(token, domain);
                    tokens.push(token.clone());
                    tokens
                })
                .collect::<Vec<_>>();

            // Extend each rule in result_local.
            let mut result_local = vec![vec![user.to_string()]];
            let tokens_length = permission.len();
            for i in 0..tokens_length - 1 {
                let mut n = Vec::new();
                for tokens in &t[i] {
                    for policy in &result_local {
                        let mut t = policy.clone();
                        t.push(tokens.clone());
                        n.push(t);
                    }
                }
                result_local = n;
            }
            result.extend(result_local.into_iter());
        }
        result
    }
}
impl<T: RbacApi> RbacApiEx for T {}

@hsluoyz
Copy link
Member

hsluoyz commented Feb 3, 2022

@PsiACE @hackerchai

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
Development

No branches or pull requests

4 participants