- Web UI: - Added secure Authentication system (Login, 2 Roles: Admin/Viewer) - Added System Monitoring Dashboard (Health, Services, Power Mgmt) - Added User Management Interface (Create, Delete, Enable/Disable) - Added Device Mapping view in iSCSI tab (lsscsi output) - Backend: - Implemented secure session management (auth.php) - Added power management APIs (restart/shutdown appliance) - Added device mapping API - CLI: - Created global 'vtl' management tool - Added scripts for reliable startup (vtllibrary fix) - Installer: - Updated install.sh with new dependencies (tgt, sudoers, permissions) - Included all new components in build-installer.sh - Docs: - Consolidated documentation into docs/ folder
313 lines
8.0 KiB
PHP
313 lines
8.0 KiB
PHP
<?php
|
|
/**
|
|
* Authentication and User Management
|
|
* Handles login, sessions, and user roles
|
|
*/
|
|
|
|
session_start();
|
|
|
|
// Configuration
|
|
$USERS_FILE = '/etc/mhvtl/users.json';
|
|
$SESSION_TIMEOUT = 3600; // 1 hour
|
|
|
|
// Initialize users file if it doesn't exist
|
|
function initializeUsersFile() {
|
|
global $USERS_FILE;
|
|
|
|
if (!file_exists($USERS_FILE)) {
|
|
// Create default admin user
|
|
$defaultUsers = [
|
|
[
|
|
'username' => 'admin',
|
|
'password' => password_hash('admin123', PASSWORD_BCRYPT),
|
|
'role' => 'admin',
|
|
'created' => date('Y-m-d H:i:s'),
|
|
'enabled' => true
|
|
]
|
|
];
|
|
|
|
file_put_contents($USERS_FILE, json_encode($defaultUsers, JSON_PRETTY_PRINT));
|
|
chmod($USERS_FILE, 0600);
|
|
}
|
|
}
|
|
|
|
// Load users from file
|
|
function loadUsers() {
|
|
global $USERS_FILE;
|
|
|
|
if (!file_exists($USERS_FILE)) {
|
|
initializeUsersFile();
|
|
}
|
|
|
|
$content = file_get_contents($USERS_FILE);
|
|
return json_decode($content, true) ?: [];
|
|
}
|
|
|
|
// Save users to file
|
|
function saveUsers($users) {
|
|
global $USERS_FILE;
|
|
|
|
file_put_contents($USERS_FILE, json_encode($users, JSON_PRETTY_PRINT));
|
|
chmod($USERS_FILE, 0600);
|
|
}
|
|
|
|
// Authenticate user
|
|
function authenticateUser($username, $password) {
|
|
$users = loadUsers();
|
|
|
|
foreach ($users as $user) {
|
|
if ($user['username'] === $username && $user['enabled']) {
|
|
if (password_verify($password, $user['password'])) {
|
|
// Set session
|
|
$_SESSION['user'] = [
|
|
'username' => $user['username'],
|
|
'role' => $user['role'],
|
|
'login_time' => time()
|
|
];
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Check if user is logged in
|
|
function isLoggedIn() {
|
|
global $SESSION_TIMEOUT;
|
|
|
|
if (!isset($_SESSION['user'])) {
|
|
return false;
|
|
}
|
|
|
|
// Check session timeout
|
|
if (time() - $_SESSION['user']['login_time'] > $SESSION_TIMEOUT) {
|
|
logout();
|
|
return false;
|
|
}
|
|
|
|
// Update last activity time
|
|
$_SESSION['user']['login_time'] = time();
|
|
|
|
return true;
|
|
}
|
|
|
|
// Check if user has admin role
|
|
function isAdmin() {
|
|
return isLoggedIn() && $_SESSION['user']['role'] === 'admin';
|
|
}
|
|
|
|
// Check if user has viewer role
|
|
function isViewer() {
|
|
return isLoggedIn() && $_SESSION['user']['role'] === 'viewer';
|
|
}
|
|
|
|
// Get current user
|
|
function getCurrentUser() {
|
|
return isset($_SESSION['user']) ? $_SESSION['user'] : null;
|
|
}
|
|
|
|
// Logout user
|
|
function logout() {
|
|
session_destroy();
|
|
$_SESSION = [];
|
|
}
|
|
|
|
// Require login
|
|
function requireLogin() {
|
|
if (!isLoggedIn()) {
|
|
http_response_code(401);
|
|
echo json_encode(['success' => false, 'error' => 'Unauthorized', 'redirect' => 'login.html']);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Require admin role
|
|
function requireAdmin() {
|
|
requireLogin();
|
|
|
|
if (!isAdmin()) {
|
|
http_response_code(403);
|
|
echo json_encode(['success' => false, 'error' => 'Forbidden: Admin access required']);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Get all users (admin only)
|
|
function getAllUsers() {
|
|
requireAdmin();
|
|
|
|
$users = loadUsers();
|
|
|
|
// Remove password hashes from response
|
|
$safeUsers = array_map(function($user) {
|
|
unset($user['password']);
|
|
return $user;
|
|
}, $users);
|
|
|
|
echo json_encode([
|
|
'success' => true,
|
|
'users' => array_values($safeUsers)
|
|
]);
|
|
}
|
|
|
|
// Create new user (admin only)
|
|
function createUser($data) {
|
|
requireAdmin();
|
|
|
|
$username = trim($data['username'] ?? '');
|
|
$password = $data['password'] ?? '';
|
|
$role = $data['role'] ?? 'viewer';
|
|
|
|
if (empty($username) || empty($password)) {
|
|
echo json_encode(['success' => false, 'error' => 'Username and password are required']);
|
|
return;
|
|
}
|
|
|
|
if (!in_array($role, ['admin', 'viewer'])) {
|
|
echo json_encode(['success' => false, 'error' => 'Invalid role']);
|
|
return;
|
|
}
|
|
|
|
$users = loadUsers();
|
|
|
|
// Check if username already exists
|
|
foreach ($users as $user) {
|
|
if ($user['username'] === $username) {
|
|
echo json_encode(['success' => false, 'error' => 'Username already exists']);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Create new user
|
|
$newUser = [
|
|
'username' => $username,
|
|
'password' => password_hash($password, PASSWORD_BCRYPT),
|
|
'role' => $role,
|
|
'created' => date('Y-m-d H:i:s'),
|
|
'enabled' => true
|
|
];
|
|
|
|
$users[] = $newUser;
|
|
saveUsers($users);
|
|
|
|
echo json_encode(['success' => true, 'message' => 'User created successfully']);
|
|
}
|
|
|
|
// Update user (admin only)
|
|
function updateUser($data) {
|
|
requireAdmin();
|
|
|
|
$username = trim($data['username'] ?? '');
|
|
$newPassword = $data['password'] ?? null;
|
|
$role = $data['role'] ?? null;
|
|
$enabled = $data['enabled'] ?? null;
|
|
|
|
if (empty($username)) {
|
|
echo json_encode(['success' => false, 'error' => 'Username is required']);
|
|
return;
|
|
}
|
|
|
|
$users = loadUsers();
|
|
$found = false;
|
|
|
|
foreach ($users as &$user) {
|
|
if ($user['username'] === $username) {
|
|
$found = true;
|
|
|
|
// Update password if provided
|
|
if ($newPassword) {
|
|
$user['password'] = password_hash($newPassword, PASSWORD_BCRYPT);
|
|
}
|
|
|
|
// Update role if provided
|
|
if ($role && in_array($role, ['admin', 'viewer'])) {
|
|
$user['role'] = $role;
|
|
}
|
|
|
|
// Update enabled status if provided
|
|
if ($enabled !== null) {
|
|
$user['enabled'] = (bool)$enabled;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$found) {
|
|
echo json_encode(['success' => false, 'error' => 'User not found']);
|
|
return;
|
|
}
|
|
|
|
saveUsers($users);
|
|
echo json_encode(['success' => true, 'message' => 'User updated successfully']);
|
|
}
|
|
|
|
// Delete user (admin only)
|
|
function deleteUser($username) {
|
|
requireAdmin();
|
|
|
|
if (empty($username)) {
|
|
echo json_encode(['success' => false, 'error' => 'Username is required']);
|
|
return;
|
|
}
|
|
|
|
// Prevent deleting yourself
|
|
if ($_SESSION['user']['username'] === $username) {
|
|
echo json_encode(['success' => false, 'error' => 'Cannot delete your own account']);
|
|
return;
|
|
}
|
|
|
|
$users = loadUsers();
|
|
$newUsers = array_filter($users, function($user) use ($username) {
|
|
return $user['username'] !== $username;
|
|
});
|
|
|
|
if (count($newUsers) === count($users)) {
|
|
echo json_encode(['success' => false, 'error' => 'User not found']);
|
|
return;
|
|
}
|
|
|
|
saveUsers(array_values($newUsers));
|
|
echo json_encode(['success' => true, 'message' => 'User deleted successfully']);
|
|
}
|
|
|
|
// Change own password
|
|
function changePassword($data) {
|
|
requireLogin();
|
|
|
|
$currentPassword = $data['current_password'] ?? '';
|
|
$newPassword = $data['new_password'] ?? '';
|
|
|
|
if (empty($currentPassword) || empty($newPassword)) {
|
|
echo json_encode(['success' => false, 'error' => 'Current and new password are required']);
|
|
return;
|
|
}
|
|
|
|
$users = loadUsers();
|
|
$currentUsername = $_SESSION['user']['username'];
|
|
|
|
foreach ($users as &$user) {
|
|
if ($user['username'] === $currentUsername) {
|
|
// Verify current password
|
|
if (!password_verify($currentPassword, $user['password'])) {
|
|
echo json_encode(['success' => false, 'error' => 'Current password is incorrect']);
|
|
return;
|
|
}
|
|
|
|
// Update password
|
|
$user['password'] = password_hash($newPassword, PASSWORD_BCRYPT);
|
|
saveUsers($users);
|
|
|
|
echo json_encode(['success' => true, 'message' => 'Password changed successfully']);
|
|
return;
|
|
}
|
|
}
|
|
|
|
echo json_encode(['success' => false, 'error' => 'User not found']);
|
|
}
|
|
|
|
// Initialize users file on first load
|
|
initializeUsersFile();
|
|
?>
|