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 binascii
|
||||
import base64
|
||||
import urllib
|
||||
import json
|
||||
import nh3
|
||||
from jsonschema import validate
|
||||
from jsonschema.exceptions import ValidationError
|
||||
|
||||
from app.classes.shared.helpers import Helpers
|
||||
from app.classes.models.users import HelperUsers
|
||||
@ -47,7 +51,7 @@ class PublicHandler(BaseHandler):
|
||||
}
|
||||
|
||||
if self.request.query:
|
||||
page_data["query"] = self.request.query
|
||||
page_data["query"] = self.request.query_arguments.get("next")[0].decode()
|
||||
|
||||
# sensible defaults
|
||||
template = "public/404.html"
|
||||
@ -77,11 +81,7 @@ class PublicHandler(BaseHandler):
|
||||
|
||||
# if we have no page, let's go to login
|
||||
else:
|
||||
if self.request.query:
|
||||
self.redirect("/login?" + self.request.query)
|
||||
else:
|
||||
self.redirect("/login")
|
||||
return
|
||||
return self.redirect("/login")
|
||||
|
||||
self.render(
|
||||
template,
|
||||
@ -91,42 +91,74 @@ class PublicHandler(BaseHandler):
|
||||
)
|
||||
|
||||
def post(self, page=None):
|
||||
# pylint: disable=no-member
|
||||
error = nh3.clean(self.get_argument("error", "Invalid Login!"))
|
||||
error_msg = nh3.clean(self.get_argument("error_msg", ""))
|
||||
# pylint: enable=no-member
|
||||
login_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"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 = {
|
||||
"version": self.helper.get_version_string(),
|
||||
"error": error,
|
||||
"lang": self.helper.get_setting("language"),
|
||||
"lang_page": self.helper.get_lang_page(self.helper.get_setting("language")),
|
||||
"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":
|
||||
data = json.loads(self.request.body)
|
||||
|
||||
auth_log.info(
|
||||
f"User attempting to authenticate from {self.get_remote_ip()}"
|
||||
)
|
||||
next_page = "/login"
|
||||
if self.request.query:
|
||||
next_page = "/login?" + self.request.query
|
||||
|
||||
entered_username = nh3.clean(
|
||||
self.get_argument("username")
|
||||
) # pylint: disable=no-member
|
||||
entered_username = nh3.clean(data["username"]) # pylint: disable=no-member
|
||||
try:
|
||||
entered_password = base64.b64decode(
|
||||
self.get_argument("encPassword")
|
||||
).decode("utf-8")
|
||||
except binascii.Error:
|
||||
error_msg = (
|
||||
"Hello? Hello? Anybody home?"
|
||||
" Go straight to jail. Do not pass go."
|
||||
entered_password = urllib.parse.unquote(
|
||||
base64.b64decode(data["password"]).decode("utf-8")
|
||||
)
|
||||
except binascii.Error:
|
||||
return self.finish_json(
|
||||
403,
|
||||
{
|
||||
"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:
|
||||
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()}"
|
||||
" 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_data")
|
||||
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
|
||||
|
||||
return self.clear_cookie("token")
|
||||
# if we don't have a user
|
||||
if not user_data:
|
||||
auth_log.error(
|
||||
@ -158,15 +190,18 @@ class PublicHandler(BaseHandler):
|
||||
" User does not exist."
|
||||
)
|
||||
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_data")
|
||||
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
|
||||
return self.clear_cookie("token")
|
||||
|
||||
# if they are disabled
|
||||
if not user_data.enabled:
|
||||
@ -176,18 +211,18 @@ class PublicHandler(BaseHandler):
|
||||
" User account disabled"
|
||||
)
|
||||
self.controller.log_attempt(self.get_remote_ip(), entered_username)
|
||||
error_msg = (
|
||||
"User account disabled. Please contact "
|
||||
"your system administrator for more info."
|
||||
self.finish_json(
|
||||
403,
|
||||
{
|
||||
"status": "error",
|
||||
"error": self.helper.translation.translate(
|
||||
"login", "disabled", self.helper.get_setting("language")
|
||||
),
|
||||
},
|
||||
)
|
||||
# self.clear_cookie("user")
|
||||
# self.clear_cookie("user_data")
|
||||
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
|
||||
return self.clear_cookie("token")
|
||||
login_result = self.helper.verify_pass(entered_password, user_data.password)
|
||||
|
||||
# Valid Login
|
||||
@ -212,12 +247,9 @@ class PublicHandler(BaseHandler):
|
||||
user_data.user_id, "Logged in", 0, self.get_remote_ip()
|
||||
)
|
||||
|
||||
if self.request.query_arguments.get("next"):
|
||||
next_page = self.request.query_arguments.get("next")[0].decode()
|
||||
else:
|
||||
next_page = "/panel/dashboard"
|
||||
|
||||
self.redirect(next_page)
|
||||
return self.finish_json(
|
||||
200, {"status": "ok", "data": {"message": "login successful!"}}
|
||||
)
|
||||
else:
|
||||
auth_log.error(
|
||||
f"User attempted to log into {entered_username}."
|
||||
@ -239,12 +271,9 @@ class PublicHandler(BaseHandler):
|
||||
self.controller.management.add_to_audit_log(
|
||||
user_data.user_id, "Tried to log in", 0, self.get_remote_ip()
|
||||
)
|
||||
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 self.finish_json(
|
||||
403,
|
||||
{"status": "error", "error": error_msg},
|
||||
)
|
||||
else:
|
||||
if self.request.query:
|
||||
self.redirect("/login?" + self.request.query)
|
||||
else:
|
||||
self.redirect("/login")
|
||||
self.redirect("/login?")
|
||||
|
@ -77,55 +77,49 @@
|
||||
box-shadow: 0 12px 16px 0 hsla(0, 0%, 0%, 0.4);
|
||||
}
|
||||
</style>
|
||||
{% if data['query'] %}
|
||||
<form id="login" action="/login?{{ data['query'] }}" method="post" onsubmit="encodePass()">
|
||||
{% else %}
|
||||
<form id="login" action="/login" method="post" onsubmit="encodePass()">
|
||||
{% end %}
|
||||
{% raw xsrf_form_html() %}
|
||||
<div class="form-group">
|
||||
<label class="label">{{ translate('login', 'username', data['lang']) }}</label>
|
||||
<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>
|
||||
<form id="login-form" data-query="{{ data.get('query', None) }}">
|
||||
{% raw xsrf_form_html() %}
|
||||
<div class="form-group">
|
||||
<label class="label">{{ translate('login', 'username', data['lang']) }}</label>
|
||||
<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 class="form-group">
|
||||
<label class="label">{{ translate('login', 'password', data['lang']) }}</label>
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control login-text-input login-input"
|
||||
placeholder="{{ translate('login', 'password', data['lang']) }}" name="password" id="password"
|
||||
required="true">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="label">{{ translate('login', 'password', data['lang']) }}</label>
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control login-text-input login-input"
|
||||
placeholder="{{ translate('login', 'password', data['lang']) }}" name="password" id="password"
|
||||
required="true">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="login-input btn btn-primary submit-btn btn-block">{{ translate('login', 'login',
|
||||
data['lang']) }}</button>
|
||||
</div>
|
||||
{% if error_msg is not None %}
|
||||
<fieldset style="color: red; text-align: center;">
|
||||
<span>{{error_msg}}</span>
|
||||
</fieldset>
|
||||
{% end %}
|
||||
<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 class="form-group">
|
||||
<button class="login-input btn btn-primary submit-btn btn-block">{{ translate('login', 'login',
|
||||
data['lang']) }}</button>
|
||||
</div>
|
||||
<fieldset id="error-field" style="color: red; text-align: center;">
|
||||
</fieldset>
|
||||
<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 class="text-block text-center my-3">
|
||||
<span class="text-small font-weight-semibold"><a href="https://craftycontrol.com/">Crafty Control
|
||||
{{data['version'] }}</a> </span>
|
||||
</div>
|
||||
|
||||
<div class="text-block text-center my-3">
|
||||
<a href="/status" class="text-small forgot-password">{{ translate('login', 'viewStatus',
|
||||
data['lang']) }}</a>
|
||||
</div>
|
||||
</form>
|
||||
<div class="text-block text-center my-3">
|
||||
<span class="text-small font-weight-semibold"><a href="https://craftycontrol.com/">Crafty Control
|
||||
{{data['version'] }}</a> </span>
|
||||
</div>
|
||||
|
||||
<div class="text-block text-center my-3">
|
||||
<a href="/status" class="text-small forgot-password">{{ translate('login', 'viewStatus',
|
||||
data['lang']) }}</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
@ -155,13 +149,13 @@
|
||||
document.getElementById('login-form-background').style.background = 'rgb(34, 36, 55, ' + (opacity / 100) + ')';
|
||||
//Register Service worker for mobile app
|
||||
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) {
|
||||
console.log('Service Worker Registered');
|
||||
});
|
||||
}
|
||||
});
|
||||
async function resetPass(){
|
||||
async function resetPass() {
|
||||
let res = await fetch(`/api/v2/crafty/resetPass/`, {
|
||||
method: 'GET',
|
||||
});
|
||||
@ -170,9 +164,38 @@
|
||||
bootbox.alert(responseData.data)
|
||||
|
||||
}
|
||||
function encodePass(){
|
||||
$("#encPassword").val(btoa($("#password").val()))
|
||||
}
|
||||
$("#login-form").on("submit", async function (e) {
|
||||
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>
|
||||
<style>
|
||||
.modal-content {
|
||||
@ -181,9 +204,6 @@
|
||||
text-align: center;
|
||||
}
|
||||
</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>
|
||||
|
||||
</html>
|
@ -221,7 +221,8 @@
|
||||
"username": "Username",
|
||||
"viewStatus": "View Public Status Page",
|
||||
"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": {
|
||||
"activityLog": "Activity Logs",
|
||||
@ -670,4 +671,4 @@
|
||||
"webhook_body": "Webhook Body",
|
||||
"webhooks": "Webhooks"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user