Преглед на файлове

add endpoints + test for delete/undelete workspace

Guénaël Muller преди 6 години
родител
ревизия
853c66a34f

+ 1 - 0
backend/doc/roles.md Целия файл

@@ -20,6 +20,7 @@ The other is workspace related and is called "workspace role".
20 20
 |-------------------------------|-------------|-------------|---------|
21 21
 | create workspace              |  no         | yes         | yes     |
22 22
 | invite user to tracim         |  no         | yes, if manager of a given workspace         | yes     |
23
+  delete workspace              |  no         | yes, if manager of a given workspace         | yes     |
23 24
 |-------------------------------|-------------|-------------|---------|
24 25
 | set user global profile rights|  no         | no          | yes     |
25 26
 | deactivate user               |  no         | no          | yes     |

+ 34 - 0
backend/tracim_backend/lib/utils/authorization.py Целия файл

@@ -90,6 +90,40 @@ def require_profile(group: int) -> typing.Callable:
90 90
     return decorator
91 91
 
92 92
 
93
+def require_profile_or_other_profile_with_workspace_role(
94
+        allow_all_group: int,
95
+        allow_if_role_group: int,
96
+        minimal_required_role: int,
97
+) -> typing.Callable:
98
+    """
99
+    Allow access for allow_all_group profile
100
+    or allow access for allow_if_role_group
101
+    profile if mininal_required_role is correct.
102
+    :param allow_all_group: value from Group Object
103
+    like Group.TIM_USER or Group.TIM_MANAGER
104
+    :param allow_if_role_group: value from Group Object
105
+    like Group.TIM_USER or Group.TIM_MANAGER
106
+    :param minimal_required_role: value from UserInWorkspace Object like
107
+    UserRoleInWorkspace.CONTRIBUTOR or UserRoleInWorkspace.READER
108
+    :return: decorator
109
+    """
110
+    def decorator(func: typing.Callable) -> typing.Callable:
111
+        @functools.wraps(func)
112
+        def wrapper(self, context, request: 'TracimRequest') -> typing.Callable:
113
+            user = request.current_user
114
+            workspace = request.current_workspace
115
+            if user.profile.id >= allow_all_group:
116
+                return func(self, context, request)
117
+            elif user.profile.id >= allow_if_role_group:
118
+                if workspace.get_user_role(user) >= minimal_required_role:
119
+                    return func(self, context, request)
120
+                raise InsufficientUserRoleInWorkspace()
121
+            else:
122
+                raise InsufficientUserProfile()
123
+        return wrapper
124
+    return decorator
125
+
126
+
93 127
 def require_workspace_role(minimal_required_role: int) -> typing.Callable:
