Skip to content

Commit 174b7d7

Browse files
authored
Merge pull request #3 from warrant-dev/v2Authz
Add RBAC methods and update to v2 authz endpoint
2 parents 9685ab2 + de1e452 commit 174b7d7

2 files changed

Lines changed: 162 additions & 41 deletions

File tree

examples/example.py

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,64 @@
11
from warrant import *
22

33
def make_warrant_requests(api_key):
4-
client = Warrant(api_key)
4+
client = WarrantClient(api_key)
55

6-
# Create users and session tokens
7-
print("Created tenant with provided id: " + client.create_tenant("custom_tenant_001"))
8-
print("Created user with provided id: " + client.create_user("custom_user_001"))
9-
new_user = client.create_user()
10-
print("Created user with generated id: " + new_user)
11-
new_subject = Subject("user", new_user)
12-
print(client.create_warrant(object_type="tenant", object_id="custom_tenant_001", relation="member", subject=new_subject))
13-
print("Created session token: " + client.create_session(new_user))
6+
# Create users, tenants, roles, permissions
7+
user1 = client.create_user()
8+
print("Created user with generated id: " + user1)
9+
provided_user_id = "custom_user_100"
10+
user2 = client.create_user(provided_user_id)
11+
print("Created user with provided id: " + user2)
12+
print("Created session token for user " + user1 + ": " + client.create_session(user1))
13+
print("Created session token for user " + user2 + ": " + client.create_session(user2))
14+
tenant1 = client.create_tenant("custom_tenant_210")
15+
print("Created tenant with provided id: " + tenant1)
16+
admin_role = client.create_role("admin1")
17+
print("Created role: " + admin_role)
18+
permission1 = client.create_permission("create_report")
19+
print("Created permission: " + permission1)
20+
permission2 = client.create_permission("delete_report")
21+
print("Created permission: " + permission2)
22+
print("Assigned role " + client.assign_role_to_user(user1, admin_role) + " to user " + user1)
23+
print("Assigned permission " + client.assign_permission_to_user(user1, permission1) + " to user " + user1)
24+
print("Assigned permission " + client.assign_permission_to_role(admin_role, permission2) + " to role " + admin_role)
1425

15-
# Create and check warrants
16-
print(client.create_warrant(object_type="store", object_id="store1", relation="owner", subject=new_subject))
17-
subject_to_check = Subject("user", new_user)
18-
is_authorized = client.is_authorized(object_type="store", object_id="store1", relation="owner", subject_to_check=subject_to_check)
19-
print(f"New user authorization result: {is_authorized}")
20-
print(f"All warrants: {client.list_warrants()}")
26+
# Create and test warrants
27+
user1_subject = Subject("user", user1)
28+
print("--- Testing Warrants ---")
29+
print(client.create_warrant(object_type="tenant", object_id=tenant1, relation="member", subject=user1_subject))
30+
subject_to_check = Subject("user", user1)
31+
warrants_to_check = [Warrant("tenant", tenant1, "member", subject_to_check)]
32+
is_authorized = client.is_authorized(WarrantCheck(warrants_to_check, "allOf"))
33+
print(f"Tenant check authorization result: {is_authorized}")
34+
role_warrants_to_check = [Warrant("role", admin_role, "member", subject_to_check)]
35+
role_check = client.is_authorized(WarrantCheck(role_warrants_to_check, "allOf"))
36+
print(f"Admin role check authorization result: {role_check}")
37+
permission_warrants_to_check = [Warrant("permission", permission1, "member", subject_to_check)]
38+
permission_check = client.is_authorized(WarrantCheck(permission_warrants_to_check, "allOf"))
39+
print(f"create_report permission check authorization result: {permission_check}")
40+
role_subject = Subject("role", admin_role)
41+
role_permission_warrants_to_check = [Warrant("permission", permission2, "parent", role_subject)]
42+
role_permission_check = client.is_authorized(WarrantCheck(role_permission_warrants_to_check, "allOf"))
43+
print(f"create_report role/permission check authorization result: {role_permission_check}")
44+
print(f"List all warrants: {client.list_warrants()}")
45+
46+
# Delete users, tenants, roles, permissions
47+
client.remove_permission_from_role(admin_role, permission2)
48+
client.remove_permission_from_user(user1, permission1)
49+
client.remove_role_from_user(user1, admin_role)
50+
client.delete_user(user1)
51+
print("Deleted user " + user1)
52+
client.delete_user(user2)
53+
print("Deleted user " + user2)
54+
client.delete_tenant(tenant1)
55+
print("Deleted tenant " + tenant1)
56+
client.delete_role(admin_role)
57+
print("Deleted role " + admin_role)
58+
client.delete_permission(permission1)
59+
print("Deleted permission " + permission1)
2160

