Skip to content

Commit 4029583

Browse files
committed
feat: enable combining PermissionsRules
1 parent 6687d2a commit 4029583

File tree

4 files changed

+79
-0
lines changed

4 files changed

+79
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,4 @@ docs/_site/
156156
docs/.jekyll-metadata
157157
docs/Gemfile.lock
158158
samples/credentials
159+
.venv/

tableauserverclient/models/permissions_item.py

+26
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,32 @@ def __init__(self, grantee: ResourceReference, capabilities: Dict[str, str]) ->
5353
def __repr__(self):
5454
return "<PermissionsRule grantee={}, capabilities={}>".format(self.grantee, self.capabilities)
5555

56+
def __and__(self, other: "PermissionsRule") -> "PermissionsRule":
57+
if self.grantee != other.grantee:
58+
raise ValueError("Cannot AND two permissions rules with different grantees")
59+
capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
60+
new_capabilities = {}
61+
for capability in capabilities:
62+
if (self.capabilities.get(capability), other.capabilities.get(capability)) == (Permission.Mode.Allow, Permission.Mode.Allow):
63+
new_capabilities[capability] = Permission.Mode.Allow
64+
elif Permission.Mode.Deny in (self.capabilities.get(capability), other.capabilities.get(capability)):
65+
new_capabilities[capability] = Permission.Mode.Deny
66+
67+
return PermissionsRule(self.grantee, new_capabilities)
68+
69+
def __or__(self, other: "PermissionsRule") -> "PermissionsRule":
70+
if self.grantee != other.grantee:
71+
raise ValueError("Cannot AND two permissions rules with different grantees")
72+
capabilities = set((*self.capabilities.keys(), *other.capabilities.keys()))
73+
new_capabilities = {}
74+
for capability in capabilities:
75+
if Permission.Mode.Allow in (self.capabilities.get(capability), other.capabilities.get(capability)):
76+
new_capabilities[capability] = Permission.Mode.Allow
77+
elif (self.capabilities.get(capability), other.capabilities.get(capability)) == (Permission.Mode.Deny, Permission.Mode.Deny):
78+
new_capabilities[capability] = Permission.Mode.Deny
79+
80+
return PermissionsRule(self.grantee, new_capabilities)
81+
5682
@classmethod
5783
def from_response(cls, resp, ns=None) -> List["PermissionsRule"]:
5884
parsed_response = fromstring(resp)

tableauserverclient/models/reference_item.py

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ def __str__(self):
88

99
__repr__ = __str__
1010

11+
def __eq__(self, other):
12+
return (self.id == other.id) and (self.tag_name == other.tag_name)
13+
1114
@property
1215
def id(self):
1316
return self._id

test/test_permissionsrule.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import unittest
2+
3+
import tableauserverclient as TSC
4+
from tableauserverclient.models.reference_item import ResourceReference
5+
6+
class TestPermissionsRules(unittest.TestCase):
7+
def test_and(self):
8+
grantee = ResourceReference("a", "user")
9+
rule1 = TSC.PermissionsRule(grantee, {
10+
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
11+
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny,
12+
TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow,
13+
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
14+
})
15+
rule2 = TSC.PermissionsRule(grantee, {
16+
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
17+
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow,
18+
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
19+
})
20+
21+
composite = rule1 & rule2
22+
23+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportData), TSC.Permission.Mode.Allow)
24+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.Delete), TSC.Permission.Mode.Deny)
25+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ViewComments), None)
26+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportXml), TSC.Permission.Mode.Deny)
27+
28+
29+
def test_or(self):
30+
grantee = ResourceReference("a", "user")
31+
rule1 = TSC.PermissionsRule(grantee, {
32+
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
33+
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Deny,
34+
TSC.Permission.Capability.ViewComments: TSC.Permission.Mode.Allow,
35+
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
36+
})
37+
rule2 = TSC.PermissionsRule(grantee, {
38+
TSC.Permission.Capability.ExportData: TSC.Permission.Mode.Allow,
39+
TSC.Permission.Capability.Delete: TSC.Permission.Mode.Allow,
40+
TSC.Permission.Capability.ExportXml: TSC.Permission.Mode.Deny,
41+
})
42+
43+
composite = rule1 | rule2
44+
45+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportData), TSC.Permission.Mode.Allow)
46+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.Delete), TSC.Permission.Mode.Allow)
47+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ViewComments), TSC.Permission.Mode.Allow)
48+
self.assertEqual(composite.capabilities.get(TSC.Permission.Capability.ExportXml), TSC.Permission.Mode.Deny)
49+

0 commit comments

Comments
 (0)