Ver código fonte

Closes #186: Radicale show deleted/disabled workspaces calendar

Bastien Sevajol (Algoo) 7 anos atrás
pai
commit
a12e7acb11

+ 1 - 1
tracim/development.ini.base Ver arquivo

@@ -204,7 +204,7 @@ email.processing_mode = sync
204 204
 # radicale.server.host = 0.0.0.0
205 205
 # radicale.server.port = 5232
206 206
 # radicale.server.ssl = false
207
-# radicale.server.filesystem.folder = ~/.config/radicale/collections
207
+# radicale.server.filesystem.folder = ./radicale/collections
208 208
 # radicale.server.allow_origin = *
209 209
 # radicale.server.realm_message = Tracim Calendar - Password Required
210 210
 ## url can be extended like http://127.0.0.1:5232/calendar

+ 1 - 1
tracim/tracim/config/app_cfg.py Ver arquivo

@@ -272,7 +272,7 @@ class CFG(object):
272 272
         self.RADICALE_SERVER_SSL = asbool(tg.config.get('radicale.server.ssl', False))
273 273
         self.RADICALE_SERVER_FILE_SYSTEM_FOLDER = tg.config.get(
274 274
             'radicale.server.filesystem.folder',
275
-            '~/.config/radicale/collections'
275
+            './radicale/collections',
276 276
         )
