~salgado/offspring/project-ssh-key-ui

« back to all changes in this revision

Viewing changes to lib/offspring/web/queuemanager/tests/test_models.py

  • Committer: Guilherme Salgado
  • Date: 2011-12-01 15:18:34 UTC
  • mfrom: (13.7.21 private-projects)
  • Revision ID: salgado@canonical.com-20111201151834-wash33tjqz5vfuw6
Add support for private objects to web.queuemanger, with a custom API for querying only the objects a given user is allowed to see and helper methods to check if a given object is visible to a given user

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from operator import attrgetter
 
2
 
 
3
from django.contrib.auth.models import AnonymousUser
 
4
from django.test import TestCase
 
5
 
 
6
from offspring.web.queuemanager.models import (
 
7
    BuildRequest,
 
8
    BuildResult,
 
9
    Lexbuilder,
 
10
    Project,
 
11
    Release)
 
12
from offspring.web.queuemanager.tests.factory import factory
 
13
 
 
14
 
 
15
class ProjectTests(TestCase):
 
16
 
 
17
    def test_default_manager(self):
 
18
        """
 
19
        Make sure .all_objects is the default manager.
 
20
        
 
21
        If that's not the case the admin UI will exclude all private objects
 
22
        and we would break model validation of unique fields if the user
 
23
        reuses a value from an object they're not allowed to see.
 
24
        """
 
25
        self.assertEquals(Project.all_objects, Project._default_manager)
 
26
 
 
27
    def test_is_private_for_public_project(self):
 
28
        """
 
29
        Check that Project.is_private returns False for public projects.
 
30
        """
 
31
        project = factory.make_project(is_private=False)
 
32
        self.assertEqual(False, project.is_private)
 
33
 
 
34
    def test_is_private_for_private_project(self):
 
35
        """
 
36
        Check that Project.is_private returns True for private projects.
 
37
        """
 
38
        private_project = factory.make_project(is_private=True)
 
39
        self.assertEqual(True, private_project.is_private)
 
40
 
 
41
    def test_is_visible_to_anyone_if_public(self):
 
42
        """
 
43
        Check that public projects are visible to anyone.
 
44
        """
 
45
        project = factory.make_project(is_private=False)
 
46
        self.assertTrue(project.is_visible_to(AnonymousUser()))
 
47
 
 
48
    def test_is_not_visible_to_anyone_if_private(self):
 
49
        """
 
50
        Check that private projects are not visible to anonymous users.
 
51
        """
 
52
        project = factory.make_project(is_private=True)
 
53
        self.assertFalse(project.is_visible_to(AnonymousUser()))
 
54
 
 
55
    def test_is_visible_to_owner_if_private(self):
 
56
        """
 
57
        Check that private projects are visible to their owners.
 
58
        """
 
59
        project = factory.make_project(is_private=True)
 
60
        self.assertTrue(project.is_visible_to(project.owner))
 
61
 
 
62
    def test_is_visible_to_member_of_access_group_if_private(self):
 
63
        """
 
64
        Check that private projects are visible to members of their access
 
65
        groups.
 
66
        """
 
67
        user = factory.make_user()
 
68
        group = factory.make_access_group([user])
 
69
        project = factory.make_project(is_private=True, access_groups=[group])
 
70
        self.assertTrue(project.is_visible_to(user))
 
71
 
 
72
    def test_dot_objects_model_manager_only_returns_public_projects(self):
 
73
        """
 
74
        Check that the .objects model manager return only public projects.
 
75
        """
 
76
        project = factory.make_project(is_private=False)
 
77
        project2 = factory.make_project(is_private=True)
 
78
        self.assertEqual([project], list(Project.objects.all()))
 
79
 
 
80
    def test_all_objects_model_manager(self):
 
81
        """
 
82
        Check that Project.all_objects includes private objects.
 
83
 
 
84
        Project.all_objects() is a separate model manager which returns
 
85
        private objects as well. Its .all() method will return public and
 
86
        private objects regardless of whether or not the current user has
 
87
        access to them. It is to be used with caution.
 
88
        """
 
89
        project = factory.make_project(is_private=False)
 
90
        project2 = factory.make_project(is_private=True)
 
91
        self.assertEqual([project, project2], list(Project.all_objects.all()))
 
92
 
 
93
    def test_accessible_by_user_with_anonymous_user(self):
 
94
        """
 
95
        Check that accessible_by_user() can be given an anonymous user as
 
96
        argument.
 
97
        """
 