94 128
     """
95 129
     Restricts access to endpoint to minimal role or raise an exception.

+ 4 - 2
backend/tracim_backend/lib/utils/request.py Целия файл

@@ -351,7 +351,8 @@ class TracimRequest(Request):
351 351
             wapi = WorkspaceApi(
352 352
                 current_user=user,
353 353
                 session=request.dbsession,
354
-                config=request.registry.settings['CFG']
354
+                config=request.registry.settings['CFG'],
355
+                show_deleted=True,
355 356
             )
356 357
             workspace = wapi.get_one(workspace_id)
357 358
         except NoResultFound as exc:
@@ -386,7 +387,8 @@ class TracimRequest(Request):
386 387
             wapi = WorkspaceApi(
387 388
                 current_user=user,
388 389
                 session=request.dbsession,
389
-                config=request.registry.settings['CFG']
390
+                config=request.registry.settings['CFG'],
391
+                show_deleted=True,
390 392
             )
391 393
             workspace = wapi.get_one(workspace_id)
392 394
         except JSONDecodeError as exc:

+ 608 - 0
backend/tracim_backend/tests/functional/test_workspaces.py Целия файл

@@ -8,9 +8,13 @@ from depot.io.utils import FileIntent
8 8
 
9 9
 from tracim_backend import models
10 10
 from tracim_backend.lib.core.content import ContentApi
11
+from tracim_backend.lib.core.group import GroupApi
12
+from tracim_backend.lib.core.user import UserApi
13
+from tracim_backend.lib.core.userworkspace import RoleApi
11 14
 from tracim_backend.lib.core.workspace import WorkspaceApi
12 15
 from tracim_backend.models import get_tm_session
13 16
 from tracim_backend.models.contents import CONTENT_TYPES
17
+from tracim_backend.models.data import UserRoleInWorkspace
14 18
 from tracim_backend.tests import FunctionalTest
15 19
 from tracim_backend.tests import set_html_document_slug_to_legacy
16 20
 from tracim_backend.fixtures.content import Content as ContentFixtures
@@ -211,6 +215,610 @@ class TestWorkspaceEndpoint(FunctionalTest):
211 215
             params=params,
212 216
         )
213 217
 
218
+    def test_api__delete_workspace__ok_200__admin(self) -> None:
219
+        """
220
+        Test delete workspace as admin
221
+        """
222
+        self.testapp.authorization = (
223
+            'Basic',
224
+            (
225
+                'admin@admin.admin',
226
+                'admin@admin.admin'
227
+            )
228
+        )
229
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
230
+        admin = dbsession.query(models.User) \
231
+            .filter(models.User.email == 'admin@admin.admin') \
232
+            .one()
233
+        uapi = UserApi(
234
+            current_user=admin,
235
+            session=dbsession,
236
+            config=self.app_config,
237
+        )
238
+        gapi = GroupApi(
239
+            current_user=admin,
240
+            session=dbsession,
241
+            config=self.app_config,
242
+        )
243
+        groups = [gapi.get_one_with_name('administrators')]
244
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False, groups=groups)  # nopep8
245
+        workspace_api = WorkspaceApi(
246
+            current_user=admin,
247
+            session=dbsession,
248
+            config=self.app_config,
249
+            show_deleted=True,
250
+        )
251
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
252
+        transaction.commit()
253
+        workspace_id = int(workspace.workspace_id)
254
+        self.testapp.authorization = (
255
+            'Basic',
256
+            (
257
+                'test@test.test',
258
+                'test@test.test'
259
+            )
260
+        )
261
+        # delete
262
+        res = self.testapp.put(
263
+            '/api/v2/workspaces/{}/delete'.format(workspace_id),
264
+            status=204
265
+        )
266
+        res = self.testapp.get(
267
+            '/api/v2/workspaces/{}'.format(workspace_id),
268
+            status=403
269
+        )
270
+        self.testapp.authorization = (
271
+            'Basic',
272
+            (
273
+                'admin@admin.admin',
274
+                'admin@admin.admin'
275
+            )
276
+        )
277
+        res = self.testapp.get(
278
+            '/api/v2/workspaces/{}'.format(workspace_id),
279
+            status=200
280
+        )
281
+        workspace = res.json_body
282
+        assert workspace['is_deleted'] is True
283
+
284
+    def test_api__delete_workspace__ok_200__manager_workspace_manager(self) -> None:
285
+        """
286
+        Test delete workspace as global manager and workspace manager
287
+        """
288
+        self.testapp.authorization = (
289
+            'Basic',
290
+            (
291
+                'admin@admin.admin',
292
+                'admin@admin.admin'
293
+            )
294
+        )
295
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
296
+        admin = dbsession.query(models.User) \
297
+            .filter(models.User.email == 'admin@admin.admin') \
298
+            .one()
299
+        uapi = UserApi(
300
+            current_user=admin,
301
+            session=dbsession,
302
+            config=self.app_config,
303
+        )
304
+        gapi = GroupApi(
305
+            current_user=admin,
306
+            session=dbsession,
307
+            config=self.app_config,
308
+        )
309
+        groups = [gapi.get_one_with_name('managers')]
310
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False, groups=groups)  # nopep8
311
+        workspace_api = WorkspaceApi(
312
+            current_user=admin,
313
+            session=dbsession,
314
+            config=self.app_config,
315
+            show_deleted=True,
316
+        )
317
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
318
+        rapi = RoleApi(
319
+            current_user=admin,
320
+            session=dbsession,
321
+            config=self.app_config,
322
+        )
323
+        rapi.create_one(user, workspace, UserRoleInWorkspace.WORKSPACE_MANAGER, False)  # nopep8
324
+        transaction.commit()
325
+        workspace_id = int(workspace.workspace_id)
326
+        self.testapp.authorization = (
327
+            'Basic',
328
+            (
329
+                'test@test.test',
330
+                'test@test.test'
331
+            )
332
+        )
333
+        # delete
334
+        res = self.testapp.put(
335
+            '/api/v2/workspaces/{}/delete'.format(workspace_id),
336
+            status=204
337
+        )
338
+        res = self.testapp.get(
339
+            '/api/v2/workspaces/{}'.format(workspace_id),
340
+            status=200
341
+        )
342
+        workspace = res.json_body
343
+        assert workspace['is_deleted'] is True
344
+
345
+    def test_api__delete_workspace__err_403__user_workspace_manager(self) -> None:
346
+        """
347
+        Test delete workspace as simple user and workspace manager
348
+        """
349
+        self.testapp.authorization = (
350
+            'Basic',
351
+            (
352
+                'admin@admin.admin',
353
+                'admin@admin.admin'
354
+            )
355
+        )
356
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
357
+        admin = dbsession.query(models.User) \
358
+            .filter(models.User.email == 'admin@admin.admin') \
359
+            .one()
360
+        uapi = UserApi(
361
+            current_user=admin,
362
+            session=dbsession,
363
+            config=self.app_config,
364
+        )
365
+        gapi = GroupApi(
366
+            current_user=admin,
367
+            session=dbsession,
368
+            config=self.app_config,
369
+        )
370
+        groups = [gapi.get_one_with_name('users')]
371
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False, groups=groups)  # nopep8
372
+        workspace_api = WorkspaceApi(
373
+            current_user=admin,
374
+            session=dbsession,
375
+            config=self.app_config,
376
+            show_deleted=True,
377
+        )
378
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
379
+        rapi = RoleApi(
380
+            current_user=admin,
381
+            session=dbsession,
382
+            config=self.app_config,
383
+        )
384
+        rapi.create_one(user, workspace, UserRoleInWorkspace.WORKSPACE_MANAGER, False)  # nopep8
385
+        transaction.commit()
386
+        workspace_id = int(workspace.workspace_id)
387
+        self.testapp.authorization = (
388
+            'Basic',
389
+            (
390
+                'test@test.test',
391
+                'test@test.test'
392
+            )
393
+        )
394
+        # delete
395
+        res = self.testapp.put(
396
+            '/api/v2/workspaces/{}/delete'.format(workspace_id),
397
+            status=403
398
+        )
399
+        res = self.testapp.get(
400
+            '/api/v2/workspaces/{}'.format(workspace_id),
401
+            status=200
402
+        )
403
+        workspace = res.json_body
404
+        assert workspace['is_deleted'] is False
405
+
406
+    def test_api__delete_workspace__err_403__manager_reader(self) -> None:
407
+        """
408
+        Test delete workspace as manager and reader of the workspace
409
+        """
410
+        self.testapp.authorization = (
411
+            'Basic',
412
+            (
413
+                'admin@admin.admin',
414
+                'admin@admin.admin'
415
+            )
416
+        )
417
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
418
+        admin = dbsession.query(models.User) \
419
+            .filter(models.User.email == 'admin@admin.admin') \
420
+            .one()
421
+        uapi = UserApi(
422
+            current_user=admin,
423
+            session=dbsession,
424
+            config=self.app_config,
425
+        )
426
+        gapi = GroupApi(
427
+            current_user=admin,
428
+            session=dbsession,
429
+            config=self.app_config,
430
+        )
431
+        groups = [gapi.get_one_with_name('managers')]
432
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False)  # nopep8
433
+        workspace_api = WorkspaceApi(
434
+            current_user=admin,
435
+            session=dbsession,
436
+            config=self.app_config,
437
+            show_deleted=True,
438
+        )
439
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
440
+        rapi = RoleApi(
441
+            current_user=admin,
442
+            session=dbsession,
443
+            config=self.app_config,
444
+        )
445
+        rapi.create_one(user, workspace, UserRoleInWorkspace.READER, False)  # nopep8
446
+        transaction.commit()
447
+        workspace_id = int(workspace.workspace_id)
448
+        self.testapp.authorization = (
449
+            'Basic',
450
+            (
451
+                'test@test.test',
452
+                'test@test.test'
453
+            )
454
+        )
455
+        # delete
456
+        res = self.testapp.put(
457
+            '/api/v2/workspaces/{}/delete'.format(workspace_id),
458
+            status=403
459
+        )
460
+        res = self.testapp.get(
461
+            '/api/v2/workspaces/{}'.format(workspace_id),
462
+            status=200
463
+        )
464
+        workspace = res.json_body
465
+        assert workspace['is_deleted'] is False
466
+
467
+    def test_api__delete_workspace__err_400__manager(self) -> None:
468
+        """
469
+        Test delete workspace as global manager without having any role in the
470
+        workspace
471
+        """
472
+        self.testapp.authorization = (
473
+            'Basic',
474
+            (
475
+                'admin@admin.admin',
476
+                'admin@admin.admin'
477
+            )
478
+        )
479
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
480
+        admin = dbsession.query(models.User) \
481
+            .filter(models.User.email == 'admin@admin.admin') \
482
+            .one()
483
+        uapi = UserApi(
484
+            current_user=admin,
485
+            session=dbsession,
486
+            config=self.app_config,
487
+        )
488
+        user = uapi.create_user('test@test.test', password='test@test.test',
489
+                                do_save=True, do_notify=False)  # nopep8
490
+        workspace_api = WorkspaceApi(
491
+            current_user=admin,
492
+            session=dbsession,
493
+            config=self.app_config,
494
+            show_deleted=True,
495
+        )
496
+        workspace = workspace_api.create_workspace('test',
497
+                                                   save_now=True)  # nopep8
498
+        rapi = RoleApi(
499
+            current_user=admin,
500
+            session=dbsession,
501
+            config=self.app_config,
502
+        )
503
+        transaction.commit()
504
+        workspace_id = int(workspace.workspace_id)
505
+        self.testapp.authorization = (
506
+            'Basic',
507
+            (
508
+                'test@test.test',
509
+                'test@test.test'
510
+            )
511
+        )
512
+        # delete
513
+        res = self.testapp.put(
514
+            '/api/v2/workspaces/{}/delete'.format(workspace_id),
515
+            status=400
516
+        )
517
+
518
+    def test_api__undelete_workspace__ok_200__admin(self) -> None:
519
+        """
520
+        Test undelete workspace as admin
521
+        """
522
+        self.testapp.authorization = (
523
+            'Basic',
524
+            (
525
+                'admin@admin.admin',
526
+                'admin@admin.admin'
527
+            )
528
+        )
529
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
530
+        admin = dbsession.query(models.User) \
531
+            .filter(models.User.email == 'admin@admin.admin') \
532
+            .one()
533
+        uapi = UserApi(
534
+            current_user=admin,
535
+            session=dbsession,
536
+            config=self.app_config,
537
+        )
538
+        gapi = GroupApi(
539
+            current_user=admin,
540
+            session=dbsession,
541
+            config=self.app_config,
542
+        )
543
+        groups = [gapi.get_one_with_name('administrators')]
544
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False, groups=groups)  # nopep8
545
+        workspace_api = WorkspaceApi(
546
+            current_user=admin,
547
+            session=dbsession,
548
+            config=self.app_config,
549
+            show_deleted=True,
550
+        )
551
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
552
+        workspace_api.delete(workspace, flush=True)
553
+        transaction.commit()
554
+        workspace_id = int(workspace.workspace_id)
555
+        self.testapp.authorization = (
556
+            'Basic',
557
+            (
558
+                'test@test.test',
559
+                'test@test.test'
560
+            )
561
+        )
562
+        # delete
563
+        res = self.testapp.put(
564
+            '/api/v2/workspaces/{}/undelete'.format(workspace_id),
565
+            status=204
566
+        )
567
+        res = self.testapp.get(
568
+            '/api/v2/workspaces/{}'.format(workspace_id),
569
+            status=403
570
+        )
571
+        self.testapp.authorization = (
572
+            'Basic',
573
+            (
574
+                'admin@admin.admin',
575
+                'admin@admin.admin'
576
+            )
577
+        )
578
+        res = self.testapp.get(
579
+            '/api/v2/workspaces/{}'.format(workspace_id),
580
+            status=200
581
+        )
582
+        workspace = res.json_body
583
+        assert workspace['is_deleted'] is False
584
+
585
+    def test_api__undelete_workspace__ok_200__manager_workspace_manager(self) -> None:
586
+        """
587
+        Test undelete workspace as global manager and workspace manager
588
+        """
589
+        self.testapp.authorization = (
590
+            'Basic',
591
+            (
592
+                'admin@admin.admin',
593
+                'admin@admin.admin'
594
+            )
595
+        )
596
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
597
+        admin = dbsession.query(models.User) \
598
+            .filter(models.User.email == 'admin@admin.admin') \
599
+            .one()
600
+        uapi = UserApi(
601
+            current_user=admin,
602
+            session=dbsession,
603
+            config=self.app_config,
604
+        )
605
+        gapi = GroupApi(
606
+            current_user=admin,
607
+            session=dbsession,
608
+            config=self.app_config,
609
+        )
610
+        groups = [gapi.get_one_with_name('managers')]
611
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False, groups=groups)  # nopep8
612
+        workspace_api = WorkspaceApi(
613
+            current_user=admin,
614
+            session=dbsession,
615
+            config=self.app_config,
616
+            show_deleted=True,
617
+        )
618
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
619
+        workspace_api.delete(workspace, flush=True)
620
+        rapi = RoleApi(
621
+            current_user=admin,
622
+            session=dbsession,
623
+            config=self.app_config,
624
+        )
625
+        rapi.create_one(user, workspace, UserRoleInWorkspace.WORKSPACE_MANAGER, False)  # nopep8
626
+        transaction.commit()
627
+        workspace_id = int(workspace.workspace_id)
628
+        self.testapp.authorization = (
629
+            'Basic',
630
+            (
631
+                'test@test.test',
632
+                'test@test.test'
633
+            )
634
+        )
635
+        # delete
636
+        res = self.testapp.put(
637
+            '/api/v2/workspaces/{}/undelete'.format(workspace_id),
638
+            status=204
639
+        )
640
+        res = self.testapp.get(
641
+            '/api/v2/workspaces/{}'.format(workspace_id),
642
+            status=200
643
+        )
644
+        workspace = res.json_body
645
+        assert workspace['is_deleted'] is False
646
+
647
+    def test_api__undelete_workspace__err_403__user_workspace_manager(self) -> None:
648
+        """
649
+        Test undelete workspace as simple user and workspace manager
650
+        """
651
+        self.testapp.authorization = (
652
+            'Basic',
653
+            (
654
+                'admin@admin.admin',
655
+                'admin@admin.admin'
656
+            )
657
+        )
658
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
659
+        admin = dbsession.query(models.User) \
660
+            .filter(models.User.email == 'admin@admin.admin') \
661
+            .one()
662
+        uapi = UserApi(
663
+            current_user=admin,
664
+            session=dbsession,
665
+            config=self.app_config,
666
+        )
667
+        gapi = GroupApi(
668
+            current_user=admin,
669
+            session=dbsession,
670
+            config=self.app_config,
671
+        )
672
+        groups = [gapi.get_one_with_name('users')]
673
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False, groups=groups)  # nopep8
674
+        workspace_api = WorkspaceApi(
675
+            current_user=admin,
676
+            session=dbsession,
677
+            config=self.app_config,
678
+            show_deleted=True,
679
+        )
680
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
681
+        workspace_api.delete(workspace, flush=True)
682
+        rapi = RoleApi(
683
+            current_user=admin,
684
+            session=dbsession,
685
+            config=self.app_config,
686
+        )
687
+        rapi.create_one(user, workspace, UserRoleInWorkspace.WORKSPACE_MANAGER, False)  # nopep8
688
+        transaction.commit()
689
+        workspace_id = int(workspace.workspace_id)
690
+        self.testapp.authorization = (
691
+            'Basic',
692
+            (
693
+                'test@test.test',
694
+                'test@test.test'
695
+            )
696
+        )
697
+        # delete
698
+        res = self.testapp.put(
699
+            '/api/v2/workspaces/{}/undelete'.format(workspace_id),
700
+            status=403
701
+        )
702
+        res = self.testapp.get(
703
+            '/api/v2/workspaces/{}'.format(workspace_id),
704
+            status=200
705
+        )
706
+        workspace = res.json_body
707
+        assert workspace['is_deleted'] is True
708
+
709
+    def test_api__undelete_workspace__err_403__manager_reader(self) -> None:
710
+        """
711
+        Test undelete workspace as manager and reader of the workspace
712
+        """
713
+        self.testapp.authorization = (
714
+            'Basic',
715
+            (
716
+                'admin@admin.admin',
717
+                'admin@admin.admin'
718
+            )
719
+        )
720
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
721
+        admin = dbsession.query(models.User) \
722
+            .filter(models.User.email == 'admin@admin.admin') \
723
+            .one()
724
+        uapi = UserApi(
725
+            current_user=admin,
726
+            session=dbsession,
727
+            config=self.app_config,
728
+        )
729
+        gapi = GroupApi(
730
+            current_user=admin,
731
+            session=dbsession,
732
+            config=self.app_config,
733
+        )
734
+        groups = [gapi.get_one_with_name('managers')]
735
+        user = uapi.create_user('test@test.test', password='test@test.test', do_save=True, do_notify=False)  # nopep8
736
+        workspace_api = WorkspaceApi(
737
+            current_user=admin,
738
+            session=dbsession,
739
+            config=self.app_config,
740
+            show_deleted=True,
741
+        )
742
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
743
+        workspace_api.delete(workspace, flush=True)
744
+        rapi = RoleApi(
745
+            current_user=admin,
746
+            session=dbsession,
747
+            config=self.app_config,
748
+        )
749
+        rapi.create_one(user, workspace, UserRoleInWorkspace.READER, False)  # nopep8
750
+        transaction.commit()
751
+        workspace_id = int(workspace.workspace_id)
752
+        self.testapp.authorization = (
753
+            'Basic',
754
+            (
755
+                'test@test.test',
756
+                'test@test.test'
757
+            )
758
+        )
759
+        # delete
760
+        res = self.testapp.put(
761
+            '/api/v2/workspaces/{}/undelete'.format(workspace_id),
762
+            status=403
763
+        )
764
+        res = self.testapp.get(
765
+            '/api/v2/workspaces/{}'.format(workspace_id),
766
+            status=200
767
+        )
768
+        workspace = res.json_body
769
+        assert workspace['is_deleted'] is True
770
+
771
+    def test_api__undelete_workspace__err_400__manager(self) -> None:
772
+        """
773
+        Test delete workspace as global manager without having any role in the
774
+        workspace
775
+        """
776
+        self.testapp.authorization = (
777
+            'Basic',
778
+            (
779
+                'admin@admin.admin',
780
+                'admin@admin.admin'
781
+            )
782
+        )
783
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
784
+        admin = dbsession.query(models.User) \
785
+            .filter(models.User.email == 'admin@admin.admin') \
786
+            .one()
787
+        uapi = UserApi(
788
+            current_user=admin,
789
+            session=dbsession,
790
+            config=self.app_config,
791
+        )
792
+        user = uapi.create_user('test@test.test', password='test@test.test',
793
+                                do_save=True, do_notify=False)  # nopep8
794
+        workspace_api = WorkspaceApi(
795
+            current_user=admin,
796
+            session=dbsession,
797
+            config=self.app_config,
798
+            show_deleted=True,
799
+        )
800
+        workspace = workspace_api.create_workspace('test', save_now=True)  # nopep8
801
+        workspace_api.delete(workspace, flush=True)
802
+        rapi = RoleApi(
803
+            current_user=admin,
804
+            session=dbsession,
805
+            config=self.app_config,
806
+        )
807
+        transaction.commit()
808
+        workspace_id = int(workspace.workspace_id)
809
+        self.testapp.authorization = (
810
+            'Basic',
811
+            (
812
+                'test@test.test',
813
+                'test@test.test'
814
+            )
815
+        )
816
+        # delete
817
+        res = self.testapp.put(
818
+            '/api/v2/workspaces/{}/undelete'.format(workspace_id),
819
+            status=400
820
+        )
821
+
214 822
     def test_api__get_workspace__err_400__unallowed_user(self) -> None:
215 823
         """