277 277
         self.RADICALE_SERVER_ALLOW_ORIGIN = tg.config.get(
278 278
             'radicale.server.allow_origin',

+ 2 - 0
tracim/tracim/controllers/admin/workspace.py Ver arquivo

@@ -239,6 +239,8 @@ class WorkspaceRestController(TIMRestController, BaseController):
239 239
 
240 240
         if calendar_enabled:
241 241
             workspace_api_controller.ensure_calendar_exist(workspace)
242
+        else:
243
+            workspace_api_controller.disable_calendar(workspace)
242 244
 
243 245
         tg.flash(_('{} workspace updated.').format(workspace.label), CST.STATUS_OK)
244 246
         tg.redirect(self.url(workspace.workspace_id))

+ 96 - 0
tracim/tracim/lib/calendar.py Ver arquivo

@@ -391,3 +391,99 @@ END:VCALENDAR
391 391
         except PutError:
392 392
             pass  # TODO BS 20161128: Radicale is down. Record this event ?
393 393
 
394
+    def get_enabled_calendar_file_path(
395
+            self,
396
+            calendar_class,
397
+            related_object_id,
398
+    ) -> str:
399
+        from tracim.config.app_cfg import CFG
400
+        cfg = CFG.get_instance()
401
+
402
+        calendar_file_name = '{}.ics'.format(related_object_id)
403
+
404
+        if calendar_class == WorkspaceCalendar:
405
+            calendar_type_folder = 'workspace'
406
+        elif calendar_class == UserCalendar:
407
+            calendar_type_folder = 'user'
408
+        else:
409
+            raise NotImplementedError()
410
+
411
+        current_calendar_file_path = os.path.join(
412
+            cfg.RADICALE_SERVER_FILE_SYSTEM_FOLDER,
413
+            calendar_type_folder,
414
+            calendar_file_name,
415
+        )
416
+
417
+        return current_calendar_file_path
418
+
419
+    def get_deleted_calendar_file_path(
420
+            self,
421
+            calendar_class,
422
+            related_object_id,
423
+    ) -> str:
424
+        from tracim.config.app_cfg import CFG
425
+        cfg = CFG.get_instance()
426
+
427
+        calendar_file_name = '{}.ics'.format(related_object_id)
428
+
429
+        if calendar_class == WorkspaceCalendar:
430
+            calendar_type_folder = 'workspace'
431
+        elif calendar_class == UserCalendar:
432
+            calendar_type_folder = 'user'
433
+        else:
434
+            raise NotImplementedError()
435
+
436
+        deleted_calendar_file_path = os.path.join(
437
+            cfg.RADICALE_SERVER_FILE_SYSTEM_FOLDER,
438
+            calendar_type_folder,
439
+            'deleted',
440
+            calendar_file_name,
441
+        )
442
+
443
+        return deleted_calendar_file_path
444
+
445
+    def disable_calendar_file(
446
+            self,
447
+            calendar_class,
448
+            related_object_id: int,
449
+            raise_: bool=False,
450
+    ) -> None:
451
+        enabled_calendar_file_path = self.get_enabled_calendar_file_path(
452
+            calendar_class,
453
+            related_object_id,
454
+        )
455
+        deleted_calendar_file_path = self.get_deleted_calendar_file_path(
456
+            calendar_class,
457
+            related_object_id,
458
+        )
459
+
460
+        deleted_folder = os.path.dirname(deleted_calendar_file_path)
461
+        if not os.path.exists(deleted_folder):
462
+            os.makedirs(deleted_folder)
463
+
464
+        try:
465
+            os.rename(enabled_calendar_file_path, deleted_calendar_file_path)
466
+        except FileNotFoundError:
467
+            if raise_:
468
+                raise
469
+
470
+    def enable_calendar_file(
471
+            self,
472
+            calendar_class,
473
+            related_object_id: int,
474
+            raise_: bool=False,
475
+    ) -> None:
476
+        enabled_calendar_file_path = self.get_enabled_calendar_file_path(
477
+            calendar_class,
478
+            related_object_id,
479
+        )
480
+        deleted_calendar_file_path = self.get_deleted_calendar_file_path(
481
+            calendar_class,
482
+            related_object_id,
483
+        )
484
+
485
+        try:
486
+            os.rename(deleted_calendar_file_path, enabled_calendar_file_path)
487
+        except FileNotFoundError:
488
+            if raise_:
489
+                raise

+ 25 - 3
tracim/tracim/lib/workspace.py Ver arquivo

@@ -64,7 +64,9 @@ class WorkspaceApi(object):
64 64
             DBSession.flush()
65 65
 
66 66
         if calendar_enabled:
67
-            self.execute_created_workspace_actions(workspace)
67
+            self.ensure_calendar_exist(workspace)
68
+        else:
69
+            self.disable_calendar(workspace)
68 70
 
69 71
         return workspace
70 72
 
@@ -145,19 +147,39 @@ class WorkspaceApi(object):
145 147
         from tracim.lib.calendar import CalendarManager
146 148
         from tracim.model.organisational import WorkspaceCalendar
147 149
 
148
-        if workspace.calendar_enabled:
150
+        calendar_manager = CalendarManager(self._user)
151
+
152
+        try:
153
+            calendar_manager.enable_calendar_file(
154
+                calendar_class=WorkspaceCalendar,
155
+                related_object_id=workspace.workspace_id,
156
+                raise_=True,
157
+            )
158
+        # If previous calendar file no exist, calendar must be created
159
+        except FileNotFoundError:
149 160
             self._user.ensure_auth_token()
150 161
 
151 162
             # Ensure database is up-to-date
152 163
             DBSession.flush()
153 164
             transaction.commit()
154 165
 
155
-            calendar_manager = CalendarManager(self._user)
156 166
             calendar_manager.create_then_remove_fake_event(
157 167
                 calendar_class=WorkspaceCalendar,
158 168
                 related_object_id=workspace.workspace_id,
159 169
             )
160 170
 
171
+    def disable_calendar(self, workspace: Workspace) -> None:
172
+        # Note: Cyclic imports
173
+        from tracim.lib.calendar import CalendarManager
174
+        from tracim.model.organisational import WorkspaceCalendar
175
+
176
+        calendar_manager = CalendarManager(self._user)
177
+        calendar_manager.disable_calendar_file(
178
+            calendar_class=WorkspaceCalendar,
179
+            related_object_id=workspace.workspace_id,
180
+            raise_=False,
181
+        )
182
+
161 183
     def get_base_query(self) -> Query:
162 184
         return self._base_query()
163 185
 

+ 155 - 0
tracim/tracim/tests/functional/test_calendar.py Ver arquivo

@@ -312,3 +312,158 @@ END:VCALENDAR
312 312
             workspace_calendar_exist,
313 313
             'Workspace calendar should be created',
314 314
         )