98
        project = factory.make_project(is_private=True)
 
99
        project2 = factory.make_project(is_private=False)
 
100
        self.assertEqual(True, project.is_private)
 
101
        self.assertEqual(False, project2.is_private)
 
102
        objects = Project.all_objects.accessible_by_user(AnonymousUser())
 
103
        self.assertEqual([project2], list(objects))
 
104
 
 
105
    def test_accessible_by_user_with_public_project(self):
 
106
        """
 
107
        Check that accessible_by_user() returns public projects regardless of
 
108
        the given user.
 
109
        """
 
110
        user = factory.make_user()
 
111
        project = factory.make_project(is_private=False)
 
112
        self.assertEqual(False, project.is_private)
 
113
        objects = Project.all_objects.accessible_by_user(user)
 
114
        self.assertEqual([project], list(objects))
 
115
 
 
116
    def test_accessible_by_user_with_private_project(self):
 
117
        """
 
118
        Check that accessible_by_user() returns only the private projects the
 
119
        given user is allowed to see.
 
120
        """
 
121
        user = factory.make_user()
 
122
        group = factory.make_access_group([user])
 
123
        project = factory.make_project(is_private=True, access_groups=[group])
 
124
        # This second project is private but has no access groups set up, so
 
125
        # the user cannot see it.
 
126
        project2 = factory.make_project(is_private=True)
 
127
        self.assertEqual(True, project.is_private)
 
128
        self.assertEqual(True, project2.is_private)
 
129
        objects = Project.all_objects.accessible_by_user(user)
 
130
        self.assertEqual([project], list(objects))
 
131
 
 
132
 
 
133
class ReleaseOrLexbuilderOrBuildResultOrBuildRequestTestsMixin(object):
 
134
    """A mixin with tests that work for the following models:
 
135
 
 
136
        Release
 
137
        Lexbuilder
 
138
        BuildResult
 
139
        BuildRequest
 
140
 
 
141
    You just need to mix this with TestCase in your subclass and define
 
142
    factoryMethod and model.
 
143
    """
 
144
    model = None
 
145
 
 
146
    def factoryMethod(self, project):
 
147
        raise NotImplementedError()
 
148
 
 
149
    def test_default_manager(self):
 
150
        """
 
151
        Make sure .all_objects is the default manager.
 
152
        
 
153
        If that's not the case the admin UI will exclude all private objects
 
154
        and we would break model validation of unique fields if the user
 
155
        reuses a value from an object they're not allowed to see.
 
156
        """
 
157
        self.assertEquals(self.model.all_objects, self.model._default_manager)
 
158
 
 
159
    def test_is_private_for_public_object(self):
 
160
        """
 
161
        Check that .is_private returns False for public objects.
 
162
        """
 
163
        public_object = self.factoryMethod(
 
164
            factory.make_project(is_private=False))
 
165
        self.assertFalse(public_object.is_private)
 
166
 
 
167
    def test_is_private_for_private_object(self):
 
168
        """
 
169
        Check that .is_private returns True for private objects.
 
170
        """
 
171
        private_object = self.factoryMethod(
 
172
            factory.make_project(is_private=True))
 
173
        self.assertTrue(private_object.is_private)
 
174
 
 
175
    def test_is_visible_to_anyone_if_public(self):
 
176
        """
 
177
        Check that public objects are visible to anyone.
 
178
        """
 
179
        public_object = self.factoryMethod(
 
180
            factory.make_project(is_private=False))
 
181
        self.assertTrue(public_object.is_visible_to(AnonymousUser()))
 
182
 
 
183
    def test_is_not_visible_to_anyone_if_private(self):
 
184
        """
 
185
        Check that private objects are not visible to anonymous users.
 
186
        """
 
187
        private_object = self.factoryMethod(
 
188
            factory.make_project(is_private=True))
 
189
        self.assertFalse(private_object.is_visible_to(AnonymousUser()))
 
190
 
 
191
    def test_is_visible_to_owner_if_private(self):
 
192
        """
 
193
        Check that private objects are visible to their project's owners.
 
194
        """
 
195
        # The object we're dealing with inherits the access-control rules from
 
196
        # the project it's related to, so the owner that matters is the
 
197
        # project owner.
 
198
        owner = factory.make_user()
 
199
        private_object = self.factoryMethod(
 
200
            factory.make_project(is_private=True, owner=owner))
 
201
        self.assertTrue(private_object.is_visible_to(owner))
 
202
 
 
203
    def test_is_visible_to_member_of_access_group_if_private(self):
 