216 824
         Check obtain workspace unreachable for user

+ 51 - 0
backend/tracim_backend/views/core_api/workspace_controller.py Целия файл

@@ -16,6 +16,7 @@ from tracim_backend.lib.core.workspace import WorkspaceApi
16 16
 from tracim_backend.lib.core.content import ContentApi
17 17
 from tracim_backend.lib.core.userworkspace import RoleApi
18 18
 from tracim_backend.lib.utils.authorization import require_workspace_role
19
+from tracim_backend.lib.utils.authorization import require_profile_or_other_profile_with_workspace_role
19 20
 from tracim_backend.lib.utils.authorization import require_profile
20 21
 from tracim_backend.models import Group
21 22
 from tracim_backend.lib.utils.authorization import require_candidate_workspace_role
@@ -118,6 +119,51 @@ class WorkspaceController(Controller):
118 119
         return wapi.get_workspace_with_context(workspace)
119 120
 
120 121
     @hapic.with_api_doc(tags=[SWAGGER_TAG_WORKSPACE_ENDPOINTS])
122
+    @hapic.handle_exception(EmptyLabelNotAllowed, HTTPStatus.BAD_REQUEST)
123
+    @require_profile_or_other_profile_with_workspace_role(
124
+        Group.TIM_ADMIN,
125
+        Group.TIM_MANAGER,
126
+        UserRoleInWorkspace.WORKSPACE_MANAGER,
127
+    )
128
+    @hapic.input_path(WorkspaceIdPathSchema())
129
+    @hapic.output_body(NoContentSchema(), default_http_code=HTTPStatus.NO_CONTENT)  # nopep8
130
+    def delete_workspace(self, context, request: TracimRequest, hapic_data=None):  # nopep8
131
+        """
132
+        delete workspace
133
+        """
134
+        app_config = request.registry.settings['CFG']
135
+        wapi = WorkspaceApi(
136
+            current_user=request.current_user,  # User
137
+            session=request.dbsession,
138
+            config=app_config,
139
+        )
140
+        wapi.delete(request.current_workspace, flush=True)
141
+        return
142
+
143
+    @hapic.with_api_doc(tags=[SWAGGER_TAG_WORKSPACE_ENDPOINTS])
144
+    @hapic.handle_exception(EmptyLabelNotAllowed, HTTPStatus.BAD_REQUEST)
145
+    @require_profile_or_other_profile_with_workspace_role(
146
+        Group.TIM_ADMIN,
147
+        Group.TIM_MANAGER,
148
+        UserRoleInWorkspace.WORKSPACE_MANAGER,
149
+    )
150
+    @hapic.input_path(WorkspaceIdPathSchema())
151
+    @hapic.output_body(NoContentSchema(), default_http_code=HTTPStatus.NO_CONTENT)  # nopep8
152
+    def undelete_workspace(self, context, request: TracimRequest, hapic_data=None):  # nopep8
153
+        """
154
+        restore deleted workspace
155
+        """
156
+        app_config = request.registry.settings['CFG']
157
+        wapi = WorkspaceApi(
158
+            current_user=request.current_user,  # User
159
+            session=request.dbsession,
160
+            config=app_config,
161
+            show_deleted=True,
162
+        )
163
+        wapi.undelete(request.current_workspace, flush=True)
164
+        return
165
+
166
+    @hapic.with_api_doc(tags=[SWAGGER_TAG_WORKSPACE_ENDPOINTS])
121 167
     @require_workspace_role(UserRoleInWorkspace.READER)
122 168
     @hapic.input_path(WorkspaceIdPathSchema())
123 169
     @hapic.output_body(WorkspaceMemberSchema(many=True))
@@ -512,6 +558,11 @@ class WorkspaceController(Controller):
512 558
         # Create workspace
513 559
         configurator.add_route('create_workspace', '/workspaces', request_method='POST')  # nopep8
514 560
         configurator.add_view(self.create_workspace, route_name='create_workspace')  # nopep8
561
+        # Delete/Undelete workpace
562
+        configurator.add_route('delete_workspace', '/workspaces/{workspace_id}/delete', request_method='PUT')  # nopep8
563
+        configurator.add_view(self.delete_workspace, route_name='delete_workspace')  # nopep8
564
+        configurator.add_route('undelete_workspace', '/workspaces/{workspace_id}/undelete', request_method='PUT')  # nopep8
565
+        configurator.add_view(self.undelete_workspace, route_name='undelete_workspace')  # nopep8
515 566
         # Update Workspace
516 567
         configurator.add_route('update_workspace', '/workspaces/{workspace_id}', request_method='PUT')  # nopep8
517 568
         configurator.add_view(self.update_workspace, route_name='update_workspace')  # nopep8