Browse Source

add gets users and gets known users endpoints

Guénaël Muller 6 years ago
parent
commit
8e159eba79

+ 8 - 0
backend/tracim_backend/models/context_models.py View File

@@ -186,6 +186,14 @@ class CommentPath(object):
186 186
         self.comment_id = comment_id
187 187
 
188 188
 
189
+class AutocompleteQuery(object):
190
+    """
191
+    Autocomplete query model
192
+    """
193
+    def __init__(self, acp: str):
194
+        self.acp = acp
195
+
196
+
189 197
 class PageQuery(object):
190 198
     """
191 199
     Page query model

+ 386 - 0
backend/tracim_backend/tests/functional/test_user.py View File

@@ -10,9 +10,11 @@ from tracim_backend import models
10 10
 from tracim_backend.lib.core.content import ContentApi
11 11
 from tracim_backend.lib.core.user import UserApi
12 12
 from tracim_backend.lib.core.group import GroupApi
13
+from tracim_backend.lib.core.userworkspace import RoleApi
13 14
 from tracim_backend.lib.core.workspace import WorkspaceApi
14 15
 from tracim_backend.models import get_tm_session
15 16
 from tracim_backend.models.contents import ContentTypeLegacy as ContentType
17
+from tracim_backend.models.data import UserRoleInWorkspace
16 18
 from tracim_backend.models.revision_protection import new_revision
17 19
 from tracim_backend.tests import FunctionalTest
18 20
 from tracim_backend.fixtures.content import Content as ContentFixtures
@@ -1009,6 +1011,390 @@ class TestUserEndpoint(FunctionalTest):
1009 1011
         )
1010 1012
 
1011 1013
 
1014
+class TestUsersEndpoint(FunctionalTest):
1015
+    # -*- coding: utf-8 -*-
1016
+    """
1017
+    Tests for GET /api/v2/users/{user_id}
1018
+    """
1019
+    fixtures = [BaseFixture]
1020
+
1021
+    def test_api__get_user__ok_200__admin(self):
1022
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1023
+        admin = dbsession.query(models.User) \
1024
+            .filter(models.User.email == 'admin@admin.admin') \
1025
+            .one()
1026
+        uapi = UserApi(
1027
+            current_user=admin,
1028
+            session=dbsession,
1029
+            config=self.app_config,
1030
+        )
1031
+        gapi = GroupApi(
1032
+            current_user=admin,
1033
+            session=dbsession,
1034
+            config=self.app_config,
1035
+        )
1036
+        groups = [gapi.get_one_with_name('users')]
1037
+        test_user = uapi.create_user(
1038
+            email='test@test.test',
1039
+            password='pass',
1040
+            name='bob',
1041
+            groups=groups,
1042
+            timezone='Europe/Paris',
1043
+            do_save=True,
1044
+            do_notify=False,
1045
+        )
1046
+        uapi.save(test_user)
1047
+        transaction.commit()
1048
+        user_id = int(test_user.user_id)
1049
+
1050
+        self.testapp.authorization = (
1051
+            'Basic',
1052
+            (
1053
+                'admin@admin.admin',
1054
+                'admin@admin.admin'
1055
+            )
1056
+        )
1057
+        res = self.testapp.get(
1058
+            '/api/v2/users',
1059
+            status=200
1060
+        )
1061
+        res = res.json_body
1062
+        assert len(res) == 2
1063
+        assert res[0]['user_id'] == admin.user_id
1064
+        assert res[0]['public_name'] == admin.display_name
1065
+        assert res[0]['avatar_url'] is None
1066
+
1067
+        assert res[1]['user_id'] == test_user.user_id
1068
+        assert res[1]['public_name'] == test_user.display_name
1069
+        assert res[1]['avatar_url'] is None
1070
+
1071
+    def test_api__get_user__err_403__normal_user(self):
1072
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1073
+        admin = dbsession.query(models.User) \
1074
+            .filter(models.User.email == 'admin@admin.admin') \
1075
+            .one()
1076
+        uapi = UserApi(
1077
+            current_user=admin,
1078
+            session=dbsession,
1079
+            config=self.app_config,
1080
+        )
1081
+        gapi = GroupApi(
1082
+            current_user=admin,
1083
+            session=dbsession,
1084
+            config=self.app_config,
1085
+        )
1086
+        groups = [gapi.get_one_with_name('users')]
1087
+        test_user = uapi.create_user(
1088
+            email='test@test.test',
1089
+            password='pass',
1090
+            name='bob',
1091
+            groups=groups,
1092
+            timezone='Europe/Paris',
1093
+            do_save=True,
1094
+            do_notify=False,
1095
+        )
1096
+        uapi.save(test_user)
1097
+        transaction.commit()
1098
+        user_id = int(test_user.user_id)
1099
+
1100
+        self.testapp.authorization = (
1101
+            'Basic',
1102
+            (
1103
+                'test@test.test',
1104
+                'pass'
1105
+            )
1106
+        )
1107
+        self.testapp.get(
1108
+            '/api/v2/users',
1109
+            status=403
1110
+        )
1111
+
1112
+
1113
+class TestKnownMembersEndpoint(FunctionalTest):
1114
+    # -*- coding: utf-8 -*-
1115
+    """
1116
+    Tests for GET /api/v2/users/{user_id}
1117
+    """
1118
+    fixtures = [BaseFixture]
1119
+
1120
+    def test_api__get_user__ok_200__admin__by_name(self):
1121
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1122
+        admin = dbsession.query(models.User) \
1123
+            .filter(models.User.email == 'admin@admin.admin') \
1124
+            .one()
1125
+        uapi = UserApi(
1126
+            current_user=admin,
1127
+            session=dbsession,
1128
+            config=self.app_config,
1129
+        )
1130
+        gapi = GroupApi(
1131
+            current_user=admin,
1132
+            session=dbsession,
1133
+            config=self.app_config,
1134
+        )
1135
+        groups = [gapi.get_one_with_name('users')]
1136
+        test_user = uapi.create_user(
1137
+            email='test@test.test',
1138
+            password='pass',
1139
+            name='bob',
1140
+            groups=groups,
1141
+            timezone='Europe/Paris',
1142
+            do_save=True,
1143
+            do_notify=False,
1144
+        )
1145
+        test_user2 = uapi.create_user(
1146
+            email='test2@test2.test2',
1147
+            password='pass',
1148
+            name='bob2',
1149
+            groups=groups,
1150
+            timezone='Europe/Paris',
1151
+            do_save=True,
1152
+            do_notify=False,
1153
+        )
1154
+        uapi.save(test_user)
1155
+        uapi.save(test_user2)
1156
+        transaction.commit()
1157
+        user_id = int(admin.user_id)
1158
+
1159
+        self.testapp.authorization = (
1160
+            'Basic',
1161
+            (
1162
+                'admin@admin.admin',
1163
+                'admin@admin.admin'
1164
+            )
1165
+        )
1166
+        params = {
1167
+            'acp': 'bob',
1168
+        }
1169
+        res = self.testapp.get(
1170
+            '/api/v2/users/{user_id}/known_members'.format(user_id=user_id),
1171
+            status=200,
1172
+            params=params,
1173
+        )
1174
+        res = res.json_body
1175
+        assert len(res) == 2
1176
+        assert res[0]['user_id'] == test_user.user_id
1177
+        assert res[0]['public_name'] == test_user.display_name
1178
+        assert res[0]['avatar_url'] is None
1179
+
1180
+        assert res[1]['user_id'] == test_user2.user_id
1181
+        assert res[1]['public_name'] == test_user2.display_name
1182
+        assert res[1]['avatar_url'] is None
1183
+
1184
+    def test_api__get_user__ok_200__admin__by_email(self):
1185
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1186
+        admin = dbsession.query(models.User) \
1187
+            .filter(models.User.email == 'admin@admin.admin') \
1188
+            .one()
1189
+        uapi = UserApi(
1190
+            current_user=admin,
1191
+            session=dbsession,
1192
+            config=self.app_config,
1193
+        )
1194
+        gapi = GroupApi(
1195
+            current_user=admin,
1196
+            session=dbsession,
1197
+            config=self.app_config,
1198
+        )
1199
+        groups = [gapi.get_one_with_name('users')]
1200
+        test_user = uapi.create_user(
1201
+            email='test@test.test',
1202
+            password='pass',
1203
+            name='bob',
1204
+            groups=groups,
1205
+            timezone='Europe/Paris',
1206
+            do_save=True,
1207
+            do_notify=False,
1208
+        )
1209
+        test_user2 = uapi.create_user(
1210
+            email='test2@test2.test2',
1211
+            password='pass',
1212
+            name='bob2',
1213
+            groups=groups,
1214
+            timezone='Europe/Paris',
1215
+            do_save=True,
1216
+            do_notify=False,
1217
+        )
1218
+        uapi.save(test_user)
1219
+        uapi.save(test_user2)
1220
+        transaction.commit()
1221
+        user_id = int(admin.user_id)
1222
+
1223
+        self.testapp.authorization = (
1224
+            'Basic',
1225
+            (
1226
+                'admin@admin.admin',
1227
+                'admin@admin.admin'
1228
+            )
1229
+        )
1230
+        params = {
1231
+            'acp': 'test',
1232
+        }
1233
+        res = self.testapp.get(
1234
+            '/api/v2/users/{user_id}/known_members'.format(user_id=user_id),
1235
+            status=200,
1236
+            params=params,
1237
+        )
1238
+        res = res.json_body
1239
+        assert len(res) == 2
1240
+        assert res[0]['user_id'] == test_user.user_id
1241
+        assert res[0]['public_name'] == test_user.display_name
1242
+        assert res[0]['avatar_url'] is None
1243
+
1244
+        assert res[1]['user_id'] == test_user2.user_id
1245
+        assert res[1]['public_name'] == test_user2.display_name
1246
+        assert res[1]['avatar_url'] is None
1247
+
1248
+    def test_api__get_user__err_403__admin__too_small_acp(self):
1249
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1250
+        admin = dbsession.query(models.User) \
1251
+            .filter(models.User.email == 'admin@admin.admin') \
1252
+            .one()
1253
+        uapi = UserApi(
1254
+            current_user=admin,
1255
+            session=dbsession,
1256
+            config=self.app_config,
1257
+        )
1258
+        gapi = GroupApi(
1259
+            current_user=admin,
1260
+            session=dbsession,
1261
+            config=self.app_config,
1262
+        )
1263
+        groups = [gapi.get_one_with_name('users')]
1264
+        test_user = uapi.create_user(
1265
+            email='test@test.test',
1266
+            password='pass',
1267
+            name='bob',
1268
+            groups=groups,
1269
+            timezone='Europe/Paris',
1270
+            do_save=True,
1271
+            do_notify=False,
1272
+        )
1273
+        test_user2 = uapi.create_user(
1274
+            email='test2@test2.test2',
1275
+            password='pass',
1276
+            name='bob2',
1277
+            groups=groups,
1278
+            timezone='Europe/Paris',
1279
+            do_save=True,
1280
+            do_notify=False,
1281
+        )
1282
+        uapi.save(test_user)
1283
+        transaction.commit()
1284
+        user_id = int(admin.user_id)
1285
+
1286
+        self.testapp.authorization = (
1287
+            'Basic',
1288
+            (
1289
+                'admin@admin.admin',
1290
+                'admin@admin.admin'
1291
+            )
1292
+        )
1293
+        params = {
1294
+            'acp': 't',
1295
+        }
1296
+        res = self.testapp.get(
1297
+            '/api/v2/users/{user_id}/known_members'.format(user_id=user_id),
1298
+            status=400,
1299
+            params=params
1300
+        )
1301
+
1302
+    def test_api__get_user__ok_200__normal_user_by_email(self):
1303
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
1304
+        admin = dbsession.query(models.User) \
1305
+            .filter(models.User.email == 'admin@admin.admin') \
1306
+            .one()
1307
+        uapi = UserApi(
1308
+            current_user=admin,
1309
+            session=dbsession,
1310
+            config=self.app_config,
1311
+        )
1312
+        gapi = GroupApi(
1313
+            current_user=admin,
1314
+            session=dbsession,
1315
+            config=self.app_config,
1316
+        )
1317
+        groups = [gapi.get_one_with_name('users')]
1318
+        test_user = uapi.create_user(
1319
+            email='test@test.test',
1320
+            password='pass',
1321
+            name='bob',
1322
+            groups=groups,
1323
+            timezone='Europe/Paris',
1324
+            do_save=True,
1325
+            do_notify=False,
1326
+        )
1327
+        test_user2 = uapi.create_user(
1328
+            email='test2@test2.test2',
1329
+            password='pass',
1330
+            name='bob2',
1331
+            groups=groups,
1332
+            timezone='Europe/Paris',
1333
+            do_save=True,
1334
+            do_notify=False,
1335
+        )
1336
+        test_user3 = uapi.create_user(
1337
+            email='test3@test3.test3',
1338
+            password='pass',
1339
+            name='bob3',
1340
+            groups=groups,
1341
+            timezone='Europe/Paris',
1342
+            do_save=True,
1343
+            do_notify=False,
1344
+        )
1345
+        uapi.save(test_user)
1346
+        uapi.save(test_user2)
1347
+        uapi.save(test_user3)
1348
+        workspace_api = WorkspaceApi(
1349
+            current_user=admin,
1350
+            session=dbsession,
1351
+            config=self.app_config
1352
+
1353
+        )
1354
+        workspace = WorkspaceApi(
1355
+            current_user=admin,
1356
+            session=dbsession,
1357
+            config=self.app_config,
1358
+        ).create_workspace(
1359
+            'test workspace',
1360
+            save_now=True
1361
+        )
1362
+        role_api = RoleApi(
1363
+            current_user=admin,
1364
+            session=dbsession,
1365
+            config=self.app_config,
1366
+        )
1367
+        role_api.create_one(test_user, workspace, UserRoleInWorkspace.READER, False)
1368
+        role_api.create_one(test_user2, workspace, UserRoleInWorkspace.READER, False)
1369
+        transaction.commit()
1370
+        user_id = int(test_user.user_id)
1371
+
1372
+        self.testapp.authorization = (
1373
+            'Basic',
1374
+            (
1375
+                'test@test.test',
1376
+                'pass'
1377
+            )
1378
+        )
1379
+        params = {
1380
+            'acp': 'test',
1381
+        }
1382
+        res = self.testapp.get(
1383
+            '/api/v2/users/{user_id}/known_members'.format(user_id=user_id),
1384
+            status=200,
1385
+            params=params
1386
+        )
1387
+        res = res.json_body
1388
+        assert len(res) == 2
1389
+        assert res[0]['user_id'] == test_user.user_id
1390
+        assert res[0]['public_name'] == test_user.display_name
1391
+        assert res[0]['avatar_url'] is None
1392
+
1393
+        assert res[1]['user_id'] == test_user2.user_id
1394
+        assert res[1]['public_name'] == test_user2.display_name
1395
+        assert res[1]['avatar_url'] is None
1396
+
1397
+
1012 1398
 class TestSetEmailEndpoint(FunctionalTest):
1013 1399
     # -*- coding: utf-8 -*-
1014 1400
     """

