mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Change login payload
This commit is contained in:
parent
d168a7f8f0
commit
aac35b14d9
@ -1,7 +1,11 @@
|
|||||||
import logging
|
import logging
|
||||||
import binascii
|
import binascii
|
||||||
import base64
|
import base64
|
||||||
|
import urllib
|
||||||
|
import json
|
||||||
import nh3
|
import nh3
|
||||||
|
from jsonschema import validate
|
||||||
|
from jsonschema.exceptions import ValidationError
|
||||||
|
|
||||||
from app.classes.shared.helpers import Helpers
|
from app.classes.shared.helpers import Helpers
|
||||||
from app.classes.models.users import HelperUsers
|
from app.classes.models.users import HelperUsers
|
||||||
@ -47,7 +51,7 @@ class PublicHandler(BaseHandler):
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.request.query:
|
if self.request.query:
|
||||||
page_data["query"] = self.request.query
|
page_data["query"] = self.request.query_arguments.get("next")[0].decode()
|
||||||
|
|
||||||
# sensible defaults
|
# sensible defaults
|
||||||
template = "public/404.html"
|
template = "public/404.html"
|
||||||
@ -77,11 +81,7 @@ class PublicHandler(BaseHandler):
|
|||||||
|
|
||||||
# if we have no page, let's go to login
|
# if we have no page, let's go to login
|
||||||
else:
|
else:
|
||||||
if self.request.query:
|
return self.redirect("/login")
|
||||||
self.redirect("/login?" + self.request.query)
|
|
||||||
else:
|
|
||||||
self.redirect("/login")
|
|
||||||
return
|
|
||||||
|
|
||||||
self.render(
|
self.render(
|
||||||
template,
|
template,
|
||||||
@ -91,42 +91,74 @@ class PublicHandler(BaseHandler):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def post(self, page=None):
|
def post(self, page=None):
|
||||||
# pylint: disable=no-member
|
login_schema = {
|
||||||
error = nh3.clean(self.get_argument("error", "Invalid Login!"))
|
"type": "object",
|
||||||
error_msg = nh3.clean(self.get_argument("error_msg", ""))
|
"properties": {
|
||||||
# pylint: enable=no-member
|
"username": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-z0-9_]+$",
|
||||||
|
},
|
||||||
|
"password": {"type": "string"},
|
||||||
|
},
|
||||||
|
"required": ["username", "password"],
|
||||||
|
"additionalProperties": False,
|
||||||
|
}
|
||||||
|
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),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
page_data = {
|
page_data = {
|
||||||
"version": self.helper.get_version_string(),
|
"version": self.helper.get_version_string(),
|
||||||
"error": error,
|
|
||||||
"lang": self.helper.get_setting("language"),
|
"lang": self.helper.get_setting("language"),
|
||||||
"lang_page": self.helper.get_lang_page(self.helper.get_setting("language")),
|
"lang_page": self.helper.get_lang_page(self.helper.get_setting("language")),
|
||||||
"query": "",
|
"query": "",
|
||||||
}
|
}
|
||||||
if self.request.query:
|
if self.request.query:
|
||||||
page_data["query"] = self.request.query
|
page_data["query"] = self.request.query_arguments.get("next")[0].decode()
|
||||||
|
|
||||||
if page == "login":
|
if page == "login":
|
||||||
|
data = json.loads(self.request.body)
|
||||||
|
|
||||||
auth_log.info(
|
auth_log.info(
|
||||||
f"User attempting to authenticate from {self.get_remote_ip()}"
|
f"User attempting to authenticate from {self.get_remote_ip()}"
|
||||||
)
|
)
|
||||||
next_page = "/login"
|
entered_username = nh3.clean(data["username"]) # pylint: disable=no-member
|
||||||
if self.request.query:
|
|
||||||
next_page = "/login?" + self.request.query
|
|
||||||
|
|
||||||
entered_username = nh3.clean(
|
|
||||||
self.get_argument("username")
|
|
||||||
) # pylint: disable=no-member
|
|
||||||
try:
|
try:
|
||||||
entered_password = base64.b64decode(
|
entered_password = urllib.parse.unquote(
|
||||||
self.get_argument("encPassword")
|
base64.b64decode(data["password"]).decode("utf-8")
|
||||||
).decode("utf-8")
|
)
|
||||||
except binascii.Error:
|
except binascii.Error:
|
||||||
error_msg = (
|
return self.finish_json(
|
||||||
"Hello? Hello? Anybody home?"
|
403,
|
||||||
" Go straight to jail. Do not pass go."
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "Hello? Hello? Anybody home?"
|
||||||
|
" Go straight to jail. Do not pass go.",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
return self.redirect(f"/login?error_msg={error_msg}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user_id = HelperUsers.get_user_id_by_name(entered_username.lower())
|
user_id = HelperUsers.get_user_id_by_name(entered_username.lower())
|
||||||
@ -138,18 +170,18 @@ class PublicHandler(BaseHandler):
|
|||||||
f" Authentication failed from remote IP {self.get_remote_ip()}"
|
f" Authentication failed from remote IP {self.get_remote_ip()}"
|
||||||
" Users does not exist."
|
" Users does not exist."
|
||||||
)
|
)
|
||||||
error_msg = "Incorrect username or password. Please try again."
|
self.finish_json(
|
||||||
|
403,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": self.helper.translation.translate(
|
||||||
|
"login", "incorrect", self.helper.get_setting("language")
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
# self.clear_cookie("user")
|
# self.clear_cookie("user")
|
||||||
# self.clear_cookie("user_data")
|
# self.clear_cookie("user_data")
|
||||||
self.clear_cookie("token")
|
return self.clear_cookie("token")
|
||||||
if self.request.query:
|
|
||||||
self.redirect(
|
|
||||||
f"/login?err or_msg={error_msg}" f"&{self.request.query}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.redirect(f"/login?error_msg={error_msg}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# if we don't have a user
|
# if we don't have a user
|
||||||
if not user_data:
|
if not user_data:
|
||||||
auth_log.error(
|
auth_log.error(
|
||||||
@ -158,15 +190,18 @@ class PublicHandler(BaseHandler):
|
|||||||
" User does not exist."
|
" User does not exist."
|
||||||
)
|
)
|
||||||
self.controller.log_attempt(self.get_remote_ip(), entered_username)
|
self.controller.log_attempt(self.get_remote_ip(), entered_username)
|
||||||
error_msg = "Incorrect username or password. Please try again."
|
self.finish_json(
|
||||||
|
403,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": self.helper.translation.translate(
|
||||||
|
"login", "incorrect", self.helper.get_setting("language")
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
# self.clear_cookie("user")
|
# self.clear_cookie("user")
|
||||||
# self.clear_cookie("user_data")
|
# self.clear_cookie("user_data")
|
||||||
self.clear_cookie("token")
|
return self.clear_cookie("token")
|
||||||
if self.request.query:
|
|
||||||
self.redirect(f"/login?error_msg={error_msg}&{self.request.query}")
|
|
||||||
else:
|
|
||||||
self.redirect(f"/login?error_msg={error_msg}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# if they are disabled
|
# if they are disabled
|
||||||
if not user_data.enabled:
|
if not user_data.enabled:
|
||||||
@ -176,18 +211,18 @@ class PublicHandler(BaseHandler):
|
|||||||
" User account disabled"
|
" User account disabled"
|
||||||
)
|
)
|
||||||
self.controller.log_attempt(self.get_remote_ip(), entered_username)
|
self.controller.log_attempt(self.get_remote_ip(), entered_username)
|
||||||
error_msg = (
|
self.finish_json(
|
||||||
"User account disabled. Please contact "
|
403,
|
||||||
"your system administrator for more info."
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": self.helper.translation.translate(
|
||||||
|
"login", "disabled", self.helper.get_setting("language")
|
||||||
|
),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
# self.clear_cookie("user")
|
# self.clear_cookie("user")
|
||||||
# self.clear_cookie("user_data")
|
# self.clear_cookie("user_data")
|
||||||
self.clear_cookie("token")
|
return self.clear_cookie("token")
|
||||||
if self.request.query:
|
|
||||||
self.redirect(f"/login?error_msg={error_msg}&{self.request.query}")
|
|
||||||
else:
|
|
||||||
self.redirect(f"/login?error_msg={error_msg}")
|
|
||||||
return
|
|
||||||
login_result = self.helper.verify_pass(entered_password, user_data.password)
|
login_result = self.helper.verify_pass(entered_password, user_data.password)
|
||||||
|
|
||||||
# Valid Login
|
# Valid Login
|
||||||
@ -212,12 +247,9 @@ class PublicHandler(BaseHandler):
|
|||||||
user_data.user_id, "Logged in", 0, self.get_remote_ip()
|
user_data.user_id, "Logged in", 0, self.get_remote_ip()
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.request.query_arguments.get("next"):
|
return self.finish_json(
|
||||||
next_page = self.request.query_arguments.get("next")[0].decode()
|
200, {"status": "ok", "data": {"message": "login successful!"}}
|
||||||
else:
|
)
|
||||||
next_page = "/panel/dashboard"
|
|
||||||
|
|
||||||
self.redirect(next_page)
|
|
||||||
else:
|
else:
|
||||||
auth_log.error(
|
auth_log.error(
|
||||||
f"User attempted to log into {entered_username}."
|
f"User attempted to log into {entered_username}."
|
||||||
@ -239,12 +271,9 @@ class PublicHandler(BaseHandler):
|
|||||||
self.controller.management.add_to_audit_log(
|
self.controller.management.add_to_audit_log(
|
||||||
user_data.user_id, "Tried to log in", 0, self.get_remote_ip()
|
user_data.user_id, "Tried to log in", 0, self.get_remote_ip()
|
||||||
)
|
)
|
||||||
if self.request.query:
|
return self.finish_json(
|
||||||
self.redirect(f"/login?error_msg={error_msg}&{self.request.query}")
|
403,
|
||||||
else:
|
{"status": "error", "error": error_msg},
|
||||||
self.redirect(f"/login?error_msg={error_msg}")
|
)
|
||||||
else:
|
else:
|
||||||
if self.request.query:
|
self.redirect("/login?")
|
||||||
self.redirect("/login?" + self.request.query)
|
|
||||||
else:
|
|
||||||
self.redirect("/login")
|
|
||||||
|
@ -77,55 +77,49 @@
|
|||||||
box-shadow: 0 12px 16px 0 hsla(0, 0%, 0%, 0.4);
|
box-shadow: 0 12px 16px 0 hsla(0, 0%, 0%, 0.4);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% if data['query'] %}
|
<form id="login-form" data-query="{{ data.get('query', None) }}">
|
||||||
<form id="login" action="/login?{{ data['query'] }}" method="post" onsubmit="encodePass()">
|
{% raw xsrf_form_html() %}
|
||||||
{% else %}
|
<div class="form-group">
|
||||||
<form id="login" action="/login" method="post" onsubmit="encodePass()">
|
<label class="label">{{ translate('login', 'username', data['lang']) }}</label>
|
||||||
{% end %}
|
<div class="input-group">
|
||||||
{% raw xsrf_form_html() %}
|
<input type="text" class="form-control login-text-input login-input"
|
||||||
<div class="form-group">
|
placeholder="{{ translate('login', 'username', data['lang']) }}" name="username" id="username"
|
||||||
<label class="label">{{ translate('login', 'username', data['lang']) }}</label>
|
required="true">
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control login-text-input login-input"
|
|
||||||
placeholder="{{ translate('login', 'username', data['lang']) }}" name="username" id="username"
|
|
||||||
required="true">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label class="label">{{ translate('login', 'password', data['lang']) }}</label>
|
<div class="form-group">
|
||||||
<div class="input-group">
|
<label class="label">{{ translate('login', 'password', data['lang']) }}</label>
|
||||||
<input type="password" class="form-control login-text-input login-input"
|
<div class="input-group">
|
||||||
placeholder="{{ translate('login', 'password', data['lang']) }}" name="password" id="password"
|
<input type="password" class="form-control login-text-input login-input"
|
||||||
required="true">
|
placeholder="{{ translate('login', 'password', data['lang']) }}" name="password" id="password"
|
||||||
</div>
|
required="true">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
</div>
|
||||||
<button class="login-input btn btn-primary submit-btn btn-block">{{ translate('login', 'login',
|
<div class="form-group">
|
||||||
data['lang']) }}</button>
|
<button class="login-input btn btn-primary submit-btn btn-block">{{ translate('login', 'login',
|
||||||
</div>
|
data['lang']) }}</button>
|
||||||
{% if error_msg is not None %}
|
</div>
|
||||||
<fieldset style="color: red; text-align: center;">
|
<fieldset id="error-field" style="color: red; text-align: center;">
|
||||||
<span>{{error_msg}}</span>
|
</fieldset>
|
||||||
</fieldset>
|
<div class="form-group d-flex justify-content-between">
|
||||||
{% end %}
|
<div class="form-check form-check-flat mt-0">
|
||||||
<div class="form-group d-flex justify-content-between">
|
|
||||||
<div class="form-check form-check-flat mt-0">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<button onclick="resetPass()" id="#resetPass" form="" class="btn btn-outline-primary btn-sm forgot-password ">{{ translate('login', 'forgotPassword',
|
|
||||||
data['lang']) }}</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<button onclick="resetPass()" id="#resetPass" form=""
|
||||||
|
class="btn btn-outline-primary btn-sm forgot-password ">{{ translate('login', 'forgotPassword',
|
||||||
|
data['lang']) }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="text-block text-center my-3">
|
<div class="text-block text-center my-3">
|
||||||
<span class="text-small font-weight-semibold"><a href="https://craftycontrol.com/">Crafty Control
|
<span class="text-small font-weight-semibold"><a href="https://craftycontrol.com/">Crafty Control
|
||||||
{{data['version'] }}</a> </span>
|
{{data['version'] }}</a> </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-block text-center my-3">
|
<div class="text-block text-center my-3">
|
||||||
<a href="/status" class="text-small forgot-password">{{ translate('login', 'viewStatus',
|
<a href="/status" class="text-small forgot-password">{{ translate('login', 'viewStatus',
|
||||||
data['lang']) }}</a>
|
data['lang']) }}</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -155,13 +149,13 @@
|
|||||||
document.getElementById('login-form-background').style.background = 'rgb(34, 36, 55, ' + (opacity / 100) + ')';
|
document.getElementById('login-form-background').style.background = 'rgb(34, 36, 55, ' + (opacity / 100) + ')';
|
||||||
//Register Service worker for mobile app
|
//Register Service worker for mobile app
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.register('/static/assets/js/shared/service-worker.js', {scope: '/'})
|
navigator.serviceWorker.register('/static/assets/js/shared/service-worker.js', { scope: '/' })
|
||||||
.then(function (registration) {
|
.then(function (registration) {
|
||||||
console.log('Service Worker Registered');
|
console.log('Service Worker Registered');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
async function resetPass(){
|
async function resetPass() {
|
||||||
let res = await fetch(`/api/v2/crafty/resetPass/`, {
|
let res = await fetch(`/api/v2/crafty/resetPass/`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
});
|
});
|
||||||
@ -170,9 +164,38 @@
|
|||||||
bootbox.alert(responseData.data)
|
bootbox.alert(responseData.data)
|
||||||
|
|
||||||
}
|
}
|
||||||
function encodePass(){
|
$("#login-form").on("submit", async function (e) {
|
||||||
$("#encPassword").val(btoa($("#password").val()))
|
e.preventDefault();
|
||||||
}
|
let loginForm = document.getElementById("login-form");
|
||||||
|
|
||||||
|
let formData = new FormData(loginForm);
|
||||||
|
|
||||||
|
//Create an object from the form data entries
|
||||||
|
let formDataObject = Object.fromEntries(formData.entries());
|
||||||
|
console.log(formDataObject)
|
||||||
|
let res = await fetch(`/login`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-XSRFToken': formDataObject._xsrf,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
"username": formDataObject.username,
|
||||||
|
"password": btoa(encodeURIComponent(formDataObject.password))
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
let responseData = await res.json();
|
||||||
|
if (responseData.status === "ok") {
|
||||||
|
console.log("OK")
|
||||||
|
if ($("#login-form").data("query")) {
|
||||||
|
location.href = `${$("#login-form").data("query")}`;
|
||||||
|
} else {
|
||||||
|
location.href = `/panel/dashboard`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$("#error-field").html(responseData.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.modal-content {
|
.modal-content {
|
||||||
@ -181,9 +204,6 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<input form="login" type="password" class="form-control login-text-input login-input"
|
|
||||||
placeholder="{{ translate('login', 'password', data['lang']) }}" name="encPassword" id="encPassword"
|
|
||||||
style="visibility: hidden;">
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -221,7 +221,8 @@
|
|||||||
"username": "Username",
|
"username": "Username",
|
||||||
"viewStatus": "View Public Status Page",
|
"viewStatus": "View Public Status Page",
|
||||||
"incorrect": "Incorrect username or password",
|
"incorrect": "Incorrect username or password",
|
||||||
"defaultPath": "The password you entered is the default credential path, not the password. Please find the default password in that location."
|
"defaultPath": "The password you entered is the default credential path, not the password. Please find the default password in that location.",
|
||||||
|
"disabled": "User account disabled. Please contact your system administrator for more info."
|
||||||
},
|
},
|
||||||
"notify": {
|
"notify": {
|
||||||
"activityLog": "Activity Logs",
|
"activityLog": "Activity Logs",
|
||||||
@ -670,4 +671,4 @@
|
|||||||
"webhook_body": "Webhook Body",
|
"webhook_body": "Webhook Body",
|
||||||
"webhooks": "Webhooks"
|
"webhooks": "Webhooks"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user