Browse Source

refactoring UserRoleinWorkspaceModel

Guénaël Muller 6 years ago
parent
commit
0fd5ceaee6

+ 4 - 0
tracim/exceptions.py View File

143
 
143
 
144
 class EmptyRawContentNotAllowed(EmptyValueNotAllowed):
144
 class EmptyRawContentNotAllowed(EmptyValueNotAllowed):
145
     pass
145
     pass
146
+
147
+
148
+class RoleDoesNotExist(TracimException):
149
+    pass

+ 78 - 64
tracim/lib/core/userworkspace.py View File

11
 from tracim.models.auth import User
11
 from tracim.models.auth import User
12
 from tracim.models.data import Workspace
12
 from tracim.models.data import Workspace
13
 from tracim.models.data import UserRoleInWorkspace
13
 from tracim.models.data import UserRoleInWorkspace
14
-from tracim.models.data import RoleType
15
 
14
 
16
 
15
 
17
 class RoleApi(object):
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
     # Dict containing readable members roles for given role
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
     def get_user_role_workspace_with_context(
58
     def get_user_role_workspace_with_context(
46
             self,
59
             self,
58
         return workspace
71
         return workspace
59
 
72
 
60
     @classmethod
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
     def create_role(cls) -> UserRoleInWorkspace:
74
     def create_role(cls) -> UserRoleInWorkspace:
74
         role = UserRoleInWorkspace()
75
         role = UserRoleInWorkspace()
75
 
76
 
120
         if flush:
121
         if flush:
121
             self._session.flush()
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
     def get_all_for_workspace(
124
     def get_all_for_workspace(
138
         self,
125
         self,
139
         workspace:Workspace
126
         workspace:Workspace
145
     def save(self, role: UserRoleInWorkspace) -> None:
132
     def save(self, role: UserRoleInWorkspace) -> None:
146
         self._session.flush()
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 View File

10
 from tracim.models.data import Content
10
 from tracim.models.data import Content
11
 from tracim.models.data import ContentRevisionRO
11
 from tracim.models.data import ContentRevisionRO
12
 from tracim.models.data import Workspace, UserRoleInWorkspace
12
 from tracim.models.data import Workspace, UserRoleInWorkspace
13
+from tracim.models.roles import WorkspaceRoles
13
 from tracim.models.workspace_menu_entries import default_workspace_menu_entry
14
 from tracim.models.workspace_menu_entries import default_workspace_menu_entry
14
 from tracim.models.workspace_menu_entries import WorkspaceMenuEntry
15
 from tracim.models.workspace_menu_entries import WorkspaceMenuEntry
15
 from tracim.models.contents import ContentTypeLegacy as ContentType
16
 from tracim.models.contents import ContentTypeLegacy as ContentType
295
         'contributor', 'content-manager', 'workspace-manager'
296
         'contributor', 'content-manager', 'workspace-manager'
296
         :return: user workspace role as slug.
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
     @property
301
     @property
301
     def user(self) -> UserInContext:
302
     def user(self) -> UserInContext:

+ 31 - 32
tracim/models/data.py View File

30
 from tracim.exceptions import ContentRevisionUpdateError
30
 from tracim.exceptions import ContentRevisionUpdateError
31
 from tracim.models.meta import DeclarativeBase
31
 from tracim.models.meta import DeclarativeBase
32
 from tracim.models.auth import User
32
 from tracim.models.auth import User
33
+from tracim.models.roles import WorkspaceRoles
33
 
34
 
34
 DEFAULT_PROPERTIES = dict(
35
 DEFAULT_PROPERTIES = dict(
35
     allowed_content=dict(
36
     allowed_content=dict(
124
     workspace = relationship('Workspace', remote_side=[Workspace.workspace_id], backref='roles', lazy='joined')
125
     workspace = relationship('Workspace', remote_side=[Workspace.workspace_id], backref='roles', lazy='joined')
125
     user = relationship('User', remote_side=[User.user_id], backref='roles')
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
     # TODO - G.M - 10-04-2018 - [Cleanup] Drop this
149
     # TODO - G.M - 10-04-2018 - [Cleanup] Drop this
148
     #
150
     #
149
     # STYLE = dict()
151
     # STYLE = dict()
170
     #     return UserRoleInWorkspace.STYLE[self.role]
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
     def role_as_label(self):
178
     def role_as_label(self):
174
-        return UserRoleInWorkspace.LABEL[self.role]
179
+        return self.role_object().label
175
 
180
 
176
     @classmethod
181
     @classmethod
177
     def get_all_role_values(cls) -> typing.List[int]:
182
     def get_all_role_values(cls) -> typing.List[int]:
178
         """
183
         """
179
         Return all valid role value
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
     @classmethod
188
     @classmethod
189
     def get_all_role_slug(cls) -> typing.List[str]:
189
     def get_all_role_slug(cls) -> typing.List[str]:
193
         # INFO - G.M - 25-05-2018 - Be carefull, as long as this method
193
         # INFO - G.M - 25-05-2018 - Be carefull, as long as this method
194
         # and get_all_role_values are both used for API, this method should
194
         # and get_all_role_values are both used for API, this method should
195
         # return item in the same order as get_all_role_values
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
         # self.fa_icon = UserRoleInWorkspace.ICON[role_id]
202
         # self.fa_icon = UserRoleInWorkspace.ICON[role_id]
204
         # self.role_label = UserRoleInWorkspace.LABEL[role_id]
203
         # self.role_label = UserRoleInWorkspace.LABEL[role_id]
205
         # self.css_style = UserRoleInWorkspace.STYLE[role_id]
204
         # self.css_style = UserRoleInWorkspace.STYLE[role_id]

+ 61 - 0
tracim/models/roles.py View File

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 View File

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')