+ 13 - 0
backend/tracim_backend/views/core_api/schemas.py View File

@@ -2,6 +2,7 @@
2 2
 import marshmallow
3 3
 from marshmallow import post_load
4 4
 from marshmallow.validate import OneOf
5
+from marshmallow.validate import Length
5 6
 from marshmallow.validate import Range
6 7
 
7 8
 from tracim_backend.lib.utils.utils import DATETIME_FORMAT
@@ -11,6 +12,7 @@ from tracim_backend.models.contents import open_status
11 12
 from tracim_backend.models.contents import ContentTypeLegacy as ContentType
12 13
 from tracim_backend.models.contents import ContentStatusLegacy as ContentStatus
13 14
 from tracim_backend.models.context_models import ActiveContentFilter
15
+from tracim_backend.models.context_models import AutocompleteQuery
14 16
 from tracim_backend.models.context_models import ContentIdsQuery
15 17
 from tracim_backend.models.context_models import UserWorkspaceAndContentPath
16 18
 from tracim_backend.models.context_models import ContentCreation
@@ -292,6 +294,17 @@ class CommentsPathSchema(WorkspaceAndContentIdPathSchema):
292 294
         return CommentPath(**data)
293 295
 
294 296
 
297
+class AutocompleteQuerySchema(marshmallow.Schema):
298
+    acp = marshmallow.fields.Str(
299
+        example='test',
300
+        description='search text to query',
301
+        validate=Length(min=2),
302
+    )
303
+    @post_load
304
+    def make_autocomplete(self, data):
305
+        return AutocompleteQuery(**data)
306
+
307
+
295 308
 class PageQuerySchema(marshmallow.Schema):
