From 0f53e66d8103b29ea8654bdfd86e0eec2c350662 Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Sat, 14 Feb 2026 23:33:25 +0100 Subject: [PATCH 01/10] Replace login keys with one-time passwords --- evap/development/fixtures/test_data.json | 1906 ----------------- evap/evaluation/auth.py | 17 +- .../management/commands/anonymize.py | 13 +- .../migrations/0161_login_key_to_otp_hash.py | 42 + evap/evaluation/models.py | 111 +- evap/evaluation/tests/test_auth.py | 64 +- evap/evaluation/tests/test_commands.py | 2 - evap/evaluation/tests/test_models.py | 11 +- evap/evaluation/urls.py | 2 +- evap/evaluation/views.py | 42 +- .../fixtures/minimal_test_data_results.json | 18 - evap/settings.py | 8 +- evap/staff/tests/test_tools.py | 2 - evap/staff/tests/test_views.py | 16 +- evap/staff/tools.py | 3 +- evap/staff/views.py | 9 +- 16 files changed, 210 insertions(+), 2056 deletions(-) create mode 100644 evap/evaluation/migrations/0161_login_key_to_otp_hash.py diff --git a/evap/development/fixtures/test_data.json b/evap/development/fixtures/test_data.json index 30cea69ace..be6bc82776 100644 --- a/evap/development/fixtures/test_data.json +++ b/evap/development/fixtures/test_data.json @@ -130782,8 +130782,6 @@ "last_name": "Schulz", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -130807,8 +130805,6 @@ "last_name": "Joe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -130832,8 +130828,6 @@ "last_name": "Whitlow", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -130857,8 +130851,6 @@ "last_name": "Perales", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2012-04-21", "is_active": true, "notes": "", "startpage": "DE", @@ -130882,8 +130874,6 @@ "last_name": "Welsh", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -130907,8 +130897,6 @@ "last_name": "Armstead", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -130932,8 +130920,6 @@ "last_name": "Ponder", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -130957,8 +130943,6 @@ "last_name": "Janes", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -130982,8 +130966,6 @@ "last_name": "Caraway", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131007,8 +130989,6 @@ "last_name": "Lyons", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131032,8 +131012,6 @@ "last_name": "Hemphill", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131057,8 +131035,6 @@ "last_name": "Honeycutt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131082,8 +131058,6 @@ "last_name": "Lattimore", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131107,8 +131081,6 @@ "last_name": "Reichert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131132,8 +131104,6 @@ "last_name": "Dixon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131157,8 +131127,6 @@ "last_name": "Hollingsworth", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131182,8 +131150,6 @@ "last_name": "Chisholm", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131207,8 +131173,6 @@ "last_name": "Starr", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131232,8 +131196,6 @@ "last_name": "Baptiste", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131257,8 +131219,6 @@ "last_name": "Hooper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131282,8 +131242,6 @@ "last_name": "Brandon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131307,8 +131265,6 @@ "last_name": "Moon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131332,8 +131288,6 @@ "last_name": "Haase", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131357,8 +131311,6 @@ "last_name": "Ly", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131382,8 +131334,6 @@ "last_name": "Shah", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131407,8 +131357,6 @@ "last_name": "Lachance", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131432,8 +131380,6 @@ "last_name": "Fairbanks", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131457,8 +131403,6 @@ "last_name": "Shuler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131482,8 +131426,6 @@ "last_name": "Lea", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131507,8 +131449,6 @@ "last_name": "Christie", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131532,8 +131472,6 @@ "last_name": "Ali", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131557,8 +131495,6 @@ "last_name": "Hoskins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131582,8 +131518,6 @@ "last_name": "Byers", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131607,8 +131541,6 @@ "last_name": "York", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131632,8 +131564,6 @@ "last_name": "Varner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131657,8 +131587,6 @@ "last_name": "Caban", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131682,8 +131610,6 @@ "last_name": "Mccorkle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131707,8 +131633,6 @@ "last_name": "Maldonado", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131732,8 +131656,6 @@ "last_name": "Cooper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131757,8 +131679,6 @@ "last_name": "Chaffin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131782,8 +131702,6 @@ "last_name": "Leboeuf", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131807,8 +131725,6 @@ "last_name": "Strain", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131832,8 +131748,6 @@ "last_name": "Guffey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131857,8 +131771,6 @@ "last_name": "David", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131882,8 +131794,6 @@ "last_name": "Sell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131907,8 +131817,6 @@ "last_name": "Horvath", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131932,8 +131840,6 @@ "last_name": "Sandoval", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131957,8 +131863,6 @@ "last_name": "Lowell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -131982,8 +131886,6 @@ "last_name": "Gerard", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132007,8 +131909,6 @@ "last_name": "Treadwell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132032,8 +131932,6 @@ "last_name": "Woodbury", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132057,8 +131955,6 @@ "last_name": "Reno", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132082,8 +131978,6 @@ "last_name": "Pope", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132107,8 +132001,6 @@ "last_name": "Craddock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132132,8 +132024,6 @@ "last_name": "Barringer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132157,8 +132047,6 @@ "last_name": "Sager", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132182,8 +132070,6 @@ "last_name": "Boisvert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132207,8 +132093,6 @@ "last_name": "Krug", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132232,8 +132116,6 @@ "last_name": "Apodaca", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132257,8 +132139,6 @@ "last_name": "Savage", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132282,8 +132162,6 @@ "last_name": "Russo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132307,8 +132185,6 @@ "last_name": "Andrade", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132332,8 +132208,6 @@ "last_name": "Kent", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132357,8 +132231,6 @@ "last_name": "Trombley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132382,8 +132254,6 @@ "last_name": "Hope", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132407,8 +132277,6 @@ "last_name": "Runyon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132432,8 +132300,6 @@ "last_name": "Carlton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132457,8 +132323,6 @@ "last_name": "Weatherly", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132482,8 +132346,6 @@ "last_name": "Skinner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132507,8 +132369,6 @@ "last_name": "Kline", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132537,8 +132397,6 @@ "last_name": "Rico", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132562,8 +132420,6 @@ "last_name": "Berry", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132587,8 +132443,6 @@ "last_name": "Cheung", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132612,8 +132466,6 @@ "last_name": "Doughty", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132637,8 +132489,6 @@ "last_name": "Carlton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132662,8 +132512,6 @@ "last_name": "Gilson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132687,8 +132535,6 @@ "last_name": "Tillery", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132712,8 +132558,6 @@ "last_name": "Callahan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132737,8 +132581,6 @@ "last_name": "Healy", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132762,8 +132604,6 @@ "last_name": "Krueger", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132787,8 +132627,6 @@ "last_name": "Palumbo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132812,8 +132650,6 @@ "last_name": "Brigham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132837,8 +132673,6 @@ "last_name": "Edwards", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132862,8 +132696,6 @@ "last_name": "Dabbs", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132887,8 +132719,6 @@ "last_name": "Shackelford", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132912,8 +132742,6 @@ "last_name": "Bickford", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132937,8 +132765,6 @@ "last_name": "Fontenot", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132962,8 +132788,6 @@ "last_name": "Neil", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -132987,8 +132811,6 @@ "last_name": "Lehman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133012,8 +132834,6 @@ "last_name": "Seibert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133037,8 +132857,6 @@ "last_name": "Clement", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133062,8 +132880,6 @@ "last_name": "Jack", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133087,8 +132903,6 @@ "last_name": "Chance", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133112,8 +132926,6 @@ "last_name": "Mcfarlane", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133137,8 +132949,6 @@ "last_name": "Vandiver", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133162,8 +132972,6 @@ "last_name": "Fry", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133187,8 +132995,6 @@ "last_name": "Simon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133212,8 +133018,6 @@ "last_name": "Hauser", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133237,8 +133041,6 @@ "last_name": "Bowers", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133262,8 +133064,6 @@ "last_name": "Patrick", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133287,8 +133087,6 @@ "last_name": "Ly", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133312,8 +133110,6 @@ "last_name": "Durbin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133337,8 +133133,6 @@ "last_name": "Steward", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133364,8 +133158,6 @@ "last_name": "Woodbury", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133389,8 +133181,6 @@ "last_name": "Thornburg", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133416,8 +133206,6 @@ "last_name": "Carlisle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133441,8 +133229,6 @@ "last_name": "Hirsch", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133466,8 +133252,6 @@ "last_name": "Estrella", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133491,8 +133275,6 @@ "last_name": "Villalobos", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133516,8 +133298,6 @@ "last_name": "Worsham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133541,8 +133321,6 @@ "last_name": "Mcmillian", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133566,8 +133344,6 @@ "last_name": "Sparkman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133591,8 +133367,6 @@ "last_name": "Martz", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133619,8 +133393,6 @@ "last_name": "Ives", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133644,8 +133416,6 @@ "last_name": "Parkinson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133669,8 +133439,6 @@ "last_name": "Murray", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133694,8 +133462,6 @@ "last_name": "Gage", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133723,8 +133489,6 @@ "last_name": "Herring", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133750,8 +133514,6 @@ "last_name": "Huffman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133775,8 +133537,6 @@ "last_name": "Tremblay", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133800,8 +133560,6 @@ "last_name": "Booker", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133825,8 +133583,6 @@ "last_name": "Tuttle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133850,8 +133606,6 @@ "last_name": "Hollingsworth", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133877,8 +133631,6 @@ "last_name": "Hancock", "language": "", "is_proxy_user": false, - "login_key": 841793788, - "login_key_valid_until": "2013-09-30", "is_active": true, "notes": "", "startpage": "DE", @@ -133905,8 +133657,6 @@ "last_name": "responsible", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133933,8 +133683,6 @@ "last_name": "Faust", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133958,8 +133706,6 @@ "last_name": "Flanagan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -133983,8 +133729,6 @@ "last_name": "Desimone", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134008,8 +133752,6 @@ "last_name": "Prater", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134033,8 +133775,6 @@ "last_name": "Isaacs", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134058,8 +133798,6 @@ "last_name": "Mayfield", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134083,8 +133821,6 @@ "last_name": "Langlois", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134108,8 +133844,6 @@ "last_name": "Nagle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134133,8 +133867,6 @@ "last_name": "Isaacson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134158,8 +133890,6 @@ "last_name": "Manson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134183,8 +133913,6 @@ "last_name": "Hoffman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134208,8 +133936,6 @@ "last_name": "Clevenger", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134233,8 +133959,6 @@ "last_name": "Pinkston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134258,8 +133982,6 @@ "last_name": "Holliman", "language": "", "is_proxy_user": false, - "login_key": 1551612459, - "login_key_valid_until": "2013-09-17", "is_active": true, "notes": "", "startpage": "DE", @@ -134286,8 +134008,6 @@ "last_name": "Rudd", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134311,8 +134031,6 @@ "last_name": "Wicks", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134336,8 +134054,6 @@ "last_name": "Steed", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134361,8 +134077,6 @@ "last_name": "Clawson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134386,8 +134100,6 @@ "last_name": "Clemmons", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134411,8 +134123,6 @@ "last_name": "Hermann", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134436,8 +134146,6 @@ "last_name": "Vann", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134461,8 +134169,6 @@ "last_name": "Leonard", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134488,8 +134194,6 @@ "last_name": "Robison", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134513,8 +134217,6 @@ "last_name": "Benoit", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134541,8 +134243,6 @@ "last_name": "Cano", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134566,8 +134266,6 @@ "last_name": "Erickson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134591,8 +134289,6 @@ "last_name": "Tipton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134616,8 +134312,6 @@ "last_name": "Biddle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134641,8 +134335,6 @@ "last_name": "Hargrove", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134666,8 +134358,6 @@ "last_name": "Squires", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134691,8 +134381,6 @@ "last_name": "Luttrell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134716,8 +134404,6 @@ "last_name": "Rhoads", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134741,8 +134427,6 @@ "last_name": "Hicks", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134766,8 +134450,6 @@ "last_name": "Taber", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134791,8 +134473,6 @@ "last_name": "Lindley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134816,8 +134496,6 @@ "last_name": "Gracia", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134841,8 +134519,6 @@ "last_name": "Billups", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134866,8 +134542,6 @@ "last_name": "Dial", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134891,8 +134565,6 @@ "last_name": "Barnette", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134916,8 +134588,6 @@ "last_name": "Hadden", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134941,8 +134611,6 @@ "last_name": "Lance", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134966,8 +134634,6 @@ "last_name": "Mcgee", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -134991,8 +134657,6 @@ "last_name": "Gonsalves", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135016,8 +134680,6 @@ "last_name": "Saddler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135041,8 +134703,6 @@ "last_name": "Lemke", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135066,8 +134726,6 @@ "last_name": "Crumpton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135091,8 +134749,6 @@ "last_name": "Leblanc", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135116,8 +134772,6 @@ "last_name": "Henke", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135141,8 +134795,6 @@ "last_name": "Cushman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135166,8 +134818,6 @@ "last_name": "Boisvert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135191,8 +134841,6 @@ "last_name": "Mata", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135216,8 +134864,6 @@ "last_name": "Morse", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135241,8 +134887,6 @@ "last_name": "Jean", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2012-10-01", "is_active": true, "notes": "", "startpage": "DE", @@ -135266,8 +134910,6 @@ "last_name": "Judkins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135291,8 +134933,6 @@ "last_name": "Winters", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135316,8 +134956,6 @@ "last_name": "Easley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135341,8 +134979,6 @@ "last_name": "Sims", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135366,8 +135002,6 @@ "last_name": "Felts", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135391,8 +135025,6 @@ "last_name": "Israel", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135416,8 +135048,6 @@ "last_name": "Eaves", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135441,8 +135071,6 @@ "last_name": "Crowley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135466,8 +135094,6 @@ "last_name": "Gallardo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135491,8 +135117,6 @@ "last_name": "Kohler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135516,8 +135140,6 @@ "last_name": "Olds", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135541,8 +135163,6 @@ "last_name": "Cress", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135566,8 +135186,6 @@ "last_name": "Terry", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135591,8 +135209,6 @@ "last_name": "Dill", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135616,8 +135232,6 @@ "last_name": "Fontenot", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135641,8 +135255,6 @@ "last_name": "Quintanilla", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135666,8 +135278,6 @@ "last_name": "Burnham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135691,8 +135301,6 @@ "last_name": "Montanez", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135716,8 +135324,6 @@ "last_name": "Kaplan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135741,8 +135347,6 @@ "last_name": "Sharkey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135766,8 +135370,6 @@ "last_name": "Buckingham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135791,8 +135393,6 @@ "last_name": "Casanova", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135816,8 +135416,6 @@ "last_name": "Murillo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135841,8 +135439,6 @@ "last_name": "Vest", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135866,8 +135462,6 @@ "last_name": "Sutter", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135891,8 +135485,6 @@ "last_name": "Hagen", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135916,8 +135508,6 @@ "last_name": "Boatright", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135941,8 +135531,6 @@ "last_name": "Dunlap", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135966,8 +135554,6 @@ "last_name": "Davison", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -135991,8 +135577,6 @@ "last_name": "Hart", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136016,8 +135600,6 @@ "last_name": "Mays", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136041,8 +135623,6 @@ "last_name": "Rushing", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136078,8 +135658,6 @@ "last_name": "Barfield", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136103,8 +135681,6 @@ "last_name": "Galbraith", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136128,8 +135704,6 @@ "last_name": "Baber", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136153,8 +135727,6 @@ "last_name": "Rutledge", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136178,8 +135750,6 @@ "last_name": "Kimbrough", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136203,8 +135773,6 @@ "last_name": "Najera", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136228,8 +135796,6 @@ "last_name": "Hart", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136253,8 +135819,6 @@ "last_name": "Mcneill", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136278,8 +135842,6 @@ "last_name": "Moultrie", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136303,8 +135865,6 @@ "last_name": "Lamb", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136328,8 +135888,6 @@ "last_name": "Godfrey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136353,8 +135911,6 @@ "last_name": "Baughman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136378,8 +135934,6 @@ "last_name": "Blankenship", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136403,8 +135957,6 @@ "last_name": "Kirkland", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136428,8 +135980,6 @@ "last_name": "Bickford", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136453,8 +136003,6 @@ "last_name": "Carper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136478,8 +136026,6 @@ "last_name": "Curtin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136503,8 +136049,6 @@ "last_name": "Rawlins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136528,8 +136072,6 @@ "last_name": "Lindsey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136553,8 +136095,6 @@ "last_name": "Lunsford", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136578,8 +136118,6 @@ "last_name": "Carrier", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136603,8 +136141,6 @@ "last_name": "Huynh", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136628,8 +136164,6 @@ "last_name": "Alfonso", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136653,8 +136187,6 @@ "last_name": "Beall", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136678,8 +136210,6 @@ "last_name": "Aiken", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136703,8 +136233,6 @@ "last_name": "Kimmel", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136728,8 +136256,6 @@ "last_name": "Brock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136753,8 +136279,6 @@ "last_name": "Spivey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136778,8 +136302,6 @@ "last_name": "Burbank", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136803,8 +136325,6 @@ "last_name": "Belt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136828,8 +136348,6 @@ "last_name": "Mullins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136853,8 +136371,6 @@ "last_name": "Lugo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136878,8 +136394,6 @@ "last_name": "Conway", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136903,8 +136417,6 @@ "last_name": "Huggins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136928,8 +136440,6 @@ "last_name": "Chaffin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136953,8 +136463,6 @@ "last_name": "Burgos", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -136978,8 +136486,6 @@ "last_name": "Aguilera", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137003,8 +136509,6 @@ "last_name": "Pike", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137028,8 +136532,6 @@ "last_name": "Fried", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137053,8 +136555,6 @@ "last_name": "Abner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137078,8 +136578,6 @@ "last_name": "Soper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137103,8 +136601,6 @@ "last_name": "Mclain", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137128,8 +136624,6 @@ "last_name": "Landry", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137153,8 +136647,6 @@ "last_name": "Bean", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137178,8 +136670,6 @@ "last_name": "Cloutier", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137203,8 +136693,6 @@ "last_name": "delegate", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137228,8 +136716,6 @@ "last_name": "Waldrop", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137253,8 +136739,6 @@ "last_name": "Farley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137278,8 +136762,6 @@ "last_name": "Culver", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137303,8 +136785,6 @@ "last_name": "Crouse", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137328,8 +136808,6 @@ "last_name": "Steed", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137353,8 +136831,6 @@ "last_name": "Ryan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137378,8 +136854,6 @@ "last_name": "Anthony", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137403,8 +136877,6 @@ "last_name": "Tolliver", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137428,8 +136900,6 @@ "last_name": "Ruby", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137453,8 +136923,6 @@ "last_name": "Buford", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137478,8 +136946,6 @@ "last_name": "Switzer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137503,8 +136969,6 @@ "last_name": "Linder", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137528,8 +136992,6 @@ "last_name": "Landrum", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137553,8 +137015,6 @@ "last_name": "Antoine", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2012-05-10", "is_active": true, "notes": "", "startpage": "DE", @@ -137578,8 +137038,6 @@ "last_name": "Song", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137603,8 +137061,6 @@ "last_name": "editor", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137628,8 +137084,6 @@ "last_name": "Pond", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137653,8 +137107,6 @@ "last_name": "Voigt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137678,8 +137130,6 @@ "last_name": "Estrella", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137703,8 +137153,6 @@ "last_name": "Jennings", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137728,8 +137176,6 @@ "last_name": "Scales", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137753,8 +137199,6 @@ "last_name": "Swank", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137778,8 +137222,6 @@ "last_name": "Clapp", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137803,8 +137245,6 @@ "last_name": "Meador", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137828,8 +137268,6 @@ "last_name": "Yarbrough", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137853,8 +137291,6 @@ "last_name": "Chitwood", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137878,8 +137314,6 @@ "last_name": "Christie", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137903,8 +137337,6 @@ "last_name": "Rau", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137928,8 +137360,6 @@ "last_name": "Villanueva", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137953,8 +137383,6 @@ "last_name": "Fairchild", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -137978,8 +137406,6 @@ "last_name": "Ceja", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138003,8 +137429,6 @@ "last_name": "Thorp", "language": "", "is_proxy_user": false, - "login_key": 658405473, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -138034,8 +137458,6 @@ "last_name": "Rees", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138059,8 +137481,6 @@ "last_name": "Osborne", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138084,8 +137504,6 @@ "last_name": "Lane", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138109,8 +137527,6 @@ "last_name": "Coker", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138136,8 +137552,6 @@ "last_name": "Alvarez", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138161,8 +137575,6 @@ "last_name": "Tran", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138186,8 +137598,6 @@ "last_name": "Gamboa", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138211,8 +137621,6 @@ "last_name": "Park", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138239,8 +137647,6 @@ "last_name": "Grove", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138264,8 +137670,6 @@ "last_name": "Grace", "language": "", "is_proxy_user": false, - "login_key": 630273331, - "login_key_valid_until": "2014-12-01", "is_active": true, "notes": "", "startpage": "DE", @@ -138292,8 +137696,6 @@ "last_name": "Branson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138317,8 +137719,6 @@ "last_name": "Seymour", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138342,8 +137742,6 @@ "last_name": "Everett", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138367,8 +137765,6 @@ "last_name": "Cano", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138392,8 +137788,6 @@ "last_name": "Cross", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138417,8 +137811,6 @@ "last_name": "Knight", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138442,8 +137834,6 @@ "last_name": "Rowley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138467,8 +137857,6 @@ "last_name": "Tennant", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138492,8 +137880,6 @@ "last_name": "Meek", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138517,8 +137903,6 @@ "last_name": "Roller", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138542,8 +137926,6 @@ "last_name": "Sanchez", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138567,8 +137949,6 @@ "last_name": "Batson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138592,8 +137972,6 @@ "last_name": "Freese", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138617,8 +137995,6 @@ "last_name": "Thorn", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2013-05-16", "is_active": true, "notes": "", "startpage": "DE", @@ -138642,8 +138018,6 @@ "last_name": "Moultrie", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138667,8 +138041,6 @@ "last_name": "Thayer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138692,8 +138064,6 @@ "last_name": "Truong", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138717,8 +138087,6 @@ "last_name": "Connor", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138742,8 +138110,6 @@ "last_name": "Roche", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138767,8 +138133,6 @@ "last_name": "Wahl", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138792,8 +138156,6 @@ "last_name": "Kober", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138817,8 +138179,6 @@ "last_name": "Westmoreland", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138842,8 +138202,6 @@ "last_name": "Hanley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138867,8 +138225,6 @@ "last_name": "Castellano", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138892,8 +138248,6 @@ "last_name": "student", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138917,8 +138271,6 @@ "last_name": "Cate", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138942,8 +138294,6 @@ "last_name": "Melendez", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138967,8 +138317,6 @@ "last_name": "Weinstein", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -138992,8 +138340,6 @@ "last_name": "Gooch", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139017,8 +138363,6 @@ "last_name": "Houghton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139042,8 +138386,6 @@ "last_name": "Hatch", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139067,8 +138409,6 @@ "last_name": "Shuler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139092,8 +138432,6 @@ "last_name": "Woody", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139117,8 +138455,6 @@ "last_name": "Early", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139142,8 +138478,6 @@ "last_name": "Metcalf", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139167,8 +138501,6 @@ "last_name": "Copeland", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139192,8 +138524,6 @@ "last_name": "Burkholder", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139217,8 +138547,6 @@ "last_name": "Dolan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139242,8 +138570,6 @@ "last_name": "Alley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139267,8 +138593,6 @@ "last_name": "Byrne", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139292,8 +138616,6 @@ "last_name": "Baker", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139317,8 +138639,6 @@ "last_name": "Lucas", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139342,8 +138662,6 @@ "last_name": "Huang", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139367,8 +138685,6 @@ "last_name": "Marquardt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139392,8 +138708,6 @@ "last_name": "Heflin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139417,8 +138731,6 @@ "last_name": "Earl", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139442,8 +138754,6 @@ "last_name": "Kinard", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139467,8 +138777,6 @@ "last_name": "Loera", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139492,8 +138800,6 @@ "last_name": "Sharp", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139517,8 +138823,6 @@ "last_name": "Chandler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139542,8 +138846,6 @@ "last_name": "Knotts", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139567,8 +138869,6 @@ "last_name": "Regan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139592,8 +138892,6 @@ "last_name": "Sawyer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139617,8 +138915,6 @@ "last_name": "Monahan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139642,8 +138938,6 @@ "last_name": "Helton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139667,8 +138961,6 @@ "last_name": "Erwin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139692,8 +138984,6 @@ "last_name": "Berger", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139717,8 +139007,6 @@ "last_name": "contributor", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139742,8 +139030,6 @@ "last_name": "Robertson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139767,8 +139053,6 @@ "last_name": "Howe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139792,8 +139076,6 @@ "last_name": "Kitchens", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139817,8 +139099,6 @@ "last_name": "Rawlings", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139842,8 +139122,6 @@ "last_name": "Vernon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139867,8 +139145,6 @@ "last_name": "Bowles", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139892,8 +139168,6 @@ "last_name": "Ybarra", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139917,8 +139191,6 @@ "last_name": "Marquis", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139946,8 +139218,6 @@ "last_name": "Box", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139971,8 +139241,6 @@ "last_name": "Slagle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -139996,8 +139264,6 @@ "last_name": "Boston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140021,8 +139287,6 @@ "last_name": "Boykin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140046,8 +139310,6 @@ "last_name": "Jay", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140071,8 +139333,6 @@ "last_name": "Olson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140096,8 +139356,6 @@ "last_name": "Nieves", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140121,8 +139379,6 @@ "last_name": "Cody", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140146,8 +139402,6 @@ "last_name": "Cleveland", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140171,8 +139425,6 @@ "last_name": "England", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140196,8 +139448,6 @@ "last_name": "Hyde", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140221,8 +139471,6 @@ "last_name": "Pfeiffer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2013-09-28", "is_active": true, "notes": "", "startpage": "DE", @@ -140246,8 +139494,6 @@ "last_name": "Moe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140271,8 +139517,6 @@ "last_name": "Aiello", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140296,8 +139540,6 @@ "last_name": "Ellis", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140321,8 +139563,6 @@ "last_name": "Humes", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140346,8 +139586,6 @@ "last_name": "Dortch", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140375,8 +139613,6 @@ "last_name": "Hendrick", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140400,8 +139636,6 @@ "last_name": "Reis", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140425,8 +139659,6 @@ "last_name": "Strange", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140450,8 +139682,6 @@ "last_name": "Soares", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140475,8 +139705,6 @@ "last_name": "Hermann", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140500,8 +139728,6 @@ "last_name": "Limon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140525,8 +139751,6 @@ "last_name": "Oldham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140550,8 +139774,6 @@ "last_name": "Holcomb", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140575,8 +139797,6 @@ "last_name": "Godfrey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140600,8 +139820,6 @@ "last_name": "Blaylock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140625,8 +139843,6 @@ "last_name": "Comstock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140650,8 +139866,6 @@ "last_name": "Arsenault", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140675,8 +139889,6 @@ "last_name": "Thurston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140700,8 +139912,6 @@ "last_name": "Nakamura", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140725,8 +139935,6 @@ "last_name": "Spears", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140750,8 +139958,6 @@ "last_name": "Reiss", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140775,8 +139981,6 @@ "last_name": "Ezell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140800,8 +140004,6 @@ "last_name": "Voigt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140825,8 +140027,6 @@ "last_name": "Spalding", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140850,8 +140050,6 @@ "last_name": "Luna", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140875,8 +140073,6 @@ "last_name": "Nobles", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140900,8 +140096,6 @@ "last_name": "Washington", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140925,8 +140119,6 @@ "last_name": "Vandiver", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140950,8 +140142,6 @@ "last_name": "Hammer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -140975,8 +140165,6 @@ "last_name": "Craddock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141000,8 +140188,6 @@ "last_name": "Childers", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141025,8 +140211,6 @@ "last_name": "Ivory", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141050,8 +140234,6 @@ "last_name": "Chaffin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141075,8 +140257,6 @@ "last_name": "Stearns", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141100,8 +140280,6 @@ "last_name": "Smalley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141125,8 +140303,6 @@ "last_name": "Carbone", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141150,8 +140326,6 @@ "last_name": "Kay", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141175,8 +140349,6 @@ "last_name": "Covert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141200,8 +140372,6 @@ "last_name": "Manzo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141225,8 +140395,6 @@ "last_name": "Bates", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141250,8 +140418,6 @@ "last_name": "Coe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141275,8 +140441,6 @@ "last_name": "Lowell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141300,8 +140464,6 @@ "last_name": "Carney", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141325,8 +140487,6 @@ "last_name": "Mattingly", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141350,8 +140510,6 @@ "last_name": "Kell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2012-05-08", "is_active": true, "notes": "", "startpage": "DE", @@ -141375,8 +140533,6 @@ "last_name": "Sandlin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141400,8 +140556,6 @@ "last_name": "Amaya", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141425,8 +140579,6 @@ "last_name": "Dexter", "language": "", "is_proxy_user": false, - "login_key": 979985223, - "login_key_valid_until": "2020-05-25", "is_active": true, "notes": "", "startpage": "DE", @@ -141450,8 +140602,6 @@ "last_name": "Swenson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141475,8 +140625,6 @@ "last_name": "Bohn", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141500,8 +140648,6 @@ "last_name": "Dew", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141525,8 +140671,6 @@ "last_name": "Kasper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141550,8 +140694,6 @@ "last_name": "Campos", "language": "", "is_proxy_user": false, - "login_key": 1818483627, - "login_key_valid_until": "2020-05-25", "is_active": true, "notes": "", "startpage": "DE", @@ -141575,8 +140717,6 @@ "last_name": "Weddle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141600,8 +140740,6 @@ "last_name": "Middleton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141625,8 +140763,6 @@ "last_name": "Battles", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141650,8 +140786,6 @@ "last_name": "Cooper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141675,8 +140809,6 @@ "last_name": "Almond", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141700,8 +140832,6 @@ "last_name": "Briscoe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141725,8 +140855,6 @@ "last_name": "Sosa", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141750,8 +140878,6 @@ "last_name": "Moll", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141775,8 +140901,6 @@ "last_name": "Bettencourt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141800,8 +140924,6 @@ "last_name": "Greenlee", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141825,8 +140947,6 @@ "last_name": "Robb", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141850,8 +140970,6 @@ "last_name": "Walker", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141875,8 +140993,6 @@ "last_name": "Stern", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141900,8 +141016,6 @@ "last_name": "Ainsworth", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141925,8 +141039,6 @@ "last_name": "Schuler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141950,8 +141062,6 @@ "last_name": "Earnest", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -141975,8 +141085,6 @@ "last_name": "Carrasco", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142000,8 +141108,6 @@ "last_name": "Arce", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142025,8 +141131,6 @@ "last_name": "Wills", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142050,8 +141154,6 @@ "last_name": "Hale", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142075,8 +141177,6 @@ "last_name": "Lester", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-01-30", "is_active": true, "notes": "", "startpage": "DE", @@ -142104,8 +141204,6 @@ "last_name": "Mcdade", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142129,8 +141227,6 @@ "last_name": "evap", "language": "de", "is_proxy_user": false, - "login_key": 530207530, - "login_key_valid_until": "2020-05-25", "is_active": true, "notes": "", "startpage": "DE", @@ -142161,8 +141257,6 @@ "last_name": "Fowler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142186,8 +141280,6 @@ "last_name": "Kersey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142211,8 +141303,6 @@ "last_name": "Bobbitt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142236,8 +141326,6 @@ "last_name": "Goodson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142261,8 +141349,6 @@ "last_name": "Worley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142286,8 +141372,6 @@ "last_name": "Heard", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142311,8 +141395,6 @@ "last_name": "Bottoms", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142336,8 +141418,6 @@ "last_name": "Whittington", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142361,8 +141441,6 @@ "last_name": "Caron", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142386,8 +141464,6 @@ "last_name": "Leatherman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142411,8 +141487,6 @@ "last_name": "Pearl", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142436,8 +141510,6 @@ "last_name": "Compton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142461,8 +141533,6 @@ "last_name": "Keel", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142486,8 +141556,6 @@ "last_name": "Henry", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142511,8 +141579,6 @@ "last_name": "Dejesus", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142536,8 +141602,6 @@ "last_name": "Cupp", "language": "", "is_proxy_user": false, - "login_key": 71453046, - "login_key_valid_until": "2020-05-25", "is_active": true, "notes": "", "startpage": "DE", @@ -142561,8 +141625,6 @@ "last_name": "Zaragoza", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142586,8 +141648,6 @@ "last_name": "Bridges", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142611,8 +141671,6 @@ "last_name": "Leung", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142636,8 +141694,6 @@ "last_name": "Broome", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142661,8 +141717,6 @@ "last_name": "Furr", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142686,8 +141740,6 @@ "last_name": "Timmerman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142711,8 +141763,6 @@ "last_name": "Carlton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142736,8 +141786,6 @@ "last_name": "Mcclintock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142761,8 +141809,6 @@ "last_name": "Bolt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142786,8 +141832,6 @@ "last_name": "Oakley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142811,8 +141855,6 @@ "last_name": "Tompkins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142836,8 +141878,6 @@ "last_name": "Ulrich", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142861,8 +141901,6 @@ "last_name": "Stump", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142886,8 +141924,6 @@ "last_name": "Grigsby", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142911,8 +141947,6 @@ "last_name": "Negrete", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142936,8 +141970,6 @@ "last_name": "Hammonds", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142961,8 +141993,6 @@ "last_name": "Lomax", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -142986,8 +142016,6 @@ "last_name": "Rivera", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143011,8 +142039,6 @@ "last_name": "Gregory", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143036,8 +142062,6 @@ "last_name": "Briggs", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143061,8 +142085,6 @@ "last_name": "Kimble", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143086,8 +142108,6 @@ "last_name": "Hamblin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143111,8 +142131,6 @@ "last_name": "Ledbetter", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143136,8 +142154,6 @@ "last_name": "Oconnor", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2013-12-22", "is_active": true, "notes": "", "startpage": "DE", @@ -143161,8 +142177,6 @@ "last_name": "Fowlkes", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143186,8 +142200,6 @@ "last_name": "Fuqua", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143211,8 +142223,6 @@ "last_name": "Engle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143236,8 +142246,6 @@ "last_name": "Cabrera", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143261,8 +142269,6 @@ "last_name": "Thacker", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143286,8 +142292,6 @@ "last_name": "Rawlins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143311,8 +142315,6 @@ "last_name": "Root", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143336,8 +142338,6 @@ "last_name": "Moe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143361,8 +142361,6 @@ "last_name": "Bohannon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143386,8 +142384,6 @@ "last_name": "Large", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143411,8 +142407,6 @@ "last_name": "Cochran", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143436,8 +142430,6 @@ "last_name": "Orta", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143461,8 +142453,6 @@ "last_name": "Larry", "language": "", "is_proxy_user": false, - "login_key": 1209312068, - "login_key_valid_until": "2020-05-25", "is_active": true, "notes": "", "startpage": "DE", @@ -143486,8 +142476,6 @@ "last_name": "Heaton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143511,8 +142499,6 @@ "last_name": "Guerrero", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143536,8 +142522,6 @@ "last_name": "Kraft", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143561,8 +142545,6 @@ "last_name": "Vega", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143586,8 +142568,6 @@ "last_name": "Fredrickson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143611,8 +142591,6 @@ "last_name": "Valerio", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143636,8 +142614,6 @@ "last_name": "Carranza", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143661,8 +142637,6 @@ "last_name": "Denman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143686,8 +142660,6 @@ "last_name": "Samples", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143711,8 +142683,6 @@ "last_name": "Feliciano", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143736,8 +142706,6 @@ "last_name": "Barnard", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2013-05-07", "is_active": true, "notes": "", "startpage": "DE", @@ -143761,8 +142729,6 @@ "last_name": "Bauer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143786,8 +142752,6 @@ "last_name": "Grigsby", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143811,8 +142775,6 @@ "last_name": "Bolton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143836,8 +142798,6 @@ "last_name": "Ruth", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143861,8 +142821,6 @@ "last_name": "Labonte", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143886,8 +142844,6 @@ "last_name": "Olds", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143911,8 +142867,6 @@ "last_name": "Casas", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143936,8 +142890,6 @@ "last_name": "Maier", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143961,8 +142913,6 @@ "last_name": "Ferro", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -143986,8 +142936,6 @@ "last_name": "Easley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144011,8 +142959,6 @@ "last_name": "Holden", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144036,8 +142982,6 @@ "last_name": "Carrington", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144061,8 +143005,6 @@ "last_name": "Burns", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144086,8 +143028,6 @@ "last_name": "Mccartney", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144111,8 +143051,6 @@ "last_name": "Roybal", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144136,8 +143074,6 @@ "last_name": "Gee", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144161,8 +143097,6 @@ "last_name": "Hyde", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144186,8 +143120,6 @@ "last_name": "Mcmullen", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144211,8 +143143,6 @@ "last_name": "Malcolm", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144236,8 +143166,6 @@ "last_name": "Ferraro", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144261,8 +143189,6 @@ "last_name": "Stump", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144286,8 +143212,6 @@ "last_name": "Kelly", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144311,8 +143235,6 @@ "last_name": "Spearman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144336,8 +143258,6 @@ "last_name": "Mcdougall", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144361,8 +143281,6 @@ "last_name": "Burnette", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144386,8 +143304,6 @@ "last_name": "Puente", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144411,8 +143327,6 @@ "last_name": "Cady", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144436,8 +143350,6 @@ "last_name": "Hastings", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144461,8 +143373,6 @@ "last_name": "Isaac", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144486,8 +143396,6 @@ "last_name": "Medeiros", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144511,8 +143419,6 @@ "last_name": "Gall", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144536,8 +143442,6 @@ "last_name": "Childs", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144561,8 +143465,6 @@ "last_name": "Rust", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144586,8 +143488,6 @@ "last_name": "Peacock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144611,8 +143511,6 @@ "last_name": "Staley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144636,8 +143534,6 @@ "last_name": "Grubbs", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144661,8 +143557,6 @@ "last_name": "Thorne", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144686,8 +143580,6 @@ "last_name": "Rayburn", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144711,8 +143603,6 @@ "last_name": "Lu", "language": "", "is_proxy_user": false, - "login_key": 679371237, - "login_key_valid_until": "2020-05-25", "is_active": true, "notes": "", "startpage": "DE", @@ -144736,8 +143626,6 @@ "last_name": "Deluca", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144761,8 +143649,6 @@ "last_name": "Trammell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144786,8 +143672,6 @@ "last_name": "Calkins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144811,8 +143695,6 @@ "last_name": "Dellinger", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144836,8 +143718,6 @@ "last_name": "Bounds", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144861,8 +143741,6 @@ "last_name": "Rose", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144886,8 +143764,6 @@ "last_name": "Reedy", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144911,8 +143787,6 @@ "last_name": "Michael", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144936,8 +143810,6 @@ "last_name": "Langston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144961,8 +143833,6 @@ "last_name": "Price", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -144986,8 +143856,6 @@ "last_name": "Cheng", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145011,8 +143879,6 @@ "last_name": "Timmons", "language": "", "is_proxy_user": false, - "login_key": 1639072630, - "login_key_valid_until": "2012-05-14", "is_active": true, "notes": "", "startpage": "DE", @@ -145039,8 +143905,6 @@ "last_name": "Dominguez", "language": "", "is_proxy_user": false, - "login_key": 500083702, - "login_key_valid_until": "2014-10-27", "is_active": true, "notes": "", "startpage": "DE", @@ -145067,8 +143931,6 @@ "last_name": "Seitz", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145092,8 +143954,6 @@ "last_name": "Bridges", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145117,8 +143977,6 @@ "last_name": "Mondragon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145142,8 +144000,6 @@ "last_name": "Powell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145167,8 +144023,6 @@ "last_name": "Tisdale", "language": "", "is_proxy_user": false, - "login_key": 2127579123, - "login_key_valid_until": "2013-03-04", "is_active": true, "notes": "", "startpage": "DE", @@ -145192,8 +144046,6 @@ "last_name": "Little", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145217,8 +144069,6 @@ "last_name": "Durand", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145242,8 +144092,6 @@ "last_name": "Homan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145267,8 +144115,6 @@ "last_name": "Parrott", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145292,8 +144138,6 @@ "last_name": "Hooks", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145317,8 +144161,6 @@ "last_name": "Minor", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145342,8 +144184,6 @@ "last_name": "Higdon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145367,8 +144207,6 @@ "last_name": "Lloyd", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2013-05-21", "is_active": true, "notes": "", "startpage": "DE", @@ -145392,8 +144230,6 @@ "last_name": "Cartwright", "language": "", "is_proxy_user": false, - "login_key": 3816853, - "login_key_valid_until": "2013-02-21", "is_active": true, "notes": "", "startpage": "DE", @@ -145417,8 +144253,6 @@ "last_name": "Shephard", "language": "", "is_proxy_user": false, - "login_key": 1456662462, - "login_key_valid_until": "2013-12-23", "is_active": true, "notes": "", "startpage": "DE", @@ -145442,8 +144276,6 @@ "last_name": "Bolden", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145467,8 +144299,6 @@ "last_name": "Rector", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145492,8 +144322,6 @@ "last_name": "Hudgins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145517,8 +144345,6 @@ "last_name": "Jacoby", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145542,8 +144368,6 @@ "last_name": "Naquin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145567,8 +144391,6 @@ "last_name": "Bassett", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145592,8 +144414,6 @@ "last_name": "Lockett", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145617,8 +144437,6 @@ "last_name": "Hansen", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145642,8 +144460,6 @@ "last_name": "Mancini", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145667,8 +144483,6 @@ "last_name": "Trevino", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145692,8 +144506,6 @@ "last_name": "Bobbitt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145717,8 +144529,6 @@ "last_name": "Matthews", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145742,8 +144552,6 @@ "last_name": "Wild", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145767,8 +144575,6 @@ "last_name": "Masterson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145792,8 +144598,6 @@ "last_name": "Galvan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145817,8 +144621,6 @@ "last_name": "Saunders", "language": "", "is_proxy_user": false, - "login_key": 28628139, - "login_key_valid_until": "2014-11-10", "is_active": true, "notes": "", "startpage": "DE", @@ -145845,8 +144647,6 @@ "last_name": "Higdon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145873,8 +144673,6 @@ "last_name": "Hills", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145898,8 +144696,6 @@ "last_name": "Harman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145923,8 +144719,6 @@ "last_name": "Helms", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145948,8 +144742,6 @@ "last_name": "Fleck", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145973,8 +144765,6 @@ "last_name": "Griffith", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -145998,8 +144788,6 @@ "last_name": "Pressley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146023,8 +144811,6 @@ "last_name": "Mccleary", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146048,8 +144834,6 @@ "last_name": "Mccallister", "language": "", "is_proxy_user": false, - "login_key": 1219355322, - "login_key_valid_until": "2012-10-07", "is_active": true, "notes": "", "startpage": "DE", @@ -146073,8 +144857,6 @@ "last_name": "Heath", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146100,8 +144882,6 @@ "last_name": "Fulton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146125,8 +144905,6 @@ "last_name": "Scruggs", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146153,8 +144931,6 @@ "last_name": "Huffman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146181,8 +144957,6 @@ "last_name": "Liu", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146208,8 +144982,6 @@ "last_name": "Grier", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146233,8 +145005,6 @@ "last_name": "Eagle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146258,8 +145028,6 @@ "last_name": "Canada", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146283,8 +145051,6 @@ "last_name": "Gagne", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146308,8 +145074,6 @@ "last_name": "Casillas", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146333,8 +145097,6 @@ "last_name": "Paul", "language": "", "is_proxy_user": false, - "login_key": 1729717352, - "login_key_valid_until": "2012-10-03", "is_active": true, "notes": "", "startpage": "DE", @@ -146358,8 +145120,6 @@ "last_name": "Huntley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146383,8 +145143,6 @@ "last_name": "Stock", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146408,8 +145166,6 @@ "last_name": "Gann", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146433,8 +145189,6 @@ "last_name": "Draper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146458,8 +145212,6 @@ "last_name": "Yoo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146483,8 +145235,6 @@ "last_name": "Escamilla", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146508,8 +145258,6 @@ "last_name": "Wolfe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146533,8 +145281,6 @@ "last_name": "Desimone", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146558,8 +145304,6 @@ "last_name": "Maldonado", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146583,8 +145327,6 @@ "last_name": "Johnson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146608,8 +145350,6 @@ "last_name": "Langdon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146633,8 +145373,6 @@ "last_name": "Osteen", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146658,8 +145396,6 @@ "last_name": "Hammond", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146683,8 +145419,6 @@ "last_name": "Osorio", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146708,8 +145442,6 @@ "last_name": "Peeler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146733,8 +145465,6 @@ "last_name": "Macias", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146758,8 +145488,6 @@ "last_name": "Mcmullen", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146783,8 +145511,6 @@ "last_name": "Bey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146808,8 +145534,6 @@ "last_name": "Gooding", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146833,8 +145557,6 @@ "last_name": "Lemus", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146858,8 +145580,6 @@ "last_name": "Child", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146883,8 +145603,6 @@ "last_name": "Patten", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146908,8 +145626,6 @@ "last_name": "Ellington", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146933,8 +145649,6 @@ "last_name": "Briscoe", "language": "", "is_proxy_user": false, - "login_key": 1049235434, - "login_key_valid_until": "2014-08-26", "is_active": true, "notes": "", "startpage": "DE", @@ -146961,8 +145675,6 @@ "last_name": "Marshall", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -146986,8 +145698,6 @@ "last_name": "Marcum", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147011,8 +145721,6 @@ "last_name": "Huntington", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147036,8 +145744,6 @@ "last_name": "Reichert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147061,8 +145767,6 @@ "last_name": "Navarrete", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147086,8 +145790,6 @@ "last_name": "Dent", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147111,8 +145813,6 @@ "last_name": "Grantham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147136,8 +145836,6 @@ "last_name": "Huang", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147161,8 +145859,6 @@ "last_name": "Luciano", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147186,8 +145882,6 @@ "last_name": "Page", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147211,8 +145905,6 @@ "last_name": "Troy", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147236,8 +145928,6 @@ "last_name": "Raney", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147261,8 +145951,6 @@ "last_name": "Slade", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147286,8 +145974,6 @@ "last_name": "Hopkins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147311,8 +145997,6 @@ "last_name": "Sierra", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147336,8 +146020,6 @@ "last_name": "Angel", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147361,8 +146043,6 @@ "last_name": "Mccall", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147386,8 +146066,6 @@ "last_name": "England", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147411,8 +146089,6 @@ "last_name": "Mcdade", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147436,8 +146112,6 @@ "last_name": "Rocha", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147461,8 +146135,6 @@ "last_name": "Sales", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147486,8 +146158,6 @@ "last_name": "Putnam", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147511,8 +146181,6 @@ "last_name": "Chesser", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147536,8 +146204,6 @@ "last_name": "Ackerman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147561,8 +146227,6 @@ "last_name": "Cranford", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147586,8 +146250,6 @@ "last_name": "Clancy", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147611,8 +146273,6 @@ "last_name": "Stamper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147636,8 +146296,6 @@ "last_name": "Norwood", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147661,8 +146319,6 @@ "last_name": "Hogue", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147690,8 +146346,6 @@ "last_name": "Sabo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147715,8 +146369,6 @@ "last_name": "Ruby", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147740,8 +146392,6 @@ "last_name": "Mccauley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147765,8 +146415,6 @@ "last_name": "Piazza", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147790,8 +146438,6 @@ "last_name": "Crawford", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147815,8 +146461,6 @@ "last_name": "Andrew", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147840,8 +146484,6 @@ "last_name": "Joyner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147865,8 +146507,6 @@ "last_name": "Stricklin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147890,8 +146530,6 @@ "last_name": "Leger", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147915,8 +146553,6 @@ "last_name": "Earley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147940,8 +146576,6 @@ "last_name": "Noonan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147965,8 +146599,6 @@ "last_name": "Browne", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -147990,8 +146622,6 @@ "last_name": "Belcher", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148015,8 +146645,6 @@ "last_name": "Hawkins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148040,8 +146668,6 @@ "last_name": "Bussey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148065,8 +146691,6 @@ "last_name": "Maple", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148090,8 +146714,6 @@ "last_name": "Watters", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148115,8 +146737,6 @@ "last_name": "Hitt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148140,8 +146760,6 @@ "last_name": "Mcallister", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148165,8 +146783,6 @@ "last_name": "Hoffmann", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148190,8 +146806,6 @@ "last_name": "Pitcher", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148215,8 +146829,6 @@ "last_name": "Baptiste", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148240,8 +146852,6 @@ "last_name": "Ness", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148265,8 +146875,6 @@ "last_name": "Glynn", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148290,8 +146898,6 @@ "last_name": "Robins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148315,8 +146921,6 @@ "last_name": "Nall", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148340,8 +146944,6 @@ "last_name": "Ferro", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148365,8 +146967,6 @@ "last_name": "Rasmussen", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148390,8 +146990,6 @@ "last_name": "Willingham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148415,8 +147013,6 @@ "last_name": "Fortier", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148440,8 +147036,6 @@ "last_name": "Guay", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148465,8 +147059,6 @@ "last_name": "Horne", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148490,8 +147082,6 @@ "last_name": "Daily", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148515,8 +147105,6 @@ "last_name": "Engle", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148540,8 +147128,6 @@ "last_name": "Baughman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148565,8 +147151,6 @@ "last_name": "David", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148590,8 +147174,6 @@ "last_name": "Marr", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148615,8 +147197,6 @@ "last_name": "Greenberg", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148640,8 +147220,6 @@ "last_name": "Devore", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148665,8 +147243,6 @@ "last_name": "Goodrich", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148690,8 +147266,6 @@ "last_name": "Buck", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148715,8 +147289,6 @@ "last_name": "Heck", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148740,8 +147312,6 @@ "last_name": "Mcduffie", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148765,8 +147335,6 @@ "last_name": "Andre", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148790,8 +147358,6 @@ "last_name": "Carlton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148815,8 +147381,6 @@ "last_name": "Cortez", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148840,8 +147404,6 @@ "last_name": "Castellanos", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148865,8 +147427,6 @@ "last_name": "Behrens", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148890,8 +147450,6 @@ "last_name": "Phillip", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148915,8 +147473,6 @@ "last_name": "West", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148940,8 +147496,6 @@ "last_name": "Turney", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148965,8 +147519,6 @@ "last_name": "Dow", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -148990,8 +147542,6 @@ "last_name": "Thurman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149015,8 +147565,6 @@ "last_name": "Surratt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149040,8 +147588,6 @@ "last_name": "Arreola", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149065,8 +147611,6 @@ "last_name": "Gilmer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149090,8 +147634,6 @@ "last_name": "Burr", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149115,8 +147657,6 @@ "last_name": "Farr", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149140,8 +147680,6 @@ "last_name": "Dozier", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149165,8 +147703,6 @@ "last_name": "Aldridge", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149190,8 +147726,6 @@ "last_name": "Greco", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149215,8 +147749,6 @@ "last_name": "Bess", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149240,8 +147772,6 @@ "last_name": "Mattson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149265,8 +147795,6 @@ "last_name": "Tobias", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149290,8 +147818,6 @@ "last_name": "Metzler", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149315,8 +147841,6 @@ "last_name": "Mcnutt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149340,8 +147864,6 @@ "last_name": "Bannister", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149365,8 +147887,6 @@ "last_name": "Picard", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149390,8 +147910,6 @@ "last_name": "Oreilly", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149415,8 +147933,6 @@ "last_name": "Ault", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149440,8 +147956,6 @@ "last_name": "Brownlee", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149465,8 +147979,6 @@ "last_name": "Soliz", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149490,8 +148002,6 @@ "last_name": "Neff", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149515,8 +148025,6 @@ "last_name": "Spear", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149540,8 +148048,6 @@ "last_name": "Oliver", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149565,8 +148071,6 @@ "last_name": "Call", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149590,8 +148094,6 @@ "last_name": "Handy", "language": "", "is_proxy_user": false, - "login_key": 165190195, - "login_key_valid_until": "2014-08-11", "is_active": true, "notes": "", "startpage": "DE", @@ -149618,8 +148120,6 @@ "last_name": "Brantley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149643,8 +148143,6 @@ "last_name": "Mcnamee", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149668,8 +148166,6 @@ "last_name": "Robins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149693,8 +148189,6 @@ "last_name": "Peters", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149718,8 +148212,6 @@ "last_name": "Deloach", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149743,8 +148235,6 @@ "last_name": "Best", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149768,8 +148258,6 @@ "last_name": "Rinehart", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149793,8 +148281,6 @@ "last_name": "Snow", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149818,8 +148304,6 @@ "last_name": "Pederson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149843,8 +148327,6 @@ "last_name": "Grisham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2013-05-30", "is_active": true, "notes": "", "startpage": "DE", @@ -149868,8 +148350,6 @@ "last_name": "Reich", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149893,8 +148373,6 @@ "last_name": "Mcculloch", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149918,8 +148396,6 @@ "last_name": "Harden", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149943,8 +148419,6 @@ "last_name": "Frasier", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149968,8 +148442,6 @@ "last_name": "Hanna", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -149993,8 +148465,6 @@ "last_name": "Bloom", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150018,8 +148488,6 @@ "last_name": "Rubio", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150043,8 +148511,6 @@ "last_name": "Forster", "language": "", "is_proxy_user": false, - "login_key": 210979156, - "login_key_valid_until": "2014-10-28", "is_active": true, "notes": "", "startpage": "DE", @@ -150068,8 +148534,6 @@ "last_name": "Benoit", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-01-21", "is_active": true, "notes": "", "startpage": "DE", @@ -150093,8 +148557,6 @@ "last_name": "Gaston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150118,8 +148580,6 @@ "last_name": "Brady", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150143,8 +148603,6 @@ "last_name": "Earley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150168,8 +148626,6 @@ "last_name": "Tarver", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150193,8 +148649,6 @@ "last_name": "Griffiths", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -150218,8 +148672,6 @@ "last_name": "Chadwick", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150243,8 +148695,6 @@ "last_name": "Person", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150268,8 +148718,6 @@ "last_name": "Swank", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150293,8 +148741,6 @@ "last_name": "Dibble", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150318,8 +148764,6 @@ "last_name": "Galbraith", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150343,8 +148787,6 @@ "last_name": "Talbert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150368,8 +148810,6 @@ "last_name": "Crocker", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150393,8 +148833,6 @@ "last_name": "Omalley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150418,8 +148856,6 @@ "last_name": "Mcnair", "language": "", "is_proxy_user": false, - "login_key": 2120134533, - "login_key_valid_until": "2014-08-11", "is_active": true, "notes": "", "startpage": "DE", @@ -150446,8 +148882,6 @@ "last_name": "Ingraham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150471,8 +148905,6 @@ "last_name": "Bettencourt", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150496,8 +148928,6 @@ "last_name": "Petrie", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150521,8 +148951,6 @@ "last_name": "Carson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150546,8 +148974,6 @@ "last_name": "Dolan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150571,8 +148997,6 @@ "last_name": "Simone", "language": "", "is_proxy_user": false, - "login_key": 983446795, - "login_key_valid_until": "2013-10-17", "is_active": true, "notes": "", "startpage": "DE", @@ -150596,8 +149020,6 @@ "last_name": "Mcmahan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150621,8 +149043,6 @@ "last_name": "Hanna", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150646,8 +149066,6 @@ "last_name": "Limon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150671,8 +149089,6 @@ "last_name": "Hammonds", "language": "", "is_proxy_user": false, - "login_key": 740394133, - "login_key_valid_until": "2013-12-22", "is_active": true, "notes": "", "startpage": "DE", @@ -150696,8 +149112,6 @@ "last_name": "Latimer", "language": "", "is_proxy_user": false, - "login_key": 822319998, - "login_key_valid_until": "2013-12-22", "is_active": true, "notes": "", "startpage": "DE", @@ -150721,8 +149135,6 @@ "last_name": "Russell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150746,8 +149158,6 @@ "last_name": "Earnest", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150771,8 +149181,6 @@ "last_name": "Rucker", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150796,8 +149204,6 @@ "last_name": "Poole", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150821,8 +149227,6 @@ "last_name": "Pinto", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150846,8 +149250,6 @@ "last_name": "Roy", "language": "", "is_proxy_user": false, - "login_key": 2052836776, - "login_key_valid_until": "2013-10-17", "is_active": true, "notes": "", "startpage": "DE", @@ -150871,8 +149273,6 @@ "last_name": "Petit", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150896,8 +149296,6 @@ "last_name": "Gresham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150921,8 +149319,6 @@ "last_name": "Whalen", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150946,8 +149342,6 @@ "last_name": "Morey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -150971,8 +149365,6 @@ "last_name": "Hinojosa", "language": "", "is_proxy_user": false, - "login_key": 2076676098, - "login_key_valid_until": "2013-10-18", "is_active": true, "notes": "", "startpage": "DE", @@ -150996,8 +149388,6 @@ "last_name": "Loya", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151021,8 +149411,6 @@ "last_name": "Calvert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151046,8 +149434,6 @@ "last_name": "Schreiner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151071,8 +149457,6 @@ "last_name": "Nation", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151096,8 +149480,6 @@ "last_name": "Hacker", "language": "", "is_proxy_user": false, - "login_key": 1692681790, - "login_key_valid_until": "2013-10-19", "is_active": true, "notes": "", "startpage": "DE", @@ -151121,8 +149503,6 @@ "last_name": "Rousseau", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151146,8 +149526,6 @@ "last_name": "Castro", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151171,8 +149549,6 @@ "last_name": "Hutchins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151196,8 +149572,6 @@ "last_name": "Broussard", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151221,8 +149595,6 @@ "last_name": "Barrientos", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151246,8 +149618,6 @@ "last_name": "Huang", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151271,8 +149641,6 @@ "last_name": "Draper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151296,8 +149664,6 @@ "last_name": "Beavers", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151321,8 +149687,6 @@ "last_name": "Ellison", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151346,8 +149710,6 @@ "last_name": "Snider", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151371,8 +149733,6 @@ "last_name": "Couture", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151396,8 +149756,6 @@ "last_name": "Akers", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151421,8 +149779,6 @@ "last_name": "Sherry", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151446,8 +149802,6 @@ "last_name": "Sam", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151471,8 +149825,6 @@ "last_name": "Bogan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151496,8 +149848,6 @@ "last_name": "Canady", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151521,8 +149871,6 @@ "last_name": "Paradis", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151546,8 +149894,6 @@ "last_name": "Breaux", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151571,8 +149917,6 @@ "last_name": "Glaser", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151596,8 +149940,6 @@ "last_name": "Edwards", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151621,8 +149963,6 @@ "last_name": "Guzman", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151646,8 +149986,6 @@ "last_name": "Flannery", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151671,8 +150009,6 @@ "last_name": "Talley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151696,8 +150032,6 @@ "last_name": "Jasper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151721,8 +150055,6 @@ "last_name": "Melendez", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151746,8 +150078,6 @@ "last_name": "Tennant", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151771,8 +150101,6 @@ "last_name": "Boyce", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -151796,8 +150124,6 @@ "last_name": "Boykin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151821,8 +150147,6 @@ "last_name": "Jordon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151846,8 +150170,6 @@ "last_name": "Rowe", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151871,8 +150193,6 @@ "last_name": "Wilke", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151896,8 +150216,6 @@ "last_name": "Lowell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151921,8 +150239,6 @@ "last_name": "True", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151946,8 +150262,6 @@ "last_name": "Stamper", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151971,8 +150285,6 @@ "last_name": "Wick", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -151996,8 +150308,6 @@ "last_name": "Pham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152021,8 +150331,6 @@ "last_name": "Aguiar", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152046,8 +150354,6 @@ "last_name": "Waggoner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152071,8 +150377,6 @@ "last_name": "Ewing", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152096,8 +150400,6 @@ "last_name": "Dillon", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152121,8 +150423,6 @@ "last_name": "Toro", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152146,8 +150446,6 @@ "last_name": "Askew", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152171,8 +150469,6 @@ "last_name": "Stroup", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152196,8 +150492,6 @@ "last_name": "Webber", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152221,8 +150515,6 @@ "last_name": "Bourne", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152246,8 +150538,6 @@ "last_name": "Dempsey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152271,8 +150561,6 @@ "last_name": "Gooden", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152296,8 +150584,6 @@ "last_name": "Groff", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152321,8 +150607,6 @@ "last_name": "Salter", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152346,8 +150630,6 @@ "last_name": "Willingham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152371,8 +150653,6 @@ "last_name": "Conrad", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152396,8 +150676,6 @@ "last_name": "Mcghee", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152421,8 +150699,6 @@ "last_name": "Brinkley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152446,8 +150722,6 @@ "last_name": "Caraballo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152471,8 +150745,6 @@ "last_name": "Kern", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152496,8 +150768,6 @@ "last_name": "Lister", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -152521,8 +150791,6 @@ "last_name": "Hendrick", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152546,8 +150814,6 @@ "last_name": "Grant", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152571,8 +150837,6 @@ "last_name": "Veal", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152596,8 +150860,6 @@ "last_name": "Lashley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152621,8 +150883,6 @@ "last_name": "Newby", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152646,8 +150906,6 @@ "last_name": "manager", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152675,8 +150933,6 @@ "last_name": "Rinaldi", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152700,8 +150956,6 @@ "last_name": "Corbin", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152725,8 +150979,6 @@ "last_name": "Burkholder", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152750,8 +151002,6 @@ "last_name": "Brody", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152775,8 +151025,6 @@ "last_name": "Oakes", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152800,8 +151048,6 @@ "last_name": "Galvan", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152825,8 +151071,6 @@ "last_name": "Findley", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152850,8 +151094,6 @@ "last_name": "Sierra", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152875,8 +151117,6 @@ "last_name": "Storey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152900,8 +151140,6 @@ "last_name": "Martindale", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152925,8 +151163,6 @@ "last_name": "Somerville", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152950,8 +151186,6 @@ "last_name": "Echols", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -152975,8 +151209,6 @@ "last_name": "Maurer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153000,8 +151232,6 @@ "last_name": "Pulido", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153025,8 +151255,6 @@ "last_name": "Trice", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153050,8 +151278,6 @@ "last_name": "Gallardo", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153075,8 +151301,6 @@ "last_name": "Turner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153100,8 +151324,6 @@ "last_name": "Cobb", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153125,8 +151347,6 @@ "last_name": "Orr", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153150,8 +151370,6 @@ "last_name": "Ritchey", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153175,8 +151393,6 @@ "last_name": "Logue", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153200,8 +151416,6 @@ "last_name": "Bunnell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153225,8 +151439,6 @@ "last_name": "Kiefer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153250,8 +151462,6 @@ "last_name": "Tibbetts", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153275,8 +151485,6 @@ "last_name": "Simpkins", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153300,8 +151508,6 @@ "last_name": "Singer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153325,8 +151531,6 @@ "last_name": "Loya", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153350,8 +151554,6 @@ "last_name": "Slattery", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153375,8 +151577,6 @@ "last_name": "See", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153400,8 +151600,6 @@ "last_name": "Jewell", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153425,8 +151623,6 @@ "last_name": "Mckay", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153450,8 +151646,6 @@ "last_name": "Lord", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153475,8 +151669,6 @@ "last_name": "Sales", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153500,8 +151692,6 @@ "last_name": "Hills", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153525,8 +151715,6 @@ "last_name": "Zarate", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153550,8 +151738,6 @@ "last_name": "Mcafee", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153575,8 +151761,6 @@ "last_name": "Gillette", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153600,8 +151784,6 @@ "last_name": "Copeland", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153625,8 +151807,6 @@ "last_name": "Everson", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153650,8 +151830,6 @@ "last_name": "Luong", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153675,8 +151853,6 @@ "last_name": "Hare", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153700,8 +151876,6 @@ "last_name": "Post", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153725,8 +151899,6 @@ "last_name": "Pinkston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153750,8 +151922,6 @@ "last_name": "Washington", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153775,8 +151945,6 @@ "last_name": "Hubert", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153800,8 +151968,6 @@ "last_name": "Hay", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153825,8 +151991,6 @@ "last_name": "Rafferty", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153850,8 +152014,6 @@ "last_name": "Bivens", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153875,8 +152037,6 @@ "last_name": "Gorham", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153900,8 +152060,6 @@ "last_name": "Hutchison", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153925,8 +152083,6 @@ "last_name": "Valles", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -153950,8 +152106,6 @@ "last_name": "Perron", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -153975,8 +152129,6 @@ "last_name": "Alston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154000,8 +152152,6 @@ "last_name": "Park", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -154025,8 +152175,6 @@ "last_name": "Reece", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154050,8 +152198,6 @@ "last_name": "Gardiner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154075,8 +152221,6 @@ "last_name": "Vergara", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": "2014-08-06", "is_active": true, "notes": "", "startpage": "DE", @@ -154100,8 +152244,6 @@ "last_name": "Soriano", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154127,8 +152269,6 @@ "last_name": "Flannery", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154152,8 +152292,6 @@ "last_name": "Eaton", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154177,8 +152315,6 @@ "last_name": "Cantu", "language": "", "is_proxy_user": false, - "login_key": 16347808, - "login_key_valid_until": "2014-10-26", "is_active": true, "notes": "", "startpage": "DE", @@ -154202,8 +152338,6 @@ "last_name": "Locke", "language": "", "is_proxy_user": false, - "login_key": 702798179, - "login_key_valid_until": "2014-08-21", "is_active": true, "notes": "", "startpage": "DE", @@ -154230,8 +152364,6 @@ "last_name": "Bustamante", "language": "", "is_proxy_user": false, - "login_key": 929495153, - "login_key_valid_until": "2014-08-21", "is_active": true, "notes": "", "startpage": "DE", @@ -154258,8 +152390,6 @@ "last_name": "Phelan", "language": "", "is_proxy_user": false, - "login_key": 110846776, - "login_key_valid_until": "2014-11-07", "is_active": true, "notes": "", "startpage": "DE", @@ -154286,8 +152416,6 @@ "last_name": "Wiles", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154311,8 +152439,6 @@ "last_name": "Mcrae", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154336,8 +152462,6 @@ "last_name": "Graves", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154364,8 +152488,6 @@ "last_name": "Moye", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154389,8 +152511,6 @@ "last_name": "Cho", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154414,8 +152534,6 @@ "last_name": "Carlisle", "language": "", "is_proxy_user": false, - "login_key": 707881715, - "login_key_valid_until": "2014-10-20", "is_active": true, "notes": "", "startpage": "DE", @@ -154439,8 +152557,6 @@ "last_name": "Elmore", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154464,8 +152580,6 @@ "last_name": "Bower", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154489,8 +152603,6 @@ "last_name": "Murry", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154514,8 +152626,6 @@ "last_name": "Greiner", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154539,8 +152649,6 @@ "last_name": "grade_publisher", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154568,8 +152676,6 @@ "last_name": "reviewer", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154597,8 +152703,6 @@ "last_name": "proxy", "language": "", "is_proxy_user": true, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154629,8 +152733,6 @@ "last_name": "proxy_delegate", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154658,8 +152760,6 @@ "last_name": "proxy_delegate_2", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154683,8 +152783,6 @@ "last_name": "Boston", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154708,8 +152806,6 @@ "last_name": "LedBetter", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -154733,8 +152829,6 @@ "last_name": "Large", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", diff --git a/evap/evaluation/auth.py b/evap/evaluation/auth.py index 581e8b9ae4..8ce4f679b9 100644 --- a/evap/evaluation/auth.py +++ b/evap/evaluation/auth.py @@ -16,23 +16,20 @@ class RequestAuthUserBackend(ModelBackend): """ - The RequestAuthBackend works together with the login_key_authentication view + The RequestAuthBackend works together with the otp_authentication view in evaluation/views.py to allow authentication of users via URL parameters, i.e. supplied in an email. - It looks for the appropriate key in the login_key field of the UserProfile. + Since the view already verifies the validity of the OTP for clearer user messaging, + this here doesn't add much, but Django's auth flow needs such a backend. """ # Having a different method signature is okay according to django documentation: # https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-an-authentication-backend - def authenticate(self, request, key): # pylint: disable=arguments-differ - if not key: - return None - - try: - return UserProfile.objects.get(login_key=key) - except UserProfile.DoesNotExist: - return None + def authenticate(self, request, otp_hash): # pylint: disable=arguments-differ + if otp_hash and otp_hash.user.is_active and otp_hash.is_valid(): + return otp_hash.user + return None class EmailAuthenticationBackend(ModelBackend): diff --git a/evap/evaluation/management/commands/anonymize.py b/evap/evaluation/management/commands/anonymize.py index 682434ef1f..1192d52450 100644 --- a/evap/evaluation/management/commands/anonymize.py +++ b/evap/evaluation/management/commands/anonymize.py @@ -1,7 +1,6 @@ import itertools import os import random -from datetime import date, timedelta from math import floor from django.conf import settings @@ -16,6 +15,7 @@ Contribution, Course, CourseType, + OtpHash, Program, RatingAnswerCounter, Semester, @@ -110,7 +110,8 @@ def anonymize_users(self, first_names, last_names): user.save() # Actually replace all the real user data - self.stdout.write("Replacing email addresses and login keys with fake ones...") + self.stdout.write("Replacing email addresses and deleting all OTPs...") + OtpHash.objects.all().delete() for user, name in zip(user_profiles, fake_usernames, strict=True): if user.email and user.email.split("@")[0] in Command.ignore_email_usernames: continue @@ -124,14 +125,6 @@ def anonymize_users(self, first_names, last_names): new_domain = Command.new_institution_domain if is_institution_domain else Command.new_external_domain user.email = (user.first_name_given + "." + user.last_name).lower() + "@" + new_domain - if user.login_key is not None: - # Create a new login key - user.login_key = None - user.valid_until = None - user.ensure_valid_login_key() - # Invalidate some keys - user.valid_until = date.today() + random.choice([1, -1]) * timedelta(365 * 100) # nosec - assert not user.has_usable_password() user.save() diff --git a/evap/evaluation/migrations/0161_login_key_to_otp_hash.py b/evap/evaluation/migrations/0161_login_key_to_otp_hash.py new file mode 100644 index 0000000000..df387d49d7 --- /dev/null +++ b/evap/evaluation/migrations/0161_login_key_to_otp_hash.py @@ -0,0 +1,42 @@ +# Generated by Django 5.2.11 on 2026-02-14 11:35 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("evaluation", "0160_evaluation_staff_notes"), + ] + + operations = [ + migrations.RemoveField( + model_name="userprofile", + name="login_key", + ), + migrations.RemoveField( + model_name="userprofile", + name="login_key_valid_until", + ), + migrations.CreateModel( + name="OtpHash", + fields=[ + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("otp_hash", models.CharField(max_length=256, unique=True, verbose_name="Hashed OTP")), + ("valid_until", models.DateTimeField(verbose_name="Valid until")), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="otp_hashes", + to=settings.AUTH_USER_MODEL, + ), + ), + ], + options={ + "verbose_name": "OTP hash", + "verbose_name_plural": "OTP hashes", + }, + ), + ] diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index 7dd32eb8a3..e46dc3a8c3 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -13,7 +13,7 @@ from django.conf import settings from django.contrib import messages -from django.contrib.auth.hashers import check_password, is_password_usable, make_password +from django.contrib.auth.hashers import PBKDF2PasswordHasher, check_password, is_password_usable, make_password from django.contrib.auth.models import BaseUserManager, Group, PermissionsMixin from django.contrib.auth.password_validation import validate_password from django.contrib.postgres.fields import ArrayField @@ -1895,12 +1895,6 @@ class UserProfile(EvapBaseUser, PermissionsMixin): help_text=_("Technical user that represents a group of users."), ) - # key for url based login of this user - MAX_LOGIN_KEY = 2**31 - 1 - - login_key = models.IntegerField(verbose_name=_("Login Key"), unique=True, blank=True, null=True) - login_key_valid_until = models.DateField(verbose_name=_("Login Key Validity"), blank=True, null=True) - is_active = models.BooleanField(default=True, verbose_name=_("active")) notes = models.TextField(verbose_name=_("notes"), blank=True, default="", max_length=1024 * 1024) @@ -2110,30 +2104,12 @@ def email_needs_login_key(email): def needs_login_key(self): return UserProfile.email_needs_login_key(self.email) - def ensure_valid_login_key(self): - if self.login_key and self.login_key_valid_until > date.today(): - self.reset_login_key_validity() - return - - while True: - key = secrets.choice(range(UserProfile.MAX_LOGIN_KEY)) - try: - self.login_key = key - self.reset_login_key_validity() - break - except IntegrityError: - # unique constraint failed, the login key was already in use. Generate another one. - continue - - def reset_login_key_validity(self): - self.login_key_valid_until = date.today() + timedelta(settings.LOGIN_KEY_VALIDITY) - self.save() - - @property - def login_url(self): + def generate_login_url(self, *, typeable: bool = False) -> str: + """Create an OTP and build a login URL for it.""" if not self.needs_login_key: return "" - return settings.PAGE_URL + reverse("evaluation:login_key_authentication", args=[self.login_key]) + otp = OtpHash.create(self, typeable=typeable) + return settings.PAGE_URL + reverse("evaluation:otp_authentication", kwargs={"otp": otp}) def get_sorted_courses_responsible_for(self): return self.courses_responsible_for.order_by("semester__created_at", "name_de") @@ -2157,6 +2133,80 @@ def get_sorted_due_evaluations(self): return sorted(evaluations_and_days_left, key=lambda tup: (tup[1], tup[0].full_name)) +class OtpHash(models.Model): + """Stores hashed one-time passwords (OTPs) for external user login via URL.""" + + _hasher = PBKDF2PasswordHasher() + + user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name="otp_hashes") + otp_hash = models.CharField(max_length=256, unique=True, verbose_name=_("Hashed OTP")) + valid_until = models.DateTimeField(verbose_name=_("Valid until")) + + class Meta: + verbose_name = _("OTP hash") + verbose_name_plural = _("OTP hashes") + + @classmethod + def create(cls, user: UserProfile, *, typeable: bool = False) -> str: + """Create a new OTP for the given user. Returns the raw OTP. + + Enforces the per-user OTP limit. + + If typeable is True, uses the TYPEABLE variants of + OTP_ALPHABET, OTP_LENGTH, and OTP_VALIDITY_HOURS. + """ + # Keep only the newest (limit - 1) OTPs, delete everything else (expired + excess) + ids_to_keep = ( + cls.objects.filter(user=user) + .order_by("-valid_until") + .values_list("id", flat=True)[: settings.MAX_OTPS_PER_USER - 1] + ) + cls.objects.filter(user=user).exclude(id__in=ids_to_keep).delete() + + if typeable: + alphabet = settings.OTP_ALPHABET_TYPEABLE + length = settings.OTP_LENGTH_TYPEABLE + validity = timedelta(hours=settings.OTP_VALIDITY_HOURS_TYPEABLE) + else: + alphabet = settings.OTP_ALPHABET + length = settings.OTP_LENGTH + validity = timedelta(hours=settings.OTP_VALIDITY_HOURS) + + while True: + raw_otp = "".join(secrets.choice(alphabet) for _ in range(length)) + try: + cls.objects.create( + user=user, + otp_hash=cls.hash_otp(raw_otp), + valid_until=now() + validity, + ) + return raw_otp + except IntegrityError: + # unique constraint failed, this OTP is already in use. Generate another one. + continue + + @classmethod + def hash_otp(cls, otp: str) -> str: + # fixed iterations so that hashes are stable and can be queried for directly + # the salt needs to be static for the same reason, thus providing no additional security. + return cls._hasher.encode(otp, salt="otp", iterations=1_000_000) + + @classmethod + def get(cls, otp: str) -> "OtpHash | None": + otp_hash = cls.hash_otp(otp) + try: + return cls.objects.select_related("user").get(otp_hash=otp_hash) + except cls.DoesNotExist: + return None + + def is_valid(self) -> bool: + return self.valid_until >= now() + + def invalidate(self) -> None: + self.valid_until = now() - timedelta(days=1) + self.save() + + def validate_template(value): """Field validator which ensures that the value can be compiled into a Django Template.""" @@ -2306,9 +2356,8 @@ def send_to_user( send_separate_login_url = False body_params["login_url"] = "" if user.needs_login_key: - user.ensure_valid_login_key() if not cc_addresses: - body_params["login_url"] = user.login_url + body_params["login_url"] = user.generate_login_url() else: send_separate_login_url = True diff --git a/evap/evaluation/tests/test_auth.py b/evap/evaluation/tests/test_auth.py index 96f8a60944..5d5a6b12a8 100644 --- a/evap/evaluation/tests/test_auth.py +++ b/evap/evaluation/tests/test_auth.py @@ -14,11 +14,11 @@ from evap.evaluation import auth from evap.evaluation.auth import class_or_function_check_decorator -from evap.evaluation.models import Contribution, Evaluation, UserProfile +from evap.evaluation.models import Contribution, EmailTemplate, Evaluation, OtpHash, UserProfile from evap.evaluation.tests.tools import WebTest -@override_settings(PASSWORD_HASHERS=["django.contrib.auth.hashers.MD5PasswordHasher"]) +@override_settings(PASSWORD_HASHERS=["django.contrib.auth.hashers.MD5PasswordHasher"], PAGE_URL="http://testserver") class LoginTests(WebTest): csrf_checks = False url = reverse("evaluation:index") @@ -26,9 +26,7 @@ class LoginTests(WebTest): @classmethod def setUpTestData(cls): cls.external_user = baker.make(UserProfile, email="extern@extern.com") - cls.external_user.ensure_valid_login_key() cls.inactive_external_user = baker.make(UserProfile, email="inactive@extern.com", is_active=False) - cls.inactive_external_user.ensure_valid_login_key() evaluation = baker.make(Evaluation, state=Evaluation.State.PUBLISHED) baker.make( Contribution, @@ -40,38 +38,36 @@ def setUpTestData(cls): _bulk_create=True, ) - @override_settings(PAGE_URL="https://example.com") def test_login_url_generation(self): - generated_url = self.external_user.login_url - self.assertEqual(generated_url, f"https://example.com/key/{self.external_user.login_key}") + generated_url = self.external_user.generate_login_url() + self.assertRegex(generated_url, r"^http://testserver/otp/\w+$") - reversed_url = reverse("evaluation:login_key_authentication", args=[self.external_user.login_key]) - self.assertEqual(reversed_url, f"/key/{self.external_user.login_key}") + short_url = self.external_user.generate_login_url(typeable=True) + self.assertRegex(short_url, r"^http://testserver/otp/\w+$") def test_login_url_works(self): self.assertRedirects(self.app.get(reverse("contributor:index")), "/?next=/contributor/") - url_with_key = reverse("evaluation:login_key_authentication", args=[self.external_user.login_key]) - old_login_key = self.external_user.login_key - old_login_key_valid_until = self.external_user.login_key_valid_until - page = self.app.get(url_with_key) - self.external_user.refresh_from_db() - self.assertEqual(old_login_key, self.external_user.login_key) - self.assertEqual(old_login_key_valid_until, self.external_user.login_key_valid_until) + url = self.external_user.generate_login_url() + otp_count_before = OtpHash.objects.filter(user=self.external_user).count() + page = self.app.get(url) + # GET should not delete the OTP + self.assertEqual(OtpHash.objects.filter(user=self.external_user).count(), otp_count_before) self.assertContains(page, "Login") self.assertContains(page, self.external_user.full_name) - page = self.app.post(url_with_key).follow().follow() + page = self.app.post(url).follow().follow() self.assertEqual(page.context["user"], self.external_user) self.assertContains(page, "Logout") self.assertContains(page, self.external_user.full_name) - def test_login_key_valid_only_once(self): - page = self.app.get(reverse("evaluation:login_key_authentication", args=[self.external_user.login_key])) + def test_otp_valid_only_once(self): + EmailTemplate.objects.filter(name=EmailTemplate.LOGIN_KEY_CREATED).update(plain_content="{{ login_url }}") + url = self.external_user.generate_login_url() + page = self.app.get(url) self.assertContains(page, self.external_user.full_name) - url_with_key = reverse("evaluation:login_key_authentication", args=[self.external_user.login_key]) - page = self.app.post(url_with_key).follow().follow() + page = self.app.post(url).follow().follow() self.assertEqual(page.context["user"], self.external_user) self.assertContains(page, "Logout") @@ -79,29 +75,31 @@ def test_login_key_valid_only_once(self): self.assertIsInstance(page.context["user"], AnonymousUser) self.assertNotContains(page, "Logout") - page = self.app.get(url_with_key).follow() + # The same OTP should no longer work (OTP was deactivated on login) + page = self.app.get(url).follow() self.assertContains(page, "The login URL is not valid anymore.") - self.assertEqual(len(mail.outbox), 1) # a new login key was sent + self.assertEqual(len(mail.outbox), 1) # a new OTP was sent - new_key = UserProfile.objects.get(id=self.external_user.id).login_key - page = self.app.post(reverse("evaluation:login_key_authentication", args=[new_key])).follow().follow() + # The old OTP triggered a new one to be sent; verify that one + new_url = mail.outbox[0].body.strip() + self.assertTrue(new_url.startswith("http://testserver/otp/")) + page = self.app.post(new_url).follow().follow() self.assertContains(page, self.external_user.full_name) def test_inactive_external_users_can_not_login(self): - page = self.app.get( - reverse("evaluation:login_key_authentication", args=[self.inactive_external_user.login_key]) - ).follow() + url = self.inactive_external_user.generate_login_url() + page = self.app.get(url).follow() self.assertContains(page, "Inactive users are not allowed to login") self.assertIsInstance(page.context["user"], AnonymousUser) self.assertNotContains(page, "Logout") - def test_login_key_resend_if_still_valid(self): - old_key = self.external_user.login_key + def test_otp_request_generates_new_otp(self): + otp_count_before = OtpHash.objects.filter(user=self.external_user).count() page = self.app.post(self.url, params={"submit_type": "new_key", "email": self.external_user.email}).follow() - new_key = UserProfile.objects.get(id=self.external_user.id).login_key + otp_count_after = OtpHash.objects.filter(user=self.external_user).count() - self.assertEqual(old_key, new_key) - self.assertEqual(len(mail.outbox), 1) # a login key was sent + self.assertEqual(otp_count_after, otp_count_before + 1) + self.assertEqual(len(mail.outbox), 1) # an OTP was sent self.assertContains(page, "We sent you an email with a one-time login URL. Please check your inbox.") @override_settings( diff --git a/evap/evaluation/tests/test_commands.py b/evap/evaluation/tests/test_commands.py index 41e3b905aa..73b5a30923 100644 --- a/evap/evaluation/tests/test_commands.py +++ b/evap/evaluation/tests/test_commands.py @@ -66,8 +66,6 @@ def setUpTestData(cls): first_name_given="Secret", last_name="User", password=make_password(None), - login_key=1234567890, - login_key_valid_until=date.today(), ) semester1 = baker.make(Semester, name_de="S1", name_en="S1") baker.make(Semester, name_de="S2", name_en="S2") diff --git a/evap/evaluation/tests/test_models.py b/evap/evaluation/tests/test_models.py index 431d8dfa9a..6a9f832667 100644 --- a/evap/evaluation/tests/test_models.py +++ b/evap/evaluation/tests/test_models.py @@ -795,7 +795,6 @@ class TestLoginUrlEmail(TestCase): def setUpTestData(cls): cls.other_user = baker.make(UserProfile, email="other@extern.com") cls.user = baker.make(UserProfile, email="extern@extern.com") - cls.user.ensure_valid_login_key() cls.evaluation = baker.make(Evaluation) baker.make( @@ -808,7 +807,7 @@ def setUpTestData(cls): cls.template = baker.make(EmailTemplate, plain_content="{{ login_url }}") - EmailTemplate.objects.filter(name="Login Key Created").update(plain_content="{{ user.login_url }}") + EmailTemplate.objects.filter(name="Login Key Created").update(plain_content="{{ login_url }}") @override_settings(PAGE_URL="https://example.com") def test_no_login_url_when_delegates_in_cc(self): @@ -818,7 +817,7 @@ def test_no_login_url_when_delegates_in_cc(self): ) self.assertEqual(len(mail.outbox), 2) self.assertEqual(mail.outbox[0].body, "") # message does not contain the login url - self.assertEqual(mail.outbox[1].body, self.user.login_url) # separate email with login url was sent + self.assertRegex(mail.outbox[1].body, r"^https://example\.com/otp/\w+$") self.assertEqual(len(mail.outbox[1].cc), 0) self.assertEqual(mail.outbox[1].to, [self.user.email]) @@ -829,7 +828,7 @@ def test_no_login_url_when_cc_users_in_cc(self): ) self.assertEqual(len(mail.outbox), 2) self.assertEqual(mail.outbox[0].body, "") # message does not contain the login url - self.assertEqual(mail.outbox[1].body, self.user.login_url) # separate email with login url was sent + self.assertIn("/otp/", mail.outbox[1].body) # separate email with login url was sent self.assertEqual(len(mail.outbox[1].cc), 0) self.assertEqual(mail.outbox[1].to, [self.user.email]) @@ -839,7 +838,7 @@ def test_login_url_when_nobody_in_cc(self): [self.evaluation], [EmailTemplate.Recipients.CONTRIBUTORS], use_cc=True, request=None ) self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].body, self.user.login_url) # message does contain the login url + self.assertIn("/otp/", mail.outbox[0].body) # message does contain the login url def test_login_url_when_use_cc_is_false(self): # message is not sent to others in cc @@ -848,7 +847,7 @@ def test_login_url_when_use_cc_is_false(self): [self.evaluation], [EmailTemplate.Recipients.CONTRIBUTORS], use_cc=False, request=None ) self.assertEqual(len(mail.outbox), 1) - self.assertEqual(mail.outbox[0].body, self.user.login_url) # message does contain the login url + self.assertIn("/otp/", mail.outbox[0].body) # message does contain the login url @override_settings(INSTITUTION_EMAIL_DOMAINS=["example.com"]) diff --git a/evap/evaluation/urls.py b/evap/evaluation/urls.py index 14177b3353..031b80d152 100644 --- a/evap/evaluation/urls.py +++ b/evap/evaluation/urls.py @@ -10,7 +10,7 @@ path("set_lang", views.set_lang, name="set_lang"), path("legal_notice", views.LegalNoticeView.as_view(), name="legal_notice"), path("contact", views.contact, name="contact"), - path("key/", views.login_key_authentication, name="login_key_authentication"), + path("otp/", views.otp_authentication, name="otp_authentication"), path("profile", views.profile_edit, name="profile_edit"), path("set_notes", views.set_notes, name="set_notes"), path("set_startpage", views.set_startpage, name="set_startpage"), diff --git a/evap/evaluation/views.py b/evap/evaluation/views.py index d94eddea23..97d3cf9d29 100644 --- a/evap/evaluation/views.py +++ b/evap/evaluation/views.py @@ -1,5 +1,4 @@ import logging -from datetime import date, timedelta from django.conf import settings from django.contrib import auth, messages @@ -17,7 +16,7 @@ from django.views.i18n import set_language from evap.evaluation.forms import LoginEmailForm, NewKeyForm, NotebookForm, ProfileForm -from evap.evaluation.models import EmailTemplate, FaqSection, Semester, UserProfile +from evap.evaluation.models import EmailTemplate, FaqSection, OtpHash, Semester, UserProfile from evap.evaluation.tools import HttpResponseNoContent, openid_login_is_active, password_login_is_active from evap.middleware import no_login_required @@ -71,12 +70,9 @@ def index(request): # process form data if request.method == "POST": if new_key_form.is_valid(): - # user wants a new login key + # user wants a new OTP profile = new_key_form.get_user() - profile.ensure_valid_login_key() - profile.save() - - EmailTemplate.send_login_url_to_user(new_key_form.get_user()) + EmailTemplate.send_login_url_to_user(profile) messages.success(request, _("We sent you an email with a one-time login URL. Please check your inbox.")) return redirect("evaluation:index") @@ -116,10 +112,15 @@ def index(request): @no_login_required -def login_key_authentication(request, key): - user = auth.authenticate(request, key=key) +def otp_authentication(request, otp: str): + otp_hash = OtpHash.get(otp) + + if not otp_hash: + messages.warning(request, _("Invalid login URL. Please request a new one below.")) + return redirect("evaluation:index") - if user and not user.is_active: + user = otp_hash.user + if not user.is_active: messages.error(request, _("Inactive users are not allowed to login.")) return redirect("evaluation:index") @@ -132,25 +133,18 @@ def login_key_authentication(request, key): ) return redirect("evaluation:index") - if user and user.login_key_valid_until >= date.today(): + if otp_hash.is_valid(): if request.method != "POST": - template_data = {"username": user.full_name} - return render(request, "external_user_confirm_login.html", template_data) + return render(request, "external_user_confirm_login.html", {"username": user.full_name}) - # User is valid. Set request.user and persist user in the session by logging the user in. - request.user = user - auth.login(request, user) + # Persist the authenticated user in the session. + authenticated_user = auth.authenticate(request, otp_hash=otp_hash) + auth.login(request, authenticated_user) messages.success(request, _("Logged in as %s.") % user.full_name) - # Invalidate the login key, but keep it stored so we can later identify the user that is trying to login and send a new link - user.login_key_valid_until = date.today() - timedelta(1) - user.save() - elif user: - # A user exists, but the login key is not valid anymore. Send the user a new one. - user.ensure_valid_login_key() + otp_hash.invalidate() + else: EmailTemplate.send_login_url_to_user(user) messages.warning(request, _("The login URL is not valid anymore. We sent you a new one to your email address.")) - else: - messages.warning(request, _("Invalid login URL. Please request a new one below.")) return redirect("evaluation:index") diff --git a/evap/results/fixtures/minimal_test_data_results.json b/evap/results/fixtures/minimal_test_data_results.json index ffbc5855fa..7be830b430 100644 --- a/evap/results/fixtures/minimal_test_data_results.json +++ b/evap/results/fixtures/minimal_test_data_results.json @@ -437,8 +437,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -464,8 +462,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -489,8 +485,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -514,8 +508,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -539,8 +531,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -566,8 +556,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -591,8 +579,6 @@ "last_name": "user", "language": "", "is_proxy_user": true, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -618,8 +604,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", @@ -643,8 +627,6 @@ "last_name": "user", "language": "", "is_proxy_user": false, - "login_key": null, - "login_key_valid_until": null, "is_active": true, "notes": "", "startpage": "DE", diff --git a/evap/settings.py b/evap/settings.py index 4bce5a7cbc..f943782480 100644 --- a/evap/settings.py +++ b/evap/settings.py @@ -33,7 +33,13 @@ ### EvaP logic -LOGIN_KEY_VALIDITY = 210 # days, so roughly 7 months +OTP_VALIDITY_HOURS = 14 * 24 # validity period for long (emailed) one-time passwords +OTP_VALIDITY_HOURS_TYPEABLE = 7 * 24 # validity period for short typeable OTPs (e.g. exported in CSV) +OTP_LENGTH = 40 # number of alphanumeric characters in a long OTP +OTP_LENGTH_TYPEABLE = 8 # number of characters in a short typeable OTP +OTP_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" +OTP_ALPHABET_TYPEABLE = "abcdefghjkmnpqrstuvwxyz23456789" # excludes ambiguous chars like 0/O and 1/l/I +MAX_OTPS_PER_USER = 10 # maximum number of OTP hashes (valid and invalid) per user VOTER_COUNT_NEEDED_FOR_PUBLISHING_RATING_RESULTS = 2 VOTER_PERCENTAGE_NEEDED_FOR_PUBLISHING_AVERAGE_GRADE = 0.2 diff --git a/evap/staff/tests/test_tools.py b/evap/staff/tests/test_tools.py index 5ea2a36686..022cace11c 100644 --- a/evap/staff/tests/test_tools.py +++ b/evap/staff/tests/test_tools.py @@ -113,8 +113,6 @@ def test_merge_handles_all_attributes(self): "last_login", # something to really not care about "user_permissions", # we don't use permissions "logentry", # wtf - "login_key", # we decided to discard other_user's login key - "login_key_valid_until", # not worth dealing with "language", # Not worth dealing with "Evaluation_voters+", # some more intermediate models, for an explanation see above "Evaluation_participants+", # intermediate model diff --git a/evap/staff/tests/test_views.py b/evap/staff/tests/test_views.py index f5962063ef..c72cfe654f 100644 --- a/evap/staff/tests/test_views.py +++ b/evap/staff/tests/test_views.py @@ -29,6 +29,7 @@ ExamType, FaqQuestion, Infotext, + OtpHash, Program, Question, QuestionAssignment, @@ -1527,17 +1528,18 @@ def setUpTestData(cls): cls.url = reverse("staff:evaluation_login_key_export", args=[evaluation.pk]) def test_login_key_export_works_as_expected(self): - self.assertEqual(self.external_user.login_key, None) - self.assertEqual(self.internal_user.login_key, None) + self.assertEqual(OtpHash.objects.filter(user=self.external_user).count(), 0) + self.assertEqual(OtpHash.objects.filter(user=self.internal_user).count(), 0) response = self.app.get(self.url, user=self.manager) - self.external_user.refresh_from_db() - self.assertNotEqual(self.external_user.login_key, None) - self.assertEqual(self.internal_user.login_key, None) + # An OTP should have been created for the external user but not the internal one + self.assertEqual(OtpHash.objects.filter(user=self.external_user).count(), 1) + self.assertEqual(OtpHash.objects.filter(user=self.internal_user).count(), 0) - expected_string = f"Last name;First name;Email;Login key\n;;user@external.com;localhost:8000/key/{self.external_user.login_key}\n" - self.assertEqual(response.body.decode(), expected_string) + body = response.body.decode() + self.assertIn("Last name;First name;Email;Login key\n", body) + self.assertRegex(body, r"(?m)^;;user@external\.com;localhost:8000/otp/[A-Za-z0-9]{8}$") class TestEvaluationOperationView(WebTestStaffMode): diff --git a/evap/staff/tools.py b/evap/staff/tools.py index 83ed4fa765..eac486bfb7 100644 --- a/evap/staff/tools.py +++ b/evap/staff/tools.py @@ -16,7 +16,7 @@ from django.utils.translation import gettext_lazy as _ from django.utils.translation import ngettext -from evap.evaluation.models import Contribution, Course, Evaluation, TextAnswer, UserProfile +from evap.evaluation.models import Contribution, Course, Evaluation, OtpHash, TextAnswer, UserProfile from evap.evaluation.models_logging import LogEntry from evap.evaluation.tools import StrOrPromise, clean_email, is_external_email from evap.grades.models import GradeDocument @@ -242,6 +242,7 @@ def merge_users( # noqa: PLR0915 # This is much stuff to do. However, splittin merged_user["represented_users"] = UserProfile.objects.filter(delegates__in=[main_user, other_user]).distinct() merged_user["cc_users"] = UserProfile.objects.filter(ccing_users__in=[main_user, other_user]).distinct() merged_user["ccing_users"] = UserProfile.objects.filter(cc_users__in=[main_user, other_user]).distinct() + merged_user["otp_hashes"] = OtpHash.objects.filter(user__in=[main_user, other_user]).distinct() errors = [] warnings = [] diff --git a/evap/staff/views.py b/evap/staff/views.py index d5d7b675b4..2097760b6d 100644 --- a/evap/staff/views.py +++ b/evap/staff/views.py @@ -1590,10 +1590,11 @@ def evaluation_login_key_export(_request, evaluation_id): writer = csv.writer(response, delimiter=";", lineterminator="\n") writer.writerow([_("Last name"), _("First name"), _("Email"), _("Login key")]) - external_participants = (participant for participant in evaluation.participants.all() if participant.is_external) - for participant in external_participants: - participant.ensure_valid_login_key() - writer.writerow([participant.last_name, participant.first_name, participant.email, participant.login_url]) + for participant in evaluation.participants.all(): + if not participant.needs_login_key: + continue + login_url = participant.generate_login_url(typeable=True) + writer.writerow([participant.last_name, participant.first_name, participant.email, login_url]) return response From 3790f4937b398c79e0239bd42d0df65ac5406287 Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Sun, 15 Feb 2026 17:38:07 +0100 Subject: [PATCH 02/10] Add test for invalid OTP for coverage --- evap/evaluation/models.py | 4 +--- evap/evaluation/tests/test_auth.py | 7 +++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index e46dc3a8c3..0b18e15e3b 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -2105,9 +2105,7 @@ def needs_login_key(self): return UserProfile.email_needs_login_key(self.email) def generate_login_url(self, *, typeable: bool = False) -> str: - """Create an OTP and build a login URL for it.""" - if not self.needs_login_key: - return "" + assert self.needs_login_key otp = OtpHash.create(self, typeable=typeable) return settings.PAGE_URL + reverse("evaluation:otp_authentication", kwargs={"otp": otp}) diff --git a/evap/evaluation/tests/test_auth.py b/evap/evaluation/tests/test_auth.py index 5d5a6b12a8..02973238ce 100644 --- a/evap/evaluation/tests/test_auth.py +++ b/evap/evaluation/tests/test_auth.py @@ -102,6 +102,13 @@ def test_otp_request_generates_new_otp(self): self.assertEqual(len(mail.outbox), 1) # an OTP was sent self.assertContains(page, "We sent you an email with a one-time login URL. Please check your inbox.") + def test_invalid_otp_shows_error_message(self): + page = self.app.get("/otp/definitely-invalid-otp").follow() + + self.assertContains(page, "Invalid login URL. Please request a new one below.") + self.assertIsInstance(page.context["user"], AnonymousUser) + self.assertNotContains(page, "Logout") + @override_settings( OIDC_OP_AUTHORIZATION_ENDPOINT="https://oidc.example.com/auth", ACTIVATE_OPEN_ID_LOGIN=True, From de1d2694511dcd3ba81a55f707094437b9e71695 Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Mon, 2 Mar 2026 19:21:49 +0100 Subject: [PATCH 03/10] Use timedelta in the settings --- evap/evaluation/models.py | 9 ++++----- evap/settings.py | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index 0b18e15e3b..5c28b9c9d6 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -2151,24 +2151,23 @@ def create(cls, user: UserProfile, *, typeable: bool = False) -> str: Enforces the per-user OTP limit. If typeable is True, uses the TYPEABLE variants of - OTP_ALPHABET, OTP_LENGTH, and OTP_VALIDITY_HOURS. + OTP_ALPHABET, OTP_LENGTH, and OTP_VALIDITY. """ # Keep only the newest (limit - 1) OTPs, delete everything else (expired + excess) ids_to_keep = ( cls.objects.filter(user=user) - .order_by("-valid_until") - .values_list("id", flat=True)[: settings.MAX_OTPS_PER_USER - 1] + .order_by("-valid_until")[: settings.MAX_OTPS_PER_USER - 1] ) cls.objects.filter(user=user).exclude(id__in=ids_to_keep).delete() if typeable: alphabet = settings.OTP_ALPHABET_TYPEABLE length = settings.OTP_LENGTH_TYPEABLE - validity = timedelta(hours=settings.OTP_VALIDITY_HOURS_TYPEABLE) + validity = settings.OTP_VALIDITY_TYPEABLE else: alphabet = settings.OTP_ALPHABET length = settings.OTP_LENGTH - validity = timedelta(hours=settings.OTP_VALIDITY_HOURS) + validity = settings.OTP_VALIDITY while True: raw_otp = "".join(secrets.choice(alphabet) for _ in range(length)) diff --git a/evap/settings.py b/evap/settings.py index f943782480..1990edabaa 100644 --- a/evap/settings.py +++ b/evap/settings.py @@ -33,8 +33,8 @@ ### EvaP logic -OTP_VALIDITY_HOURS = 14 * 24 # validity period for long (emailed) one-time passwords -OTP_VALIDITY_HOURS_TYPEABLE = 7 * 24 # validity period for short typeable OTPs (e.g. exported in CSV) +OTP_VALIDITY = timedelta(days=14) # validity period for long (emailed) one-time passwords +OTP_VALIDITY_TYPEABLE = timedelta(days=7) # validity period for short typeable OTPs (e.g. exported in CSV) OTP_LENGTH = 40 # number of alphanumeric characters in a long OTP OTP_LENGTH_TYPEABLE = 8 # number of characters in a short typeable OTP OTP_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" From 3765007ead46fd8c80a366d72c09bce8d08d867e Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Mon, 2 Mar 2026 19:32:01 +0100 Subject: [PATCH 04/10] Add test, remove endless loop --- evap/evaluation/models.py | 2 +- evap/evaluation/tests/test_auth.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index 5c28b9c9d6..271770d048 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -2169,7 +2169,7 @@ def create(cls, user: UserProfile, *, typeable: bool = False) -> str: length = settings.OTP_LENGTH validity = settings.OTP_VALIDITY - while True: + for _ in range(10): raw_otp = "".join(secrets.choice(alphabet) for _ in range(length)) try: cls.objects.create( diff --git a/evap/evaluation/tests/test_auth.py b/evap/evaluation/tests/test_auth.py index 02973238ce..eb00214d07 100644 --- a/evap/evaluation/tests/test_auth.py +++ b/evap/evaluation/tests/test_auth.py @@ -102,6 +102,16 @@ def test_otp_request_generates_new_otp(self): self.assertEqual(len(mail.outbox), 1) # an OTP was sent self.assertContains(page, "We sent you an email with a one-time login URL. Please check your inbox.") + def test_generating_more_than_max_otps_invalidates_oldest_only(self): + otps = [OtpHash.create(self.external_user) for _ in range(settings.MAX_OTPS_PER_USER + 1)] + + self.assertIsNone(OtpHash.get(otps[0])) + + for otp in otps[1:]: + otp_hash = OtpHash.get(otp) + self.assertIsNotNone(otp_hash) + self.assertTrue(otp_hash.is_valid()) + def test_invalid_otp_shows_error_message(self): page = self.app.get("/otp/definitely-invalid-otp").follow() From 0321fea45e1fef176d8889987d0e755bce5ea087 Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Fri, 6 Mar 2026 22:30:16 +0100 Subject: [PATCH 05/10] Add tests for typeable=True --- evap/evaluation/tests/test_auth.py | 39 ++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/evap/evaluation/tests/test_auth.py b/evap/evaluation/tests/test_auth.py index eb00214d07..f8308573ff 100644 --- a/evap/evaluation/tests/test_auth.py +++ b/evap/evaluation/tests/test_auth.py @@ -18,9 +18,10 @@ from evap.evaluation.tests.tools import WebTest -@override_settings(PASSWORD_HASHERS=["django.contrib.auth.hashers.MD5PasswordHasher"], PAGE_URL="http://testserver") -class LoginTests(WebTest): +@override_settings(PAGE_URL="http://testserver") +class LoginTestsOtp(WebTest): csrf_checks = False + typeable = False url = reverse("evaluation:index") @classmethod @@ -39,16 +40,13 @@ def setUpTestData(cls): ) def test_login_url_generation(self): - generated_url = self.external_user.generate_login_url() + generated_url = self.external_user.generate_login_url(typeable=self.typeable) self.assertRegex(generated_url, r"^http://testserver/otp/\w+$") - short_url = self.external_user.generate_login_url(typeable=True) - self.assertRegex(short_url, r"^http://testserver/otp/\w+$") - def test_login_url_works(self): self.assertRedirects(self.app.get(reverse("contributor:index")), "/?next=/contributor/") - url = self.external_user.generate_login_url() + url = self.external_user.generate_login_url(typeable=self.typeable) otp_count_before = OtpHash.objects.filter(user=self.external_user).count() page = self.app.get(url) # GET should not delete the OTP @@ -63,7 +61,7 @@ def test_login_url_works(self): def test_otp_valid_only_once(self): EmailTemplate.objects.filter(name=EmailTemplate.LOGIN_KEY_CREATED).update(plain_content="{{ login_url }}") - url = self.external_user.generate_login_url() + url = self.external_user.generate_login_url(typeable=self.typeable) page = self.app.get(url) self.assertContains(page, self.external_user.full_name) @@ -87,7 +85,7 @@ def test_otp_valid_only_once(self): self.assertContains(page, self.external_user.full_name) def test_inactive_external_users_can_not_login(self): - url = self.inactive_external_user.generate_login_url() + url = self.inactive_external_user.generate_login_url(typeable=self.typeable) page = self.app.get(url).follow() self.assertContains(page, "Inactive users are not allowed to login") self.assertIsInstance(page.context["user"], AnonymousUser) @@ -103,7 +101,7 @@ def test_otp_request_generates_new_otp(self): self.assertContains(page, "We sent you an email with a one-time login URL. Please check your inbox.") def test_generating_more_than_max_otps_invalidates_oldest_only(self): - otps = [OtpHash.create(self.external_user) for _ in range(settings.MAX_OTPS_PER_USER + 1)] + otps = [OtpHash.create(self.external_user, typeable=self.typeable) for _ in range(settings.MAX_OTPS_PER_USER + 1)] self.assertIsNone(OtpHash.get(otps[0])) @@ -112,6 +110,16 @@ def test_generating_more_than_max_otps_invalidates_oldest_only(self): self.assertIsNotNone(otp_hash) self.assertTrue(otp_hash.is_valid()) + +class LoginTestsOtpTypeable(LoginTestsOtp): + typeable = True + + +class LoginTestsOtpAdditional(WebTest): + """ OTP tests that don't need the typeable parameter """ + csrf_checks = False + url = reverse("evaluation:index") + def test_invalid_otp_shows_error_message(self): page = self.app.get("/otp/definitely-invalid-otp").follow() @@ -119,6 +127,11 @@ def test_invalid_otp_shows_error_message(self): self.assertIsInstance(page.context["user"], AnonymousUser) self.assertNotContains(page, "Logout") + +class LoginTestsOidc(WebTest): + csrf_checks = False + url = reverse("evaluation:index") + @override_settings( OIDC_OP_AUTHORIZATION_ENDPOINT="https://oidc.example.com/auth", ACTIVATE_OPEN_ID_LOGIN=True, @@ -240,6 +253,12 @@ def assert_existence(old_exists, reported_exists, cleaned_exists): assert_existence(True, False, True) self.assertEqual(len(mail.outbox), 1) + +@override_settings(PASSWORD_HASHERS=["django.contrib.auth.hashers.MD5PasswordHasher"]) +class LoginTestsPassword(WebTest): + csrf_checks = False + url = reverse("evaluation:index") + @override_settings(INSTITUTION_EMAIL_DOMAINS=["example.com"]) def test_passworduser_login(self): """Tests whether a user can login with an incorrect and a correct password.""" From 1435b516d2d5bb73e32de746c23299cebd562f42 Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Fri, 6 Mar 2026 22:36:10 +0100 Subject: [PATCH 06/10] Speed up the tests (hashing one OTP took ~100ms on my machine. auth tests took ~9s in total) --- evap/evaluation/models.py | 2 +- evap/evaluation/tests/test_auth.py | 4 +++- evap/settings.py | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index 271770d048..69c60cdb17 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -2186,7 +2186,7 @@ def create(cls, user: UserProfile, *, typeable: bool = False) -> str: def hash_otp(cls, otp: str) -> str: # fixed iterations so that hashes are stable and can be queried for directly # the salt needs to be static for the same reason, thus providing no additional security. - return cls._hasher.encode(otp, salt="otp", iterations=1_000_000) + return cls._hasher.encode(otp, salt="otp", iterations=settings.OTP_HASH_ITERATIONS) @classmethod def get(cls, otp: str) -> "OtpHash | None": diff --git a/evap/evaluation/tests/test_auth.py b/evap/evaluation/tests/test_auth.py index f8308573ff..4402d4337d 100644 --- a/evap/evaluation/tests/test_auth.py +++ b/evap/evaluation/tests/test_auth.py @@ -18,7 +18,8 @@ from evap.evaluation.tests.tools import WebTest -@override_settings(PAGE_URL="http://testserver") + +@override_settings(PAGE_URL="http://testserver", OTP_HASH_ITERATIONS=10_000) # speed up tests class LoginTestsOtp(WebTest): csrf_checks = False typeable = False @@ -115,6 +116,7 @@ class LoginTestsOtpTypeable(LoginTestsOtp): typeable = True +@override_settings(OTP_HASH_ITERATIONS=10_000) # speed up tests class LoginTestsOtpAdditional(WebTest): """ OTP tests that don't need the typeable parameter """ csrf_checks = False diff --git a/evap/settings.py b/evap/settings.py index 1990edabaa..f509a6909d 100644 --- a/evap/settings.py +++ b/evap/settings.py @@ -40,6 +40,7 @@ OTP_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" OTP_ALPHABET_TYPEABLE = "abcdefghjkmnpqrstuvwxyz23456789" # excludes ambiguous chars like 0/O and 1/l/I MAX_OTPS_PER_USER = 10 # maximum number of OTP hashes (valid and invalid) per user +OTP_HASH_ITERATIONS = 1_000_000 # changing this will invalidate all existing OTPs. This is here only so tests can reduce it. VOTER_COUNT_NEEDED_FOR_PUBLISHING_RATING_RESULTS = 2 VOTER_PERCENTAGE_NEEDED_FOR_PUBLISHING_AVERAGE_GRADE = 0.2 From 8110c51c1900fe5c78d5a950aa368e8a2b9e408b Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Fri, 6 Mar 2026 22:39:12 +0100 Subject: [PATCH 07/10] lints, formatting --- evap/evaluation/models.py | 8 +++----- evap/evaluation/tests/test_auth.py | 12 +++++++----- evap/settings.py | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index 69c60cdb17..ce2210c82f 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -2154,10 +2154,7 @@ def create(cls, user: UserProfile, *, typeable: bool = False) -> str: OTP_ALPHABET, OTP_LENGTH, and OTP_VALIDITY. """ # Keep only the newest (limit - 1) OTPs, delete everything else (expired + excess) - ids_to_keep = ( - cls.objects.filter(user=user) - .order_by("-valid_until")[: settings.MAX_OTPS_PER_USER - 1] - ) + ids_to_keep = cls.objects.filter(user=user).order_by("-valid_until")[: settings.MAX_OTPS_PER_USER - 1] cls.objects.filter(user=user).exclude(id__in=ids_to_keep).delete() if typeable: @@ -2169,7 +2166,7 @@ def create(cls, user: UserProfile, *, typeable: bool = False) -> str: length = settings.OTP_LENGTH validity = settings.OTP_VALIDITY - for _ in range(10): + for _i in range(10): raw_otp = "".join(secrets.choice(alphabet) for _ in range(length)) try: cls.objects.create( @@ -2181,6 +2178,7 @@ def create(cls, user: UserProfile, *, typeable: bool = False) -> str: except IntegrityError: # unique constraint failed, this OTP is already in use. Generate another one. continue + raise RuntimeError("Failed to create OTP after 10 attempts") @classmethod def hash_otp(cls, otp: str) -> str: diff --git a/evap/evaluation/tests/test_auth.py b/evap/evaluation/tests/test_auth.py index 4402d4337d..44e57bda29 100644 --- a/evap/evaluation/tests/test_auth.py +++ b/evap/evaluation/tests/test_auth.py @@ -18,8 +18,7 @@ from evap.evaluation.tests.tools import WebTest - -@override_settings(PAGE_URL="http://testserver", OTP_HASH_ITERATIONS=10_000) # speed up tests +@override_settings(PAGE_URL="http://testserver", OTP_HASH_ITERATIONS=10_000) # speed up tests class LoginTestsOtp(WebTest): csrf_checks = False typeable = False @@ -102,7 +101,9 @@ def test_otp_request_generates_new_otp(self): self.assertContains(page, "We sent you an email with a one-time login URL. Please check your inbox.") def test_generating_more_than_max_otps_invalidates_oldest_only(self): - otps = [OtpHash.create(self.external_user, typeable=self.typeable) for _ in range(settings.MAX_OTPS_PER_USER + 1)] + otps = [ + OtpHash.create(self.external_user, typeable=self.typeable) for _ in range(settings.MAX_OTPS_PER_USER + 1) + ] self.assertIsNone(OtpHash.get(otps[0])) @@ -116,9 +117,10 @@ class LoginTestsOtpTypeable(LoginTestsOtp): typeable = True -@override_settings(OTP_HASH_ITERATIONS=10_000) # speed up tests +@override_settings(OTP_HASH_ITERATIONS=10_000) # speed up tests class LoginTestsOtpAdditional(WebTest): - """ OTP tests that don't need the typeable parameter """ + """OTP tests that don't need the typeable parameter""" + csrf_checks = False url = reverse("evaluation:index") diff --git a/evap/settings.py b/evap/settings.py index f509a6909d..707db29302 100644 --- a/evap/settings.py +++ b/evap/settings.py @@ -40,7 +40,7 @@ OTP_ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" OTP_ALPHABET_TYPEABLE = "abcdefghjkmnpqrstuvwxyz23456789" # excludes ambiguous chars like 0/O and 1/l/I MAX_OTPS_PER_USER = 10 # maximum number of OTP hashes (valid and invalid) per user -OTP_HASH_ITERATIONS = 1_000_000 # changing this will invalidate all existing OTPs. This is here only so tests can reduce it. +OTP_HASH_ITERATIONS = 1_000_000 # changing this will invalidate all existing OTPs. VOTER_COUNT_NEEDED_FOR_PUBLISHING_RATING_RESULTS = 2 VOTER_PERCENTAGE_NEEDED_FOR_PUBLISHING_AVERAGE_GRADE = 0.2 From 60d537e3d406af402d12439e89b70757f1d234ec Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Fri, 6 Mar 2026 22:44:03 +0100 Subject: [PATCH 08/10] Enforce the limit also when merging users --- evap/evaluation/models.py | 12 +++++++----- evap/staff/tools.py | 2 ++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index ce2210c82f..ca6ebf2588 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -2144,18 +2144,20 @@ class Meta: verbose_name = _("OTP hash") verbose_name_plural = _("OTP hashes") + @classmethod + def enforce_otp_count_limit(cls, user: UserProfile) -> None: + """Keep only the newest (limit - 1) OTPs for the user, delete the rest.""" + ids_to_keep = cls.objects.filter(user=user).order_by("-valid_until")[: settings.MAX_OTPS_PER_USER - 1] + cls.objects.filter(user=user).exclude(id__in=ids_to_keep).delete() + @classmethod def create(cls, user: UserProfile, *, typeable: bool = False) -> str: """Create a new OTP for the given user. Returns the raw OTP. - Enforces the per-user OTP limit. - If typeable is True, uses the TYPEABLE variants of OTP_ALPHABET, OTP_LENGTH, and OTP_VALIDITY. """ - # Keep only the newest (limit - 1) OTPs, delete everything else (expired + excess) - ids_to_keep = cls.objects.filter(user=user).order_by("-valid_until")[: settings.MAX_OTPS_PER_USER - 1] - cls.objects.filter(user=user).exclude(id__in=ids_to_keep).delete() + cls.enforce_otp_count_limit(user) if typeable: alphabet = settings.OTP_ALPHABET_TYPEABLE diff --git a/evap/staff/tools.py b/evap/staff/tools.py index eac486bfb7..426e60aeb8 100644 --- a/evap/staff/tools.py +++ b/evap/staff/tools.py @@ -315,6 +315,8 @@ def merge_users( # noqa: PLR0915 # This is much stuff to do. However, splittin setattr(main_user, key, value) # use direct assignment for everything else main_user.save() + OtpHash.enforce_otp_count_limit(main_user) + # delete rewards other_user.reward_point_grantings.all().delete() other_user.reward_point_redemptions.all().delete() From 37a4f48d3a13e2d96fbd4e54a02cbacf91634c06 Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Fri, 6 Mar 2026 23:00:45 +0100 Subject: [PATCH 09/10] AI review tweaks and comments --- evap/evaluation/models.py | 3 ++- evap/evaluation/views.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/evap/evaluation/models.py b/evap/evaluation/models.py index ca6ebf2588..4c729a0c0c 100644 --- a/evap/evaluation/models.py +++ b/evap/evaluation/models.py @@ -2200,7 +2200,8 @@ def is_valid(self) -> bool: return self.valid_until >= now() def invalidate(self) -> None: - self.valid_until = now() - timedelta(days=1) + # send it way back so enforce_otp_count_limit deletes it before any active OTPs + self.valid_until = now() - timedelta(days=365) self.save() diff --git a/evap/evaluation/views.py b/evap/evaluation/views.py index 97d3cf9d29..981becd938 100644 --- a/evap/evaluation/views.py +++ b/evap/evaluation/views.py @@ -141,6 +141,7 @@ def otp_authentication(request, otp: str): authenticated_user = auth.authenticate(request, otp_hash=otp_hash) auth.login(request, authenticated_user) messages.success(request, _("Logged in as %s.") % user.full_name) + # Invalidate, not delete, so the branch below can send a new one on expired keys otp_hash.invalidate() else: EmailTemplate.send_login_url_to_user(user) From 463952b5fbeeba951482c8f697a6e4feb2d6ca65 Mon Sep 17 00:00:00 2001 From: Johannes Linke Date: Fri, 6 Mar 2026 23:09:50 +0100 Subject: [PATCH 10/10] Rename migration after rebase --- ...1_login_key_to_otp_hash.py => 0163_login_key_to_otp_hash.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename evap/evaluation/migrations/{0161_login_key_to_otp_hash.py => 0163_login_key_to_otp_hash.py} (95%) diff --git a/evap/evaluation/migrations/0161_login_key_to_otp_hash.py b/evap/evaluation/migrations/0163_login_key_to_otp_hash.py similarity index 95% rename from evap/evaluation/migrations/0161_login_key_to_otp_hash.py rename to evap/evaluation/migrations/0163_login_key_to_otp_hash.py index df387d49d7..68941e57bb 100644 --- a/evap/evaluation/migrations/0161_login_key_to_otp_hash.py +++ b/evap/evaluation/migrations/0163_login_key_to_otp_hash.py @@ -7,7 +7,7 @@ class Migration(migrations.Migration): dependencies = [ - ("evaluation", "0160_evaluation_staff_notes"), + ("evaluation", "0162_unified_questions_from_tmp_relation"), ] operations = [