From 7e1c3e7f4afadb66f0e2b84f406bc97821f8c464 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Thu, 4 Oct 2018 23:33:09 +0200 Subject: [PATCH] users: add cronjob to delete users (#24430) --- tests/test_users.py | 49 ++++++++++++++++++++++++++++++++++++++++++++- wcs/publisher.py | 6 ++++++ wcs/sql.py | 13 ++++++++++++ wcs/users.py | 15 ++++++++++++++ 4 files changed, 82 insertions(+), 1 deletion(-) diff --git a/tests/test_users.py b/tests/test_users.py index fc44d6be5..6b29aafa4 100644 --- a/tests/test_users.py +++ b/tests/test_users.py @@ -1,7 +1,8 @@ +import datetime import shutil import pytest -from quixote import cleanup +from quixote import cleanup, get_publisher from wcs import fields from wcs.variables import LazyUser @@ -92,3 +93,49 @@ def test_user_formdef_getattr(): with pytest.raises(AttributeError): # noqa pylint: disable=pointless-statement user.xxx + + +def test_clean_deleted_users(): + from wcs.formdef import FormDef + from wcs.qommon import storage as st + + User = pub.user_class + + User.wipe() + FormDef.wipe() + + formdef = FormDef() + formdef.name = 'foobar' + formdef.url_name = 'foobar' + formdef.fields = [] + formdef.store() + data_class = formdef.data_class() + + user1 = User() + user1.name = 'Pierre' + user1.deleted_timestamp = datetime.datetime.now() + user1.store() + + user2 = User() + user2.name = 'Jean' + user2.deleted_timestamp = datetime.datetime.now() + user2.store() + + formdata1 = data_class() + formdata1.user_id = user1.id + formdata1.store() + + assert User.count() == 2 + + get_publisher().clean_deleted_users() + + assert User.count() == 1 + + assert len(User.select([st.Equal('name', 'Pierre')])) == 1 + assert len(User.select([st.Equal('name', 'Jean')])) == 0 + + data_class.wipe() + + get_publisher().clean_deleted_users() + + assert User.count() == 0 diff --git a/wcs/publisher.py b/wcs/publisher.py index 28742dfa1..f35a91ef1 100644 --- a/wcs/publisher.py +++ b/wcs/publisher.py @@ -123,6 +123,8 @@ class WcsPublisher(QommonPublisher): cls.register_cronjob( CronJob(cls.update_deprecations_report, name='update_deprecations_report', hours=[2], minutes=[0]) ) + # once a day delete users without any formdata + cls.register_cronjob(CronJob(cls.clean_deleted_users, name='clean_deleted_users', minutes=[0])) # other jobs data_sources.register_cronjob() formdef.register_cronjobs() @@ -508,6 +510,10 @@ class WcsPublisher(QommonPublisher): return value_.get_value() return value_ + def clean_deleted_users(self): + for user_id in self.user_class.get_to_delete_ids(): + self.user_class.remove_object(user_id) + set_publisher_class(WcsPublisher) WcsPublisher.register_extra_dir(os.path.join(os.path.dirname(__file__), 'extra')) diff --git a/wcs/sql.py b/wcs/sql.py index 5ba8d68e4..8a6a6dec3 100644 --- a/wcs/sql.py +++ b/wcs/sql.py @@ -3248,6 +3248,19 @@ class SqlUser(SqlMixin, wcs.users.User): return objects + @classmethod + def get_to_delete_ids(cls): + conn, cur = get_connection_and_cursor() + sql_statement = '''SELECT users.id + FROM users LEFT JOIN wcs_all_forms ON users.id = CAST(wcs_all_forms.user_id AS INTEGER) + WHERE users.deleted_timestamp IS NOT NULL + AND wcs_all_forms.id IS NULL''' + cur.execute(sql_statement) + deleted_ids = [user_id for user_id, in cur.fetchall()] + conn.commit() + cur.close() + return deleted_ids + class Role(SqlMixin, wcs.roles.Role): _table_name = 'roles' diff --git a/wcs/users.py b/wcs/users.py index 176b3aabb..92bd71211 100644 --- a/wcs/users.py +++ b/wcs/users.py @@ -320,6 +320,21 @@ class User(StorableObject): def get_full_name(self): return self.display_name + @classmethod + def get_to_delete_ids(cls): + from .formdef import FormDef + + deleted_ids = {user.id for user in cls.select([st.NotNull('deleted_timestamp')])} + + active_ids = set() + for formdef in FormDef.select(): + data_class = formdef.data_class() + active_ids.update( + formdata.user_id for formdata in data_class.select(iterator=True) if formdata.user_id + ) + + return deleted_ids - active_ids + Substitutions.register( 'session_user_display_name', -- 2.36.1