Browse Source

Test security of ContentApi

Bastien Sevajol (Algoo) 8 years ago
parent
commit
2f10402141

+ 10 - 1
tracim/tracim/lib/content.py View File

@@ -186,12 +186,21 @@ class ContentApi(object):
186 186
         if workspace:
187 187
             result = result.filter(Content.workspace_id==workspace.workspace_id)
188 188
 
189
+        # Security layer: if user provided, filter
190
+        # with user workspaces privileges
189 191
         if self._user and not self._disable_user_workspaces_filter:
190 192
             user = DBSession.query(User).get(self._user_id)
191 193
             # Filter according to user workspaces
192 194
             workspace_ids = [r.workspace_id for r in user.roles \
193 195
                              if r.role>=UserRoleInWorkspace.READER]
194
-            result = result.filter(Content.workspace_id.in_(workspace_ids))
196
+            result = result.filter(or_(
197
+                Content.workspace_id.in_(workspace_ids),
198
+                # And allow access to non workspace document when he is owner
199
+                and_(
200
+                    Content.workspace_id == None,
201
+                    Content.owner_id == self._user_id,
202
+                )
203
+            ))
195 204
 
196 205
         return result
197 206
 

+ 1 - 1
tracim/tracim/lib/user.py View File

@@ -50,7 +50,7 @@ class UserApi(object):
50 50
         if do_save:
51 51
             self.save(user)
52 52
 
53
-        if self._user and user.user_id==self._user.user_id:
53
+        if email and self._user and user.user_id==self._user.user_id:
54 54
             # this is required for the session to keep on being up-to-date
55 55
             tg.request.identity['repoze.who.userid'] = email
56 56
             tg.auth_force_login(email)

+ 46 - 3
tracim/tracim/tests/library/test_content_api.py View File

@@ -2,7 +2,6 @@
2 2
 
3 3
 from nose.tools import eq_, ok_
4 4
 from nose.tools import raises
5
-from tracim.lib.group import GroupApi
6 5
 
7 6
 import transaction
8 7
 
@@ -20,8 +19,9 @@ from tracim.model.data import ActionDescription, ContentRevisionRO, Workspace
20 19
 from tracim.model.data import Content
21 20
 from tracim.model.data import ContentType
22 21
 from tracim.model.data import UserRoleInWorkspace
23
-
24
-from tracim.tests import TestStandard, BaseTest
22
+from tracim.fixtures.users_and_groups import Test as TestFixture
23
+from tracim.tests import TestStandard
24
+from tracim.tests import BaseTest
25 25
 
26 26
 
27 27
 class TestContentApi(BaseTest, TestStandard):
@@ -788,3 +788,46 @@ class TestContentApi(BaseTest, TestStandard):
788 788
         bar_result = api.search(['bar']).all()
789 789
         api.exclude_unavailable(bar_result)
790 790
         eq_(0, len(bar_result))
791
+
792
+
793
+class TestContentApiSecurity(TestStandard):
794
+    fixtures = [TestFixture, ]
795
+
796
+    def test_unit__cant_get_non_access_content__ok__nominal_case(self):
797
+        admin = DBSession.query(User)\
798
+            .filter(User.email == 'admin@admin.admin').one()
799
+        bob = DBSession.query(User)\
800
+            .filter(User.email == 'bob@fsf.local').one()
801
+
802
+        bob_workspace = WorkspaceApi(bob).create_workspace(
803
+            'bob_workspace',
804
+            save_now=True,
805
+        )
806
+        admin_workspace = WorkspaceApi(admin).create_workspace(
807
+            'admin_workspace',
808
+            save_now=True,
809
+        )
810
+
811
+        bob_page = ContentApi(bob).create(
812
+            content_type=ContentType.Page,
813
+            workspace=bob_workspace,
814
+            label='bob_page',
815
+            do_save=True,
816
+        )
817
+
818
+        admin_page = ContentApi(bob).create(
819
+            content_type=ContentType.Page,
820
+            workspace=admin_workspace,
821
+            label='admin_page',
822
+            do_save=True,
823
+        )
824
+
825
+        bob_viewable = ContentApi(bob).get_all()
826
+        eq_(1, len(bob_viewable), 'Bob should view only one content')
827
+        eq_(
828
+            'bob_page',
829
+            bob_viewable[0].label,
830
+            'Bob should not view "{0}" content'.format(
831
+                bob_viewable[0].label,
832
+            )
833
+        )