Skip to content

Commit

Permalink
log user creation timestamp (#3416)
Browse files Browse the repository at this point in the history
* use SQL's NOW() fct to log creation of a new user account (validated or not).

* at -> on

* add new col

* use patch for DB changes

* forgot to remove addition of comment here

* moving changes to patch 92

* move adding date from populate_test_db.sql to here

* revert changes, see patch

* adding table name :-/

* order in DB changed due to UPDATE of creation_timestamp for user [email protected]

* fix test
  • Loading branch information
sjanssen2 authored Jun 20, 2024
1 parent cca6de7 commit 8b3f717
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 12 deletions.
5 changes: 3 additions & 2 deletions qiita_db/handlers/tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ def test_get(self):

obs = loads(obs.body)
exp = {'data': [
{'email': '[email protected]', 'name': 'Dude'},
{'email': '[email protected]', 'name': 'Shared'},
{'email': '[email protected]', 'name': 'Admin'},
{'email': '[email protected]', 'name': 'Demo'}]}
{'email': '[email protected]', 'name': 'Demo'},
{'email': '[email protected]', 'name': 'Dude'}
]}
self.assertEqual(obs, exp)


Expand Down
13 changes: 13 additions & 0 deletions qiita_db/support_files/patches/92.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,16 @@ ALTER TABLE qiita.prep_template ADD current_human_filtering boolean DEFAULT Fals
-- Adding a new column: reprocess_job_id to qiita.prep_template to keep track of
-- the job that reprocessed this prep
ALTER TABLE qiita.prep_template ADD reprocess_job_id uuid DEFAULT NULL;

-- Jun 19, 2024
-- Adding a new column to the user table that logs when this account was created
-- Usefull e.g. to prune non-verified=inactive user or to plot user growth

ALTER TABLE qiita.qiita_user
ADD creation_timestamp timestamp without time zone DEFAULT NOW();

COMMENT ON COLUMN qiita.qiita_user.creation_timestamp IS 'The date the user account was created';

-- for testing: provide creation date for one of the existing users

UPDATE qiita.qiita_user SET creation_timestamp = '2015-12-03 13:52:42.751331-07' WHERE email = '[email protected]';
49 changes: 42 additions & 7 deletions qiita_db/test/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ def setUp(self):
'receive_processing_job_emails': True,
'social_orcid': None,
'social_researchgate': None,
'social_googlescholar': None
'social_googlescholar': None,
'creation_timestamp': datetime(2015, 12, 3, 13, 52, 42, 751331)
}

def tearDown(self):
Expand All @@ -88,7 +89,22 @@ def test_instantiate_unknown_user(self):
with self.assertRaises(qdb.exceptions.QiitaDBUnknownIDError):
qdb.user.User('[email protected]')

def _check_correct_info(self, obs, exp):
def _check_correct_info(self, obs, exp, ts_before=None):
"""Compares info dict of user with special handling of specific keys.
Parameters
----------
obs : dict
Observed user info dictionary.
exp : dict
Expected user info dictionary.
ts_before : datetime.datetime or None
User.create records the creation timestamp through SQL's NOW().
Since it is set by the database to the microsecond, we can't
predict it a priori and therefore simply record timestamp before
execution of user.create() and compare the relation.
The DB creation_timestamp column is optional, i.e. can be None.
"""
self.assertEqual(set(exp.keys()), set(obs.keys()))
for key in exp:
# user_verify_code and password seed randomly generated so just
Expand All @@ -97,10 +113,14 @@ def _check_correct_info(self, obs, exp):
self.assertEqual(len(obs[key]), 20)
elif key == "password":
self.assertEqual(len(obs[key]), 60)
elif key == "creation_timestamp":
self.assertTrue(((exp[key] is None) and (obs[key] is None))
or (ts_before <= exp[key]))
else:
self.assertEqual(obs[key], exp[key])

def test_create_user(self):
before = datetime.now()
user = qdb.user.User.create('[email protected]', 'password')