2261
if __name__ == '__main__':
2362
# Replace with your Warrant api key
2463
api_key = "API_KEY"
25-
make_warrant_requests(api_key)
64+
make_warrant_requests(api_key)

warrant/__init__.py

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
__version__ = "0.2.1"
55

66
API_ENDPOINT = "https://api.warrant.dev"
7-
API_VERSION = "/v1"
87

98
class WarrantException(Exception):
109
def __init__(self, msg, status_code=-1):
@@ -21,45 +20,134 @@ def __init__(self, object_type, object_id, relation=""):
2120
self.relation = relation
2221

2322
class Warrant(object):
23+
def __init__(self, object_type, object_id, relation, subject):
24+
self.objectType = object_type
25+
self.objectId = object_id
26+
self.relation = relation
27+
self.subject = subject
28+
29+
class WarrantCheck(object):
30+
def __init__(self, warrants, op):
31+
self.warrants = warrants
32+
self.op = op
33+
34+
class WarrantClient(object):
2435
def __init__(self, api_key):
2536
self._apiKey = api_key
2637

2738
def _make_post_request(self, uri, json={}):
2839
headers = { "Authorization": "ApiKey " + self._apiKey }
29-
resp = requests.post(url = API_ENDPOINT+API_VERSION+uri, headers = headers, json = json)
40+
resp = requests.post(url = API_ENDPOINT+uri, headers = headers, json = json)
3041
if resp.status_code == 200:
3142
return resp.json()
3243
else:
3344
raise WarrantException(msg=resp.text, status_code=resp.status_code)
3445

3546
def _make_get_request(self, uri, params={}):
3647
headers = { "Authorization": "ApiKey " + self._apiKey }
37-
resp = requests.get(url = API_ENDPOINT+API_VERSION+uri, headers = headers, params = params)
48+
resp = requests.get(url = API_ENDPOINT+uri, headers = headers, params = params)
3849
if resp.status_code == 200:
3950
return resp.json()
4051
else:
4152
raise WarrantException(msg=resp.text, status_code=resp.status_code)
4253

54+
def _make_delete_request(self, uri, params={}):
55+
headers = { "Authorization": "ApiKey " + self._apiKey }
56+
resp = requests.delete(url = API_ENDPOINT+uri, headers = headers, params = params)
57+
if resp.status_code != 200:
58+
raise WarrantException(msg=resp.text, status_code=resp.status_code)
59+
4360
def create_user(self, user_id=""):
4461
if user_id == "":
4562
payload = {}
4663
else:
4764
payload = { "userId": user_id }
48-
json = self._make_post_request(uri="/users", json=payload)
65+
json = self._make_post_request(uri="/v1/users", json=payload)
4966
return json['userId']
5067

68+
def delete_user(self, user_id):
69+
if user_id == "":
70+
raise WarrantException(msg="Must include a userId")
71+
self._make_delete_request(uri="/v1/users/"+user_id)
72+
5173
def create_tenant(self, tenant_id=""):
5274
if tenant_id == "":
5375
payload = {}
5476
else:
5577
payload = { "tenantId": tenant_id }
56-
json = self._make_post_request(uri="/tenants", json=payload)
78+
json = self._make_post_request(uri="/v1/tenants", json=payload)
5779
return json['tenantId']
5880