315
+
316
+    def unit_test__disable_workspace_disable_file__ok__nominal_case(self):
317
+        self._connect_user(
318
+            'admin@admin.admin',
319
+            'admin@admin.admin',
320
+        )
321
+        radicale_workspaces_folder = '{0}/workspace'.format(
322
+            config.get('radicale.server.filesystem.folder'),
323
+        )
324
+        delete_radicale_workspaces_folder = '{0}/workspace/deleted'.format(
325
+            config.get('radicale.server.filesystem.folder'),
326
+        )
327
+
328
+        # Core after assume "test_created_workspace_radicale_calendar" is ok
329
+        self.app.post(
330
+            '/admin/workspaces',
331
+            OrderedDict([
332
+                ('name', 'WTESTCAL2'),
333
+                ('description', 'WTESTCAL2DESCR'),
334
+                ('calendar_enabled', 'on'),
335
+            ])
336
+        )
337
+        created_workspace = DBSession.query(Workspace)\
338
+            .filter(Workspace.label == 'WTESTCAL2')\
339
+            .one()
340
+        disable_response = self.app.put(
341
+            '/admin/workspaces/{}?_method=PUT'.format(
342
+                created_workspace.workspace_id,
343
+            ),
344
+            OrderedDict([
345
+                ('name', 'WTESTCAL2'),
346
+                ('description', 'WTESTCAL2DESCR'),
347
+                ('calendar_enabled', 'off'),
348
+            ])
349
+        )
350
+        eq_(disable_response.status_code, 302,
351
+            "Code should be 302, but is %d" % disable_response.status_code)
352
+        workspaces_calendars = [
353
+            name for name in
354
+            os.listdir(radicale_workspaces_folder)
355
+            if name.endswith('.ics')
356
+        ]
357
+        deleted_workspaces_calendars = [
358
+            name for name in
359
+            os.listdir(delete_radicale_workspaces_folder)
360
+            if name.endswith('.ics')
361
+        ]
362
+
363
+        eq_(
364
+            0,
365
+            len(workspaces_calendars),
366
+            msg='No workspace ics file should exist, but {} found'.format(
367
+                len(workspaces_calendars),
368
+            ),
369
+        )
370
+        eq_(
371
+            1,
372
+            len(deleted_workspaces_calendars),
373
+            msg='1 deleted workspace ics file should exist, but {} found'
374
+                .format(
375
+                    len(deleted_workspaces_calendars),
376
+                ),
377
+        )
378
+        workspace_ics_file_name = '{}.ics'.format(
379
+                created_workspace.workspace_id
380
+        )
381
+        ok_(
382
+            workspace_ics_file_name in deleted_workspaces_calendars,
383
+            '{} should be in deleted workspace calendar folder'.format(
384
+                workspace_ics_file_name
385
+            ),
386
+        )
387
+
388
+    def unit_test__re_enable_workspace_re_enable_file__ok__nominal_case(self):
389
+        self._connect_user(
390
+            'admin@admin.admin',
391
+            'admin@admin.admin',
392
+        )
393
+        radicale_workspaces_folder = '{0}/workspace'.format(
394
+            config.get('radicale.server.filesystem.folder'),
395
+        )
396
+        delete_radicale_workspaces_folder = '{0}/workspace/deleted'.format(
397
+            config.get('radicale.server.filesystem.folder'),
398
+        )
399
+
400
+        # Core after assume
401
+        # "unit_test__disable_workspace_disable_file__ok__nominal_case" is ok
402
+        self.app.post(
403
+            '/admin/workspaces',
404
+            OrderedDict([
405
+                ('name', 'WTESTCAL2'),
406
+                ('description', 'WTESTCAL2DESCR'),
407
+                ('calendar_enabled', 'on'),
408
+            ])
409
+        )
410
+        created_workspace = DBSession.query(Workspace) \
411
+            .filter(Workspace.label == 'WTESTCAL2') \
412
+            .one()
413
+        self.app.put(
414
+            '/admin/workspaces/{}?_method=PUT'.format(
415
+                created_workspace.workspace_id,
416
+            ),
417
+            OrderedDict([
418
+                ('name', 'WTESTCAL2'),
419
+                ('description', 'WTESTCAL2DESCR'),
420
+                ('calendar_enabled', 'off'),
421
+            ])
422
+        )
423
+        re_enable_response = self.app.put(
424
+            '/admin/workspaces/{}?_method=PUT'.format(
425
+                created_workspace.workspace_id,
426
+            ),
427
+            OrderedDict([
428
+                ('name', 'WTESTCAL2'),
429
+                ('description', 'WTESTCAL2DESCR'),
430
+                ('calendar_enabled', 'on'),
431
+            ])
432
+        )
433
+        eq_(re_enable_response.status_code, 302,
434
+            "Code should be 302, but is %d" % re_enable_response.status_code)
435
+        workspaces_calendars = [
436
+            name for name in
437
+            os.listdir(radicale_workspaces_folder)
438
+            if name.endswith('.ics')
439
+            ]
440
+        deleted_workspaces_calendars = [
441
+            name for name in
442
+            os.listdir(delete_radicale_workspaces_folder)
443
+            if name.endswith('.ics')
444
+            ]
445
+
446
+        eq_(
447
+            1,
448
+            len(workspaces_calendars),
449
+            msg='1 workspace ics file should exist, but {} found'.format(
450
+                len(workspaces_calendars),
451
+            ),
452
+        )
453
+        eq_(
454
+            0,
455
+            len(deleted_workspaces_calendars),
456
+            msg='0 deleted workspace ics file should exist, but {} found'
457
+                .format(
458
+                len(deleted_workspaces_calendars),
459
+            ),
460
+        )
461
+        workspace_ics_file_name = '{}.ics'.format(
462
+            created_workspace.workspace_id
463
+        )
464
+        ok_(
465
+            workspace_ics_file_name in workspaces_calendars,
466
+            '{} should be in workspace calendar folder'.format(
467
+                workspace_ics_file_name
468
+            ),
469
+        )