blob: 37f7521f833a8e8c6f56dcf04969392fb2010030 [file] [log] [blame]
Scott Bakere30ce6d2014-10-09 10:59:58 -07001""" useraccesstest.py
2
3 This is a basic REST API permission test. Call it with a username and a
4 password, and it will try to read and update some user and slice object,
5 and report if something is broken.
6
7 This is not an exhaustive test.
8"""
9
10
Scott Baker134fff72014-10-07 12:54:51 -070011import inspect
12import json
13import os
14import requests
15import sys
Scott Baker3495c5a2015-02-18 09:56:21 -080016import time
17from urllib import urlencode
Scott Baker134fff72014-10-07 12:54:51 -070018
19from operator import itemgetter, attrgetter
20
Scott Baker3495c5a2015-02-18 09:56:21 -080021if (len(sys.argv)!=6):
22 print "syntax: usertest <hostname> <username> <password> <admin_username> <admin_password>"
23 sys.exit(-1)
24
25hostname = sys.argv[1]
26username = sys.argv[2]
27password = sys.argv[3]
28
29opencloud_auth=(username, password)
30admin_auth=(sys.argv[4], sys.argv[5])
31
32REST_API="http://%s:8000/xos/" % hostname
Scott Baker134fff72014-10-07 12:54:51 -070033USERS_API = REST_API + "users/"
34SLICES_API = REST_API + "slices/"
35SITES_API = REST_API + "sites/"
Scott Baker3495c5a2015-02-18 09:56:21 -080036SITEPRIV_API = REST_API + "siteprivileges/"
37SLICEPRIV_API = REST_API + "slice_privileges/"
Scott Baker134fff72014-10-07 12:54:51 -070038SITEROLE_API = REST_API + "site_roles/"
Scott Bakere30ce6d2014-10-09 10:59:58 -070039SLICEROLE_API = REST_API + "slice_roles/"
40
Scott Baker3495c5a2015-02-18 09:56:21 -080041TEST_USER_EMAIL = "test" + str(time.time()) + "@test.com" # in case observer not running, objects won't be purged, so use unique email
Scott Baker134fff72014-10-07 12:54:51 -070042
43def fail_unless(x, msg):
44 if not x:
45 (frame, filename, line_number, function_name, lines, index) = inspect.getouterframes(inspect.currentframe())[1]
46 print "FAIL (%s:%d)" % (function_name, line_number), msg
47
Scott Baker134fff72014-10-07 12:54:51 -070048print "downloading objects using admin"
49r = requests.get(USERS_API + "?no_hyperlinks=1", auth=admin_auth)
Scott Baker3495c5a2015-02-18 09:56:21 -080050fail_unless(r.status_code==200, "failed to get users")
Scott Baker134fff72014-10-07 12:54:51 -070051allUsers = r.json()
52r = requests.get(SLICES_API + "?no_hyperlinks=1", auth=admin_auth)
Scott Baker3495c5a2015-02-18 09:56:21 -080053fail_unless(r.status_code==200, "failed to get slices")
Scott Baker134fff72014-10-07 12:54:51 -070054allSlices = r.json()
55r = requests.get(SITES_API + "?no_hyperlinks=1", auth=admin_auth)
56allSites = r.json()
57r = requests.get(SITEPRIV_API + "?no_hyperlinks=1", auth=admin_auth)
58allSitePriv = r.json()
59r = requests.get(SLICEPRIV_API + "?no_hyperlinks=1", auth=admin_auth)
60allSlicePriv = r.json()
61r = requests.get(SITEROLE_API + "?no_hyperlinks=1", auth=admin_auth)
62allSiteRole = r.json()
Scott Bakere30ce6d2014-10-09 10:59:58 -070063r = requests.get(SLICEROLE_API + "?no_hyperlinks=1", auth=admin_auth)
64allSliceRole = r.json()
Scott Baker134fff72014-10-07 12:54:51 -070065
66def should_see_user(myself, otherUser):
67 if myself["is_admin"]:
68 return True
69 if myself["id"] == otherUser["id"]:
70 return True
71 for sitePriv in allSitePriv:
72 if (sitePriv["user"] == myself["id"]) and (sitePriv["site"] == otherUser["site"]):
73 for role in allSiteRole:
74 if role["role"]=="pi" and role["id"] == sitePriv["role"]:
75 return True
76 return False
77
Scott Bakere30ce6d2014-10-09 10:59:58 -070078def should_see_slice(myself, slice):
79 if myself["is_admin"]:
80 return True
81 for sitePriv in allSitePriv:
82 if (sitePriv["user"] == myself["id"]) and (sitePriv["site"] == slice["site"]):
83 for role in allSiteRole:
84 if role["role"]=="pi" and role["id"] == sitePriv["role"]:
85 return True
86 for slicePriv in allSlicePriv:
87 if (slicePriv["user"] == myself["id"]) and (sitePriv["slice"] == slice["id"]):
88 for role in allSliceRole:
89 if role["role"]=="pi" and role["id"] == slicePriv["role"]:
90 return True
91 return False
92
Scott Baker134fff72014-10-07 12:54:51 -070093def flip_phone(user):
94 if user["phone"] == "123":
95 user["phone"] = "456"
96 else:
97 user["phone"] = "123"
98
Scott Bakere30ce6d2014-10-09 10:59:58 -070099def flip_desc(slice):
100 if slice["description"] == "some_description":
101 slice["description"] = "some_other_description"
102 else:
103 slice["description"] = "some_description"
104
105def delete_user_if_exists(email):
106 r = requests.get(USERS_API +"?email=%s" % email, auth=admin_auth)
107 if r.status_code==200:
108 user = r.json()
109 if len(user)>0:
110 user=user[0]
111 r = requests.delete(USERS_API + str(user["id"]) + "/", auth=admin_auth)
112 fail_unless(r.status_code==200, "failed to delete the test user")
113
Scott Baker134fff72014-10-07 12:54:51 -0700114print " loaded user:%d slice:%d, site:%d, site_priv:%d slice_priv:%d" % (len(allUsers), len(allSlices), len(allSites), len(allSitePriv), len(allSlicePriv))
115
116# get our own user record
117
Scott Baker3495c5a2015-02-18 09:56:21 -0800118r = requests.get(USERS_API + "?" + urlencode({"email": username, "no_hyperlinks": "1"}), auth=opencloud_auth)
Scott Baker134fff72014-10-07 12:54:51 -0700119fail_unless(r.status_code==200, "failed to get user %s" % username)
120myself = r.json()
121fail_unless(len(myself)==1, "wrong number of results when getting user %s" % username)
122myself = myself[0]
123
124# check to see that we see the users we should be able to
125
126r = requests.get(USERS_API, auth=opencloud_auth)
127myUsers = r.json()
128for user in myUsers:
129 fail_unless(should_see_user(myself, user), "saw user %s but we shouldn't have" % user["email"])
130myUsersIds = [r["id"] for r in myUsers]
131for user in allUsers:
132 if should_see_user(myself, user):
133 fail_unless(user["id"] in myUsersIds, "should have seen user %s but didnt" % user["email"])
134
135# toggle the phone number on the users we should be able to
136
Scott Bakere30ce6d2014-10-09 10:59:58 -0700137"""
Scott Baker134fff72014-10-07 12:54:51 -0700138for user in allUsers:
139 user = requests.get(USERS_API + str(user["id"]) + "/", auth=admin_auth).json()
140 flip_phone(user)
141 r = requests.put(USERS_API + str(user["id"]) +"/", data=user, auth=opencloud_auth)
142 if should_see_user(myself, user):
143 fail_unless(r.status_code==200, "failed to change phone number on %s" % user["email"])
144 else:
145 # XXX: this is failing, but for the wrong reason
146 fail_unless(r.status_code!=200, "was able to change phone number on %s but shouldn't have" % user["email"])
147
Scott Bakere30ce6d2014-10-09 10:59:58 -0700148# try changing is_staff. We should be able to do it if we're an admin, but not
149# otherwise.
150
Scott Baker134fff72014-10-07 12:54:51 -0700151for user in allUsers:
152 user = requests.get(USERS_API + str(user["id"]) + "/", auth=admin_auth).json()
153 user["is_staff"] = not user["is_staff"]
154 r = requests.put(USERS_API + str(user["id"]) +"/", data=user, auth=opencloud_auth)
155 if myself["is_admin"]:
156 fail_unless(r.status_code==200, "failed to change is_staff on %s" % user["email"])
157 else:
158 # XXX: this is failing, but for the wrong reason
159 fail_unless(r.status_code!=200, "was able to change is_staff on %s but shouldn't have" % user["email"])
160
161 # put it back to false, in case we successfully changed it...
162 user["is_staff"] = False
163 r = requests.put(USERS_API + str(user["id"]) +"/", data=user, auth=opencloud_auth)
Scott Bakere30ce6d2014-10-09 10:59:58 -0700164"""
165
166# delete the TEST_USER_EMAIL if it exists
167delete_user_if_exists(TEST_USER_EMAIL)
168
Scott Baker3495c5a2015-02-18 09:56:21 -0800169# XXX - enacted and policed should not be required
170
171newUser = {"firstname": "test", "lastname": "1234", "email": TEST_USER_EMAIL, "password": "letmein", "site": allSites[0]["id"], "enacted": "2015-01-01T00:00", "policed": "2015-01-01T00:00"}
172r = requests.post(USERS_API + "?no_hyperlinks=1", data=newUser, auth=opencloud_auth)
Scott Bakere30ce6d2014-10-09 10:59:58 -0700173if myself["is_admin"]:
174 fail_unless(r.status_code==200, "failed to create %s" % TEST_USER_EMAIL)
175else:
176 fail_unless(r.status_code!=200, "created %s but we shouldn't have been able to" % TEST_USER_EMAIL)
177
178delete_user_if_exists(TEST_USER_EMAIL)
179
Scott Bakere30ce6d2014-10-09 10:59:58 -0700180# now create it as admin
Scott Baker3495c5a2015-02-18 09:56:21 -0800181r = requests.post(USERS_API + "?no_hyperlinks=1", data=newUser, auth=admin_auth)
182if (r.status_code!=201):
183 print r.text
Scott Bakere30ce6d2014-10-09 10:59:58 -0700184fail_unless(r.status_code==201, "failed to create %s as admin" % TEST_USER_EMAIL)
Scott Baker134fff72014-10-07 12:54:51 -0700185
Scott Baker3495c5a2015-02-18 09:56:21 -0800186r = requests.get(USERS_API +"?" + urlencode({"email": TEST_USER_EMAIL}), auth=admin_auth)
187fail_unless(r.status_code==200, "failed to get user %s" % TEST_USER_EMAIL)
188user=r.json()[0]
Scott Bakere30ce6d2014-10-09 10:59:58 -0700189r = requests.delete(USERS_API + str(user["id"]) + "/", auth=opencloud_auth)
190if myself["is_admin"]:
191 fail_unless(r.status_code==200, "failed to delete %s" % TEST_USER_EMAIL)
192else:
193 fail_unless(r.status_code!=200, "deleted %s but we shouldn't have been able to" % TEST_USER_EMAIL)
Scott Baker134fff72014-10-07 12:54:51 -0700194
Scott Bakere30ce6d2014-10-09 10:59:58 -0700195# slice tests
Scott Baker134fff72014-10-07 12:54:51 -0700196
Scott Bakere30ce6d2014-10-09 10:59:58 -0700197r = requests.get(SLICES_API, auth=opencloud_auth)
198mySlices = r.json()
199
200for slice in mySlices:
201 fail_unless(should_see_slice(myself, slice), "saw slice %s but we shouldn't have" % slice["name"])
202mySlicesIds = [r["id"] for r in mySlices]
203for slice in allSlices:
204 if should_see_slice(myself, slice):
205 fail_unless(slice["id"] in mySliceIds, "should have seen slice %s but didnt" % slice["name"])
206
207for slice in allSlices:
208 slice = requests.get(SLICES_API + str(slice["id"]) + "/", auth=admin_auth).json()
209 flip_desc(slice)
210 r = requests.put(SLICES_API + str(slice["id"]) +"/", data=slice, auth=opencloud_auth)
211 if should_see_slice(myself, slice):
212 fail_unless(r.status_code==200, "failed to change desc on %s" % slice["name"])
213 else:
214 fail_unless(r.status_code!=200, "was able to change desc on %s but shouldn't have" % slice["name"])
215
216print "Done."