81+
def delete_tenant(self, tenant_id):
82+
if tenant_id == "":
83+
raise WarrantException(msg="Must include a tenantId")
84+
self._make_delete_request(uri="/v1/tenants/"+tenant_id)
85+
86+
def create_role(self, role_id):
87+
if role_id == "":
88+
raise WarrantException(msg="Must include a roleId")
89+
payload = { "roleId": role_id }
90+
json = self._make_post_request(uri="/v1/roles", json=payload)
91+
return json['roleId']
92+
93+
def delete_role(self, role_id):
94+
if role_id == "":
95+
raise WarrantException(msg="Must include a roleId")
96+
self._make_delete_request(uri="/v1/roles/"+role_id)
97+
98+
def create_permission(self, permission_id):
99+
if permission_id == "":
100+
raise WarrantException(msg="Must include a permissionId")
101+
payload = { "permissionId": permission_id }
102+
json = self._make_post_request(uri="/v1/permissions", json=payload)
103+
return json['permissionId']
104+
105+
def delete_permission(self, permission_id):
106+
if permission_id == "":
107+
raise WarrantException(msg="Must include a permissionId")
108+
self._make_delete_request(uri="/v1/permissions/"+permission_id)
109+
110+
def assign_role_to_user(self, user_id, role_id):
111+
if user_id == "" or role_id == "":
112+
raise WarrantException(msg="Must include a userId and roleId")
113+
json = self._make_post_request(uri="/v1/users/" + user_id + "/roles/" + role_id)
114+
return json['roleId']
115+
116+
def remove_role_from_user(self, user_id, role_id):
117+
if user_id == "" or role_id == "":
118+
raise WarrantException(msg="Must include a userId and roleId")
119+
self._make_delete_request(uri="/v1/users/"+user_id+"/roles/"+role_id)
120+
121+
def assign_permission_to_user(self, user_id, permission_id):
122+
if user_id == "" or permission_id == "":
123+
raise WarrantException(msg="Must include a userId and permissionId")
124+
json = self._make_post_request(uri="/v1/users/" + user_id + "/permissions/" + permission_id)
125+
return json['permissionId']
126+
127+
def remove_permission_from_user(self, user_id, permission_id):
128+
if user_id == "" or permission_id == "":
129+
raise WarrantException(msg="Must include a userId and permissionId")
130+
self._make_delete_request(uri="/v1/users/"+user_id+"/permissions/"+permission_id)
131+
132+
def assign_permission_to_role(self, role_id, permission_id):
133+
if role_id == "" or permission_id == "":
134+
raise WarrantException(msg="Must include a roleId and permissionId")
135+
json = self._make_post_request(uri="/v1/roles/" + role_id + "/permissions/" + permission_id)
136+
return json['permissionId']
137+
138+
def remove_permission_from_role(self, role_id, permission_id):
139+
if role_id == "" or permission_id == "":
140+
raise WarrantException(msg="Must include a roleId and permissionId")
141+
self._make_delete_request(uri="/v1/roles/"+role_id+"/permissions/"+permission_id)
142+
59143
def create_session(self, user_id):
60144
if user_id == "":
61145
raise WarrantException(msg="Invalid userId provided")
62-
json = self._make_post_request(uri="/users/"+user_id+"/sessions")
146+
payload = {
147+
"type": "sess",
148+
"userId": user_id
149+
}
150+
json = self._make_post_request(uri="/v1/sessions", json=payload)
63151
return json['token']
64152

65153
def create_warrant(self, object_type, object_id, relation, subject):
@@ -74,7 +162,7 @@ def create_warrant(self, object_type, object_id, relation, subject):
74162
payload["subject"] = subject.__dict__
75163
else:
76164
raise WarrantException(msg="Invalid type for \'subject\'. Must be of type Subject")
77-
resp = self._make_post_request(uri="/warrants", json=payload)
165+
resp = self._make_post_request(uri="/v1/warrants", json=payload)
78166
return resp['id']
79167

80168
def list_warrants(self, object_type="", object_id="", relation="", user_id=""):
@@ -84,26 +172,20 @@ def list_warrants(self, object_type="", object_id="", relation="", user_id=""):
84172
"relation": relation,
85173
"userId": user_id,
86174
}
87-
resp = self._make_get_request(uri="/warrants", params=filters)
175+
resp = self._make_get_request(uri="/v1/warrants", params=filters)
88176
return resp
89177

90-
def is_authorized(self, object_type, object_id, relation, subject_to_check):
91-
if object_type == "" or object_id == "" or relation == "":
92-
raise WarrantException(msg="Invalid object_type, object_id and/or relation")
93-
payload = {
94-
"objectType": object_type,
95-
"objectId": object_id,
96-
"relation": relation
97-
}
98-
if isinstance(subject_to_check, Subject):
99-
payload["subject"] = subject_to_check.__dict__
100-
else:
101-
raise WarrantException(msg="Invalid type for \'subject_to_check\'. Must be of type Subject")
178+
def is_authorized(self, warrant_check):
179+
if not isinstance(warrant_check.warrants, list):
180+
raise WarrantException(msg="Invalid list of warrants to check")
181+
payload = json.dumps(warrant_check, default = lambda x: x.__dict__)
102182
headers = { "Authorization": "ApiKey " + self._apiKey }
103-
resp = requests.post(url = API_ENDPOINT+API_VERSION+"/authorize", headers = headers, json=payload)
104-
if resp.status_code == 200:
183+
resp = requests.post(url = API_ENDPOINT+"/v2/authorize", headers = headers, data=payload)
184+
if resp.status_code != 200:
185+
raise WarrantException(msg=resp.text, status_code=resp.status_code)
186+
response_payload = resp.json()
187+
result = response_payload['code']
188+
if result == 200:
105189
return True
106-
elif resp.status_code == 401:
107-
return False
108190
else:
109-
raise WarrantException(msg=resp.text, status_code=resp.status_code)
191+
return False

0 commit comments

Comments
 (0)