mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'bugfix/password-encode' into 'dev'
Fix Sanitisation on Passwords See merge request crafty-controller/crafty-4!715
This commit is contained in:
commit
cb5d0f46f8
@ -10,10 +10,11 @@ TBD
|
||||
- Do not allow users at server limit to clone servers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/718))
|
||||
- Fix bug where you cannot get to config with unloaded server ([Commit](https://gitlab.com/crafty-controller/crafty-4/-/commit/9de08973b6bb2ddf91283c5c6b0e189ff34f7e24))
|
||||
- Fix forge install v1.20, 1.20.1 and 1.20.2 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/710))
|
||||
- Fix Sanitisation on Passwords ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/715))
|
||||
### Tweaks
|
||||
- Bump pyOpenSSL & cryptography for CVE-2024-0727, CVE-2023-50782 ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/716))
|
||||
### Lang
|
||||
TBD
|
||||
- Update `de_DE, en_EN, es_ES, fr_FR, he_IL, lol_EN, lv_LV, nl_BE pl_PL, th_TH, tr_TR, uk_UA, zh_CN` translations for `4.3.0` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/715))
|
||||
<br><br>
|
||||
|
||||
## --- [4.2.3] - 2023/02/02
|
||||
|
@ -52,7 +52,7 @@ class UsersController:
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"minLength": 8,
|
||||
"minLength": self.helper.minimum_password_length,
|
||||
"examples": ["crafty"],
|
||||
"title": "Password",
|
||||
},
|
||||
|
@ -77,11 +77,11 @@ class MainPrompt(cmd.Cmd):
|
||||
# get new password from user
|
||||
new_pass = getpass.getpass(prompt=f"NEW password for: {username} > ")
|
||||
# check to make sure it fits our requirements.
|
||||
if len(new_pass) > 512:
|
||||
Console.warning("Passwords must be greater than 6char long and under 512")
|
||||
return False
|
||||
if len(new_pass) < 6:
|
||||
Console.warning("Passwords must be greater than 6char long and under 512")
|
||||
if len(new_pass) < self.helper.minimum_password_length:
|
||||
Console.warning(
|
||||
"Passwords must be greater than"
|
||||
f" {self.helper.minimum_password_length} char long"
|
||||
)
|
||||
return False
|
||||
# grab repeated password input
|
||||
new_pass_conf = getpass.getpass(prompt="Re-enter your password: > ")
|
||||
|
@ -81,6 +81,7 @@ class Helpers:
|
||||
self.update_available = False
|
||||
self.ignored_names = ["crafty_managed.txt", "db_stats"]
|
||||
self.crafty_starting = False
|
||||
self.minimum_password_length = 8
|
||||
|
||||
@staticmethod
|
||||
def auto_installer_fix(ex):
|
||||
|
@ -18,13 +18,20 @@ class DatabaseBuilder:
|
||||
logger.info("Fresh Install Detected - Creating Default Settings")
|
||||
Console.info("Fresh Install Detected - Creating Default Settings")
|
||||
default_data = self.helper.find_default_password()
|
||||
if password not in default_data:
|
||||
if "password" not in default_data:
|
||||
Console.help(
|
||||
"No default password found. Using password created "
|
||||
"by Crafty. Find it in app/config/default-creds.txt"
|
||||
)
|
||||
username = default_data.get("username", "admin")
|
||||
password = default_data.get("password", password)
|
||||
if self.helper.minimum_password_length > default_data.get("password", password):
|
||||
Console.critical(
|
||||
"Default password too short"
|
||||
" using Crafty's created default."
|
||||
" Find it in app/config/default-creds.txt"
|
||||
)
|
||||
else:
|
||||
password = default_data.get("password", password)
|
||||
|
||||
self.users_helper.add_user(
|
||||
username=username,
|
||||
|
@ -1,5 +1,8 @@
|
||||
import logging
|
||||
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
|
||||
@ -45,7 +48,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"
|
||||
@ -75,11 +78,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,
|
||||
@ -89,33 +88,61 @@ 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",
|
||||
},
|
||||
"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": "VWggb2ghIFN0aW5reS 🪠",
|
||||
"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
|
||||
|
||||
# pylint: disable=no-member
|
||||
entered_username = nh3.clean(self.get_argument("username"))
|
||||
entered_password = self.get_argument("password")
|
||||
# pylint: enable=no-member
|
||||
entered_username = nh3.clean(data["username"]) # pylint: disable=no-member
|
||||
entered_password = data["password"]
|
||||
|
||||
try:
|
||||
user_id = HelperUsers.get_user_id_by_name(entered_username.lower())
|
||||
@ -127,16 +154,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?error_msg={error_msg}&{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(
|
||||
@ -145,15 +174,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:
|
||||
@ -163,19 +195,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
|
||||
@ -200,32 +231,34 @@ 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"
|
||||
return self.finish_json(
|
||||
200, {"status": "ok", "data": {"message": "login successful!"}}
|
||||
)
|
||||
|
||||
self.redirect(next_page)
|
||||
else:
|
||||
auth_log.error(
|
||||
f"User attempted to log into {entered_username}."
|
||||
f" Authentication failed from remote IP {self.get_remote_ip()}"
|
||||
# We'll continue on and handle unsuccessful logins
|
||||
auth_log.error(
|
||||
f"User attempted to log into {entered_username}."
|
||||
f" Authentication failed from remote IP {self.get_remote_ip()}"
|
||||
)
|
||||
self.controller.log_attempt(self.get_remote_ip(), entered_username)
|
||||
# self.clear_cookie("user")
|
||||
# self.clear_cookie("user_data")
|
||||
self.clear_cookie("token")
|
||||
error_msg = self.helper.translation.translate(
|
||||
"login", "incorrect", self.helper.get_setting("language")
|
||||
)
|
||||
if entered_password == "app/config/default-creds.txt":
|
||||
error_msg += ". "
|
||||
error_msg += self.helper.translation.translate(
|
||||
"login", "defaultPath", self.helper.get_setting("language")
|
||||
)
|
||||
self.controller.log_attempt(self.get_remote_ip(), entered_username)
|
||||
# self.clear_cookie("user")
|
||||
# self.clear_cookie("user_data")
|
||||
self.clear_cookie("token")
|
||||
error_msg = "Incorrect username or password. Please try again."
|
||||
# log this failed login attempt
|
||||
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}")
|
||||
# log this failed login attempt
|
||||
self.controller.management.add_to_audit_log(
|
||||
user_data.user_id, "Tried to log in", 0, self.get_remote_ip()
|
||||
)
|
||||
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?")
|
||||
|
@ -17,7 +17,7 @@ login_schema = {
|
||||
"minLength": 4,
|
||||
"pattern": "^[a-z0-9_]+$",
|
||||
},
|
||||
"password": {"type": "string", "maxLength": 20, "minLength": 4},
|
||||
"password": {"type": "string", "minLength": 4},
|
||||
},
|
||||
"required": ["username", "password"],
|
||||
"additionalProperties": False,
|
||||
|
@ -77,55 +77,49 @@
|
||||
box-shadow: 0 12px 16px 0 hsla(0, 0%, 0%, 0.4);
|
||||
}
|
||||
</style>
|
||||
{% if data['query'] %}
|
||||
<form action="/login?{{ data['query'] }}" method="post">
|
||||
{% else %}
|
||||
<form action="/login" method="post">
|
||||
{% 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,7 +164,38 @@
|
||||
bootbox.alert(responseData.data)
|
||||
|
||||
}
|
||||
$("#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": 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 {
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "Version"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Der eingegebene Text ist der Pfad zum Passwort, nicht das Passwort selbst. Das Standartpasswort kann unter diesen Pfad eingesehen werden.",
|
||||
"disabled": "Account gesperrt. Für weitere Informationen den Serveradministrator kontaktieren",
|
||||
"forgotPassword": "Passwort vergessen",
|
||||
"incorrect": "Benutzername oder Passwort falsch",
|
||||
"login": "Einloggen",
|
||||
"password": "Passwort",
|
||||
"username": "Nutzername",
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "Version"
|
||||
},
|
||||
"login": {
|
||||
"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.",
|
||||
"forgotPassword": "Forgot Password",
|
||||
"incorrect": "Incorrect username or password",
|
||||
"login": "Log In",
|
||||
"password": "Password",
|
||||
"username": "Username",
|
||||
|
@ -111,6 +111,7 @@
|
||||
"starting": "Inicio-retrasado",
|
||||
"status": "Estado",
|
||||
"stop": "Detener",
|
||||
"storage": "Almacenamiento",
|
||||
"version": "Versión",
|
||||
"welcome": "Bienvenido a Crafty Controller"
|
||||
},
|
||||
@ -214,7 +215,10 @@
|
||||
"version": "Versión"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "La contraseña introducida es la ruta default de las credenciales, no la contraseña. Busca la contraseña accediendo a la carpeta de la ruta",
|
||||
"disabled": "Cuenta del usuario desactivada. Porfavor contacta al administrador para mas informacion.",
|
||||
"forgotPassword": "Olvidé mi contraseña",
|
||||
"incorrect": "El nombre de usuario o contraseña es incorrecto",
|
||||
"login": "Iniciar Sesión",
|
||||
"password": "Contraseña",
|
||||
"username": "Usuario",
|
||||
@ -326,6 +330,7 @@
|
||||
"bePatientDeleteFiles": "Tenga paciencia mientras eliminamos su servidor del panel de Crafty y eliminamos todos los archivos. Esta pantalla se cerrará en unos momentos.",
|
||||
"bePatientUpdate": "Tenga paciencia mientras actualizamos el servidor. El tiempo de descarga puede variar según la velocidad del Internet...<br /> Esta pantalla se actualizará en unos momentos.",
|
||||
"cancel": "Cancelar",
|
||||
"countPlayers": "Incluir el servidor en la cuenta total de jugadores",
|
||||
"crashTime": "Tiempo de espera por crasheo",
|
||||
"crashTimeDesc": "¿Cuanto tiempo esperar para considerar el servidor como crasheado?",
|
||||
"deleteFilesQuestion": "¿Eliminar archivos del servidor del host?",
|
||||
@ -510,6 +515,7 @@
|
||||
"cpuUsage": "Uso de CPU",
|
||||
"description": "Descripción",
|
||||
"errorCalculatingUptime": "Error calculando tiempo de actividad",
|
||||
"loadingMotd": "Cargando MOTD",
|
||||
"memUsage": "Uso de memoria",
|
||||
"offline": "Desconectado",
|
||||
"online": "En línea",
|
||||
@ -577,6 +583,7 @@
|
||||
"serverUpload": "Subir servidor comprimido",
|
||||
"serverVersion": "Versión del servidor",
|
||||
"sizeInGB": "Tamaño en GB",
|
||||
"unsupported": "Versiones de Minecraft inferiores a la 1.8 no estan soportadas por Crafty. Es posible instalarlas. Resultados pueden variar.",
|
||||
"uploadButton": "Subir",
|
||||
"uploadZip": "Subir archivo Zip para importar servidor",
|
||||
"zipPath": "Ruta del servidor"
|
||||
@ -591,6 +598,15 @@
|
||||
"newServer": "Crear nuevo Servidor",
|
||||
"servers": "Servidores"
|
||||
},
|
||||
"startup": {
|
||||
"almost": "Terminando. Espera un momento...",
|
||||
"internals": "Configurando e inicializando los componentes internos de Crafty",
|
||||
"internet": "Verificando conexion a internet",
|
||||
"server": "Inicializando ",
|
||||
"serverInit": "Inicializando Servidores",
|
||||
"starting": "Crafty esta iniciando...",
|
||||
"tasks": "Iniciando el programador de tareas"
|
||||
},
|
||||
"userConfig": {
|
||||
"apiKey": "Claves API",
|
||||
"auth": "¿Autorizado? ",
|
@ -215,7 +215,10 @@
|
||||
"version": "Version"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Ce que tu as renseigné n'est pas le mot de passe, mais le chemin du fichier où le trouver.",
|
||||
"disabled": "Ce compte est désactivé. Merci de contacter l'administrateur de ton serveur pour plus d'informations.",
|
||||
"forgotPassword": "Mot de Passe Oublié",
|
||||
"incorrect": "Identifiant et/ou mot de passe incorrect.",
|
||||
"login": "Connexion",
|
||||
"password": "Mot de Passe",
|
||||
"username": "Nom d'Utilisateur",
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "גרסה"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "הסיסמה שהזנת היא נתיב האישורים המוגדר כברירת מחדל, ולא הסיסמה עצמה. אנא מצא את הסיסמה המוגדרת כברירת מחדל במיקום זה.",
|
||||
"disabled": "חשבון המשתמש מושבת. אנא פנה למנהל המערכת שלך לקבלת מידע נוסף.",
|
||||
"forgotPassword": "שכחתי סיסמה",
|
||||
"incorrect": "שם משתמש או סיסמה שגויים",
|
||||
"login": "התחברות",
|
||||
"password": "סיסמה",
|
||||
"username": "שם משתמש",
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "VERSHUN"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Silleh hooman, dat iz da dafault secret path, not da passwurd. Plz find da default passwurd in dat spot.",
|
||||
"disabled": "User account no play. Plz boop ur system hooman for moar infoz.",
|
||||
"forgotPassword": "FORGWOTS YOUR SEEKRET",
|
||||
"incorrect": "U gotz wrong name or passwurd",
|
||||
"login": "WOG INZ",
|
||||
"password": "SEEKRET",
|
||||
"username": "USERNAEM",
|
||||
|
@ -216,7 +216,10 @@
|
||||
"version": "Versija"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Parole ko ievadijāt ir celš uz noklusētās paroles vietu, nevis noklusētā parole. Lūdzu apskatiet noklusēto paroli šajā vietā.",
|
||||
"disabled": "Lietotāja konts atspējots. Lūdzu sazinieties ar savu sistēmas administratoru priekš papildus informācijas.",
|
||||
"forgotPassword": "Aizmirsu Paroli",
|
||||
"incorrect": "Nepareizs lietotājvārds vai parole",
|
||||
"login": "Ieiet",
|
||||
"password": "Parole",
|
||||
"username": "Lietotājvārds",
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "Versie"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Het ingevoerde wachtwoord is het pad naar de standaardreferentie, niet het wachtwoord zelf. Raadpleeg de standaardwachtwoord op de aangegeven locatie.",
|
||||
"disabled": "Gebruikersaccount uitgeschakeld. Neem voor meer informatie contact op met uw systeembeheerder.",
|
||||
"forgotPassword": "Wachtwoord vergeten",
|
||||
"incorrect": "Verkeerde gebruikersnaam of wachtwoord",
|
||||
"login": "Log In",
|
||||
"password": "Wachtwoord",
|
||||
"username": "gebruikersnaam",
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "Wersja"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Hasło które wprowadziłeś jest podstawową ścieżką w której przechowywane są dane logowania. Znajdź podstawowe hasło w tej lokalizacji.",
|
||||
"disabled": "Konto tego użytkownika jest wyłączone. Skontaktuj się z administratorem by uzyskać więcej informacji.",
|
||||
"forgotPassword": "Zapomniałem hasła",
|
||||
"incorrect": "Niepoprawny login lub hasło/Niepoprawna nazwa użytkownika lub hasło",
|
||||
"login": "Zaloguj się",
|
||||
"password": "Hasło",
|
||||
"username": "Nazwa użytkownika",
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "เวอร์ชั่น"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "รหัสผ่านที่คุณกรอกคือเส้นทางข้อมูลเริ่มต้น ไม่ใช่รหัสผ่าน กรุณาค้นหารหัสผ่านเริ่มต้นในตำแหน่งนั้น",
|
||||
"disabled": "บัญชีผู้ใช้ถูกปิดใช้งาน กรุณาติดต่อผู้ดูแลระบบของคุณสำหรับข้อมูลเพิ่มเติม",
|
||||
"forgotPassword": "ลืมรหัสผ่าน",
|
||||
"incorrect": "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง",
|
||||
"login": "เข้าสู่ระบบ",
|
||||
"password": "รหัสผ่าน",
|
||||
"username": "ชื่อผู้ใช้",
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "Sürüm"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Girdiğiniz şifre varsayılan şifrenin konumudur, varsayılan şifre değil. Lütfen o konumda bulunan varsayılan şifreyi bulunuz.",
|
||||
"disabled": "Bu kullanıcı hesabı engellenmiştir. Daha fazla bilgi için lütfen sunucu yöneticiniz ile konuşunuz.",
|
||||
"forgotPassword": "Şifremi Unuttum",
|
||||
"incorrect": "Kullanıcı adınız veya şifreniz yanlış.",
|
||||
"login": "Oturum Aç",
|
||||
"password": "Şifre",
|
||||
"username": "Kullanıcı Adı",
|
||||
|
@ -85,7 +85,7 @@
|
||||
"cpuCurFreq": "Швидкість CPU",
|
||||
"cpuMaxFreq": "Максимальна швидкість CPU",
|
||||
"cpuUsage": "Використання CPU",
|
||||
"crashed": "Аварійне завершення",
|
||||
"crashed": "Краш",
|
||||
"dashboard": "Панель",
|
||||
"delay-explained": "Служба/агент нещодавно запущено та затримує запуск серверів minecraft",
|
||||
"host": "Хост",
|
||||
@ -215,7 +215,10 @@
|
||||
"version": "Версія"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "Пароль, який ви ввели, є шляхом до облікових даних за умовчанням, а не паролем. Будь ласка, знайдіть стандартний пароль у цьому місці.",
|
||||
"disabled": "Користувача вимкнено. Зверніться до вашого системного адміністратора за допомогою.",
|
||||
"forgotPassword": "Забули пароль",
|
||||
"incorrect": "Неправильний логін або пароль",
|
||||
"login": "Вхід",
|
||||
"password": "Пароль",
|
||||
"username": "Логін",
|
||||
@ -351,7 +354,7 @@
|
||||
"sendingRequest": "Надсилання вашого запиту...",
|
||||
"serverAutoStart": "Сервер Авто-старт",
|
||||
"serverAutostartDelay": "Сервер Авто-старт затримка",
|
||||
"serverAutostartDelayDesc": "Затримка Авто-старту сервера (Якщо увімкнуто раніше)",
|
||||
"serverAutostartDelayDesc": "Затримка Авто-старту сервера (Після запуску Crafty))",
|
||||
"serverCrashDetection": "Детектор крашу сервера",
|
||||
"serverExecutable": "Виконуваний файл Серверу",
|
||||
"serverExecutableDesc": "Це виконуваний файл для запуску сервера",
|
||||
@ -369,7 +372,7 @@
|
||||
"serverPortDesc": "Цей порт призначений для статистики Crafty",
|
||||
"serverStopCommand": "Команда зупинки сервера",
|
||||
"serverStopCommandDesc": "Команда яка буде надсилатись, щоб зупинити сервер",
|
||||
"showStatus": "Показувати на публічній сторінці статус",
|
||||
"showStatus": "Показувати статус на публічній сторінці",
|
||||
"shutdownTimeout": "Час відклику зупинки",
|
||||
"statsHint1": "Цей порт на якому працює сервер. Це потрібно лиш для того щоб Crafty міг виводити статистику для цього сервера.",
|
||||
"statsHint2": "Це не змінює порт вашого сервера. Ви мусите власноруч змінити налаштування в server.properties або іншому конфігураційному файлі.",
|
||||
@ -406,7 +409,7 @@
|
||||
"logs": "Логи",
|
||||
"metrics": "Графік",
|
||||
"playerControls": "Керування Гравцями",
|
||||
"reset": "Повернутись нагору",
|
||||
"reset": "Вниз",
|
||||
"schedule": "Розклад",
|
||||
"serverDetails": "Деталі сервера",
|
||||
"terminal": "Термінал"
|
||||
|
@ -215,7 +215,10 @@
|
||||
"version": "版本"
|
||||
},
|
||||
"login": {
|
||||
"defaultPath": "您输入的密码是默认凭据的路径,不是其中的密码。请在此路径中找到默认密码。",
|
||||
"disabled": "用户账号已禁用。请联系您的系统管理员以了解更多信息。",
|
||||
"forgotPassword": "忘记密码",
|
||||
"incorrect": "用户名或密码错误",
|
||||
"login": "登录",
|
||||
"password": "密码",
|
||||
"username": "用户名",
|
||||
|
Loading…
Reference in New Issue
Block a user