mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add lockout user for forgot password
Hide lockout user from users list
This commit is contained in:
parent
c89dbed26c
commit
3d4153f941
@ -1,5 +1,9 @@
|
|||||||
import logging
|
import logging
|
||||||
import typing as t
|
import typing as t
|
||||||
|
import datetime
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
from app.classes.models.servers import HelperServers
|
from app.classes.models.servers import HelperServers
|
||||||
|
|
||||||
from app.classes.models.users import HelperUsers
|
from app.classes.models.users import HelperUsers
|
||||||
@ -22,6 +26,7 @@ class UsersController:
|
|||||||
self.helper = helper
|
self.helper = helper
|
||||||
self.users_helper = users_helper
|
self.users_helper = users_helper
|
||||||
self.authentication = authentication
|
self.authentication = authentication
|
||||||
|
self.scheduler = BackgroundScheduler(timezone="Etc/UTC")
|
||||||
|
|
||||||
_permissions_props = {
|
_permissions_props = {
|
||||||
"name": {
|
"name": {
|
||||||
@ -353,3 +358,41 @@ class UsersController:
|
|||||||
|
|
||||||
def delete_user_api_key(self, key_id: str):
|
def delete_user_api_key(self, key_id: str):
|
||||||
return self.users_helper.delete_user_api_key(key_id)
|
return self.users_helper.delete_user_api_key(key_id)
|
||||||
|
|
||||||
|
# **********************************************************************************
|
||||||
|
# Lockout Methods
|
||||||
|
# **********************************************************************************
|
||||||
|
def start_anti_lockout(self, app_dir):
|
||||||
|
lockout_pass = self.helper.create_pass()
|
||||||
|
self.users_helper.add_user(
|
||||||
|
"anti-lockout-user",
|
||||||
|
None,
|
||||||
|
password=lockout_pass,
|
||||||
|
email="",
|
||||||
|
enabled=True,
|
||||||
|
superuser=True,
|
||||||
|
theme="ronald",
|
||||||
|
)
|
||||||
|
with open(
|
||||||
|
os.path.join(app_dir, "app", "config", "anti-lockout.txt"),
|
||||||
|
"w",
|
||||||
|
encoding="utf-8",
|
||||||
|
) as cred_file:
|
||||||
|
cred_file.write(
|
||||||
|
json.dumps(
|
||||||
|
{"username": "anti-lockout-user", "password": lockout_pass},
|
||||||
|
indent=4,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
os.chmod(os.path.join(app_dir, "app", "config", "anti-lockout.txt"), 0o600)
|
||||||
|
self.scheduler.add_job(
|
||||||
|
self.stop_anti_lockout,
|
||||||
|
"interval",
|
||||||
|
hours=1,
|
||||||
|
id="anti-lockout-watcher",
|
||||||
|
start_date=datetime.datetime.now(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def stop_anti_lockout(self):
|
||||||
|
self.scheduler.remove_all_jobs()
|
||||||
|
self.users_helper.remove_user(self.get_id_by_name("anti-lockout-user"))
|
||||||
|
@ -103,7 +103,9 @@ class HelperUsers:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_all_users():
|
def get_all_users():
|
||||||
query = Users.select().where(Users.username != "system")
|
query = Users.select().where(
|
||||||
|
Users.username != "system", Users.username != "anti-lockout-user"
|
||||||
|
)
|
||||||
return query
|
return query
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -12,6 +12,7 @@ from app.classes.shared.file_helpers import FileHelpers
|
|||||||
from app.classes.shared.main_controller import Controller
|
from app.classes.shared.main_controller import Controller
|
||||||
from app.classes.shared.translation import Translation
|
from app.classes.shared.translation import Translation
|
||||||
from app.classes.shared.main_models import DatabaseShortcuts
|
from app.classes.shared.main_models import DatabaseShortcuts
|
||||||
|
from app.classes.models.users import DoesNotExist
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
auth_log = logging.getLogger("auth")
|
auth_log = logging.getLogger("auth")
|
||||||
@ -91,7 +92,10 @@ class BaseHandler(tornado.web.RequestHandler):
|
|||||||
t.Dict[str, t.Any]: The token's payload.
|
t.Dict[str, t.Any]: The token's payload.
|
||||||
t.Dict[str, t.Any]: The user's data from the database.
|
t.Dict[str, t.Any]: The user's data from the database.
|
||||||
"""
|
"""
|
||||||
return self.controller.authentication.check(self.get_cookie("token"))
|
try:
|
||||||
|
return self.controller.authentication.check(self.get_cookie("token"))
|
||||||
|
except DoesNotExist:
|
||||||
|
return None
|
||||||
|
|
||||||
def autobleach(self, name, text):
|
def autobleach(self, name, text):
|
||||||
for r in self.redactables:
|
for r in self.redactables:
|
||||||
|
@ -79,6 +79,7 @@ from app.classes.web.routes.api.crafty.stats.stats import ApiCraftyHostStatsHand
|
|||||||
from app.classes.web.routes.api.crafty.clogs.index import ApiCraftyLogIndexHandler
|
from app.classes.web.routes.api.crafty.clogs.index import ApiCraftyLogIndexHandler
|
||||||
from app.classes.web.routes.api.crafty.imports.index import ApiImportFilesIndexHandler
|
from app.classes.web.routes.api.crafty.imports.index import ApiImportFilesIndexHandler
|
||||||
from app.classes.web.routes.api.crafty.exe_cache import ApiCraftyJarCacheIndexHandler
|
from app.classes.web.routes.api.crafty.exe_cache import ApiCraftyJarCacheIndexHandler
|
||||||
|
from app.classes.web.routes.api.crafty.antilockout.index import ApiCraftyLockoutHandler
|
||||||
|
|
||||||
|
|
||||||
def api_handlers(handler_args):
|
def api_handlers(handler_args):
|
||||||
@ -94,6 +95,11 @@ def api_handlers(handler_args):
|
|||||||
ApiAuthInvalidateTokensHandler,
|
ApiAuthInvalidateTokensHandler,
|
||||||
handler_args,
|
handler_args,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
r"/api/v2/crafty/resetPass/?",
|
||||||
|
ApiCraftyLockoutHandler,
|
||||||
|
handler_args,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
r"/api/v2/crafty/announcements/?",
|
r"/api/v2/crafty/announcements/?",
|
||||||
ApiAnnounceIndexHandler,
|
ApiAnnounceIndexHandler,
|
||||||
|
24
app/classes/web/routes/api/crafty/antilockout/index.py
Normal file
24
app/classes/web/routes/api/crafty/antilockout/index.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import logging
|
||||||
|
from app.classes.web.base_api_handler import BaseApiHandler
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ApiCraftyLockoutHandler(BaseApiHandler):
|
||||||
|
def get(self):
|
||||||
|
if self.controller.users.get_id_by_name("anti-lockout-user"):
|
||||||
|
return self.finish_json(
|
||||||
|
425, {"status": "error", "data": "Lockout recovery already in progress"}
|
||||||
|
)
|
||||||
|
self.controller.users.start_anti_lockout(self.controller.project_root)
|
||||||
|
lockout_msg = (
|
||||||
|
"Lockout account has been activated for 1 hour."
|
||||||
|
" Please find credentials in confg/anti-lockout.txt"
|
||||||
|
)
|
||||||
|
return self.finish_json(
|
||||||
|
200,
|
||||||
|
{
|
||||||
|
"status": "ok",
|
||||||
|
"data": lockout_msg,
|
||||||
|
},
|
||||||
|
)
|
@ -112,8 +112,8 @@
|
|||||||
<div class="form-check form-check-flat mt-0">
|
<div class="form-check form-check-flat mt-0">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<a href="#" class="text-small forgot-password ">{{ translate('login', 'forgotPassword',
|
<button onclick="resetPass()" id="#resetPass" form="" class="btn btn-outline-primary btn-sm forgot-password ">{{ translate('login', 'forgotPassword',
|
||||||
data['lang']) }}</a>
|
data['lang']) }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-block text-center my-3">
|
<div class="text-block text-center my-3">
|
||||||
@ -146,6 +146,7 @@
|
|||||||
<script src="/static/assets/js/shared/misc.js"></script>
|
<script src="/static/assets/js/shared/misc.js"></script>
|
||||||
<script src="/static/assets/js/shared/settings.js"></script>
|
<script src="/static/assets/js/shared/settings.js"></script>
|
||||||
<script src="/static/assets/js/shared/todolist.js"></script>
|
<script src="/static/assets/js/shared/todolist.js"></script>
|
||||||
|
<script src="../static/assets/vendors/js/bootbox.min.js"></script>
|
||||||
<!-- endinject -->
|
<!-- endinject -->
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
@ -160,8 +161,24 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
async function resetPass(){
|
||||||
|
let res = await fetch(`/api/v2/crafty/resetPass/`, {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
let responseData = await res.json();
|
||||||
|
console.log(responseData);
|
||||||
|
bootbox.alert(responseData.data)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
.modal-content {
|
||||||
|
background-color: rgb(34, 36, 55) !important;
|
||||||
|
color: lightgray;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
2
main.py
2
main.py
@ -388,6 +388,8 @@ if __name__ == "__main__":
|
|||||||
# Master config.json in helpers.py
|
# Master config.json in helpers.py
|
||||||
Console.info("Checking for remote changes to config.json")
|
Console.info("Checking for remote changes to config.json")
|
||||||
controller.get_config_diff()
|
controller.get_config_diff()
|
||||||
|
# Delete anti-lockout-user
|
||||||
|
controller.users.stop_anti_lockout()
|
||||||
Console.info("Remote change complete.")
|
Console.info("Remote change complete.")
|
||||||
|
|
||||||
# startup the web server
|
# startup the web server
|
||||||
|
Loading…
Reference in New Issue
Block a user