# adding a couple of messages
Expand Down Expand Up @@ -131,8 +151,9 @@ def test_create_user(self):
'email': '[email protected]',
'social_orcid': None,
'social_researchgate': None,
'social_googlescholar': None}
self._check_correct_info(obs, exp)
'social_googlescholar': None,
'creation_timestamp': datetime.now()}
self._check_correct_info(obs, exp, before)

# Make sure new system messages are linked to user
sql = """SELECT message_id FROM qiita.message_user
Expand All @@ -146,6 +167,7 @@ def test_create_user(self):
qdb.util.clear_system_messages()

def test_create_user_info(self):
before = datetime.now()
user = qdb.user.User.create('[email protected]', 'password',
self.userinfo)
self.assertEqual(user.id, '[email protected]')
Expand All @@ -171,8 +193,9 @@ def test_create_user_info(self):
'email': '[email protected]',
'social_orcid': None,
'social_researchgate': None,
'social_googlescholar': None}
self._check_correct_info(obs, exp)
'social_googlescholar': None,
'creation_timestamp': datetime.now()}
self._check_correct_info(obs, exp, before)

def test_create_user_column_not_allowed(self):
self.userinfo["email"] = "FAIL"
Expand Down Expand Up @@ -241,8 +264,20 @@ def test_get_info(self):
'phone': '222-444-6789',
'social_orcid': None,
'social_researchgate': None,
'social_googlescholar': None
'social_googlescholar': None,
'creation_timestamp': datetime(2015, 12, 3, 13, 52, 42, 751331)
}

# test database is re-populated during testing several times.
# Creation_timestamp depends on the percise timing of the repopulation,
# i.e. we cannot predict its value. We just test that this date should
# be within an hour and now. For the remainder of tests, we update
# our expectation.
self.assertTrue(datetime.now() - timedelta(hours=1) <
self.user.info['creation_timestamp'] <
datetime.now())
expinfo['creation_timestamp'] = self.user.info['creation_timestamp']

self.assertEqual(self.user.info, expinfo)

def test_set_info(self):
Expand Down
3 changes: 2 additions & 1 deletion qiita_db/test/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ def test_get_table_cols(self):
exp = {"email", "user_level_id", "password", "name", "affiliation",
"address", "phone", "user_verify_code", "pass_reset_code",
"pass_reset_timestamp", "receive_processing_job_emails",
"social_orcid", "social_researchgate", "social_googlescholar"}
"social_orcid", "social_researchgate", "social_googlescholar",
"creation_timestamp"}
self.assertEqual(set(obs), exp)

def test_exists_table(self):
Expand Down
8 changes: 6 additions & 2 deletions qiita_pet/handlers/user_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@ class UserProfileHandler(BaseHandler):
def get(self):
profile = UserProfile()
profile.process(data=self.current_user.info)
self.render("user_profile.html", profile=profile, msg="", passmsg="")
self.render("user_profile.html", profile=profile, msg="", passmsg="",
creation_timestamp=self.current_user.info[
'creation_timestamp'])

@authenticated
@execute_as_transaction
Expand Down Expand Up @@ -248,7 +250,9 @@ def post(self):
else:
passmsg = "Incorrect old password"
self.render("user_profile.html", user=user.id, profile=form_data,
msg=msg, passmsg=passmsg)
msg=msg, passmsg=passmsg,
creation_timestamp=self.current_user.info[
'creation_timestamp'])


class ForgotPasswordHandler(BaseHandler):
Expand Down
3 changes: 3 additions & 0 deletions qiita_pet/templates/user_profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ <h3>User Information</h3>
{% end %}
</div>
{% end %}
{%if creation_timestamp is not None %}
<div style="padding-left: 1em; padding-bottom: 1em; color: grey;">account created on {{creation_timestamp}}</div>
{% end %}
<div style="color:{% if msg.startswith('ERROR:') %}red{% else %}darkgreen{% end %};">{{msg}}</div>
<button type="submit" class="btn btn-success">Save Edits</button>
</form>
Expand Down

0 comments on commit 8b3f717

Please sign in to comment.