diff --git a/files/helpers/config/const.py b/files/helpers/config/const.py index f8ee8e8bf..a7cb19f94 100644 --- a/files/helpers/config/const.py +++ b/files/helpers/config/const.py @@ -554,6 +554,7 @@ PERMS = { # Minimum admin_level to perform action. 'MODS_EVERY_GROUP': 5, 'IGNORE_AWARD_IMMUNITY': 5, 'IGNORE_DOMAIN_BAN': 5, + 'USER_RESET_PASSWORD': 5, } FEATURES = { diff --git a/files/helpers/config/modaction_types.py b/files/helpers/config/modaction_types.py index 30b120ee5..d04294a6c 100644 --- a/files/helpers/config/modaction_types.py +++ b/files/helpers/config/modaction_types.py @@ -401,6 +401,11 @@ MODACTION_TYPES = { "icon": 'fa-cat', "color": 'bg-danger' }, + 'reset_password': { + "str": 'reset the password of {self.target_link}', + "icon": 'fa-lock', + "color": 'bg-danger' + }, } MODACTION_TYPES = dict(sorted(MODACTION_TYPES.items())) @@ -413,7 +418,8 @@ MODACTION_PRIVILEGED_TYPES = { 'unprogstack_post', 'unprogstack_comment' 'enable_signups', 'delete_media', 'link_accounts', 'delink_accounts', - 'enable_login_required' + 'enable_login_required', + 'reset_password', } MODACTION_PRIVILEGED__TYPES = {'progstack_post', 'progstack_comment', 'unprogstack_post', 'unprogstack_comment'} @@ -423,4 +429,4 @@ MODACTION_TYPES__FILTERED = deepcopy({t:v for t,v in MODACTION_TYPES.items() if not t in MODACTION_PRIVILEGED__TYPES}) AEVANN_MODACTION_TYPES = {'ban_user','unban_user', 'shadowban','unshadowban', - 'delete_media'} + 'delete_media','reset_password'} diff --git a/files/routes/admin.py b/files/routes/admin.py index 7e3a7e547..01182a098 100644 --- a/files/routes/admin.py +++ b/files/routes/admin.py @@ -1881,3 +1881,28 @@ def delete_media_post(v): purge_files_in_cache(url) return render_template("admin/delete_media.html", v=v, msg="Media deleted successfully!") + +@app.post("/admin/reset_password/") +@limiter.limit('1/second', scope=rpath) +@limiter.limit('1/second', scope=rpath, key_func=get_ID) +@limiter.limit(DEFAULT_RATELIMIT) +@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) +@admin_level_required(PERMS['USER_RESET_PASSWORD']) +def admin_reset_password(user_id, v): + user = get_account(user_id) + new_password = secrets.token_hex(31) + user.passhash = hash_password(new_password) + g.db.add(user) + + ma = ModAction( + kind="reset_password", + user_id=v.id, + target_user_id=user.id + ) + g.db.add(ma) + + text = f"At your request, @{v.username} (a site admin) has reset your password to `{new_password}`, please change this to something else for personal security reasons. And be sure to save it this time, retard." + + send_repeatable_notification(user.id, text) + + return {"message": f"@{user.username}'s password has been reset! The new password has been messaged to them!"} diff --git a/files/templates/userpage/admintools.html b/files/templates/userpage/admintools.html index 8918004b2..a0f83f7d1 100644 --- a/files/templates/userpage/admintools.html +++ b/files/templates/userpage/admintools.html @@ -108,6 +108,9 @@ {% endif %} + {% if v.admin_level >= PERMS['USER_RESET_PASSWORD'] %} + + {% endif %} {% endif %}