-
Notifications
You must be signed in to change notification settings - Fork 179
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
Get all roles from resource #1427
Comments
Hey @jneo8! That's a great idea, we can definitely consider adding that. In the meantime, it's actually not too bad to implement that yourself. Here's how oso/languages/python/oso/oso/oso.py Line 152 in 0c5d33f
So it would be something like: from oso import Variable
role_results = oso.query_rule("has_role", actor, Variable("role"), resource)
roles = set()
for result in role_results:
role = result.get("bindings").get("role")
roles.add(role) This wouldn't handle the "wildcard" case (the user is allowed to have any role). But that's not commonly needed. |
@samscott89 Thanks for your reply. But I get this error msg when I try to implement
Because I'm not using either django-oso or sqlalchemy-oso, I add class Roles(enum.Enum):
manager = "manager"
member = "member"
...
def get_actor_roles(oso: Oso, actor, resource) -> Set[Union[Roles]]:
roles = set()
for result in oso.query_rule(
"has_role",
actor,
Variable("role"),
resource,
accept_expression=True,
):
role = result.get("bindings").get("role")
if isinstance(role, str): # Make sure is return type is string
if role in Roles._value2member_map_:
roles.add(Roles(role))
return roles |
Hey @jneo8. Glad you have a workaround, but to make sure it's correct would you mind sharing the policy that caused this? |
@samscott89 thanks for you reply.
OrgIDSeq = Sequence("org_id_seq")
class Org(Base):
"""Org."""
__tablename__ = "org"
id: Any = Column(Integer, OrgIDSeq, primary_key=True)
name = Column(String, nullable=False)
path = Column(LtreeType, nullable=False)
is_root = Column(Boolean, default=False)
types = Column(
ARRAY(
ChoiceType(OrgType, impl=String()),
as_tuple=True,
),
)
# relationship
parent = relationship(
"Org",
primaryjoin=remote(path) == foreign(func.subpath(path, 0, -1)),
backref="children",
viewonly=True,
lazy="immediate",
)
org_roles = relationship(
"OrgRole",
back_populates="org",
)
__table_args__ = (Index("ix_org_path", path, postgresql_using="gist"),)
UserOrgRole = Table(
"user_org_role",
Base.metadata,
Column("user_id", Integer, ForeignKey("user.id"), primary_key=True),
Column(
"org_role_id", Integer, ForeignKey("org_role.id"), primary_key=True
),
)
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(EmailType)
password = Column(String(length=128), nullable=False)
is_active = Column(Boolean, default=False, nullable=False)
is_verified = Column(Boolean, default=False, nullable=False)
is_superuser = Column(Boolean, default=False, nullable=False)
org_roles = relationship(
"OrgRole",
secondary=UserOrgRole,
back_populates="users",
lazy="immediate",
)
class OrgRole(Base):
__tablename__ = "org_role"
id = Column(Integer, primary_key=True)
org_id = Column(Integer, ForeignKey("org.id"))
org = relationship("Org", back_populates="org_roles", lazy="immediate")
role = Column(ChoiceType(Roles, impl=String()))
users = relationship(
"User",
secondary=UserOrgRole,
back_populates="org_roles",
) |
Thanks for sharing @jneo8! That generally looks good to me. One thing is that you might want to change the
|
The example provided worked for me with my policy. @samscott89 let me know if you'd like me to make a PR for the this functionality. |
Just following up on this to see if this would be of interest as a pull request as I hadn’t heard back in the past couple of months. |
Never heard back, so just submitted #1675 in hopes of getting some feedback for or against |
Hey @kkirsche, I'm sorry we didn't get back to you sooner on this one. I'll talk to @samscott89 about it this week. Personally, I'm leaning (slightly) against shipping it mostly b/c I think the code you wrote in #1675 shows that it isn't too burdensome for users to implement this functionality even without a dedicated API, and I'm a bit wary of extending language library APIs in a piecemeal fashion (e.g., we ship this and then someone wonders why it's only in Python). Also I think to get #1675 shipshape I'd probably want to add tests and maybe see if there's a logical place to mention the new API in the docs (maybe where we talk about |
I think the problem I have with that reasoning is I had to dig through your GitHub issues to figure out how to do it. For a less experienced or interested user, I expect they'd believe this simply isn't possible to do. I only figured it out due to dumb luck not because it was easy |
I'd rather ask for those items, file backlog issues to add to other languages, etc than expect users to understand how to use a low level API like query rule, which personally I don't understand well at all |
Totally fair points. I talked to @samscott89 about it, and unfortunately right now we don't have the bandwidth to add tests & docs and get this ready to ship. Would you be up for doing that @kkirsche? |
Ah I missed this. Yeah, this is actually going to be in #1572 in example code I'm sharing there |
Is there any function like
authorized_actions
but list all roles instead of actions?authorized_roles(actor, resource)
The text was updated successfully, but these errors were encountered: