kundenkarte/pwa_auth.php
data 50ae4e4a08 fix(pwa): Terminal-Ausrichtung, gebündelte Pfeile, Block-Value Größe
- Gebündelte Terminals: Pfeil jetzt in Zeile 2/4 statt Label-Zeile
- Terminal-Punkte mit CSS-Klassen terminal-row-top/bottom
- Equipment-Block-Value auf 8px verkleinert
- Grid gap auf 0 für kompaktere Darstellung
- Service Worker v6.1

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-04 08:34:17 +01:00

152 lines
4 KiB
PHP
Executable file

<?php
/* Copyright (C) 2026 Alles Watt lauft
*
* PWA Authentication - Token-basierte Authentifizierung
* Für Offline-First Mobile App
*/
if (!defined('NOLOGIN')) {
define('NOLOGIN', '1');
}
if (!defined('NOREQUIREMENU')) {
define('NOREQUIREMENU', '1');
}
if (!defined('NOREQUIREHTML')) {
define('NOREQUIREHTML', '1');
}
if (!defined('NOREQUIREAJAX')) {
define('NOREQUIREAJAX', '1');
}
// Load Dolibarr environment
$res = 0;
if (!$res && file_exists("../main.inc.php")) {
$res = @include "../main.inc.php";
}
if (!$res && file_exists("../../main.inc.php")) {
$res = @include "../../main.inc.php";
}
if (!$res) {
die(json_encode(array('success' => false, 'error' => 'Dolibarr not loaded')));
}
header('Content-Type: application/json; charset=UTF-8');
$action = GETPOST('action', 'aZ09');
$response = array('success' => false);
switch ($action) {
case 'login':
$username = GETPOST('username', 'alphanohtml');
$password = GETPOST('password', 'none');
if (empty($username) || empty($password)) {
$response['error'] = 'Benutzername und Passwort erforderlich';
break;
}
// Brute force protection
usleep(100000); // 100ms delay
// Load user
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
$userLogin = new User($db);
// Find user by login
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."user WHERE login = '".$db->escape($username)."' AND statut = 1";
$result = $db->query($sql);
if ($result && $db->num_rows($result) > 0) {
$obj = $db->fetch_object($result);
$userLogin->fetch($obj->rowid);
$userLogin->getrights();
// Check password
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
$passOk = false;
if (!empty($userLogin->pass_indatabase_crypted)) {
// Check crypted password
$passOk = dol_verifyHash($password, $userLogin->pass_indatabase_crypted);
}
if ($passOk) {
// Check kundenkarte permission
if ($userLogin->hasRight('kundenkarte', 'read')) {
// Generate token (valid for 15 days)
$tokenData = array(
'user_id' => $userLogin->id,
'login' => $userLogin->login,
'created' => time(),
'expires' => time() + (15 * 24 * 60 * 60),
'hash' => md5($userLogin->id . $userLogin->login . getDolGlobalString('MAIN_SECURITY_SALT', 'defaultsalt'))
);
$token = base64_encode(json_encode($tokenData));
$response['success'] = true;
$response['token'] = $token;
$response['user'] = array(
'id' => $userLogin->id,
'login' => $userLogin->login,
'name' => $userLogin->getFullName($langs)
);
} else {
$response['error'] = 'Keine Berechtigung für KundenKarte';
}
} else {
$response['error'] = 'Falsches Passwort';
}
} else {
$response['error'] = 'Benutzer nicht gefunden';
}
break;
case 'verify':
$token = GETPOST('token', 'none');
if (empty($token)) {
$response['error'] = 'Kein Token';
break;
}
$tokenData = json_decode(base64_decode($token), true);
if (!$tokenData || empty($tokenData['user_id']) || empty($tokenData['expires'])) {
$response['error'] = 'Ungültiges Token';
break;
}
// Check expiration
if ($tokenData['expires'] < time()) {
$response['error'] = 'Token abgelaufen';
break;
}
// Verify hash
$expectedHash = md5($tokenData['user_id'] . $tokenData['login'] . getDolGlobalString('MAIN_SECURITY_SALT', 'defaultsalt'));
if ($tokenData['hash'] !== $expectedHash) {
$response['error'] = 'Token manipuliert';
break;
}
// Load user to verify still active
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
$userCheck = new User($db);
if ($userCheck->fetch($tokenData['user_id']) > 0 && $userCheck->statut == 1) {
$response['success'] = true;
$response['user'] = array(
'id' => $userCheck->id,
'login' => $userCheck->login,
'name' => $userCheck->getFullName($langs)
);
} else {
$response['error'] = 'Benutzer nicht mehr aktiv';
}
break;
default:
$response['error'] = 'Unbekannte Aktion';
}
echo json_encode($response);
$db->close();