Преглед изворни кода

refactoring UserRoleinWorkspaceModel

Guénaël Muller пре 6 година
родитељ
комит
0fd5ceaee6

+ 4 - 0
tracim/exceptions.py Прегледај датотеку

@@ -143,3 +143,7 @@ class EmptyLabelNotAllowed(EmptyValueNotAllowed):
143 143
 
144 144
 class EmptyRawContentNotAllowed(EmptyValueNotAllowed):
145 145
     pass
146
+
147
+
148
+class RoleDoesNotExist(TracimException):
149
+    pass

+ 78 - 64
tracim/lib/core/userworkspace.py Прегледај датотеку

@@ -11,36 +11,49 @@ from sqlalchemy.orm import Query
11 11
 from tracim.models.auth import User
12 12
 from tracim.models.data import Workspace
13 13
 from tracim.models.data import UserRoleInWorkspace
14
-from tracim.models.data import RoleType
15 14
 
16 15
 
17 16
 class RoleApi(object):
18 17
 
19
-    ALL_ROLE_VALUES = UserRoleInWorkspace.get_all_role_values()
18
+    # TODO - G.M - 29-06-2018 - [Cleanup] Drop this
19
+    # ALL_ROLE_VALUES = UserRoleInWorkspace.get_all_role_values()
20 20
     # Dict containing readable members roles for given role
21
-    members_read_rights = {
22
-        UserRoleInWorkspace.NOT_APPLICABLE: [],
23
-        UserRoleInWorkspace.READER: [
24
-            UserRoleInWorkspace.WORKSPACE_MANAGER,
25
-        ],
26
-        UserRoleInWorkspace.CONTRIBUTOR: [
27
-            UserRoleInWorkspace.WORKSPACE_MANAGER,
28
-            UserRoleInWorkspace.CONTENT_MANAGER,
29
-            UserRoleInWorkspace.CONTRIBUTOR,
30
-        ],
31
-        UserRoleInWorkspace.CONTENT_MANAGER: [
32
-            UserRoleInWorkspace.WORKSPACE_MANAGER,
33
-            UserRoleInWorkspace.CONTENT_MANAGER,
34
-            UserRoleInWorkspace.CONTRIBUTOR,
35
-            UserRoleInWorkspace.READER,
36
-        ],
37
-        UserRoleInWorkspace.WORKSPACE_MANAGER: [
38
-            UserRoleInWorkspace.WORKSPACE_MANAGER,
39
-            UserRoleInWorkspace.CONTENT_MANAGER,
40
-            UserRoleInWorkspace.CONTRIBUTOR,
41
-            UserRoleInWorkspace.READER,
42
-        ],
43
-    }
21
+    # members_read_rights = {
22
+    #     UserRoleInWorkspace.NOT_APPLICABLE: [],
23
+    #     UserRoleInWorkspace.READER: [
24
+    #         UserRoleInWorkspace.WORKSPACE_MANAGER,
25
+    #     ],
26
+    #     UserRoleInWorkspace.CONTRIBUTOR: [
27
+    #         UserRoleInWorkspace.WORKSPACE_MANAGER,
28
+    #         UserRoleInWorkspace.CONTENT_MANAGER,
29
+    #         UserRoleInWorkspace.CONTRIBUTOR,
30
+    #     ],
31
+    #     UserRoleInWorkspace.CONTENT_MANAGER: [
32
+    #         UserRoleInWorkspace.WORKSPACE_MANAGER,
33
+    #         UserRoleInWorkspace.CONTENT_MANAGER,
34
+    #         UserRoleInWorkspace.CONTRIBUTOR,
35
+    #         UserRoleInWorkspace.READER,
36
+    #     ],
37
+    #     UserRoleInWorkspace.WORKSPACE_MANAGER: [
38
+    #         UserRoleInWorkspace.WORKSPACE_MANAGER,
39
+    #         UserRoleInWorkspace.CONTENT_MANAGER,
40
+    #         UserRoleInWorkspace.CONTRIBUTOR,
41
+    #         UserRoleInWorkspace.READER,
42
+    #     ],
43
+    # }
44
+
45
+    # TODO - G.M - 29-06-2018 - [Cleanup] Drop this
46
+    # @classmethod
47
+    # def role_can_read_member_role(cls, reader_role: int, tested_role: int) \
48
+    #         -> bool:
49
+    #     """
50
+    #     :param reader_role: role as viewer
51
+    #     :param tested_role: role as viwed
52
+    #     :return: True if given role can view member role in workspace.
53
+    #     """
54
+    #     if reader_role in cls.members_read_rights:
55
+    #         return tested_role in cls.members_read_rights[reader_role]
56
+    #     return False
44 57
 
