mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2025-01-18 17:15:13 +01:00
Login working
This commit is contained in:
parent
da002cb02a
commit
5528c9b858
@ -18,6 +18,11 @@ login_schema = {
|
||||
"pattern": "^[a-z0-9_]+$",
|
||||
},
|
||||
"password": {"type": "string", "minLength": 4},
|
||||
"totp": {
|
||||
"type": "string",
|
||||
"minLength": 6,
|
||||
"maxLength": 6,
|
||||
},
|
||||
},
|
||||
"required": ["username", "password"],
|
||||
"additionalProperties": False,
|
||||
@ -55,7 +60,7 @@ class ApiAuthLoginHandler(BaseApiHandler):
|
||||
|
||||
username = data["username"]
|
||||
password = data["password"]
|
||||
|
||||
totp = data.get("totp")
|
||||
# pylint: disable=no-member
|
||||
user_data = Users.get_or_none(Users.username == username)
|
||||
|
||||
@ -92,8 +97,24 @@ class ApiAuthLoginHandler(BaseApiHandler):
|
||||
},
|
||||
)
|
||||
return
|
||||
|
||||
login_result = self.helper.verify_pass(password, user_data.password)
|
||||
# Establish login result
|
||||
login_result = None
|
||||
# Verify user password
|
||||
pass_login_result = self.helper.verify_pass(password, user_data.password)
|
||||
# Get the length of user TOTP actions
|
||||
totp_enabled = len(list(user_data.totp_user)) > 0
|
||||
# Check if user has TOTP and if we got any type of TOTP data in the login
|
||||
# payload
|
||||
if totp_enabled and totp:
|
||||
totp_login_result = self.controller.totp.verify_user_totp(
|
||||
user_data.user_id, totp
|
||||
)
|
||||
# Check if both password auth and totp auth passed
|
||||
login_result = pass_login_result is True and totp_login_result is True
|
||||
elif not totp_enabled and not totp:
|
||||
# If the user doesn't have TOTP enabled and they didn't send a TOTP code
|
||||
# We'll pass them through
|
||||
login_result = pass_login_result
|
||||
|
||||
# Valid Login
|
||||
if login_result:
|
||||
@ -168,155 +189,3 @@ class ApiAuthLoginHandler(BaseApiHandler):
|
||||
self.clear_cookie("token")
|
||||
# self.clear_cookie("user")
|
||||
# self.clear_cookie("user_data")
|
||||
|
||||
|
||||
class ApiAuthLoginHandler(BaseApiHandler):
|
||||
def post(self):
|
||||
try:
|
||||
data = json.loads(self.request.body)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
logger.error(
|
||||
"Invalid JSON schema for API"
|
||||
f" login attempt from {self.get_remote_ip()}"
|
||||
)
|
||||
return self.finish_json(
|
||||
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||
)
|
||||
|
||||
try:
|
||||
validate(data, login_schema)
|
||||
except ValidationError as e:
|
||||
logger.error(
|
||||
"Invalid JSON schema for API"
|
||||
f" login attempt from {self.get_remote_ip()}"
|
||||
)
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID_JSON_SCHEMA",
|
||||
"error_data": str(e),
|
||||
},
|
||||
)
|
||||
|
||||
username = data["username"]
|
||||
password = data["password"]
|
||||
|
||||
# pylint: disable=no-member
|
||||
user_data = Users.get_or_none(Users.username == username)
|
||||
|
||||
if user_data is None:
|
||||
self.controller.log_attempt(self.get_remote_ip(), username)
|
||||
auth_log.error(
|
||||
f"User attempted to log into {username}."
|
||||
" Authentication failed from remote IP"
|
||||
f" {self.get_remote_ip()}. User not found"
|
||||
)
|
||||
return self.finish_json(
|
||||
401,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INCORRECT_CREDENTIALS",
|
||||
"error_data": "INVALID CREDENTIALS",
|
||||
"token": None,
|
||||
},
|
||||
)
|
||||
|
||||
if not user_data.enabled:
|
||||
auth_log.error(
|
||||
f"User attempted to log into {username}."
|
||||
" Authentication failed from remote"
|
||||
f" IP {self.get_remote_ip()} account disabled"
|
||||
)
|
||||
self.finish_json(
|
||||
403,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "ACCOUNT_DISABLED",
|
||||
"error_data": "ACCOUNT DISABLED",
|
||||
"token": None,
|
||||
},
|
||||
)
|
||||
return
|
||||
|
||||
login_result = self.helper.verify_pass(password, user_data.password)
|
||||
|
||||
# Valid Login
|
||||
if login_result:
|
||||
auth_log.info(
|
||||
f"{username} successfully"
|
||||
" authenticated and logged"
|
||||
f" into panel from remote IP {self.get_remote_ip()}"
|
||||
)
|
||||
logger.info(f"User: {user_data} Logged in from IP: {self.get_remote_ip()}")
|
||||
|
||||
# record this login
|
||||
query = Users.select().where(Users.username == username.lower()).get()
|
||||
query.last_ip = self.get_remote_ip()
|
||||
query.last_login = Helpers.get_time_as_string()
|
||||
query.save()
|
||||
|
||||
# log this login
|
||||
self.controller.management.add_to_audit_log(
|
||||
user_data.user_id, "logged in via the API", None, self.get_remote_ip()
|
||||
)
|
||||
extra = None
|
||||
totp_req = False
|
||||
if list(user_data.totp_user) > 0:
|
||||
totp_req = True
|
||||
extra = {"type": "temp"}
|
||||
token = self.controller.authentication.generate(user_data.user_id, extra)
|
||||
self.set_current_user(user_data.user_id, token)
|
||||
self.finish_json(
|
||||
200,
|
||||
{
|
||||
"status": "ok",
|
||||
"data": {
|
||||
"token": token,
|
||||
"user_id": str(user_data.user_id),
|
||||
"page": "/panel/dashboard",
|
||||
"totp": totp_req,
|
||||
},
|
||||
},
|
||||
)
|
||||
else:
|
||||
# log this failed login attempt
|
||||
self.controller.management.add_to_audit_log(
|
||||
user_data.user_id, "Tried to log in", None, self.get_remote_ip()
|
||||
)
|
||||
self.controller.log_attempt(self.get_remote_ip(), username)
|
||||
# Setup error message for failed login
|
||||
error_msg = self.helper.translation.translate(
|
||||
"login", "incorrect", self.helper.get_setting("language")
|
||||
)
|
||||
if password == "app/config/default-creds.txt":
|
||||
error_msg += ". "
|
||||
error_msg += self.helper.translation.translate(
|
||||
"login", "defaultPath", self.helper.get_setting("language")
|
||||
)
|
||||
self.finish_json(
|
||||
401,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INCORRECT_CREDENTIALS",
|
||||
"error_data": error_msg,
|
||||
},
|
||||
)
|
||||
|
||||
def set_current_user(self, user_id: str = None, token: str = None):
|
||||
expire_days = self.helper.get_setting("cookie_expire")
|
||||
|
||||
# if helper comes back with false
|
||||
if not expire_days:
|
||||
expire_days = "5"
|
||||
|
||||
if user_id is not None:
|
||||
self.set_cookie(
|
||||
"token",
|
||||
token,
|
||||
expires_days=int(expire_days),
|
||||
)
|
||||
else:
|
||||
self.clear_cookie("token")
|
||||
# self.clear_cookie("user")
|
||||
# self.clear_cookie("user_data")
|
||||
|
@ -183,17 +183,24 @@
|
||||
|
||||
//Create an object from the form data entries
|
||||
let formDataObject = Object.fromEntries(formData.entries());
|
||||
let body = {
|
||||
"username": formDataObject.username,
|
||||
"password": formDataObject.password,
|
||||
}
|
||||
if (formDataObject.totp != "") {
|
||||
body = {
|
||||
"username": formDataObject.username,
|
||||
"password": formDataObject.password,
|
||||
"totp": formDataObject.totp,
|
||||
}
|
||||
}
|
||||
let res = await fetch(`/api/v2/auth/login/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-XSRFToken': formDataObject._xsrf,
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"username": formDataObject.username,
|
||||
"password": formDataObject.password,
|
||||
"totp": formDataObject.totp,
|
||||
}),
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
let responseData = await res.json();
|
||||
if (responseData.status === "ok") {
|
||||
|
@ -664,6 +664,7 @@
|
||||
"roleName": "Role Name",
|
||||
"selectManager": "Select Manager for User",
|
||||
"super": "Super User",
|
||||
"totpIdReq": "TOTP ID Required for request",
|
||||
"userLang": "User Language",
|
||||
"userName": "User Name",
|
||||
"userNameDesc": "What do you want to call this user?",
|
||||
@ -671,7 +672,8 @@
|
||||
"userRolesDesc": "Roles this user is a member of.",
|
||||
"userSettings": "User Settings",
|
||||
"userTheme": "UI Theme",
|
||||
"uses": "Number of uses allowed (-1==No Limit)"
|
||||
"uses": "Number of uses allowed (-1==No Limit)",
|
||||
"optReq": "TOTP is required for super users. You cannot remove your only TOTP method."
|
||||
},
|
||||
"validators": {
|
||||
"backupName": "Backup name must be a string and a minimum length of 3.",
|
||||
|
Loading…
x
Reference in New Issue
Block a user