def test_unit__delete_revision__ok__with_unsafe_context( self, admin_user, session, content_type_list): with unprotected_content_revision(session) as unsafe_session: workspace = Workspace(label="TEST_WORKSPACE_1", owner=admin_user) unsafe_session.add(workspace) unsafe_session.flush() content = Content( owner=admin_user, workspace=workspace, type=content_type_list.Page.slug, label="TEST_CONTENT_1", description="TEST_CONTENT_DESCRIPTION_1", revision_type=ActionDescription.CREATION, is_deleted=False, is_archived=False, ) unsafe_session.add(content) unsafe_session.flush() with new_revision(session=unsafe_session, tm=transaction.manager, content=content): content.description = "TEST_CONTENT_DESCRIPTION_1_UPDATED" unsafe_session.add(content) unsafe_session.flush() unsafe_session.delete(content.revisions[0]) unsafe_session.flush()
def take_app_action(self, parsed_args: argparse.Namespace, app_context: AppEnvironment) -> None: self._session = app_context["request"].dbsession self._app_config = app_context["registry"].settings["CFG"] if parsed_args.dry_run_mode: print("(!) Running in dry-run mode, not change will be applied.") app_context["request"].tm.doom() with unprotected_content_revision(self._session) as session: uapi = UserApi( config=self._app_config, session=session, current_user=None, show_deleted=True, show_deactivated=True, ) user_list = [] # type: typing.List[User] for login in parsed_args.logins: try: user = uapi.get_one_by_login(login) user_list.append(user) except UserDoesNotExist as exc: print('ERROR: user with email "{}" does not exist'.format( login)) raise exc for user in user_list: print("~~~~~~~~~~") cleanup_lib = CleanupLib(session, self._app_config, dry_run_mode=parsed_args.dry_run_mode) print("anonymize user {}.".format(user.user_id)) cleanup_lib.anonymize_user( user, anonymized_user_display_name=parsed_args.anonymize_name) self._session.flush() print('user {} anonymized to "{} <{}/{}>".'.format( user.user_id, user.display_name, user.email, user.username)) print("~~~~~~~~~~")
def test_unit__delete_content__ok__nominal_case( self, session, app_config, content_type_list, content_api_factory, workspace_api_factory, share_lib_factory, ) -> None: content_api = content_api_factory.get(show_deleted=True, show_active=True, show_archived=True) workspace_api = workspace_api_factory.get() test_workspace = workspace_api.create_workspace("test_workspace") folder = content_api.create( label="test-folder", content_type_slug=content_type_list.Folder.slug, workspace=test_workspace, do_save=True, do_notify=False, ) folder_id = folder.content_id file_ = content_api.create( content_type_slug=content_type_list.File.slug, workspace=test_workspace, parent=folder, label="Test file", do_save=True, do_notify=False, ) file_id = file_.content_id comment = content_api.create_comment(workspace=test_workspace, parent=file_, content="Toto", do_save=True, do_notify=False) comment_id = comment.content_id share_api = share_lib_factory.get() shares = share_api.share_content(file_, emails=["*****@*****.**"]) share_id = shares[0].share_id session.flush() transaction.commit() assert content_api.get_one(folder_id, content_type=content_type_list.Any_SLUG) assert content_api.get_one(file_id, content_type=content_type_list.Any_SLUG) assert content_api.get_one(comment_id, content_type=content_type_list.Any_SLUG) assert session.query(ContentShare).filter( ContentShare.share_id == share_id).one() with unprotected_content_revision(session) as unprotected_session: cleanup_lib = CleanupLib(app_config=app_config, session=unprotected_session) cleanup_lib.delete_content(folder) session.flush() transaction.commit() with pytest.raises(ContentNotFound): content_api.get_one(folder_id, content_type=content_type_list.Any_SLUG) with pytest.raises(ContentNotFound): content_api.get_one(file_id, content_type=content_type_list.Any_SLUG) with pytest.raises(ContentNotFound): content_api.get_one(comment_id, content_type=content_type_list.Any_SLUG) with pytest.raises(NoResultFound): session.query(ContentShare).filter( ContentShare.share_id == share_id).one()
def test_unit__delete_revision__ok__delete_older_revision( self, admin_user, session, app_config, content_type_list, content_api_factory, workspace_api_factory, share_lib_factory, upload_permission_lib_factory, ) -> None: content_api = content_api_factory.get(show_deleted=True, show_active=True, show_archived=True) workspace_api = workspace_api_factory.get() test_workspace = workspace_api.create_workspace("test_workspace") session.add(test_workspace) folder = content_api.create( label="test-folder", content_type_slug=content_type_list.Folder.slug, workspace=test_workspace, do_save=True, do_notify=False, ) file_ = content_api.create( content_type_slug=content_type_list.File.slug, workspace=test_workspace, parent=folder, label="Test file", do_save=True, do_notify=False, ) with new_revision(session=session, tm=transaction.manager, content=file_): content_api.update_file_data(file_, "Test_file.txt", new_mimetype="plain/text", new_content=b"Test file") content_api.mark_read(file_) file_id = file_.content_id revisions = file_.revisions session.flush() transaction.commit() assert len(revisions) == 2 first_revision_id = revisions[0].revision_id second_revision_id = revisions[1].revision_id content = content_api.get_one(file_id, content_type=content_type_list.Any_SLUG) assert content assert content.revision.revision_id == second_revision_id assert (session.query(ContentRevisionRO).filter( ContentRevisionRO.revision_id == first_revision_id).one()) assert (session.query(ContentRevisionRO).filter( ContentRevisionRO.revision_id == second_revision_id).one()) assert (session.query(RevisionReadStatus).filter( RevisionReadStatus.revision_id == first_revision_id).one()) assert (session.query(RevisionReadStatus).filter( RevisionReadStatus.revision_id == second_revision_id).one()) with unprotected_content_revision(session) as unprotected_session: cleanup_lib = CleanupLib(app_config=app_config, session=unprotected_session) cleanup_lib.delete_revision(revision=revisions[0]) session.flush() transaction.commit() assert content assert content.revision.revision_id == second_revision_id assert (session.query(ContentRevisionRO).filter( ContentRevisionRO.revision_id == second_revision_id).one()) with pytest.raises(NoResultFound): assert (session.query(ContentRevisionRO).filter( ContentRevisionRO.revision_id == first_revision_id).one()) assert (session.query(RevisionReadStatus).filter( RevisionReadStatus.revision_id == second_revision_id).one()) with pytest.raises(NoResultFound): assert (session.query(RevisionReadStatus).filter( RevisionReadStatus.revision_id == first_revision_id).one())
def test_unit__delete_user_associated_data__ok__nominal_case( self, admin_user, session, app_config, content_type_list, content_api_factory, workspace_api_factory, share_lib_factory, upload_permission_lib_factory, ) -> None: content_api = content_api_factory.get(show_deleted=True, show_active=True, show_archived=True) workspace_api = workspace_api_factory.get() test_workspace = workspace_api.create_workspace("test_workspace") session.add(test_workspace) session.flush() workspace_id = test_workspace.workspace_id folder = content_api.create( label="test-folder", content_type_slug=content_type_list.Folder.slug, workspace=test_workspace, do_save=True, do_notify=False, ) folder_id = folder.content_id folder2 = content_api.create( label="test-folder2", content_type_slug=content_type_list.Folder.slug, workspace=test_workspace, do_save=True, do_notify=False, ) folder2_id = folder2.content_id file_ = content_api.create( content_type_slug=content_type_list.File.slug, workspace=test_workspace, parent=folder, label="Test file", do_save=True, do_notify=False, ) file_id = file_.content_id comment = content_api.create_comment(workspace=test_workspace, parent=file_, content="Toto", do_save=True, do_notify=False) comment_id = comment.content_id share_api = share_lib_factory.get() shares = share_api.share_content(file_, emails=["*****@*****.**"]) share_id = shares[0].share_id upload_permission_lib = upload_permission_lib_factory.get() upload_permissions = upload_permission_lib.add_permission_to_workspace( workspace=test_workspace, emails=["*****@*****.**"]) upload_permission_id = upload_permissions[0].upload_permission_id session.flush() transaction.commit() assert content_api.get_one(folder_id, content_type=content_type_list.Any_SLUG) assert content_api.get_one(file_id, content_type=content_type_list.Any_SLUG) assert content_api.get_one(comment_id, content_type=content_type_list.Any_SLUG) assert session.query(ContentShare).filter( ContentShare.share_id == share_id).one() assert (session.query(UploadPermission).filter( UploadPermission.upload_permission_id == upload_permission_id).one()) session.query(Workspace).filter( Workspace.workspace_id == workspace_id).one() with unprotected_content_revision(session) as unprotected_session: cleanup_lib = CleanupLib(app_config=app_config, session=unprotected_session) cleanup_lib.delete_user_associated_data(admin_user) session.flush() transaction.commit() # INFO - G.M - 2019-12-20 - workspace is not deleted by this method session.query(Workspace).filter( Workspace.workspace_id == workspace_id).one() with pytest.raises(NoResultFound): session.query(UserRoleInWorkspace).filter( UserRoleInWorkspace.workspace_id == workspace_id).one() with pytest.raises(NoResultFound): session.query(UploadPermission).filter( UploadPermission.workspace_id == workspace_id).one() with pytest.raises(ContentNotFound): content_api.get_one(folder2_id, content_type=content_type_list.Any_SLUG) with pytest.raises(ContentNotFound): content_api.get_one(folder_id, content_type=content_type_list.Any_SLUG) with pytest.raises(ContentNotFound): content_api.get_one(file_id, content_type=content_type_list.Any_SLUG) with pytest.raises(ContentNotFound): content_api.get_one(comment_id, content_type=content_type_list.Any_SLUG) with pytest.raises(NoResultFound): session.query(ContentShare).filter( ContentShare.share_id == share_id).one() with pytest.raises(NoResultFound): session.query(UploadPermission).filter( UploadPermission.upload_permission_id == upload_permission_id).one()
def take_app_action(self, parsed_args: argparse.Namespace, app_context: AppEnvironment) -> None: self._session = app_context["request"].dbsession self._app_config = app_context["registry"].settings["CFG"] delete_user_revision = parsed_args.force or parsed_args.delete_revisions delete_owned_sharespaces = (parsed_args.force or parsed_args.best_effort or parsed_args.delete_sharespaces) anonymize_if_required = parsed_args.best_effort or parsed_args.anonymize_if_required if parsed_args.dry_run_mode: print("(!) Running in dry-run mode, no changes will be applied.") app_context["request"].tm.doom() if parsed_args.force: print("(!) Running in force mode") if parsed_args.best_effort: print("(!) Running in best-effort mode") if delete_user_revision: print( "/!\\ Delete all user revisions, database created may be broken /!\\." ) if delete_owned_sharespaces: print("(!) User owned sharespaces will be deleted too.") if anonymize_if_required: print("(!) Will anonymize user if not possible to delete it") if parsed_args.anonymize_name: print('(!) Custom anonymize name choosen is: "{}"'.format( parsed_args.anonymize_name)) print("") deleted_user_ids = set() # typing.Set[int] deleted_workspace_ids = set() # typing.Set[int] with unprotected_content_revision(self._session) as session: uapi = UserApi( config=self._app_config, session=session, current_user=None, show_deleted=True, show_deactivated=True, ) user_list = [] # type: typing.List[User] for login in parsed_args.logins: try: user = uapi.get_one_by_login(login) user_list.append(user) except UserDoesNotExist as exc: print( 'ERROR: user with email/username "{}" does not exist'. format(login)) raise exc print("~~~~") print("Deletion of user from Database") print("~~~~\n") print("~~~~") for user in user_list: cleanup_lib = CleanupLib(session, self._app_config, dry_run_mode=parsed_args.dry_run_mode) deleted_user_ids_result = self._delete_user_database_info( user, force_delete_all_user_revisions=delete_user_revision, anonymize_if_required=anonymize_if_required, delete_owned_workspaces=delete_owned_sharespaces, anonymized_user_display_name=parsed_args.anonymize_name, cleanup_lib=cleanup_lib, ) deleted_user_ids.add(deleted_user_ids_result.user_id) deleted_workspace_ids.update( deleted_user_ids_result.workspace_ids) print("~~~~") print( "deletion of user(s) from database process almost finished, change will be applied at end " "of this script.\n") print("~~~~") print("Deletion of Caldav Agenda\n") app_lib = ApplicationApi(app_list=app_list) if app_lib.exist(AGENDA__APP_SLUG): # INFO - G.M - 2019-12-13 - cleanup agenda at end of process if deleted_workspace_ids: deleted_workspace_ids_str = [ '"{}"'.format(workspace_id) for workspace_id in deleted_workspace_ids ] print("delete agenda of workspaces {}".format( ", ".join(deleted_workspace_ids_str))) for workspace_id in deleted_workspace_ids: try: cleanup_lib.delete_workspace_agenda(workspace_id) except AgendaNotFoundError: print( 'Warning: Cannot delete agenda for workspace "{}", agenda not found. Agenda path may be incorrect or agenda not created' .format(workspace_id)) print(traceback.format_exc()) if deleted_user_ids: deleted_user_ids_str = [ '"{}"'.format(user_id) for user_id in deleted_user_ids ] print("delete agenda of users {}".format( ", ".join(deleted_user_ids_str))) for user_id in deleted_user_ids: try: cleanup_lib.delete_user_agenda(user_id) except AgendaNotFoundError: print( 'Warning: Cannot delete agenda for user "{}", agenda not found. Agenda path may be incorrect or agenda not created' .format(user_id)) print(traceback.format_exc()) else: print( "Warning ! Agenda app not enabled, agenda will not be deleted." ) print("~~~~") print("deletion of Agenda process finished") print("~~~~") if parsed_args.dry_run_mode: print("Finished (dry-run mode, no change applied)") else: print("Finished")