Merge lp:~trapnine/maas/fix-1576417-controllers-admin-only into lp:~maas-committers/maas/trunk
- fix-1576417-controllers-admin-only
- Merge into trunk
Proposed by
Jeffrey C Jones
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Jeffrey C Jones | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 5027 | ||||
Proposed branch: | lp:~trapnine/maas/fix-1576417-controllers-admin-only | ||||
Merge into: | lp:~maas-committers/maas/trunk | ||||
Diff against target: |
357 lines (+135/-12) 11 files modified
src/maasserver/api/rackcontrollers.py (+2/-0) src/maasserver/api/tests/test_events.py (+2/-0) src/maasserver/api/tests/test_rackcontroller.py (+33/-0) src/maasserver/api/tests/test_regioncontroller.py (+1/-0) src/maasserver/api/tests/test_tag.py (+42/-6) src/maasserver/models/node.py (+8/-1) src/maasserver/models/tests/test_node.py (+21/-0) src/maasserver/static/js/angular/controllers/nodes_list.js (+5/-0) src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js (+16/-0) src/maasserver/static/partials/nodes-list.html (+2/-2) src/maasserver/websockets/handlers/tests/test_controller.py (+3/-3) |
||||
To merge this branch: | bzr merge lp:~trapnine/maas/fix-1576417-controllers-admin-only | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeffrey C Jones (community) | Approve | ||
Gavin Panella (community) | Approve | ||
Review via email: mp+294785@code.launchpad.net |
Commit message
Non-admins can't see controllers.
Description of the change
Non-admins can't see controllers.
To post a comment you must log in.
Revision history for this message
Jeffrey C Jones (trapnine) wrote : | # |
Approved by Gavin.
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/maasserver/api/rackcontrollers.py' | |||
2 | --- src/maasserver/api/rackcontrollers.py 2016-04-28 01:11:50 +0000 | |||
3 | +++ src/maasserver/api/rackcontrollers.py 2016-05-16 16:20:02 +0000 | |||
4 | @@ -154,6 +154,7 @@ | |||
5 | 154 | "Import of boot images started on %s" % rack.hostname, | 154 | "Import of boot images started on %s" % rack.hostname, |
6 | 155 | content_type=("text/plain; charset=%s" % settings.DEFAULT_CHARSET)) | 155 | content_type=("text/plain; charset=%s" % settings.DEFAULT_CHARSET)) |
7 | 156 | 156 | ||
8 | 157 | @admin_method | ||
9 | 157 | @operation(idempotent=True) | 158 | @operation(idempotent=True) |
10 | 158 | def list_boot_images(self, request, system_id): | 159 | def list_boot_images(self, request, system_id): |
11 | 159 | """List all available boot images. | 160 | """List all available boot images. |
12 | @@ -192,6 +193,7 @@ | |||
13 | 192 | "Import of boot images started on all rack controllers", | 193 | "Import of boot images started on all rack controllers", |
14 | 193 | content_type=("text/plain; charset=%s" % settings.DEFAULT_CHARSET)) | 194 | content_type=("text/plain; charset=%s" % settings.DEFAULT_CHARSET)) |
15 | 194 | 195 | ||
16 | 196 | @admin_method | ||
17 | 195 | @operation(idempotent=True) | 197 | @operation(idempotent=True) |
18 | 196 | def describe_power_types(self, request): | 198 | def describe_power_types(self, request): |
19 | 197 | """Query all of the rack controllers for power information. | 199 | """Query all of the rack controllers for power information. |
20 | 198 | 200 | ||
21 | === modified file 'src/maasserver/api/tests/test_events.py' | |||
22 | --- src/maasserver/api/tests/test_events.py 2016-02-02 14:20:45 +0000 | |||
23 | +++ src/maasserver/api/tests/test_events.py 2016-05-16 16:20:02 +0000 | |||
24 | @@ -143,6 +143,7 @@ | |||
25 | 143 | # Even when node ids are passed to "list," events for nodes are | 143 | # Even when node ids are passed to "list," events for nodes are |
26 | 144 | # returned in event id order, not necessarily in the order of the | 144 | # returned in event id order, not necessarily in the order of the |
27 | 145 | # node id arguments. | 145 | # node id arguments. |
28 | 146 | self.become_admin() | ||
29 | 146 | nodes = [factory.make_Node() for _ in range(3)] | 147 | nodes = [factory.make_Node() for _ in range(3)] |
30 | 147 | events = [factory.make_Event(node=node) for node in nodes] | 148 | events = [factory.make_Event(node=node) for node in nodes] |
31 | 148 | response = self.client.get( | 149 | response = self.client.get( |
32 | @@ -310,6 +311,7 @@ | |||
33 | 310 | self.assertEqual(parsed_result['count'], len(events)) | 311 | self.assertEqual(parsed_result['count'], len(events)) |
34 | 311 | 312 | ||
35 | 312 | def test_GET_query_doesnt_list_devices(self): | 313 | def test_GET_query_doesnt_list_devices(self): |
36 | 314 | self.become_admin() | ||
37 | 313 | machines = [ | 315 | machines = [ |
38 | 314 | factory.make_Node( | 316 | factory.make_Node( |
39 | 315 | agent_name=factory.make_name('agent-name'), | 317 | agent_name=factory.make_name('agent-name'), |
40 | 316 | 318 | ||
41 | === modified file 'src/maasserver/api/tests/test_rackcontroller.py' | |||
42 | --- src/maasserver/api/tests/test_rackcontroller.py 2016-04-15 22:14:33 +0000 | |||
43 | +++ src/maasserver/api/tests/test_rackcontroller.py 2016-05-16 16:20:02 +0000 | |||
44 | @@ -6,6 +6,7 @@ | |||
45 | 6 | import http.client | 6 | import http.client |
46 | 7 | 7 | ||
47 | 8 | from django.core.urlresolvers import reverse | 8 | from django.core.urlresolvers import reverse |
48 | 9 | from maasserver.api import rackcontrollers | ||
49 | 9 | from maasserver.models import node as node_module | 10 | from maasserver.models import node as node_module |
50 | 10 | from maasserver.testing.api import ( | 11 | from maasserver.testing.api import ( |
51 | 11 | APITestCase, | 12 | APITestCase, |
52 | @@ -17,6 +18,7 @@ | |||
53 | 17 | from maastesting.matchers import ( | 18 | from maastesting.matchers import ( |
54 | 18 | MockCalledOnce, | 19 | MockCalledOnce, |
55 | 19 | MockCalledOnceWith, | 20 | MockCalledOnceWith, |
56 | 21 | MockNotCalled, | ||
57 | 20 | ) | 22 | ) |
58 | 21 | 23 | ||
59 | 22 | 24 | ||
60 | @@ -87,6 +89,7 @@ | |||
61 | 87 | 89 | ||
62 | 88 | def test_GET_list_boot_images(self): | 90 | def test_GET_list_boot_images(self): |
63 | 89 | rack = factory.make_RackController(owner=factory.make_User()) | 91 | rack = factory.make_RackController(owner=factory.make_User()) |
64 | 92 | self.become_admin() | ||
65 | 90 | response = self.client.get( | 93 | response = self.client.get( |
66 | 91 | self.get_rack_uri(rack), {'op': 'list_boot_images'}) | 94 | self.get_rack_uri(rack), {'op': 'list_boot_images'}) |
67 | 92 | self.assertEqual( | 95 | self.assertEqual( |
68 | @@ -96,6 +99,14 @@ | |||
69 | 96 | ['connected', 'images', 'status'], | 99 | ['connected', 'images', 'status'], |
70 | 97 | json_load_bytes(response.content)) | 100 | json_load_bytes(response.content)) |
71 | 98 | 101 | ||
72 | 102 | def test_GET_list_boot_images_denied_if_not_admin(self): | ||
73 | 103 | rack = factory.make_RackController(owner=factory.make_User()) | ||
74 | 104 | response = self.client.get( | ||
75 | 105 | self.get_rack_uri(rack), {'op': 'list_boot_images'}) | ||
76 | 106 | self.assertEqual( | ||
77 | 107 | http.client.FORBIDDEN, response.status_code, | ||
78 | 108 | explain_unexpected_response(http.client.FORBIDDEN, response)) | ||
79 | 109 | |||
80 | 99 | 110 | ||
81 | 100 | class TestRackControllersAPI(APITestCase): | 111 | class TestRackControllersAPI(APITestCase): |
82 | 101 | """Tests for /api/2.0/rackcontrollers/.""" | 112 | """Tests for /api/2.0/rackcontrollers/.""" |
83 | @@ -110,6 +121,7 @@ | |||
84 | 110 | '/api/2.0/rackcontrollers/', reverse('rackcontrollers_handler')) | 121 | '/api/2.0/rackcontrollers/', reverse('rackcontrollers_handler')) |
85 | 111 | 122 | ||
86 | 112 | def test_read_returns_limited_fields(self): | 123 | def test_read_returns_limited_fields(self): |
87 | 124 | self.become_admin() | ||
88 | 113 | factory.make_RackController(owner=self.logged_in_user) | 125 | factory.make_RackController(owner=self.logged_in_user) |
89 | 114 | response = self.client.get(reverse('rackcontrollers_handler')) | 126 | response = self.client.get(reverse('rackcontrollers_handler')) |
90 | 115 | parsed_result = json_load_bytes(response.content) | 127 | parsed_result = json_load_bytes(response.content) |
91 | @@ -159,3 +171,24 @@ | |||
92 | 159 | self.assertEqual( | 171 | self.assertEqual( |
93 | 160 | http.client.FORBIDDEN, response.status_code, | 172 | http.client.FORBIDDEN, response.status_code, |
94 | 161 | explain_unexpected_response(http.client.FORBIDDEN, response)) | 173 | explain_unexpected_response(http.client.FORBIDDEN, response)) |
95 | 174 | |||
96 | 175 | def test_GET_describe_power_types(self): | ||
97 | 176 | get_all_power_types_from_clusters = self.patch( | ||
98 | 177 | rackcontrollers, "get_all_power_types_from_clusters") | ||
99 | 178 | self.become_admin() | ||
100 | 179 | response = self.client.get( | ||
101 | 180 | self.get_rack_uri(), {'op': 'describe_power_types'}) | ||
102 | 181 | self.assertEqual( | ||
103 | 182 | http.client.OK, response.status_code, | ||
104 | 183 | explain_unexpected_response(http.client.OK, response)) | ||
105 | 184 | self.assertThat(get_all_power_types_from_clusters, MockCalledOnce()) | ||
106 | 185 | |||
107 | 186 | def test_GET_describe_power_types_denied_if_not_admin(self): | ||
108 | 187 | get_all_power_types_from_clusters = self.patch( | ||
109 | 188 | rackcontrollers, "get_all_power_types_from_clusters") | ||
110 | 189 | response = self.client.get( | ||
111 | 190 | self.get_rack_uri(), {'op': 'describe_power_types'}) | ||
112 | 191 | self.assertEqual( | ||
113 | 192 | http.client.FORBIDDEN, response.status_code, | ||
114 | 193 | explain_unexpected_response(http.client.FORBIDDEN, response)) | ||
115 | 194 | self.assertThat(get_all_power_types_from_clusters, MockNotCalled()) | ||
116 | 162 | 195 | ||
117 | === modified file 'src/maasserver/api/tests/test_regioncontroller.py' | |||
118 | --- src/maasserver/api/tests/test_regioncontroller.py 2016-04-13 02:20:16 +0000 | |||
119 | +++ src/maasserver/api/tests/test_regioncontroller.py 2016-05-16 16:20:02 +0000 | |||
120 | @@ -54,6 +54,7 @@ | |||
121 | 54 | reverse('regioncontrollers_handler')) | 54 | reverse('regioncontrollers_handler')) |
122 | 55 | 55 | ||
123 | 56 | def test_read_returns_limited_fields(self): | 56 | def test_read_returns_limited_fields(self): |
124 | 57 | self.become_admin() | ||
125 | 57 | factory.make_RegionController() | 58 | factory.make_RegionController() |
126 | 58 | response = self.client.get(reverse('regioncontrollers_handler')) | 59 | response = self.client.get(reverse('regioncontrollers_handler')) |
127 | 59 | parsed_result = json_load_bytes(response.content) | 60 | parsed_result = json_load_bytes(response.content) |
128 | 60 | 61 | ||
129 | === modified file 'src/maasserver/api/tests/test_tag.py' | |||
130 | --- src/maasserver/api/tests/test_tag.py 2016-05-12 19:07:37 +0000 | |||
131 | +++ src/maasserver/api/tests/test_tag.py 2016-05-16 16:20:02 +0000 | |||
132 | @@ -147,11 +147,8 @@ | |||
133 | 147 | self.assertEqual(http.client.OK, response.status_code) | 147 | self.assertEqual(http.client.OK, response.status_code) |
134 | 148 | parsed_result = json.loads( | 148 | parsed_result = json.loads( |
135 | 149 | response.content.decode(settings.DEFAULT_CHARSET)) | 149 | response.content.decode(settings.DEFAULT_CHARSET)) |
136 | 150 | # XXX lamont Bug#1576417 : Region controllers should not be here | ||
137 | 151 | # either, but are the subject of said bug. | ||
138 | 152 | self.assertItemsEqual( | 150 | self.assertItemsEqual( |
141 | 153 | [machine.system_id, device.system_id, | 151 | [machine.system_id, device.system_id], |
140 | 154 | region.system_id], | ||
142 | 155 | [r['system_id'] for r in parsed_result]) | 152 | [r['system_id'] for r in parsed_result]) |
143 | 156 | 153 | ||
144 | 157 | def test_GET_machines_returns_machines(self): | 154 | def test_GET_machines_returns_machines(self): |
145 | @@ -196,8 +193,6 @@ | |||
146 | 196 | [device.system_id], | 193 | [device.system_id], |
147 | 197 | [r['system_id'] for r in parsed_result]) | 194 | [r['system_id'] for r in parsed_result]) |
148 | 198 | 195 | ||
149 | 199 | # XXX lamont Bug#1576417: Add a test that non-admins do not get to fetch | ||
150 | 200 | # rack controllers. | ||
151 | 201 | def test_GET_rack_controllers_returns_rack_controllers(self): | 196 | def test_GET_rack_controllers_returns_rack_controllers(self): |
152 | 202 | self.become_admin() | 197 | self.become_admin() |
153 | 203 | tag = factory.make_Tag() | 198 | tag = factory.make_Tag() |
154 | @@ -221,7 +216,28 @@ | |||
155 | 221 | [rack.system_id], | 216 | [rack.system_id], |
156 | 222 | [r['system_id'] for r in parsed_result]) | 217 | [r['system_id'] for r in parsed_result]) |
157 | 223 | 218 | ||
158 | 219 | def test_GET_rack_controllers_returns_no_rack_controllers_nonadmin(self): | ||
159 | 220 | tag = factory.make_Tag() | ||
160 | 221 | machine = factory.make_Node() | ||
161 | 222 | device = factory.make_Device() | ||
162 | 223 | rack = factory.make_RackController() | ||
163 | 224 | region = factory.make_RegionController() | ||
164 | 225 | # Create a second node that isn't tagged. | ||
165 | 226 | factory.make_Node() | ||
166 | 227 | machine.tags.add(tag) | ||
167 | 228 | device.tags.add(tag) | ||
168 | 229 | rack.tags.add(tag) | ||
169 | 230 | region.tags.add(tag) | ||
170 | 231 | response = self.client.get( | ||
171 | 232 | self.get_tag_uri(tag), {'op': 'rack_controllers'}) | ||
172 | 233 | |||
173 | 234 | self.assertEqual(http.client.OK, response.status_code) | ||
174 | 235 | parsed_result = json.loads( | ||
175 | 236 | response.content.decode(settings.DEFAULT_CHARSET)) | ||
176 | 237 | self.assertItemsEqual([], parsed_result) | ||
177 | 238 | |||
178 | 224 | def test_GET_region_controllers_returns_region_controllers(self): | 239 | def test_GET_region_controllers_returns_region_controllers(self): |
179 | 240 | self.become_admin() | ||
180 | 225 | tag = factory.make_Tag() | 241 | tag = factory.make_Tag() |
181 | 226 | machine = factory.make_Node() | 242 | machine = factory.make_Node() |
182 | 227 | device = factory.make_Device() | 243 | device = factory.make_Device() |
183 | @@ -243,6 +259,26 @@ | |||
184 | 243 | [region.system_id], | 259 | [region.system_id], |
185 | 244 | [r['system_id'] for r in parsed_result]) | 260 | [r['system_id'] for r in parsed_result]) |
186 | 245 | 261 | ||
187 | 262 | def test_GET_region_controllers_returns_no_controllers_nonadmin(self): | ||
188 | 263 | tag = factory.make_Tag() | ||
189 | 264 | machine = factory.make_Node() | ||
190 | 265 | device = factory.make_Device() | ||
191 | 266 | rack = factory.make_RackController() | ||
192 | 267 | region = factory.make_RegionController() | ||
193 | 268 | # Create a second node that isn't tagged. | ||
194 | 269 | factory.make_Node() | ||
195 | 270 | machine.tags.add(tag) | ||
196 | 271 | device.tags.add(tag) | ||
197 | 272 | rack.tags.add(tag) | ||
198 | 273 | region.tags.add(tag) | ||
199 | 274 | response = self.client.get( | ||
200 | 275 | self.get_tag_uri(tag), {'op': 'region_controllers'}) | ||
201 | 276 | |||
202 | 277 | self.assertEqual(http.client.OK, response.status_code) | ||
203 | 278 | parsed_result = json.loads( | ||
204 | 279 | response.content.decode(settings.DEFAULT_CHARSET)) | ||
205 | 280 | self.assertItemsEqual([], parsed_result) | ||
206 | 281 | |||
207 | 246 | def test_GET_nodes_hides_invisible_nodes(self): | 282 | def test_GET_nodes_hides_invisible_nodes(self): |
208 | 247 | user2 = factory.make_User() | 283 | user2 = factory.make_User() |
209 | 248 | node1 = factory.make_Node() | 284 | node1 = factory.make_Node() |
210 | 249 | 285 | ||
211 | === modified file 'src/maasserver/models/node.py' | |||
212 | --- src/maasserver/models/node.py 2016-05-12 19:07:37 +0000 | |||
213 | +++ src/maasserver/models/node.py 2016-05-16 16:20:02 +0000 | |||
214 | @@ -409,7 +409,14 @@ | |||
215 | 409 | if user.is_superuser: | 409 | if user.is_superuser: |
216 | 410 | # Admin is allowed to see all nodes. | 410 | # Admin is allowed to see all nodes. |
217 | 411 | return nodes | 411 | return nodes |
219 | 412 | elif perm == NODE_PERMISSION.VIEW: | 412 | # Non-admins aren't allowed to see controllers. |
220 | 413 | nodes = nodes.exclude( | ||
221 | 414 | Q(node_type__in=[ | ||
222 | 415 | NODE_TYPE.RACK_CONTROLLER, | ||
223 | 416 | NODE_TYPE.REGION_CONTROLLER, | ||
224 | 417 | NODE_TYPE.REGION_AND_RACK_CONTROLLER, | ||
225 | 418 | ])) | ||
226 | 419 | if perm == NODE_PERMISSION.VIEW: | ||
227 | 413 | return nodes.filter(Q(owner__isnull=True) | Q(owner=user)) | 420 | return nodes.filter(Q(owner__isnull=True) | Q(owner=user)) |
228 | 414 | elif perm == NODE_PERMISSION.EDIT: | 421 | elif perm == NODE_PERMISSION.EDIT: |
229 | 415 | return nodes.filter(owner=user) | 422 | return nodes.filter(owner=user) |
230 | 416 | 423 | ||
231 | === modified file 'src/maasserver/models/tests/test_node.py' | |||
232 | --- src/maasserver/models/tests/test_node.py 2016-05-12 19:07:37 +0000 | |||
233 | +++ src/maasserver/models/tests/test_node.py 2016-05-16 16:20:02 +0000 | |||
234 | @@ -3255,6 +3255,9 @@ | |||
235 | 3255 | def test_get_nodes_with_admin_perm_returns_all_nodes_for_admin(self): | 3255 | def test_get_nodes_with_admin_perm_returns_all_nodes_for_admin(self): |
236 | 3256 | user = factory.make_User() | 3256 | user = factory.make_User() |
237 | 3257 | nodes = [self.make_node(user) for counter in range(5)] | 3257 | nodes = [self.make_node(user) for counter in range(5)] |
238 | 3258 | nodes.append(factory.make_RackController()) | ||
239 | 3259 | nodes.append(factory.make_RegionController()) | ||
240 | 3260 | nodes.append(factory.make_RegionRackController()) | ||
241 | 3258 | self.assertItemsEqual( | 3261 | self.assertItemsEqual( |
242 | 3259 | nodes, | 3262 | nodes, |
243 | 3260 | Node.objects.get_nodes( | 3263 | Node.objects.get_nodes( |
244 | @@ -3282,6 +3285,24 @@ | |||
245 | 3282 | from_nodes=Node.objects.all()) | 3285 | from_nodes=Node.objects.all()) |
246 | 3283 | ) | 3286 | ) |
247 | 3284 | 3287 | ||
248 | 3288 | def test_get_nodes_non_admin_hides_controllers(self): | ||
249 | 3289 | user = factory.make_User() | ||
250 | 3290 | user_visible_nodes = [self.make_node(user), self.make_node(None)] | ||
251 | 3291 | admin_visible_nodes = user_visible_nodes + [ | ||
252 | 3292 | self.make_node(factory.make_User()), | ||
253 | 3293 | factory.make_RackController(owner=user), | ||
254 | 3294 | factory.make_RackController(owner=None), | ||
255 | 3295 | factory.make_RegionController(), | ||
256 | 3296 | factory.make_RegionRackController(), | ||
257 | 3297 | ] | ||
258 | 3298 | self.assertItemsEqual( | ||
259 | 3299 | admin_visible_nodes, | ||
260 | 3300 | Node.objects.get_nodes( | ||
261 | 3301 | factory.make_admin(), NODE_PERMISSION.ADMIN)) | ||
262 | 3302 | self.assertItemsEqual( | ||
263 | 3303 | user_visible_nodes, | ||
264 | 3304 | Node.objects.get_nodes(user, NODE_PERMISSION.VIEW)) | ||
265 | 3305 | |||
266 | 3285 | def test_filter_nodes_by_spaces(self): | 3306 | def test_filter_nodes_by_spaces(self): |
267 | 3286 | # Create a throwaway node and a throwaway space. | 3307 | # Create a throwaway node and a throwaway space. |
268 | 3287 | # (to ensure they are filtered out.) | 3308 | # (to ensure they are filtered out.) |
269 | 3288 | 3309 | ||
270 | === modified file 'src/maasserver/static/js/angular/controllers/nodes_list.js' | |||
271 | --- src/maasserver/static/js/angular/controllers/nodes_list.js 2016-04-29 19:31:59 +0000 | |||
272 | +++ src/maasserver/static/js/angular/controllers/nodes_list.js 2016-05-16 16:20:02 +0000 | |||
273 | @@ -585,6 +585,11 @@ | |||
274 | 585 | }); | 585 | }); |
275 | 586 | }; | 586 | }; |
276 | 587 | 587 | ||
277 | 588 | // Return true if the authenticated user is super user. | ||
278 | 589 | $scope.isSuperUser = function() { | ||
279 | 590 | return UsersManager.isSuperUser(); | ||
280 | 591 | }; | ||
281 | 592 | |||
282 | 588 | // Load the required managers for this controller. The ServicesManager | 593 | // Load the required managers for this controller. The ServicesManager |
283 | 589 | // is required by the maasControllerStatus directive that is used | 594 | // is required by the maasControllerStatus directive that is used |
284 | 590 | // in the partial for this controller. | 595 | // in the partial for this controller. |
285 | 591 | 596 | ||
286 | === modified file 'src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js' | |||
287 | --- src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js 2016-04-29 07:41:09 +0000 | |||
288 | +++ src/maasserver/static/js/angular/controllers/tests/test_nodes_list.js 2016-05-16 16:20:02 +0000 | |||
289 | @@ -134,6 +134,22 @@ | |||
290 | 134 | return null; | 134 | return null; |
291 | 135 | } | 135 | } |
292 | 136 | 136 | ||
293 | 137 | describe("isSuperUser", function() { | ||
294 | 138 | it("returns true if the user is a superuser", function() { | ||
295 | 139 | var controller = makeController(); | ||
296 | 140 | spyOn(UsersManager, "getAuthUser").and.returnValue( | ||
297 | 141 | { is_superuser: true }); | ||
298 | 142 | expect($scope.isSuperUser()).toBe(true); | ||
299 | 143 | }); | ||
300 | 144 | |||
301 | 145 | it("returns false if the user is not a superuser", function() { | ||
302 | 146 | var controller = makeController(); | ||
303 | 147 | spyOn(UsersManager, "getAuthUser").and.returnValue( | ||
304 | 148 | { is_superuser: false }); | ||
305 | 149 | expect($scope.isSuperUser()).toBe(false); | ||
306 | 150 | }); | ||
307 | 151 | }); | ||
308 | 152 | |||
309 | 137 | it("sets title and page on $rootScope", function() { | 153 | it("sets title and page on $rootScope", function() { |
310 | 138 | var controller = makeController(); | 154 | var controller = makeController(); |
311 | 139 | expect($rootScope.title).toBe("Machines"); | 155 | expect($rootScope.title).toBe("Machines"); |
312 | 140 | 156 | ||
313 | === modified file 'src/maasserver/static/partials/nodes-list.html' | |||
314 | --- src/maasserver/static/partials/nodes-list.html 2016-05-11 19:01:48 +0000 | |||
315 | +++ src/maasserver/static/partials/nodes-list.html 2016-05-16 16:20:02 +0000 | |||
316 | @@ -11,8 +11,8 @@ | |||
317 | 11 | data-ng-class="{ active: currentpage === 'devices' }" | 11 | data-ng-class="{ active: currentpage === 'devices' }" |
318 | 12 | data-ng-click="toggleTab('devices')">{$ devices.length $} <ng-pluralize count="devices.length" when="{'one': 'Device', 'other': 'Devices'}"></ng-pluralize> | 12 | data-ng-click="toggleTab('devices')">{$ devices.length $} <ng-pluralize count="devices.length" when="{'one': 'Device', 'other': 'Devices'}"></ng-pluralize> |
319 | 13 | </a> | 13 | </a> |
322 | 14 | <span class="divide"></span> | 14 | <span data-ng-show="isSuperUser()" class="divide"></span> |
323 | 15 | <a href="" | 15 | <a href="" data-ng-show="isSuperUser()" |
324 | 16 | data-ng-class="{ active: currentpage === 'controllers' }" | 16 | data-ng-class="{ active: currentpage === 'controllers' }" |
325 | 17 | data-ng-click="toggleTab('controllers')">{$ controllers.length $} <ng-pluralize count="controllers.length" when="{'one': 'Controller', 'other': 'Controllers'}"></ng-pluralize> | 17 | data-ng-click="toggleTab('controllers')">{$ controllers.length $} <ng-pluralize count="controllers.length" when="{'one': 'Controller', 'other': 'Controllers'}"></ng-pluralize> |
326 | 18 | </a> | 18 | </a> |
327 | 19 | 19 | ||
328 | === modified file 'src/maasserver/websockets/handlers/tests/test_controller.py' | |||
329 | --- src/maasserver/websockets/handlers/tests/test_controller.py 2016-04-22 16:25:08 +0000 | |||
330 | +++ src/maasserver/websockets/handlers/tests/test_controller.py 2016-05-16 16:20:02 +0000 | |||
331 | @@ -21,7 +21,7 @@ | |||
332 | 21 | factory.make_RackController() | 21 | factory.make_RackController() |
333 | 22 | 22 | ||
334 | 23 | def test_last_image_sync(self): | 23 | def test_last_image_sync(self): |
336 | 24 | owner = factory.make_User() | 24 | owner = factory.make_admin() |
337 | 25 | handler = ControllerHandler(owner, {}) | 25 | handler = ControllerHandler(owner, {}) |
338 | 26 | node = factory.make_RackController(owner=owner) | 26 | node = factory.make_RackController(owner=owner) |
339 | 27 | result = handler.list({}) | 27 | result = handler.list({}) |
340 | @@ -34,7 +34,7 @@ | |||
341 | 34 | node.last_image_sync)) | 34 | node.last_image_sync)) |
342 | 35 | 35 | ||
343 | 36 | def test_last_image_sync_returns_none_for_none(self): | 36 | def test_last_image_sync_returns_none_for_none(self): |
345 | 37 | owner = factory.make_User() | 37 | owner = factory.make_admin() |
346 | 38 | handler = ControllerHandler(owner, {}) | 38 | handler = ControllerHandler(owner, {}) |
347 | 39 | node = factory.make_RackController(owner=owner, last_image_sync=None) | 39 | node = factory.make_RackController(owner=owner, last_image_sync=None) |
348 | 40 | result = handler.list({}) | 40 | result = handler.list({}) |
349 | @@ -45,7 +45,7 @@ | |||
350 | 45 | self.assertIsNone(data.get("last_image_sync")) | 45 | self.assertIsNone(data.get("last_image_sync")) |
351 | 46 | 46 | ||
352 | 47 | def test_list_ignores_devices_and_nodes(self): | 47 | def test_list_ignores_devices_and_nodes(self): |
354 | 48 | owner = factory.make_User() | 48 | owner = factory.make_admin() |
355 | 49 | handler = ControllerHandler(owner, {}) | 49 | handler = ControllerHandler(owner, {}) |
356 | 50 | # Create a device. | 50 | # Create a device. |
357 | 51 | factory.make_Node(owner=owner, node_type=NODE_TYPE.DEVICE) | 51 | factory.make_Node(owner=owner, node_type=NODE_TYPE.DEVICE) |
Looks good, except that isSuperUser needs a simple test.