204
        """
 
205
        Check that private objects are visible to members of their project's
 
206
        access groups.
 
207
        """
 
208
        user = factory.make_user()
 
209
        group = factory.make_access_group([user])
 
210
        private_object = self.factoryMethod(
 
211
            factory.make_project(is_private=True, access_groups=[group]))
 
212
        self.assertTrue(private_object.is_visible_to(user))
 
213
 
 
214
    def test_dot_objects_model_manager_only_returns_public_objects(self):
 
215
        """
 
216
        Check that the .objects model manager return only public objects.
 
217
        """
 
218
        private_object = self.factoryMethod(
 
219
            factory.make_project(is_private=True))
 
220
        public_object = self.factoryMethod(
 
221
            factory.make_project(is_private=False))
 
222
        self.assertEqual([public_object], list(self.model.objects.all()))
 
223
 
 
224
    def test_all_objects_model_manager(self):
 
225
        """
 
226
        Check that .all_objects includes private objects.
 
227
 
 
228
        self.model.all_objects() is a separate model manager which returns
 
229
        private objects as well. Its .all() method will return public and
 
230
        private objects regardless of whether or not the current user has
 
231
        access to them. It is to be used with caution.
 
232
        """
 
233
        public_object = self.factoryMethod(
 
234
            project=factory.make_project(is_private=False))
 
235
        private_object = self.factoryMethod(
 
236
            project=factory.make_project(is_private=True))
 
237
        self.assertEqual([public_object, private_object],
 
238
                         list(self.model.all_objects.all()))
 
239
 
 
240
    def test_accessible_by_user(self):
 
241
        """
 
242
        Check that accessible_by_user() returns only the private objects the
 
243
        user is allowed to see.
 
244
        """
 
245
        user = factory.make_user()
 
246
        group = factory.make_access_group([user])
 
247
        visible_object = self.factoryMethod(
 
248
            factory.make_project(is_private=True, access_groups=[group]))
 
249
        # This object is linked to a private project which has no access
 
250
        # groups set up, so the user cannot see it.
 
251
        invisible_object = self.factoryMethod(
 
252
            project=factory.make_project(is_private=True))
 
253
        self.assertEqual(
 
254
            [visible_object],
 
255
            list(self.model.all_objects.accessible_by_user(user)))
 
256
 
 
257
 
 
258
class ReleaseTests(
 
259
    TestCase, ReleaseOrLexbuilderOrBuildResultOrBuildRequestTestsMixin):
 
260
    model = Release
 
261
 
 
262
    def factoryMethod(self, project):
 
263
        return factory.make_release(
 
264
            build=factory.make_build_result(project=project))
 
265
 
 
266
 
 
267
class LexbuilderTests(
 
268
        TestCase, ReleaseOrLexbuilderOrBuildResultOrBuildRequestTestsMixin):
 
269
    model = Lexbuilder
 
270
 
 
271
    def factoryMethod(self, project):
 
272
        return factory.make_lexbuilder(
 
273
            current_job=factory.make_build_result(project=project))
 
274
 
 
275
 
 
276
class BuildResultTests(
 
277
        TestCase, ReleaseOrLexbuilderOrBuildResultOrBuildRequestTestsMixin):
 
278
    model = BuildResult
 
279
    factoryMethod = factory.make_build_result
 
280
 
 
281
 
 
282
class BuildRequestTests(
 
283
        TestCase, ReleaseOrLexbuilderOrBuildResultOrBuildRequestTestsMixin):
 
284
    model = BuildRequest
 
285
    factoryMethod = factory.make_build_request
 
286
 
 
287
 
 
288
class ProjectGroupTests(TestCase):
 
289
 
 
290
    def test_get_projects_filters_private_objects(self):
 
291
        """
 
292
        ProjectGroup.get_projects() will return only the private projects the
 
293
        given user is allowed to see.
 
294
        """
 
295
        user = factory.make_user()
 
296
        group = factory.make_project_group()
 
297
        public_project = factory.make_project(
 
298
            is_private=False, project_group=group)
 
299
        private_project_visible_to_user = factory.make_project(
 
300
            is_private=True, project_group=group, owner=user)
 
301
        private_project = factory.make_project(
 
302
            is_private=True, project_group=group)
 
303
        self.assertEqual(
 
304
            sorted([public_project, private_project_visible_to_user],
 
305
                   key=attrgetter('name')),
 
306
            sorted(group.get_projects(user), key=attrgetter('name')))