296 309
     page = marshmallow.fields.Int(
297 310
         example=2,

+ 51 - 0
backend/tracim_backend/views/core_api/user_controller.py View File

@@ -17,6 +17,8 @@ from tracim_backend.lib.utils.authorization import require_profile
17 17
 from tracim_backend.exceptions import WrongUserPassword
18 18
 from tracim_backend.exceptions import PasswordDoNotMatch
19 19
 from tracim_backend.views.core_api.schemas import UserSchema
20
+from tracim_backend.views.core_api.schemas import AutocompleteQuerySchema
21
+from tracim_backend.views.core_api.schemas import UserDigestSchema
20 22
 from tracim_backend.views.core_api.schemas import SetEmailSchema
21 23
 from tracim_backend.views.core_api.schemas import SetPasswordSchema
22 24
 from tracim_backend.views.core_api.schemas import UserInfosSchema
@@ -35,6 +37,7 @@ from tracim_backend.views.core_api.schemas import WorkspaceDigestSchema
35 37
 SWAGGER_TAG__USER_ENDPOINTS = 'Users'
36 38
 
37 39
 
40
+
38 41
 class UserController(Controller):
39 42
 
40 43
     @hapic.with_api_doc(tags=[SWAGGER_TAG__USER_ENDPOINTS])
@@ -75,6 +78,46 @@ class UserController(Controller):
75 78
         return uapi.get_user_with_context(request.candidate_user)
76 79
 
77 80
     @hapic.with_api_doc(tags=[SWAGGER_TAG__USER_ENDPOINTS])
81
+    @require_profile(Group.TIM_ADMIN)
82
+    @hapic.output_body(UserDigestSchema(many=True))
83
+    def users(self, context, request: TracimRequest, hapic_data=None):
84
+        """
85
+        Get all users
86
+        """
87
+        app_config = request.registry.settings['CFG']
88
+        uapi = UserApi(
89
+            current_user=request.current_user,  # User
90
+            session=request.dbsession,
91
+            config=app_config,
92
+        )
93
+        users = uapi.get_all()
94
+        context_users = [
95
+            uapi.get_user_with_context(user) for user in users
96
+        ]
97
+        return context_users
98
+
99
+    @hapic.with_api_doc(tags=[SWAGGER_TAG__USER_ENDPOINTS])
100
+    @require_same_user_or_profile(Group.TIM_MANAGER)
101
+    @hapic.input_path(UserIdPathSchema())
102
+    @hapic.input_query(AutocompleteQuerySchema())
103
+    @hapic.output_body(UserDigestSchema(many=True))
104
+    def known_members(self, context, request: TracimRequest, hapic_data=None):
105
+        """
106
+        Get known users list
107
+        """
108
+        app_config = request.registry.settings['CFG']
109
+        uapi = UserApi(
110
+            current_user=request.candidate_user,  # User
111
+            session=request.dbsession,
112
+            config=app_config,
113
+        )
114
+        users = uapi.get_known_user(acp=hapic_data.query.acp)
115
+        context_users = [
116
+            uapi.get_user_with_context(user) for user in users
117
+        ]
118
+        return context_users
119
+
120
+    @hapic.with_api_doc(tags=[SWAGGER_TAG__USER_ENDPOINTS])
78 121
     @hapic.handle_exception(WrongUserPassword, HTTPStatus.FORBIDDEN)
79 122
     @require_same_user_or_profile(Group.TIM_ADMIN)
80 123
     @hapic.input_body(SetEmailSchema())
@@ -375,6 +418,14 @@ class UserController(Controller):
375 418
         configurator.add_route('user', '/users/{user_id}', request_method='GET')  # nopep8
376 419
         configurator.add_view(self.user, route_name='user')
377 420
 
421
+        # users lists
422
+        configurator.add_route('users', '/users', request_method='GET')  # nopep8
423
+        configurator.add_view(self.users, route_name='users')
424
+
425
+        # known members lists
426
+        configurator.add_route('known_members', '/users/{user_id}/known_members', request_method='GET')  # nopep8
427
+        configurator.add_view(self.known_members, route_name='known_members')
428
+
378 429
         # set user email
379 430
         configurator.add_route('set_user_email', '/users/{user_id}/email', request_method='PUT')  # nopep8
380 431
         configurator.add_view(self.set_user_email, route_name='set_user_email')