45 58
     def get_user_role_workspace_with_context(
46 59
             self,
@@ -58,18 +71,6 @@ class RoleApi(object):
58 71
         return workspace
59 72
 
60 73
     @classmethod
61
-    def role_can_read_member_role(cls, reader_role: int, tested_role: int) \
62
-            -> bool:
63
-        """
64
-        :param reader_role: role as viewer
65
-        :param tested_role: role as viwed
66
-        :return: True if given role can view member role in workspace.
67
-        """
68
-        if reader_role in cls.members_read_rights:
69
-            return tested_role in cls.members_read_rights[reader_role]
70
-        return False
71
-
72
-    @classmethod
73 74
     def create_role(cls) -> UserRoleInWorkspace:
74 75
         role = UserRoleInWorkspace()
75 76
 
@@ -120,20 +121,6 @@ class RoleApi(object):
120 121
         if flush:
121 122
             self._session.flush()
122 123
 
123
-    def _get_all_for_user(self, user_id) -> typing.List[UserRoleInWorkspace]:
124
-        return self._session.query(UserRoleInWorkspace)\
125
-            .filter(UserRoleInWorkspace.user_id == user_id)
126
-
127
-    def get_all_for_user(self, user: User) -> typing.List[UserRoleInWorkspace]:
128
-        return self._get_all_for_user(user.user_id).all()
129
-
130
-    def get_all_for_user_order_by_workspace(
131
-        self,
132
-        user_id: int
133
-    ) -> typing.List[UserRoleInWorkspace]:
134
-        return self._get_all_for_user(user_id)\
135
-            .join(UserRoleInWorkspace.workspace).order_by(Workspace.label).all()
136
-
137 124
     def get_all_for_workspace(
138 125
         self,
139 126
         workspace:Workspace
@@ -145,18 +132,45 @@ class RoleApi(object):
145 132
     def save(self, role: UserRoleInWorkspace) -> None:
146 133
         self._session.flush()
147 134
 
148
-    # TODO - G.M - 07-06-2018 - [Cleanup] Check if this method is already needed
149
-    @classmethod
150
-    def get_roles_for_select_field(cls) -> typing.List[RoleType]:
151
-        """
152
-
153
-        :return: list of DictLikeClass instances representing available Roles
154
-        (to be used in select fields)
155
-        """
156
-        result = list()
157 135
 
158
-        for role_id in UserRoleInWorkspace.get_all_role_values():
159
-            role = RoleType(role_id)
160
-            result.append(role)
136
+    # TODO - G.M - 29-06-2018 - [Cleanup] Drop this
137
+    # @classmethod
138
+    # def role_can_read_member_role(cls, reader_role: int, tested_role: int) \
139
+    #         -> bool:
140
+    #     """
141
+    #     :param reader_role: role as viewer
142
+    #     :param tested_role: role as viwed
143
+    #     :return: True if given role can view member role in workspace.
144
+    #     """
145
+    #     if reader_role in cls.members_read_rights:
146
+    #         return tested_role in cls.members_read_rights[reader_role]
147
+    #     return False
148
+    # def _get_all_for_user(self, user_id) -> typing.List[UserRoleInWorkspace]:
149
+    #     return self._session.query(UserRoleInWorkspace)\
150
+    #         .filter(UserRoleInWorkspace.user_id == user_id)
151
+    #
152
+    # def get_all_for_user(self, user: User) -> typing.List[UserRoleInWorkspace]:
153
+    #     return self._get_all_for_user(user.user_id).all()
154
+    #
155
+    # def get_all_for_user_order_by_workspace(
156
+    #     self,
157
+    #     user_id: int
158
+    # ) -> typing.List[UserRoleInWorkspace]:
159
+    #     return self._get_all_for_user(user_id)\
160
+    #         .join(UserRoleInWorkspace.workspace).order_by(Workspace.label).all()
161 161
 
162
-        return result
162
+    # TODO - G.M - 07-06-2018 - [Cleanup] Check if this method is already needed
163
+    # @classmethod
164
+    # def get_roles_for_select_field(cls) -> typing.List[RoleType]:
165
+    #     """
166
+    #
167
+    #     :return: list of DictLikeClass instances representing available Roles
168
+    #     (to be used in select fields)
169
+    #     """
170
+    #     result = list()
171
+    #
172
+    #     for role_id in UserRoleInWorkspace.get_all_role_values():
173
+    #         role = RoleType(role_id)
174
+    #         result.append(role)
175
+    #
176
+    #     return result

+ 2 - 1
tracim/models/context_models.py Прегледај датотеку

@@ -10,6 +10,7 @@ from tracim.models.auth import Profile
10 10
 from tracim.models.data import Content
11 11
 from tracim.models.data import ContentRevisionRO
12 12
 from tracim.models.data import Workspace, UserRoleInWorkspace
13
+from tracim.models.roles import WorkspaceRoles
13 14
 from tracim.models.workspace_menu_entries import default_workspace_menu_entry
14 15
 from tracim.models.workspace_menu_entries import WorkspaceMenuEntry
15 16
 from tracim.models.contents import ContentTypeLegacy as ContentType
@@ -295,7 +296,7 @@ class UserRoleWorkspaceInContext(object):
295 296
         'contributor', 'content-manager', 'workspace-manager'
296 297
         :return: user workspace role as slug.
297 298
         """
298
-        return UserRoleInWorkspace.SLUG[self.user_role.role]
299
+        return WorkspaceRoles.get_role_from_level(self.user_role.role).slug
299 300
 
300 301
     @property
301 302
     def user(self) -> UserInContext:

+ 31 - 32
tracim/models/data.py Прегледај датотеку

@@ -30,6 +30,7 @@ from tracim.lib.utils.translation import get_locale
30 30
 from tracim.exceptions import ContentRevisionUpdateError
31 31
 from tracim.models.meta import DeclarativeBase
32 32
 from tracim.models.auth import User
33
+from tracim.models.roles import WorkspaceRoles
33 34
 
34 35
 DEFAULT_PROPERTIES = dict(
35 36
     allowed_content=dict(
@@ -124,26 +125,27 @@ class UserRoleInWorkspace(DeclarativeBase):
124 125
     workspace = relationship('Workspace', remote_side=[Workspace.workspace_id], backref='roles', lazy='joined')
125 126
     user = relationship('User', remote_side=[User.user_id], backref='roles')
126 127
 
127
-    NOT_APPLICABLE = 0
128
-    READER = 1
129
-    CONTRIBUTOR = 2
130
-    CONTENT_MANAGER = 4
131
-    WORKSPACE_MANAGER = 8
132
-
133
-    SLUG = {
134
-        NOT_APPLICABLE: 'not-applicable',
135
-        READER: 'reader',
136
-        CONTRIBUTOR: 'contributor',
137
-        CONTENT_MANAGER: 'content-manager',
138
-        WORKSPACE_MANAGER: 'workspace-manager',
139
-    }
128
+    NOT_APPLICABLE = WorkspaceRoles.NOT_APPLICABLE.level
129
+    READER = WorkspaceRoles.READER.level
130
+    CONTRIBUTOR = WorkspaceRoles.CONTRIBUTOR.level
131
+    CONTENT_MANAGER = WorkspaceRoles.CONTENT_MANAGER.level
132
+    WORKSPACE_MANAGER = WorkspaceRoles.WORKSPACE_MANAGER.level
133
+
134
+    # TODO - G.M - 10-04-2018 - [Cleanup] Drop this
135
+    # SLUG = {
136
+    #     NOT_APPLICABLE: 'not-applicable',
137
+    #     READER: 'reader',
138
+    #     CONTRIBUTOR: 'contributor',
139
+    #     CONTENT_MANAGER: 'content-manager',
140
+    #     WORKSPACE_MANAGER: 'workspace-manager',
141
+    # }
140 142
 
141
-    LABEL = dict()
142
-    LABEL[0] = l_('N/A')
143
-    LABEL[1] = l_('Reader')
144
-    LABEL[2] = l_('Contributor')
145
-    LABEL[4] = l_('Content Manager')
146
-    LABEL[8] = l_('Workspace Manager')
143
+    # LABEL = dict()
144
+    # LABEL[0] = l_('N/A')
145
+    # LABEL[1] = l_('Reader')
146
+    # LABEL[2] = l_('Contributor')
147
+    # LABEL[4] = l_('Content Manager')
148
+    # LABEL[8] = l_('Workspace Manager')
147 149
     # TODO - G.M - 10-04-2018 - [Cleanup] Drop this
148 150
     #
149 151
     # STYLE = dict()
@@ -170,20 +172,18 @@ class UserRoleInWorkspace(DeclarativeBase):
170 172
     #     return UserRoleInWorkspace.STYLE[self.role]
171 173
     #
172 174
 
175
+    def role_object(self):
176
+        return WorkspaceRoles.get_role_from_level(level=self.role)
177
+
173 178
     def role_as_label(self):
174
-        return UserRoleInWorkspace.LABEL[self.role]
179
+        return self.role_object().label
175 180
 
176 181
     @classmethod
177 182
     def get_all_role_values(cls) -> typing.List[int]:
178 183
         """
179 184
         Return all valid role value
180 185
         """
181
-        return [
182
-            UserRoleInWorkspace.READER,
183
-            UserRoleInWorkspace.CONTRIBUTOR,
184
-            UserRoleInWorkspace.CONTENT_MANAGER,
185
-            UserRoleInWorkspace.WORKSPACE_MANAGER
186
-        ]
186
+        return [role.level for role in WorkspaceRoles.get_all_valid_role()]
187 187
 
188 188
     @classmethod
189 189
     def get_all_role_slug(cls) -> typing.List[str]:
@@ -193,13 +193,12 @@ class UserRoleInWorkspace(DeclarativeBase):
193 193
         # INFO - G.M - 25-05-2018 - Be carefull, as long as this method
194 194
         # and get_all_role_values are both used for API, this method should
195 195
         # return item in the same order as get_all_role_values
196
-        return [cls.SLUG[value] for value in cls.get_all_role_values()]
197
-
196
+        return [role.slug for role in WorkspaceRoles.get_all_valid_role()]
198 197
 
199
-class RoleType(object):
200
-    def __init__(self, role_id):
201
-        self.role_type_id = role_id
202
-        # TODO - G.M - 10-04-2018 - [Cleanup] Drop this
198
+# TODO - G.M - 10-04-2018 - [Cleanup] Drop this
199
+# class RoleType(object):
200
+#     def __init__(self, role_id):
201
+#         self.role_type_id = role_id
203 202
         # self.fa_icon = UserRoleInWorkspace.ICON[role_id]
204 203
         # self.role_label = UserRoleInWorkspace.LABEL[role_id]
205 204
         # self.css_style = UserRoleInWorkspace.STYLE[role_id]

+ 61 - 0
tracim/models/roles.py Прегледај датотеку

@@ -0,0 +1,61 @@
1
+import typing
2
+from enum import Enum
3
+
4
+from tracim.exceptions import RoleDoesNotExist
5
+
6
+
7
+class WorkspaceRoles(Enum):
8
+    """
9
+    Available role for workspace.
10
+    All roles should have a unique level and unique slug.
11
+    level is role value store in database and is also use for
12
+    permission check.
13
+    slug is for http endpoints and other place where readability is
14
+    needed.
15
+    """
16
+    NOT_APPLICABLE = (0, 'not-applicable')
17
+    READER = (1, 'reader')
18
+    CONTRIBUTOR = (2, 'contributor')
19
+    CONTENT_MANAGER = (4, 'content-manager')
20
+    WORKSPACE_MANAGER = (8, 'workspace-manager')
21
+
22
+    def __init__(self, level, slug):
23
+        self.level = level
24
+        self.slug = slug
25
+    
26
+    @property
27
+    def label(self):
28
+        """ Return valid label associated to role"""
29
+        # TODO - G.M - 2018-06-180 - Make this work correctly
30
+        return self.slug
31
+    
32
+    @classmethod
33
+    def get_all_valid_role(cls) -> typing.List['WorkspaceRoles']:
34
+        """
35
+        Return all valid role value
36
+        """
37
+        return [item for item in list(WorkspaceRoles) if item.level > 0]
38
+
39
+    @classmethod
40
+    def get_role_from_level(cls, level: int) -> 'WorkspaceRoles':
41
+        """
42
+        Obtain Workspace role from a level value
43
+        :param level: level value as int
44
+        :return: correct workspace role related
45
+        """
46
+        roles = [item for item in list(WorkspaceRoles) if item.level == level]
47
+        if len(roles) != 1:
48
+            raise RoleDoesNotExist()
49
+        return roles[0]
50
+
51
+    @classmethod
52
+    def get_role_from_slug(cls, slug: str) -> 'WorkspaceRoles':
53
+        """
54
+        Obtain Workspace role from a slug value
55
+        :param slug: slug value as str
56
+        :return: correct workspace role related
57
+        """
58
+        roles = [item for item in list(WorkspaceRoles) if item.slug == slug]
59
+        if len(roles) != 1:
60
+            raise RoleDoesNotExist()
61
+        return roles[0]

+ 80 - 0
tracim/tests/models/tests_roles.py Прегледај датотеку

@@ -0,0 +1,80 @@
1
+# coding=utf-8
2
+import unittest
3
+import pytest
4
+from tracim.exceptions import RoleDoesNotExist
5
+from tracim.models.roles import WorkspaceRoles
6
+
7
+
8
+class TestWorkspacesRoles(unittest.TestCase):
9
+    """
10
+    Test for WorkspaceRoles Enum Object
11
+    """
12
+    def test_workspace_roles__ok__all_list(self):
13
+        roles = list(WorkspaceRoles)
14
+        assert len(roles) == 5
15
+        for role in roles:
16
+            assert role
17
+            assert role.slug
18
+            assert isinstance(role.slug, str)
19
+            assert role.level or role.level == 0
20
+            assert isinstance(role.level, int)
21
+            assert role.label
22
+            assert isinstance(role.slug, str)
23
+        assert WorkspaceRoles['READER']
24
+        assert WorkspaceRoles['NOT_APPLICABLE']
25
+        assert WorkspaceRoles['CONTRIBUTOR']
26
+        assert WorkspaceRoles['WORKSPACE_MANAGER']
27
+        assert WorkspaceRoles['CONTENT_MANAGER']
28
+
29
+    def test__workspace_roles__ok__check_model(self):
30
+        role = WorkspaceRoles.WORKSPACE_MANAGER
31
+        assert role
32
+        assert role.slug
33
+        assert isinstance(role.slug, str)
34
+        assert role.level
35
+        assert isinstance(role.level, int)
36
+        assert role.label
37
+        assert isinstance(role.slug, str)
38
+
39
+    def test_workspace_roles__ok__get_all_valid_roles(self):
40
+        roles = WorkspaceRoles.get_all_valid_role()
41
+        assert len(roles) == 4
42
+        for role in roles:
43
+            assert role
44
+            assert role.slug
45
+            assert isinstance(role.slug, str)
46
+            assert role.level or role.level == 0
47
+            assert isinstance(role.level, int)
48
+            assert role.level > 0
49
+            assert role.label
50
+            assert isinstance(role.slug, str)
51
+
52
+    def test_workspace_roles__ok__get_role__from_level__ok__nominal_case(self):
53
+        role = WorkspaceRoles.get_role_from_level(0)
54
+
55
+        assert role
56
+        assert role.slug
57
+        assert isinstance(role.slug, str)
58
+        assert role.level == 0
59
+        assert isinstance(role.level, int)
60
+        assert role.label
61
+        assert isinstance(role.slug, str)
62
+
63
+    def test_workspace_roles__ok__get_role__from_slug__ok__nominal_case(self):
64
+        role = WorkspaceRoles.get_role_from_slug('reader')
65
+
66
+        assert role
67
+        assert role.slug
68
+        assert isinstance(role.slug, str)
69
+        assert role.level > 0
70
+        assert isinstance(role.level, int)
71
+        assert role.label
72
+        assert isinstance(role.slug, str)
73
+
74
+    def test_workspace_roles__ok__get_role__from_level__err__role_does_not_exist(self):  # nopep8
75
+        with pytest.raises(RoleDoesNotExist):
76
+            WorkspaceRoles.get_role_from_level(-1000)
77
+
78
+    def test_workspace_roles__ok__get_role__from_slug__err__role_does_not_exist(self):  # nopep8
79
+        with pytest.raises(RoleDoesNotExist):
80
+            WorkspaceRoles.get_role_from_slug('this slug does not exist')